From 1dec05476660069283fa4fa6048c2de34e1267e2 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 10 Aug 2021 15:41:25 +0300 Subject: [PATCH] Check if native window frame fits for saved geometry. --- .../platform/win/main_window_win.cpp | 2 +- .../platform/win/main_window_win.h | 2 +- Telegram/SourceFiles/window/main_window.cpp | 191 +++++++++++------- Telegram/SourceFiles/window/main_window.h | 11 +- 4 files changed, 129 insertions(+), 77 deletions(-) diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index 27e1bfbc8..d7edc9442 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -287,7 +287,7 @@ bool MainWindow::hasTabletView() const { return (mode == ViewManagement::UserInteractionMode_Touch); } -bool MainWindow::initSizeFromSystem() { +bool MainWindow::initGeometryFromSystem() { if (!hasTabletView()) { return false; } diff --git a/Telegram/SourceFiles/platform/win/main_window_win.h b/Telegram/SourceFiles/platform/win/main_window_win.h index dfc958d98..34ef24676 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.h +++ b/Telegram/SourceFiles/platform/win/main_window_win.h @@ -65,7 +65,7 @@ protected: void workmodeUpdated(Core::Settings::WorkMode mode) override; - bool initSizeFromSystem() override; + bool initGeometryFromSystem() override; QRect computeDesktopRect() const override; diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 40db1f0a2..0cb156c33 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -299,7 +299,7 @@ void MainWindow::init() { } refreshTitleWidget(); - initSize(); + initGeometry(); updateUnreadCounter(); } @@ -426,13 +426,7 @@ void MainWindow::recountGeometryConstraints() { fixOrder(); } -void MainWindow::initSize() { - updateMinimumSize(); - - if (initSizeFromSystem()) { - return; - } - +Core::WindowPosition MainWindow::positionFromSettings() const { auto position = Core::App().settings().windowPosition(); DEBUG_LOG(("Window Pos: Initializing first %1, %2, %3, %4 " "(scale %5%, maximized %6)") @@ -443,16 +437,20 @@ void MainWindow::initSize() { .arg(position.scale) .arg(Logs::b(position.maximized))); - if (position.scale != 0) { - const auto scaleFactor = cScale() / float64(position.scale); - position.x *= scaleFactor; - position.y *= scaleFactor; - position.w *= scaleFactor; - position.h *= scaleFactor; + if (!position.scale) { + return position; } + const auto scaleFactor = cScale() / float64(position.scale); + position.x *= scaleFactor; + position.y *= scaleFactor; + position.w *= scaleFactor; + position.h *= scaleFactor; + return position; +} +QRect MainWindow::countInitialGeometry(Core::WindowPosition position) { const auto primaryScreen = QGuiApplication::primaryScreen(); - const auto available = primaryScreen + const auto primaryAvailable = primaryScreen ? primaryScreen->availableGeometry() : QRect(0, 0, st::windowDefaultWidth, st::windowDefaultHeight); const auto initialWidth = Core::Settings::ThirdColumnByDefault() @@ -461,72 +459,119 @@ void MainWindow::initSize() { const auto initialHeight = Core::Settings::ThirdColumnByDefault() ? st::windowBigDefaultHeight : st::windowDefaultHeight; - auto geometry = QRect( - available.x() + std::max( - (available.width() - initialWidth) / 2, + const auto initial = QRect( + primaryAvailable.x() + std::max( + (primaryAvailable.width() - initialWidth) / 2, 0), - available.y() + std::max( - (available.height() - initialHeight) / 2, + primaryAvailable.y() + std::max( + (primaryAvailable.height() - initialHeight) / 2, 0), initialWidth, initialHeight); - if (position.w && position.h) { - for (auto screen : QGuiApplication::screens()) { + if (!position.w || !position.h) { + return initial; + } + const auto screen = [&]() -> QScreen* { + for (const auto screen : QGuiApplication::screens()) { if (position.moncrc == screenNameChecksum(screen->name())) { - auto screenGeometry = screen->geometry(); - auto availableGeometry = screen->availableGeometry(); - DEBUG_LOG(("Window Pos: Screen found, screen geometry: %1, %2, %3, %4").arg(screenGeometry.x()).arg(screenGeometry.y()).arg(screenGeometry.width()).arg(screenGeometry.height())); - - const auto x = availableGeometry.x() - screenGeometry.x(); - const auto y = availableGeometry.y() - screenGeometry.y(); - const auto w = availableGeometry.width(); - const auto h = availableGeometry.height(); - if (w >= st::windowMinWidth && h >= st::windowMinHeight) { - if (position.x < x) position.x = x; - if (position.y < y) position.y = y; - if (position.w > w) position.w = w; - if (position.h > h) position.h = h; - const auto rightPoint = position.x + position.w; - const auto screenRightPoint = x + w; - if (rightPoint > screenRightPoint) { - const auto distance = rightPoint - screenRightPoint; - const auto newXPos = position.x - distance; - if (newXPos >= x) { - position.x = newXPos; - } else { - position.x = x; - const auto newRightPoint = position.x + position.w; - const auto newDistance = newRightPoint - screenRightPoint; - position.w -= newDistance; - } - } - const auto bottomPoint = position.y + position.h; - const auto screenBottomPoint = y + h; - if (bottomPoint > screenBottomPoint) { - const auto distance = bottomPoint - screenBottomPoint; - const auto newYPos = position.y - distance; - if (newYPos >= y) { - position.y = newYPos; - } else { - position.y = y; - const auto newBottomPoint = position.y + position.h; - const auto newDistance = newBottomPoint - screenBottomPoint; - position.h -= newDistance; - } - } - position.x += screenGeometry.x(); - position.y += screenGeometry.y(); - if (position.x + st::windowMinWidth <= screenGeometry.x() + screenGeometry.width() && - position.y + st::windowMinHeight <= screenGeometry.y() + screenGeometry.height()) { - DEBUG_LOG(("Window Pos: Resulting geometry is %1, %2, %3, %4").arg(position.x).arg(position.y).arg(position.w).arg(position.h)); - geometry = QRect(position.x, position.y, position.w, position.h); - } - } - break; + return screen; } } + return nullptr; + }(); + if (!screen) { + return initial; } - DEBUG_LOG(("Window Pos: Setting first %1, %2, %3, %4").arg(geometry.x()).arg(geometry.y()).arg(geometry.width()).arg(geometry.height())); + const auto frame = [&] { + if (!Core::App().settings().nativeWindowFrame()) { + return QMargins(); + } + const auto inner = geometry(); + const auto outer = frameGeometry(); + return QMargins( + inner.x() - outer.x(), + inner.y() - outer.y(), + outer.x() + outer.width() - inner.x() - inner.width(), + outer.y() + outer.height() - inner.y() - inner.height()); + }(); + + const auto screenGeometry = screen->geometry(); + const auto availableGeometry = screen->availableGeometry(); + const auto spaceForInner = availableGeometry.marginsRemoved( + frame); + DEBUG_LOG(("Window Pos: " + "Screen found, screen geometry: %1, %2, %3, %4" + ).arg(screenGeometry.x() + ).arg(screenGeometry.y() + ).arg(screenGeometry.width() + ).arg(screenGeometry.height())); + + const auto x = spaceForInner.x() - screenGeometry.x(); + const auto y = spaceForInner.y() - screenGeometry.y(); + const auto w = spaceForInner.width(); + const auto h = spaceForInner.height(); + if (w < st::windowMinWidth || h < st::windowMinHeight) { + return initial; + } + if (position.x < x) position.x = x; + if (position.y < y) position.y = y; + if (position.w > w) position.w = w; + if (position.h > h) position.h = h; + const auto rightPoint = position.x + position.w; + const auto screenRightPoint = x + w; + if (rightPoint > screenRightPoint) { + const auto distance = rightPoint - screenRightPoint; + const auto newXPos = position.x - distance; + if (newXPos >= x) { + position.x = newXPos; + } else { + position.x = x; + const auto newRightPoint = position.x + position.w; + const auto newDistance = newRightPoint - screenRightPoint; + position.w -= newDistance; + } + } + const auto bottomPoint = position.y + position.h; + const auto screenBottomPoint = y + h; + if (bottomPoint > screenBottomPoint) { + const auto distance = bottomPoint - screenBottomPoint; + const auto newYPos = position.y - distance; + if (newYPos >= y) { + position.y = newYPos; + } else { + position.y = y; + const auto newBottomPoint = position.y + position.h; + const auto newDistance = newBottomPoint - screenBottomPoint; + position.h -= newDistance; + } + } + position.x += screenGeometry.x(); + position.y += screenGeometry.y(); + if ((position.x + st::windowMinWidth + > screenGeometry.x() + screenGeometry.width()) + || (position.y + st::windowMinHeight + > screenGeometry.y() + screenGeometry.height())) { + return initial; + } + DEBUG_LOG(("Window Pos: Resulting geometry is %1, %2, %3, %4" + ).arg(position.x + ).arg(position.y + ).arg(position.w + ).arg(position.h)); + return QRect(position.x, position.y, position.w, position.h); +} + +void MainWindow::initGeometry() { + updateMinimumSize(); + if (initGeometryFromSystem()) { + return; + } + const auto geometry = countInitialGeometry(positionFromSettings()); + DEBUG_LOG(("Window Pos: Setting first %1, %2, %3, %4" + ).arg(geometry.x() + ).arg(geometry.y() + ).arg(geometry.width() + ).arg(geometry.height())); setGeometry(geometry); } diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index 60562fc4d..8d831fc55 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -24,6 +24,10 @@ class BoxContent; class PlainShadow; } // namespace Ui +namespace Core { +struct WindowPosition; +} // namespace Core + namespace Window { class Controller; @@ -166,7 +170,7 @@ protected: virtual void createGlobalMenu() { } - virtual bool initSizeFromSystem() { + virtual bool initGeometryFromSystem() { return false; } @@ -185,7 +189,10 @@ private: void refreshTitleWidget(); void updateMinimumSize(); void updatePalette(); - void initSize(); + + [[nodiscard]] Core::WindowPosition positionFromSettings() const; + [[nodiscard]] QRect countInitialGeometry(Core::WindowPosition position); + void initGeometry(); bool computeIsActive() const;