mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-31 06:35:14 +00:00
Switch MainWindow to Ui::RpWindow
This commit is contained in:
@@ -9,9 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "storage/localstorage.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "ui/platform/ui_platform_window.h"
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "history/history.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "window/window_lock_widgets.h"
|
||||
@@ -161,9 +161,8 @@ QIcon CreateIcon(Main::Session *session) {
|
||||
MainWindow::MainWindow(not_null<Controller*> controller)
|
||||
: _controller(controller)
|
||||
, _positionUpdatedTimer([=] { savePosition(); })
|
||||
, _outdated(CreateOutdatedBar(this))
|
||||
, _body(this)
|
||||
, _titleText(qsl("Telegram")) {
|
||||
, _outdated(CreateOutdatedBar(body()))
|
||||
, _body(body()) {
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
updatePalette();
|
||||
@@ -266,8 +265,6 @@ QRect MainWindow::desktopRect() const {
|
||||
}
|
||||
|
||||
void MainWindow::init() {
|
||||
Expects(!windowHandle());
|
||||
|
||||
createWinId();
|
||||
|
||||
initHook();
|
||||
@@ -293,7 +290,7 @@ void MainWindow::init() {
|
||||
|
||||
updatePalette();
|
||||
|
||||
if (Platform::AllowNativeWindowFrameToggle()) {
|
||||
if (Ui::Platform::NativeWindowFrameSupported()) {
|
||||
Core::App().settings().nativeWindowFrameChanges(
|
||||
) | rpl::start_with_next([=](bool native) {
|
||||
refreshTitleWidget();
|
||||
@@ -308,7 +305,6 @@ void MainWindow::init() {
|
||||
|
||||
void MainWindow::handleStateChanged(Qt::WindowState state) {
|
||||
stateChangedHook(state);
|
||||
updateShadowSize();
|
||||
updateControlsGeometry();
|
||||
if (state == Qt::WindowMinimized) {
|
||||
controller().updateIsActiveBlur();
|
||||
@@ -381,27 +377,6 @@ void MainWindow::updatePalette() {
|
||||
setPalette(p);
|
||||
}
|
||||
|
||||
HitTestResult MainWindow::hitTest(const QPoint &p) const {
|
||||
auto titleResult = _title ? _title->hitTest(p - _title->geometry().topLeft()) : Window::HitTestResult::None;
|
||||
if (titleResult != Window::HitTestResult::None) {
|
||||
return titleResult;
|
||||
} else if (rect().contains(p)) {
|
||||
return Window::HitTestResult::Client;
|
||||
}
|
||||
return Window::HitTestResult::None;
|
||||
}
|
||||
|
||||
bool MainWindow::hasShadow() const {
|
||||
const auto center = geometry().center();
|
||||
return Ui::Platform::WindowExtentsSupported()
|
||||
&& Ui::Platform::TranslucentWindowsSupported(center)
|
||||
&& _title;
|
||||
}
|
||||
|
||||
QRect MainWindow::inner() const {
|
||||
return rect().marginsRemoved(_padding);
|
||||
}
|
||||
|
||||
int MainWindow::computeMinWidth() const {
|
||||
auto result = st::windowMinWidth;
|
||||
if (const auto session = _controller->sessionController()) {
|
||||
@@ -412,38 +387,32 @@ int MainWindow::computeMinWidth() const {
|
||||
if (_rightColumn) {
|
||||
result += _rightColumn->width();
|
||||
}
|
||||
return result + _padding.left() + _padding.right();
|
||||
return result;
|
||||
}
|
||||
|
||||
int MainWindow::computeMinHeight() const {
|
||||
const auto title = _title ? _title->height() : 0;
|
||||
const auto outdated = [&] {
|
||||
if (!_outdated) {
|
||||
return 0;
|
||||
}
|
||||
_outdated->resizeToWidth(st::windowMinWidth - _padding.left() - _padding.right());
|
||||
_outdated->resizeToWidth(st::windowMinWidth);
|
||||
return _outdated->height();
|
||||
}();
|
||||
return title + outdated + st::windowMinHeight + _padding.top() + _padding.bottom();
|
||||
return outdated + st::windowMinHeight;
|
||||
}
|
||||
|
||||
void MainWindow::refreshTitleWidget() {
|
||||
if (Platform::AllowNativeWindowFrameToggle()
|
||||
if (Ui::Platform::NativeWindowFrameSupported()
|
||||
&& Core::App().settings().nativeWindowFrame()) {
|
||||
_title.destroy();
|
||||
setNativeFrame(true);
|
||||
if (Platform::NativeTitleRequiresShadow()) {
|
||||
_titleShadow.create(this);
|
||||
_titleShadow->show();
|
||||
}
|
||||
} else if ((_title = Platform::CreateTitleWidget(this))) {
|
||||
_title->show();
|
||||
_title->init();
|
||||
} else {
|
||||
setNativeFrame(false);
|
||||
_titleShadow.destroy();
|
||||
}
|
||||
|
||||
const auto withShadow = hasShadow();
|
||||
windowHandle()->setFlag(Qt::NoDropShadowWindowHint, withShadow);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, !withShadow);
|
||||
}
|
||||
|
||||
void MainWindow::updateMinimumSize() {
|
||||
@@ -451,21 +420,13 @@ void MainWindow::updateMinimumSize() {
|
||||
setMinimumHeight(computeMinHeight());
|
||||
}
|
||||
|
||||
void MainWindow::updateShadowSize() {
|
||||
_padding = hasShadow() && !isMaximized()
|
||||
? st::callShadow.extend
|
||||
: style::margins();
|
||||
}
|
||||
|
||||
void MainWindow::recountGeometryConstraints() {
|
||||
updateShadowSize();
|
||||
updateMinimumSize();
|
||||
updateControlsGeometry();
|
||||
fixOrder();
|
||||
}
|
||||
|
||||
void MainWindow::initSize() {
|
||||
updateShadowSize();
|
||||
updateMinimumSize();
|
||||
|
||||
if (initSizeFromSystem()) {
|
||||
@@ -565,7 +526,6 @@ void MainWindow::initSize() {
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry += _padding;
|
||||
DEBUG_LOG(("Window Pos: Setting first %1, %2, %3, %4").arg(geometry.x()).arg(geometry.y()).arg(geometry.width()).arg(geometry.height()));
|
||||
setGeometry(geometry);
|
||||
}
|
||||
@@ -574,18 +534,6 @@ void MainWindow::positionUpdated() {
|
||||
_positionUpdatedTimer.callOnce(kSaveWindowPositionTimeout);
|
||||
}
|
||||
|
||||
bool MainWindow::titleVisible() const {
|
||||
return _title && !_title->isHidden();
|
||||
}
|
||||
|
||||
void MainWindow::setTitleVisible(bool visible) {
|
||||
if (_title && (_title->isHidden() == visible)) {
|
||||
_title->setVisible(visible);
|
||||
updateControlsGeometry();
|
||||
}
|
||||
titleVisibilityChangedHook();
|
||||
}
|
||||
|
||||
int32 MainWindow::screenNameChecksum(const QString &name) const {
|
||||
const auto bytes = name.toUtf8();
|
||||
return base::crc32(bytes.constData(), bytes.size());
|
||||
@@ -605,15 +553,7 @@ void MainWindow::attachToTrayIcon(not_null<QSystemTrayIcon*> icon) {
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::paintEvent(QPaintEvent *e) {
|
||||
if (hasShadow() && !isMaximized()) {
|
||||
QPainter p(this);
|
||||
Ui::Shadow::paint(p, inner(), width(), st::callShadow);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent *e) {
|
||||
updateShadowSize();
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
@@ -626,14 +566,10 @@ void MainWindow::leaveEventHook(QEvent *e) {
|
||||
}
|
||||
|
||||
void MainWindow::updateControlsGeometry() {
|
||||
const auto inner = this->inner();
|
||||
const auto inner = body()->rect();
|
||||
auto bodyLeft = inner.x();
|
||||
auto bodyTop = inner.y();
|
||||
auto bodyWidth = inner.width();
|
||||
if (_title && !_title->isHidden()) {
|
||||
_title->setGeometry(inner.x(), bodyTop, inner.width(), _title->height());
|
||||
bodyTop += _title->height();
|
||||
}
|
||||
if (_titleShadow) {
|
||||
_titleShadow->setGeometry(inner.x(), bodyTop, inner.width(), st::lineWidth);
|
||||
}
|
||||
@@ -656,7 +592,7 @@ void MainWindow::updateUnreadCounter() {
|
||||
}
|
||||
|
||||
const auto counter = Core::App().unreadBadge();
|
||||
_titleText = (counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram");
|
||||
setTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"));
|
||||
|
||||
unreadCounterChangedHook();
|
||||
}
|
||||
@@ -683,7 +619,7 @@ void MainWindow::savePosition(Qt::WindowState state) {
|
||||
realPosition.maximized = 1;
|
||||
DEBUG_LOG(("Window Pos: Saving maximized position."));
|
||||
} else {
|
||||
auto r = geometry().marginsRemoved(_padding);
|
||||
auto r = body()->mapToGlobal(body()->rect());
|
||||
realPosition.x = r.x();
|
||||
realPosition.y = r.y();
|
||||
realPosition.w = r.width() - (_rightColumn ? _rightColumn->width() : 0);
|
||||
@@ -774,7 +710,7 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
|
||||
const auto wasRightWidth = _rightColumn ? _rightColumn->width() : 0;
|
||||
_rightColumn = std::move(widget);
|
||||
if (_rightColumn) {
|
||||
_rightColumn->setParent(this);
|
||||
_rightColumn->setParent(body());
|
||||
_rightColumn->show();
|
||||
_rightColumn->setFocus();
|
||||
} else {
|
||||
@@ -799,12 +735,12 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
|
||||
|
||||
int MainWindow::maximalExtendBy() const {
|
||||
auto desktop = QDesktopWidget().availableGeometry(this);
|
||||
return std::max(desktop.width() - inner().width(), 0);
|
||||
return std::max(desktop.width() - body()->width(), 0);
|
||||
}
|
||||
|
||||
bool MainWindow::canExtendNoMove(int extendBy) const {
|
||||
auto desktop = QDesktopWidget().availableGeometry(this);
|
||||
auto inner = geometry().marginsRemoved(_padding);
|
||||
auto inner = body()->mapToGlobal(body()->rect());
|
||||
auto innerRight = (inner.x() + inner.width() + extendBy);
|
||||
auto desktopRight = (desktop.x() + desktop.width());
|
||||
return innerRight <= desktopRight;
|
||||
@@ -812,7 +748,7 @@ bool MainWindow::canExtendNoMove(int extendBy) const {
|
||||
|
||||
int MainWindow::tryToExtendWidthBy(int addToWidth) {
|
||||
auto desktop = QDesktopWidget().availableGeometry(this);
|
||||
auto inner = geometry();
|
||||
auto inner = body()->mapToGlobal(body()->rect());
|
||||
accumulate_min(
|
||||
addToWidth,
|
||||
std::max(desktop.width() - inner.width(), 0));
|
||||
@@ -821,7 +757,7 @@ int MainWindow::tryToExtendWidthBy(int addToWidth) {
|
||||
inner.x(),
|
||||
desktop.x() + desktop.width() - newWidth);
|
||||
if (inner.x() != newLeft || inner.width() != newWidth) {
|
||||
setGeometry(newLeft, inner.y(), newWidth, inner.height());
|
||||
setGeometry(QRect(newLeft, inner.y(), newWidth, inner.height()));
|
||||
} else {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
@@ -841,8 +777,6 @@ void MainWindow::launchDrag(
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
_title.destroy();
|
||||
|
||||
// Otherwise:
|
||||
// ~QWidget
|
||||
// QWidgetPrivate::close_helper
|
||||
|
@@ -7,8 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/window_title.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "ui/widgets/rp_window.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/object_ptr.h"
|
||||
#include "core/core_settings.h"
|
||||
@@ -37,7 +36,7 @@ QImage LoadLogoNoMargin();
|
||||
QIcon CreateIcon(Main::Session *session = nullptr);
|
||||
void ConvertIconToBlack(QImage &image);
|
||||
|
||||
class MainWindow : public Ui::RpWidget {
|
||||
class MainWindow : public Ui::RpWindow {
|
||||
public:
|
||||
explicit MainWindow(not_null<Controller*> controller);
|
||||
virtual ~MainWindow();
|
||||
@@ -60,7 +59,6 @@ public:
|
||||
[[nodiscard]] QRect desktopRect() const;
|
||||
|
||||
void init();
|
||||
[[nodiscard]] HitTestResult hitTest(const QPoint &p) const;
|
||||
|
||||
void updateIsActive();
|
||||
|
||||
@@ -77,12 +75,6 @@ public:
|
||||
}
|
||||
void positionUpdated();
|
||||
|
||||
bool titleVisible() const;
|
||||
void setTitleVisible(bool visible);
|
||||
QString titleText() const {
|
||||
return _titleText;
|
||||
}
|
||||
|
||||
void reActivateWindow();
|
||||
|
||||
void showRightColumn(object_ptr<TWidget> widget);
|
||||
@@ -112,22 +104,18 @@ public:
|
||||
|
||||
void clearWidgets();
|
||||
|
||||
QRect inner() const;
|
||||
int computeMinWidth() const;
|
||||
int computeMinHeight() const;
|
||||
|
||||
void recountGeometryConstraints();
|
||||
virtual void updateControlsGeometry();
|
||||
|
||||
bool hasShadow() const;
|
||||
|
||||
bool minimizeToTray();
|
||||
void updateGlobalMenu() {
|
||||
updateGlobalMenuHook();
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
|
||||
@@ -154,9 +142,6 @@ protected:
|
||||
virtual void stateChangedHook(Qt::WindowState state) {
|
||||
}
|
||||
|
||||
virtual void titleVisibilityChangedHook() {
|
||||
}
|
||||
|
||||
virtual void unreadCounterChangedHook() {
|
||||
}
|
||||
|
||||
@@ -180,10 +165,6 @@ protected:
|
||||
|
||||
virtual void createGlobalMenu() {
|
||||
}
|
||||
virtual void initShadows() {
|
||||
}
|
||||
virtual void firstShadowsUpdate() {
|
||||
}
|
||||
|
||||
virtual bool initSizeFromSystem() {
|
||||
return false;
|
||||
@@ -203,7 +184,6 @@ protected:
|
||||
private:
|
||||
void refreshTitleWidget();
|
||||
void updateMinimumSize();
|
||||
void updateShadowSize();
|
||||
void updatePalette();
|
||||
void initSize();
|
||||
|
||||
@@ -214,7 +194,6 @@ private:
|
||||
base::Timer _positionUpdatedTimer;
|
||||
bool _positionInited = false;
|
||||
|
||||
object_ptr<TitleWidget> _title = { nullptr };
|
||||
object_ptr<Ui::PlainShadow> _titleShadow = { nullptr };
|
||||
object_ptr<Ui::RpWidget> _outdated;
|
||||
object_ptr<Ui::RpWidget> _body;
|
||||
@@ -222,8 +201,6 @@ private:
|
||||
|
||||
QIcon _icon;
|
||||
bool _usingSupportIcon = false;
|
||||
QString _titleText;
|
||||
style::margins _padding;
|
||||
|
||||
bool _isActive = false;
|
||||
|
||||
|
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "export/export_manager.h"
|
||||
#include "ui/platform/ui_platform_window.h"
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_domain.h"
|
||||
@@ -267,7 +268,7 @@ void Controller::showSettings() {
|
||||
|
||||
int Controller::verticalShadowTop() const {
|
||||
return (Platform::NativeTitleRequiresShadow()
|
||||
&& Platform::AllowNativeWindowFrameToggle()
|
||||
&& Ui::Platform::NativeWindowFrameSupported()
|
||||
&& Core::App().settings().nativeWindowFrame())
|
||||
? st::lineWidth
|
||||
: 0;
|
||||
|
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace Window {
|
||||
|
||||
enum class HitTestResult {
|
||||
None = 0,
|
||||
Client,
|
||||
SysButton,
|
||||
Caption,
|
||||
Top,
|
||||
TopRight,
|
||||
Right,
|
||||
BottomRight,
|
||||
Bottom,
|
||||
BottomLeft,
|
||||
Left,
|
||||
TopLeft,
|
||||
};
|
||||
|
||||
class TitleWidget : public Ui::RpWidget {
|
||||
public:
|
||||
using RpWidget::RpWidget;
|
||||
|
||||
virtual void init() {
|
||||
}
|
||||
virtual HitTestResult hitTest(const QPoint &p) const {
|
||||
return HitTestResult::None;
|
||||
}
|
||||
virtual QRect iconRect() const {
|
||||
return QRect();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace Window
|
@@ -1,417 +0,0 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "window/window_title_qt.h"
|
||||
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
namespace Window {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] style::margins ShadowExtents() {
|
||||
return st::callShadow.extend;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RemoveDuplicates(std::vector<T> &v) {
|
||||
auto end = v.end();
|
||||
for (auto it = v.begin(); it != end; ++it) {
|
||||
end = std::remove(it + 1, end, *it);
|
||||
}
|
||||
|
||||
v.erase(end, v.end());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TitleWidgetQt::TitleWidgetQt(QWidget *parent)
|
||||
: TitleWidget(parent)
|
||||
, _st(st::defaultWindowTitle)
|
||||
, _minimize(this, _st.minimize)
|
||||
, _maximizeRestore(this, _st.maximize)
|
||||
, _close(this, _st.close)
|
||||
, _shadow(this, st::titleShadow)
|
||||
, _maximizedState(parent->window()->windowState() & Qt::WindowMaximized) {
|
||||
_minimize->setClickedCallback([=] {
|
||||
window()->setWindowState(
|
||||
window()->windowState() | Qt::WindowMinimized);
|
||||
_minimize->clearState();
|
||||
});
|
||||
_minimize->setPointerCursor(false);
|
||||
_maximizeRestore->setClickedCallback([=] {
|
||||
window()->setWindowState(_maximizedState
|
||||
? Qt::WindowNoState
|
||||
: Qt::WindowMaximized);
|
||||
_maximizeRestore->clearState();
|
||||
});
|
||||
_maximizeRestore->setPointerCursor(false);
|
||||
_close->setClickedCallback([=] {
|
||||
window()->close();
|
||||
_close->clearState();
|
||||
});
|
||||
_close->setPointerCursor(false);
|
||||
|
||||
Ui::Platform::TitleControlsLayoutChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateControlsPosition();
|
||||
}, lifetime());
|
||||
|
||||
QCoreApplication::instance()->installEventFilter(this);
|
||||
|
||||
_windowWasFrameless = (window()->windowFlags()
|
||||
& Qt::FramelessWindowHint) != 0;
|
||||
|
||||
if (!_windowWasFrameless) {
|
||||
toggleFramelessWindow(true);
|
||||
}
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
resize(width(), _st.height);
|
||||
|
||||
updateWindowExtents();
|
||||
}
|
||||
|
||||
TitleWidgetQt::~TitleWidgetQt() {
|
||||
restoreCursor();
|
||||
|
||||
if (!_windowWasFrameless) {
|
||||
toggleFramelessWindow(false);
|
||||
}
|
||||
|
||||
if (_extentsSet) {
|
||||
Ui::Platform::UnsetWindowExtents(window()->windowHandle());
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::init() {
|
||||
connect(
|
||||
window()->windowHandle(),
|
||||
&QWindow::windowStateChanged,
|
||||
this,
|
||||
[=](Qt::WindowState state) { windowStateChanged(state); });
|
||||
connect(
|
||||
window()->windowHandle(),
|
||||
&QWindow::visibleChanged,
|
||||
this,
|
||||
[=](bool visible) { visibleChanged(visible); });
|
||||
_maximizedState = (window()->windowState() & Qt::WindowMaximized);
|
||||
_activeState = isActiveWindow();
|
||||
updateButtonsState();
|
||||
}
|
||||
|
||||
bool TitleWidgetQt::hasShadow() const {
|
||||
const auto center = window()->geometry().center();
|
||||
return Ui::Platform::WindowExtentsSupported()
|
||||
&& Ui::Platform::TranslucentWindowsSupported(center);
|
||||
}
|
||||
|
||||
Ui::IconButton *TitleWidgetQt::controlWidget(Control control) const {
|
||||
switch (control) {
|
||||
case Control::Minimize: return _minimize;
|
||||
case Control::Maximize: return _maximizeRestore;
|
||||
case Control::Close: return _close;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TitleWidgetQt::paintEvent(QPaintEvent *e) {
|
||||
auto active = isActiveWindow();
|
||||
if (_activeState != active) {
|
||||
_activeState = active;
|
||||
updateButtonsState();
|
||||
}
|
||||
Painter(this).fillRect(rect(), active ? _st.bgActive : _st.bg);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::toggleFramelessWindow(bool enabled) {
|
||||
window()->windowHandle()->setFlag(Qt::FramelessWindowHint, enabled);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateWindowExtents() {
|
||||
if (hasShadow()) {
|
||||
Ui::Platform::SetWindowExtents(
|
||||
window()->windowHandle(),
|
||||
resizeArea());
|
||||
|
||||
_extentsSet = true;
|
||||
} else if (_extentsSet) {
|
||||
Ui::Platform::UnsetWindowExtents(window()->windowHandle());
|
||||
_extentsSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateControlsPosition() {
|
||||
const auto controlsLayout = Ui::Platform::TitleControlsLayout();
|
||||
const auto controlsLeft = controlsLayout.left;
|
||||
const auto controlsRight = controlsLayout.right;
|
||||
|
||||
const auto controlPresent = [&](Control control) {
|
||||
return ranges::contains(controlsLeft, control)
|
||||
|| ranges::contains(controlsRight, control);
|
||||
};
|
||||
|
||||
if (controlPresent(Control::Minimize)) {
|
||||
_minimize->show();
|
||||
} else {
|
||||
_minimize->hide();
|
||||
}
|
||||
|
||||
if (controlPresent(Control::Maximize)) {
|
||||
_maximizeRestore->show();
|
||||
} else {
|
||||
_maximizeRestore->hide();
|
||||
}
|
||||
|
||||
if (controlPresent(Control::Close)) {
|
||||
_close->show();
|
||||
} else {
|
||||
_close->hide();
|
||||
}
|
||||
|
||||
updateControlsPositionBySide(controlsLeft, false);
|
||||
updateControlsPositionBySide(controlsRight, true);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateControlsPositionBySide(
|
||||
const std::vector<Control> &controls,
|
||||
bool right) {
|
||||
auto preparedControls = right
|
||||
? (ranges::views::reverse(controls) | ranges::to_vector)
|
||||
: controls;
|
||||
|
||||
RemoveDuplicates(preparedControls);
|
||||
|
||||
auto position = 0;
|
||||
for (const auto &control : preparedControls) {
|
||||
const auto widget = controlWidget(control);
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (right) {
|
||||
widget->moveToRight(position, 0);
|
||||
} else {
|
||||
widget->moveToLeft(position, 0);
|
||||
}
|
||||
|
||||
position += widget->width();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsPosition();
|
||||
_shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mousePressEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
_mousePressed = true;
|
||||
} else if (e->button() == Qt::RightButton) {
|
||||
Ui::Platform::ShowWindowMenu(window()->windowHandle());
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
_mousePressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (_mousePressed) {
|
||||
window()->windowHandle()->startSystemMove();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||
if (_maximizedState) {
|
||||
window()->setWindowState(Qt::WindowNoState);
|
||||
} else {
|
||||
window()->setWindowState(Qt::WindowMaximized);
|
||||
}
|
||||
}
|
||||
|
||||
bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) {
|
||||
if (e->type() == QEvent::MouseMove
|
||||
|| e->type() == QEvent::MouseButtonPress) {
|
||||
if (obj->isWidgetType()
|
||||
&& window()->isAncestorOf(static_cast<QWidget*>(obj))) {
|
||||
const auto mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
const auto currentPoint = mouseEvent->windowPos().toPoint();
|
||||
const auto edges = edgesFromPos(currentPoint);
|
||||
|
||||
if (e->type() == QEvent::MouseMove
|
||||
&& mouseEvent->buttons() == Qt::NoButton) {
|
||||
if (_mousePressed) {
|
||||
_mousePressed = false;
|
||||
}
|
||||
|
||||
updateCursor(edges);
|
||||
}
|
||||
|
||||
if (e->type() == QEvent::MouseButtonPress
|
||||
&& mouseEvent->button() == Qt::LeftButton
|
||||
&& edges) {
|
||||
return window()->windowHandle()->startSystemResize(edges);
|
||||
}
|
||||
}
|
||||
} else if (e->type() == QEvent::Leave) {
|
||||
if (obj->isWidgetType() && window() == static_cast<QWidget*>(obj)) {
|
||||
restoreCursor();
|
||||
}
|
||||
} else if (e->type() == QEvent::Move
|
||||
|| e->type() == QEvent::Resize) {
|
||||
if (obj->isWidgetType() && window() == static_cast<QWidget*>(obj)) {
|
||||
updateWindowExtents();
|
||||
}
|
||||
}
|
||||
|
||||
return TitleWidget::eventFilter(obj, e);
|
||||
}
|
||||
|
||||
void TitleWidgetQt::windowStateChanged(Qt::WindowState state) {
|
||||
if (state == Qt::WindowMinimized) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto maximized = (state == Qt::WindowMaximized);
|
||||
if (_maximizedState != maximized) {
|
||||
_maximizedState = maximized;
|
||||
updateButtonsState();
|
||||
updateWindowExtents();
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::visibleChanged(bool visible) {
|
||||
if (visible) {
|
||||
updateWindowExtents();
|
||||
|
||||
// workaround a bug in Qt 5.12, works ok in Qt 5.15
|
||||
// https://github.com/telegramdesktop/tdesktop/issues/10119
|
||||
if (!_windowWasFrameless) {
|
||||
toggleFramelessWindow(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateButtonsState() {
|
||||
_minimize->setIconOverride(_activeState
|
||||
? &_st.minimizeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.minimizeIconActiveOver
|
||||
: nullptr);
|
||||
if (_maximizedState) {
|
||||
_maximizeRestore->setIconOverride(
|
||||
_activeState
|
||||
? &_st.restoreIconActive : &_st.restoreIcon,
|
||||
_activeState
|
||||
? &_st.restoreIconActiveOver
|
||||
: &_st.restoreIconOver);
|
||||
} else {
|
||||
_maximizeRestore->setIconOverride(_activeState
|
||||
? &_st.maximizeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.maximizeIconActiveOver
|
||||
: nullptr);
|
||||
}
|
||||
_close->setIconOverride(_activeState
|
||||
? &_st.closeIconActive
|
||||
: nullptr,
|
||||
_activeState
|
||||
? &_st.closeIconActiveOver
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
QMargins TitleWidgetQt::resizeArea() const {
|
||||
if (_maximizedState) {
|
||||
return QMargins();
|
||||
} else if (!hasShadow()) {
|
||||
return QMargins(
|
||||
st::windowResizeArea,
|
||||
st::windowResizeArea,
|
||||
st::windowResizeArea,
|
||||
st::windowResizeArea);
|
||||
}
|
||||
|
||||
return ShadowExtents();
|
||||
}
|
||||
|
||||
Qt::Edges TitleWidgetQt::edgesFromPos(const QPoint &pos) const {
|
||||
const auto area = resizeArea();
|
||||
|
||||
if (area.isNull()) {
|
||||
return Qt::Edges();
|
||||
} else if (pos.x() <= area.left()) {
|
||||
if (pos.y() <= area.top()) {
|
||||
return Qt::LeftEdge | Qt::TopEdge;
|
||||
} else if (pos.y() >= (window()->height() - area.bottom())) {
|
||||
return Qt::LeftEdge | Qt::BottomEdge;
|
||||
}
|
||||
|
||||
return Qt::LeftEdge;
|
||||
} else if (pos.x() >= (window()->width() - area.right())) {
|
||||
if (pos.y() <= area.top()) {
|
||||
return Qt::RightEdge | Qt::TopEdge;
|
||||
} else if (pos.y() >= (window()->height() - area.bottom())) {
|
||||
return Qt::RightEdge | Qt::BottomEdge;
|
||||
}
|
||||
|
||||
return Qt::RightEdge;
|
||||
} else if (pos.y() <= area.top()) {
|
||||
return Qt::TopEdge;
|
||||
} else if (pos.y() >= (window()->height() - area.bottom())) {
|
||||
return Qt::BottomEdge;
|
||||
}
|
||||
|
||||
return Qt::Edges();
|
||||
}
|
||||
|
||||
void TitleWidgetQt::updateCursor(Qt::Edges edges) {
|
||||
if (!edges) {
|
||||
restoreCursor();
|
||||
return;
|
||||
} else if (!QGuiApplication::overrideCursor()) {
|
||||
_cursorOverriden = false;
|
||||
}
|
||||
|
||||
if (!_cursorOverriden) {
|
||||
_cursorOverriden = true;
|
||||
QGuiApplication::setOverrideCursor(QCursor());
|
||||
}
|
||||
|
||||
if (((edges & Qt::LeftEdge) && (edges & Qt::TopEdge))
|
||||
|| ((edges & Qt::RightEdge) && (edges & Qt::BottomEdge))) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeFDiagCursor));
|
||||
} else if (((edges & Qt::LeftEdge) && (edges & Qt::BottomEdge))
|
||||
|| ((edges & Qt::RightEdge) && (edges & Qt::TopEdge))) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeBDiagCursor));
|
||||
} else if ((edges & Qt::LeftEdge) || (edges & Qt::RightEdge)) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeHorCursor));
|
||||
} else if ((edges & Qt::TopEdge) || (edges & Qt::BottomEdge)) {
|
||||
QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeVerCursor));
|
||||
}
|
||||
}
|
||||
|
||||
void TitleWidgetQt::restoreCursor() {
|
||||
if (_cursorOverriden) {
|
||||
_cursorOverriden = false;
|
||||
QGuiApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Window
|
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "window/window_title.h"
|
||||
#include "ui/platform/ui_platform_window_title.h"
|
||||
#include "base/object_ptr.h"
|
||||
|
||||
namespace style {
|
||||
struct WindowTitle;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui {
|
||||
class IconButton;
|
||||
class PlainShadow;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
|
||||
class TitleWidgetQt : public TitleWidget {
|
||||
public:
|
||||
using Control = Ui::Platform::TitleControls::Control;
|
||||
|
||||
TitleWidgetQt(QWidget *parent);
|
||||
~TitleWidgetQt();
|
||||
|
||||
void init() override;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *e) override;
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *e) override;
|
||||
|
||||
private:
|
||||
void windowStateChanged(Qt::WindowState state = Qt::WindowNoState);
|
||||
void visibleChanged(bool visible);
|
||||
void updateWindowExtents();
|
||||
void updateButtonsState();
|
||||
void updateControlsPosition();
|
||||
void updateControlsPositionBySide(
|
||||
const std::vector<Control> &controls,
|
||||
bool right);
|
||||
|
||||
void toggleFramelessWindow(bool enabled);
|
||||
bool hasShadow() const;
|
||||
Ui::IconButton *controlWidget(Control control) const;
|
||||
QMargins resizeArea() const;
|
||||
Qt::Edges edgesFromPos(const QPoint &pos) const;
|
||||
void updateCursor(Qt::Edges edges);
|
||||
void restoreCursor();
|
||||
|
||||
const style::WindowTitle &_st;
|
||||
object_ptr<Ui::IconButton> _minimize;
|
||||
object_ptr<Ui::IconButton> _maximizeRestore;
|
||||
object_ptr<Ui::IconButton> _close;
|
||||
object_ptr<Ui::PlainShadow> _shadow;
|
||||
|
||||
bool _maximizedState = false;
|
||||
bool _activeState = false;
|
||||
bool _windowWasFrameless = false;
|
||||
bool _cursorOverriden = false;
|
||||
bool _extentsSet = false;
|
||||
bool _mousePressed = false;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Window
|
Reference in New Issue
Block a user