mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-19 05:31:22 +00:00
Use better initial geometry for new windows.
This commit is contained in:
parent
933f1944c7
commit
0495cf4187
@ -91,6 +91,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "boxes/connection_box.h"
|
||||
#include "boxes/premium_limits_box.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "styles/style_window.h"
|
||||
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QMimeDatabase>
|
||||
@ -185,7 +186,7 @@ Application::~Application() {
|
||||
}
|
||||
|
||||
setLastActiveWindow(nullptr);
|
||||
_lastActivePrimaryWindow = nullptr;
|
||||
_windowInSettings = _lastActivePrimaryWindow = nullptr;
|
||||
_closingAsyncWindows.clear();
|
||||
_secondaryWindows.clear();
|
||||
_primaryWindows.clear();
|
||||
@ -289,7 +290,7 @@ void Application::run() {
|
||||
|
||||
_primaryWindows.emplace(nullptr, std::make_unique<Window::Controller>());
|
||||
setLastActiveWindow(_primaryWindows.front().second.get());
|
||||
_lastActivePrimaryWindow = _lastActiveWindow;
|
||||
_windowInSettings = _lastActivePrimaryWindow = _lastActiveWindow;
|
||||
|
||||
_domain->activeChanges(
|
||||
) | rpl::start_with_next([=](not_null<Main::Account*> account) {
|
||||
@ -1162,6 +1163,11 @@ void Application::localPasscodeChanged() {
|
||||
checkAutoLock(crl::now());
|
||||
}
|
||||
|
||||
bool Application::savingPositionFor(
|
||||
not_null<Window::Controller*> window) const {
|
||||
return !_windowInSettings || (_windowInSettings == window);
|
||||
}
|
||||
|
||||
bool Application::hasActiveWindow(not_null<Main::Session*> session) const {
|
||||
if (Quitting() || !_lastActiveWindow) {
|
||||
return false;
|
||||
@ -1319,6 +1325,9 @@ void Application::closeWindow(not_null<Window::Controller*> window) {
|
||||
if (_lastActivePrimaryWindow == window) {
|
||||
_lastActivePrimaryWindow = next;
|
||||
}
|
||||
if (_windowInSettings == window) {
|
||||
_windowInSettings = next;
|
||||
}
|
||||
if (_lastActiveWindow == window) {
|
||||
setLastActiveWindow(next);
|
||||
if (_lastActiveWindow) {
|
||||
@ -1331,6 +1340,7 @@ void Application::closeWindow(not_null<Window::Controller*> window) {
|
||||
if (i->second.get() == window) {
|
||||
Assert(_lastActiveWindow != window);
|
||||
Assert(_lastActivePrimaryWindow != window);
|
||||
Assert(_windowInSettings != window);
|
||||
i = _primaryWindows.erase(i);
|
||||
} else {
|
||||
++i;
|
||||
|
@ -153,8 +153,8 @@ public:
|
||||
|
||||
// Windows interface.
|
||||
bool hasActiveWindow(not_null<Main::Session*> session) const;
|
||||
|
||||
// Don't auto-switch.
|
||||
[[nodiscard]] bool savingPositionFor(
|
||||
not_null<Window::Controller*> window) const;
|
||||
[[nodiscard]] Window::Controller *activeWindow() const;
|
||||
[[nodiscard]] Window::Controller *activePrimaryWindow() const;
|
||||
[[nodiscard]] Window::Controller *separateWindowForAccount(
|
||||
@ -397,6 +397,7 @@ private:
|
||||
std::unique_ptr<Window::Controller>> _secondaryWindows;
|
||||
Window::Controller *_lastActiveWindow = nullptr;
|
||||
Window::Controller *_lastActivePrimaryWindow = nullptr;
|
||||
Window::Controller *_windowInSettings = nullptr;
|
||||
|
||||
std::unique_ptr<Media::View::OverlayWidget> _mediaView;
|
||||
const std::unique_ptr<Lang::Instance> _langpack;
|
||||
|
@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "tray.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "styles/style_dialogs.h" // ChildSkip().x() for new child windows.
|
||||
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtGui/QGuiApplication>
|
||||
@ -51,6 +52,42 @@ namespace {
|
||||
|
||||
constexpr auto kSaveWindowPositionTimeout = crl::time(1000);
|
||||
|
||||
using Core::WindowPosition;
|
||||
|
||||
[[nodiscard]] WindowPosition AdjustToScale(WindowPosition position) {
|
||||
DEBUG_LOG(("Window Pos: Initializing first %1, %2, %3, %4 "
|
||||
"(scale %5%, maximized %6)")
|
||||
.arg(position.x)
|
||||
.arg(position.y)
|
||||
.arg(position.w)
|
||||
.arg(position.h)
|
||||
.arg(position.scale)
|
||||
.arg(Logs::b(position.maximized)));
|
||||
|
||||
if (!position.scale) {
|
||||
return position;
|
||||
}
|
||||
const auto scaleFactor = cScale() / float64(position.scale);
|
||||
if (scaleFactor != 1.) {
|
||||
// Change scale while keeping the position center in place.
|
||||
position.x += position.w / 2;
|
||||
position.y += position.h / 2;
|
||||
position.w *= scaleFactor;
|
||||
position.h *= scaleFactor;
|
||||
position.x -= position.w / 2;
|
||||
position.y -= position.h / 2;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
[[nodiscard]] QPoint ChildSkip() {
|
||||
const auto skipx = st::defaultDialogRow.padding.left()
|
||||
+ st::defaultDialogRow.photoSize
|
||||
+ st::defaultDialogRow.padding.left();
|
||||
const auto skipy = st::windowTitleHeight;
|
||||
return { skipx, skipy };
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const QImage &Logo() {
|
||||
@ -587,34 +624,43 @@ void MainWindow::recountGeometryConstraints() {
|
||||
fixOrder();
|
||||
}
|
||||
|
||||
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)")
|
||||
.arg(position.x)
|
||||
.arg(position.y)
|
||||
.arg(position.w)
|
||||
.arg(position.h)
|
||||
.arg(position.scale)
|
||||
.arg(Logs::b(position.maximized)));
|
||||
|
||||
if (!position.scale) {
|
||||
return position;
|
||||
}
|
||||
const auto scaleFactor = cScale() / float64(position.scale);
|
||||
if (scaleFactor != 1.) {
|
||||
// Change scale while keeping the position center in place.
|
||||
position.x += position.w / 2;
|
||||
position.y += position.h / 2;
|
||||
position.w *= scaleFactor;
|
||||
position.h *= scaleFactor;
|
||||
position.x -= position.w / 2;
|
||||
position.y -= position.h / 2;
|
||||
}
|
||||
return position;
|
||||
WindowPosition MainWindow::initialPosition() const {
|
||||
const auto active = Core::App().activeWindow();
|
||||
return (!active || active == &controller())
|
||||
? AdjustToScale(Core::App().settings().windowPosition())
|
||||
: active->widget()->nextInitialChildPosition(isPrimary());
|
||||
}
|
||||
|
||||
QRect MainWindow::countInitialGeometry(Core::WindowPosition position) {
|
||||
WindowPosition MainWindow::nextInitialChildPosition(bool primary) {
|
||||
const auto rect = geometry().marginsRemoved(frameMargins());
|
||||
const auto position = rect.topLeft();
|
||||
const auto adjust = [&](int value) {
|
||||
return primary ? value : (value * 3 / 4);
|
||||
};
|
||||
const auto width = adjust(st::windowDefaultWidth);
|
||||
const auto height = adjust(st::windowDefaultHeight);
|
||||
const auto skip = ChildSkip();
|
||||
const auto delta = _lastChildIndex
|
||||
? (_lastMyChildCreatePosition - position)
|
||||
: skip;
|
||||
if (qAbs(delta.x()) >= skip.x() || qAbs(delta.y()) >= skip.y()) {
|
||||
_lastChildIndex = 1;
|
||||
} else {
|
||||
++_lastChildIndex;
|
||||
}
|
||||
|
||||
_lastMyChildCreatePosition = position;
|
||||
const auto use = position + (skip * _lastChildIndex);
|
||||
return withScreenInPosition({
|
||||
.scale = cScale(),
|
||||
.x = position.x(),
|
||||
.y = position.y(),
|
||||
.w = width,
|
||||
.h = height,
|
||||
});
|
||||
}
|
||||
|
||||
QRect MainWindow::countInitialGeometry(WindowPosition position) {
|
||||
const auto primaryScreen = QGuiApplication::primaryScreen();
|
||||
const auto primaryAvailable = primaryScreen
|
||||
? primaryScreen->availableGeometry()
|
||||
@ -735,9 +781,7 @@ void MainWindow::initGeometry() {
|
||||
if (initGeometryFromSystem()) {
|
||||
return;
|
||||
}
|
||||
const auto geometry = countInitialGeometry(isPrimary()
|
||||
? positionFromSettings()
|
||||
: SecondaryInitPosition());
|
||||
const auto geometry = countInitialGeometry(initialPosition());
|
||||
DEBUG_LOG(("Window Pos: Setting first %1, %2, %3, %4"
|
||||
).arg(geometry.x()
|
||||
).arg(geometry.y()
|
||||
@ -829,7 +873,7 @@ void MainWindow::savePosition(Qt::WindowState state) {
|
||||
|
||||
if (state == Qt::WindowMinimized
|
||||
|| !isVisible()
|
||||
|| !isPrimary() // #TODO windows
|
||||
|| !Core::App().savingPositionFor(&controller())
|
||||
|| !positionInited()) {
|
||||
return;
|
||||
}
|
||||
@ -874,51 +918,38 @@ void MainWindow::savePosition(Qt::WindowState state) {
|
||||
}
|
||||
}
|
||||
|
||||
Core::WindowPosition MainWindow::withScreenInPosition(
|
||||
Core::WindowPosition position) const {
|
||||
auto centerX = position.x + position.w / 2;
|
||||
auto centerY = position.y + position.h / 2;
|
||||
int minDelta = 0;
|
||||
QScreen *chosen = nullptr;
|
||||
const auto screens = QGuiApplication::screens();
|
||||
for (auto screen : screens) {
|
||||
auto delta = (screen->geometry().center() - QPoint(centerX, centerY)).manhattanLength();
|
||||
if (!chosen || delta < minDelta) {
|
||||
minDelta = delta;
|
||||
chosen = screen;
|
||||
}
|
||||
}
|
||||
WindowPosition MainWindow::withScreenInPosition(
|
||||
WindowPosition position) const {
|
||||
const auto my = screen();
|
||||
const auto chosen = my ? my : QGuiApplication::primaryScreen();
|
||||
if (!chosen) {
|
||||
return position;
|
||||
}
|
||||
auto screenGeometry = chosen->geometry();
|
||||
const auto available = chosen->availableGeometry();
|
||||
if (available.width() < st::windowMinWidth
|
||||
|| available.height() < st::windowMinHeight) {
|
||||
return position;
|
||||
}
|
||||
accumulate_min(position.w, available.width());
|
||||
accumulate_min(position.h, available.height());
|
||||
if (position.x + position.w > available.x() + available.width()) {
|
||||
position.x = available.x() + available.width() - position.w;
|
||||
}
|
||||
if (position.y + position.h > available.y() + available.height()) {
|
||||
position.y = available.y() + available.height() - position.h;
|
||||
}
|
||||
const auto geometry = chosen->geometry();
|
||||
DEBUG_LOG(("Window Pos: Screen found, geometry: %1, %2, %3, %4"
|
||||
).arg(screenGeometry.x()
|
||||
).arg(screenGeometry.y()
|
||||
).arg(screenGeometry.width()
|
||||
).arg(screenGeometry.height()));
|
||||
position.x -= screenGeometry.x();
|
||||
position.y -= screenGeometry.y();
|
||||
).arg(geometry.x()
|
||||
).arg(geometry.y()
|
||||
).arg(geometry.width()
|
||||
).arg(geometry.height()));
|
||||
position.x -= geometry.x();
|
||||
position.y -= geometry.y();
|
||||
position.moncrc = screenNameChecksum(chosen->name());
|
||||
return position;
|
||||
}
|
||||
|
||||
Core::WindowPosition MainWindow::SecondaryInitPosition() {
|
||||
const auto active = Core::App().activeWindow();
|
||||
if (!active) {
|
||||
return {};
|
||||
}
|
||||
const auto geometry = active->widget()->geometry();
|
||||
const auto skip = st::windowMinWidth / 6;
|
||||
return active->widget()->withScreenInPosition({
|
||||
.scale = cScale(),
|
||||
.x = geometry.x() + skip,
|
||||
.y = geometry.y() + skip,
|
||||
.w = st::windowMinWidth,
|
||||
.h = st::windowDefaultHeight,
|
||||
});
|
||||
}
|
||||
|
||||
bool MainWindow::minimizeToTray() {
|
||||
if (Core::Quitting() || !Core::App().tray().has()) {
|
||||
return false;
|
||||
|
@ -77,7 +77,6 @@ public:
|
||||
[[nodiscard]] QRect desktopRect() const;
|
||||
[[nodiscard]] Core::WindowPosition withScreenInPosition(
|
||||
Core::WindowPosition position) const;
|
||||
[[nodiscard]] static Core::WindowPosition SecondaryInitPosition();
|
||||
|
||||
void init();
|
||||
|
||||
@ -191,7 +190,9 @@ private:
|
||||
void updateMinimumSize();
|
||||
void updatePalette();
|
||||
|
||||
[[nodiscard]] Core::WindowPosition positionFromSettings() const;
|
||||
[[nodiscard]] Core::WindowPosition initialPosition() const;
|
||||
[[nodiscard]] Core::WindowPosition nextInitialChildPosition(
|
||||
bool primary);
|
||||
[[nodiscard]] QRect countInitialGeometry(Core::WindowPosition position);
|
||||
void initGeometry();
|
||||
|
||||
@ -213,6 +214,9 @@ private:
|
||||
|
||||
bool _maximizedBeforeHide = false;
|
||||
|
||||
QPoint _lastMyChildCreatePosition;
|
||||
int _lastChildIndex = 0;
|
||||
|
||||
mutable QRect _monitorRect;
|
||||
mutable crl::time _monitorLastGot = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user