Save media viewer position to Settings.

This commit is contained in:
John Preston 2023-02-17 20:12:29 +04:00
parent 783d1cd4c1
commit 832d47121f
12 changed files with 390 additions and 144 deletions

View File

@ -38,6 +38,18 @@ namespace {
return result;
}
void LogPosition(const WindowPosition &position, const QString &name) {
DEBUG_LOG(("%1 Pos: Writing to storage %2, %3, %4, %5"
" (scale %6%, maximized %7)")
.arg(name)
.arg(position.x)
.arg(position.y)
.arg(position.w)
.arg(position.h)
.arg(position.scale)
.arg(position.maximized));
}
[[nodiscard]] QByteArray Serialize(const WindowPosition &position) {
auto result = QByteArray();
const auto size = 7 * sizeof(qint32);
@ -54,14 +66,6 @@ namespace {
<< qint32(position.maximized)
<< qint32(position.scale);
}
DEBUG_LOG(("Window Pos: Writing to storage %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)));
return result;
}
@ -85,6 +89,35 @@ namespace {
} // namespace
[[nodiscard]] WindowPosition AdjustToScale(
WindowPosition position,
const QString &name) {
DEBUG_LOG(("%1 Pos: Initializing first %2, %3, %4, %5 "
"(scale %6%, maximized %7)")
.arg(name)
.arg(position.x)
.arg(position.y)
.arg(position.w)
.arg(position.h)
.arg(position.scale)
.arg(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;
}
Settings::Settings()
: _sendSubmitWay(Ui::InputSubmitSettings::Enter)
, _floatPlayerColumn(Window::Column::Second)
@ -97,6 +130,9 @@ Settings::~Settings() = default;
QByteArray Settings::serialize() const {
const auto themesAccentColors = _themesAccentColors.serialize();
const auto windowPosition = Serialize(_windowPosition);
LogPosition(_windowPosition, u"Window"_q);
const auto mediaViewPosition = Serialize(_mediaViewPosition);
LogPosition(_mediaViewPosition, u"Viewer"_q);
const auto proxy = _proxy.serialize();
const auto skipLanguages = _skipTranslationLanguages.current();
@ -160,7 +196,8 @@ QByteArray Settings::serialize() const {
+ (skipLanguages.size() * sizeof(quint64))
+ sizeof(qint32)
+ sizeof(quint64)
+ sizeof(qint32) * 3;
+ sizeof(qint32) * 3
+ Serialize::bytearraySize(mediaViewPosition);
auto result = QByteArray();
result.reserve(size);
@ -291,7 +328,8 @@ QByteArray Settings::serialize() const {
<< quint64(QLocale::Language(_translateToRaw.current()))
<< qint32(_windowTitleContent.current().hideChatName ? 1 : 0)
<< qint32(_windowTitleContent.current().hideAccountName ? 1 : 0)
<< qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0);
<< qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0)
<< mediaViewPosition;
}
return result;
}
@ -394,6 +432,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
qint32 hideChatName = _windowTitleContent.current().hideChatName ? 1 : 0;
qint32 hideAccountName = _windowTitleContent.current().hideAccountName ? 1 : 0;
qint32 hideTotalUnread = _windowTitleContent.current().hideTotalUnread ? 1 : 0;
QByteArray mediaViewPosition;
stream >> themesAccentColors;
if (!stream.atEnd()) {
@ -619,6 +658,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
>> hideAccountName
>> hideTotalUnread;
}
if (!stream.atEnd()) {
stream >> mediaViewPosition;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
@ -809,6 +851,12 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
.hideAccountName = (hideAccountName == 1),
.hideTotalUnread = (hideTotalUnread == 1),
};
if (!mediaViewPosition.isEmpty()) {
_mediaViewPosition = Deserialize(mediaViewPosition);
if (!_mediaViewPosition.w && !_mediaViewPosition.maximized) {
_mediaViewPosition = { .maximized = 2 };
}
}
}
QString Settings::getSoundPath(const QString &key) const {

View File

@ -52,8 +52,20 @@ struct WindowPosition {
int y = 0;
int w = 0;
int h = 0;
friend inline constexpr auto operator<=>(
WindowPosition,
WindowPosition) = default;
[[nodiscard]] QRect rect() const {
return QRect(x, y, w, h);
}
};
[[nodiscard]] WindowPosition AdjustToScale(
WindowPosition position,
const QString &name);
struct WindowTitleContent {
bool hideChatName : 1 = false;
bool hideAccountName : 1 = false;
@ -759,6 +771,13 @@ public:
void setRememberedDeleteMessageOnlyForYou(bool value);
[[nodiscard]] bool rememberedDeleteMessageOnlyForYou() const;
[[nodiscard]] const WindowPosition &mediaViewPosition() const {
return _mediaViewPosition;
}
void setMediaViewPosition(const WindowPosition &position) {
_mediaViewPosition = position;
}
[[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) {
@ -880,6 +899,7 @@ private:
rpl::variable<std::vector<LanguageId>> _skipTranslationLanguages;
rpl::event_stream<> _skipTranslationLanguagesChanges;
bool _rememberedDeleteMessageOnlyForYou = false;
WindowPosition _mediaViewPosition = { .maximized = 2 };
bool _tabbedReplacedWithInfo = false; // per-window
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window

View File

@ -262,6 +262,13 @@ mediaviewGroupWidthMax: 160px;
mediaviewGroupSkip: 3px;
mediaviewGroupSkipCurrent: 12px;
mediaviewMinWidth: 480px;
mediaviewMinHeight: 360px;
mediaviewDefaultLeft: 160px;
mediaviewDefaultTop: 120px;
mediaviewDefaultWidth: 800px;
mediaviewDefaultHeight: 600px;
themePreviewSize: size(903px, 584px);
themePreviewBg: windowBg;
themePreviewOverlayOpacity: 0.8;

View File

@ -88,7 +88,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_media_view.h"
#include "styles/style_chat.h"
#include "styles/style_menu_icons.h"
#include "styles/style_window.h" // windowDefaultWidth / windowDefaultHeight
#include "styles/style_calls.h"
#ifdef Q_OS_MAC
@ -137,6 +136,26 @@ private:
};
[[nodiscard]] Core::WindowPosition DefaultPosition() {
const auto moncrc = [&] {
if (const auto active = Core::App().activeWindow()) {
const auto widget = active->widget();
if (const auto screen = widget->screen()) {
return Platform::ScreenNameChecksum(screen->name());
}
}
return Core::App().settings().windowPosition().moncrc;
}();
return {
.moncrc = moncrc,
.scale = cScale(),
.x = st::mediaviewDefaultLeft,
.y = st::mediaviewDefaultTop,
.w = st::mediaviewDefaultWidth,
.h = st::mediaviewDefaultHeight,
};
}
PipDelegate::PipDelegate(QWidget *parent, not_null<Main::Session*> session)
: _parent(parent)
, _session(session) {
@ -299,8 +318,7 @@ OverlayWidget::PipWrap::PipWrap(
}
OverlayWidget::OverlayWidget()
: _supportWindowMode(true)
, _wrap(std::make_unique<Ui::GL::Window>())
: _wrap(std::make_unique<Ui::GL::Window>())
, _window(_wrap->window())
, _helper(Platform::CreateOverlayWidgetHelper(_window.get(), [=](bool maximized) {
toggleFullScreen(maximized);
@ -309,7 +327,8 @@ OverlayWidget::OverlayWidget()
, _surface(
Ui::GL::CreateSurface(_body, chooseRenderer(_wrap->backend())))
, _widget(_surface->rpWidget())
, _fullscreen(true || !_supportWindowMode)
, _fullscreen(Core::App().settings().mediaViewPosition().maximized == 2)
, _windowed(Core::App().settings().mediaViewPosition().maximized == 0)
, _docDownload(_body, tr::lng_media_download(tr::now), st::mediaviewFileLink)
, _docSaveAs(_body, tr::lng_mediaview_save_as(tr::now), st::mediaviewFileLink)
, _docCancel(_body, tr::lng_cancel(tr::now), st::mediaviewFileLink)
@ -365,6 +384,15 @@ OverlayWidget::OverlayWidget()
.arg(position.x())
.arg(position.y()));
moveToScreen(true);
if (_windowed) {
savePosition();
} else {
moveToScreen(true);
}
} else if (type == QEvent::Resize) {
if (_windowed) {
savePosition();
}
} else if (type == QEvent::Close
&& !Core::Sandbox::Instance().isSavingSession()
&& !Core::Quitting()) {
@ -505,31 +533,34 @@ void OverlayWidget::setupWindow() {
return Flag::Move | Flag(0);
});
if (_supportWindowMode) {
const auto callback = [=](Qt::WindowState state) {
if (state == Qt::WindowMinimized || Platform::IsMac()) {
return;
} else if (state == Qt::WindowFullScreen) {
_fullscreen = true;
_windowed = false;
} else if (state == Qt::WindowMaximized) {
const auto callback = [=](Qt::WindowState state) {
if (state == Qt::WindowMinimized || Platform::IsMac()) {
return;
} else if (state == Qt::WindowMaximized) {
if (_fullscreen || _windowed) {
_fullscreen = _windowed = false;
} else {
_fullscreen = false;
_windowed = true;
savePosition();
}
};
QObject::connect(
_window->windowHandle(),
&QWindow::windowStateChanged,
callback);
}
} else if (_fullscreen || _windowed) {
return;
} else if (state == Qt::WindowFullScreen) {
_fullscreen = true;
savePosition();
} else {
_windowed = true;
savePosition();
}
};
QObject::connect(
_window->windowHandle(),
&QWindow::windowStateChanged,
callback);
_window->setAttribute(Qt::WA_NoSystemBackground, true);
_window->setAttribute(Qt::WA_TranslucentBackground, true);
_window->setMinimumSize(
{ st::windowMinHeight, st::windowMinWidth });
{ st::mediaviewMinWidth, st::mediaviewMinHeight });
_window->shownValue(
) | rpl::start_with_next([=](bool shown) {
@ -555,7 +586,7 @@ void OverlayWidget::refreshLang() {
}
void OverlayWidget::moveToScreen(bool inMove) {
if (!_fullscreen) {
if (!_fullscreen || _wasWindowedMode) {
return;
}
const auto widgetScreen = [&](auto &&widget) -> QScreen* {
@ -587,10 +618,111 @@ void OverlayWidget::moveToScreen(bool inMove) {
updateGeometry(inMove);
}
void OverlayWidget::updateGeometry(bool inMove) {
if (Platform::IsWayland() || Platform::IsWindows() || !_fullscreen) {
void OverlayWidget::initFullScreen() {
if (_fullscreenInited) {
return;
}
_fullscreenInited = true;
switch (Core::App().settings().mediaViewPosition().maximized) {
case 2:
_fullscreen = true;
_windowed = false;
break;
case 1:
_fullscreen = Platform::IsMac();
_windowed = false;
break;
}
}
void OverlayWidget::initNormalGeometry() {
if (_normalGeometryInited) {
return;
}
_normalGeometryInited = true;
const auto saved = Core::App().settings().mediaViewPosition();
const auto adjusted = Core::AdjustToScale(saved, u"Viewer"_q);
const auto initial = DefaultPosition();
_normalGeometry = initial.rect();
if (const auto active = Core::App().activeWindow()) {
_normalGeometry = active->widget()->countInitialGeometry(
adjusted,
initial,
{ st::mediaviewMinWidth, st::mediaviewMinHeight });
}
}
void OverlayWidget::savePosition() {
if (isHidden() || isMinimized() || !_normalGeometryInited) {
return;
}
const auto &savedPosition = Core::App().settings().mediaViewPosition();
auto realPosition = savedPosition;
if (_fullscreen) {
realPosition.maximized = 2;
realPosition.moncrc = 0;
DEBUG_LOG(("Viewer Pos: Saving fullscreen position."));
} else if (!_windowed) {
realPosition.maximized = 1;
realPosition.moncrc = 0;
DEBUG_LOG(("Viewer Pos: Saving maximized position."));
} else {
auto r = _window->geometry();
realPosition.x = r.x();
realPosition.y = r.y();
realPosition.w = r.width();
realPosition.h = r.height();
realPosition.scale = cScale();
realPosition.maximized = 0;
realPosition.moncrc = 0;
DEBUG_LOG(("Viewer Pos: "
"Saving non-maximized position: %1, %2, %3, %4"
).arg(realPosition.x
).arg(realPosition.y
).arg(realPosition.w
).arg(realPosition.h));
}
realPosition = Window::PositionWithScreen(
realPosition,
_window,
{ st::mediaviewMinWidth, st::mediaviewMinHeight });
if (realPosition.w >= st::mediaviewMinWidth
&& realPosition.h >= st::mediaviewMinHeight
&& realPosition != savedPosition) {
DEBUG_LOG(("Viewer Pos: "
"Writing: %1, %2, %3, %4 (scale %5%, maximized %6)")
.arg(realPosition.x)
.arg(realPosition.y)
.arg(realPosition.w)
.arg(realPosition.h)
.arg(realPosition.scale)
.arg(Logs::b(realPosition.maximized)));
Core::App().settings().setMediaViewPosition(realPosition);
Core::App().saveSettingsDelayed();
}
}
void OverlayWidget::updateGeometry(bool inMove) {
initFullScreen();
if (_fullscreen) {
updateGeometryToScreen(inMove);
} else if (_windowed && _normalGeometryInited) {
_window->setGeometry(_normalGeometry);
}
if constexpr (!Platform::IsMac()) {
if (_fullscreen) {
if (!isHidden() && !isMinimized()) {
_window->showFullScreen();
}
} else if (!_windowed) {
if (!isHidden() && !isMinimized()) {
_window->showMaximized();
}
}
}
}
void OverlayWidget::updateGeometryToScreen(bool inMove) {
const auto available = _window->screen()->geometry();
const auto openglWidget = _opengl
? static_cast<QOpenGLWidget*>(_widget.get())
@ -624,9 +756,7 @@ void OverlayWidget::updateGeometry(bool inMove) {
}
void OverlayWidget::updateControlsGeometry() {
const auto navSkip = _supportWindowMode
? st::mediaviewHeaderTop
: st::mediaviewControlSize;
const auto navSkip = st::mediaviewHeaderTop;
_closeNav = QRect(width() - st::mediaviewControlSize, 0, st::mediaviewControlSize, st::mediaviewControlSize);
_closeNavIcon = style::centerrect(_closeNav, st::mediaviewClose);
_leftNav = QRect(0, navSkip, st::mediaviewControlSize, height() - 2 * navSkip);
@ -1617,19 +1747,22 @@ void OverlayWidget::minimize() {
}
void OverlayWidget::toggleFullScreen(bool fullscreen) {
_fullscreen = fullscreen;
_windowed = !fullscreen;
initNormalGeometry();
if constexpr (Platform::IsMac()) {
_fullscreen = fullscreen;
_windowed = !fullscreen;
_helper->beforeShow(_fullscreen);
if (_fullscreen) {
moveToScreen();
}
updateGeometry();
_helper->afterShow(_fullscreen);
} else if (fullscreen) {
} else if (_fullscreen) {
updateGeometry();
_window->showFullScreen();
} else {
_window->showNormal();
updateGeometry();
_wasWindowedMode = true;
}
savePosition();
}
void OverlayWidget::activateControls() {
@ -1707,7 +1840,9 @@ void OverlayWidget::subscribeToScreenGeometry() {
base::qt_signal_producer(
screen,
&QScreen::geometryChanged
) | rpl::start_with_next([=] {
) | rpl::filter([=] {
return !isHidden() && !isMinimized() && _fullscreen;
}) | rpl::start_with_next([=] {
updateGeometry();
}, _screenGeometryLifetime);
}
@ -2573,7 +2708,7 @@ void OverlayWidget::update(const QRegion &region) {
}
bool OverlayWidget::isActive() const {
return !isHidden() && !isMinimized() && Ui::InFocusChain(_window);
return !isHidden() && !isMinimized() && _window->isActiveWindow();
}
bool OverlayWidget::isHidden() const {
@ -2910,8 +3045,11 @@ void OverlayWidget::displayFinished() {
void OverlayWidget::showAndActivate() {
_body->show();
initNormalGeometry();
updateGeometry();
if (_windowed || Platform::IsMac()) {
_window->showNormal();
_wasWindowedMode = true;
} else if (_fullscreen) {
_window->showFullScreen();
} else {
@ -3995,7 +4133,7 @@ void OverlayWidget::paintControls(
st::mediaviewRight },
{
OverClose,
!_supportWindowMode,
false,
_closeNav,
_closeNavIcon,
st::mediaviewClose },
@ -4702,8 +4840,10 @@ void OverlayWidget::updateOver(QPoint pos) {
updateOverState(OverIcon);
} else if (_moreNav.contains(pos)) {
updateOverState(OverMore);
} else if (!_supportWindowMode && _closeNav.contains(pos)) {
#if 0 // close
} else if (_closeNav.contains(pos)) {
updateOverState(OverClose);
#endif
} else if (documentContentShown() && finalContentRect().contains(pos)) {
if ((_document->isVideoFile() || _document->isVideoMessage()) && _streamed) {
updateOverState(OverVideo);

View File

@ -241,8 +241,12 @@ private:
void assignMediaPointer(not_null<PhotoData*> photo);
void updateOver(QPoint mpos);
void initFullScreen();
void initNormalGeometry();
void savePosition();
void moveToScreen(bool inMove = false);
void updateGeometry(bool inMove = false);
void updateGeometryToScreen(bool inMove = false);
bool moveToNext(int delta);
void preloadData(int delta);
@ -454,7 +458,6 @@ private:
Window::SessionController *findWindow(bool switchTo = true) const;
const bool _supportWindowMode = false;
bool _opengl = false;
const std::unique_ptr<Ui::GL::Window> _wrap;
const not_null<Ui::RpWindow*> _window;
@ -462,6 +465,10 @@ private:
const not_null<Ui::RpWidget*> _body;
const std::unique_ptr<Ui::RpWidgetWrap> _surface;
const not_null<QWidget*> _widget;
QRect _normalGeometry;
bool _wasWindowedMode = false;
bool _fullscreenInited = false;
bool _normalGeometryInited = false;
bool _fullscreen = true;
bool _windowed = false;

View File

@ -65,4 +65,8 @@ private:
};
[[nodiscard]] int32 ScreenNameChecksum(const QString &name) {
return Window::DefaultScreenNameChecksum(name);
}
} // namespace Platform

View File

@ -85,4 +85,8 @@ private:
};
[[nodiscard]] int32 ScreenNameChecksum(const QString &name) {
return Window::DefaultScreenNameChecksum(name);
}
} // namespace Platform

View File

@ -412,17 +412,6 @@ void MainWindow::validateDwmPreviewColors() {
_dwmPreview.reset();
}
int32 MainWindow::screenNameChecksum(const QString &name) const {
constexpr int DeviceNameSize = base::array_size(MONITORINFOEX().szDevice);
wchar_t buffer[DeviceNameSize] = { 0 };
if (name.size() < DeviceNameSize) {
name.toWCharArray(buffer);
} else {
memcpy(buffer, name.toStdWString().data(), sizeof(buffer));
}
return base::crc32(buffer, sizeof(buffer));
}
void MainWindow::forceIconRefresh() {
const auto refresher = std::make_unique<QWidget>(this);
refresher->setWindowFlags(
@ -483,10 +472,7 @@ bool MainWindow::hasTabletView() const {
}
bool MainWindow::initGeometryFromSystem() {
if (!hasTabletView()) {
return false;
}
if (!screen()) {
if (!hasTabletView() || !screen()) {
return false;
}
Ui::RpWidget::setGeometry(screen()->availableGeometry());
@ -708,4 +694,15 @@ MainWindow::~MainWindow() {
destroyCachedIcons();
}
int32 ScreenNameChecksum(const QString &name) {
constexpr int DeviceNameSize = base::array_size(MONITORINFOEX().szDevice);
wchar_t buffer[DeviceNameSize] = { 0 };
if (name.size() < DeviceNameSize) {
name.toWCharArray(buffer);
} else {
memcpy(buffer, name.toStdWString().data(), sizeof(buffer));
}
return base::crc32(buffer, sizeof(buffer));
}
} // namespace Platform

View File

@ -41,7 +41,6 @@ public:
protected:
void initHook() override;
int32 screenNameChecksum(const QString &name) const override;
void unreadCounterChangedHook() override;
void workmodeUpdated(Core::Settings::WorkMode mode) override;
@ -100,4 +99,6 @@ private:
};
[[nodiscard]] int32 ScreenNameChecksum(const QString &name);
} // namespace Platform

View File

@ -56,32 +56,6 @@ 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
@ -629,7 +603,9 @@ void MainWindow::recountGeometryConstraints() {
WindowPosition MainWindow::initialPosition() const {
const auto active = Core::App().activeWindow();
return (!active || active == &controller())
? AdjustToScale(Core::App().settings().windowPosition())
? Core::AdjustToScale(
Core::App().settings().windowPosition(),
u"Window"_q)
: active->widget()->nextInitialChildPosition(isPrimary());
}
@ -673,28 +649,38 @@ QRect MainWindow::countInitialGeometry(WindowPosition position) {
const auto initialHeight = Core::Settings::ThirdColumnByDefault()
? st::windowBigDefaultHeight
: st::windowDefaultHeight;
const auto initial = QRect(
primaryAvailable.x() + std::max(
(primaryAvailable.width() - initialWidth) / 2,
0),
primaryAvailable.y() + std::max(
(primaryAvailable.height() - initialHeight) / 2,
0),
initialWidth,
initialHeight);
const auto initial = WindowPosition{
.x = (primaryAvailable.x()
+ std::max((primaryAvailable.width() - initialWidth) / 2, 0)),
.y = (primaryAvailable.y()
+ std::max((primaryAvailable.height() - initialHeight) / 2, 0)),
.w = initialWidth,
.h = initialHeight,
};
return countInitialGeometry(
position,
initial,
{ st::windowMinWidth, st::windowMinHeight });
}
QRect MainWindow::countInitialGeometry(
WindowPosition position,
WindowPosition initial,
QSize minSize) const {
if (!position.w || !position.h) {
return initial;
return initial.rect();
}
const auto screen = [&]() -> QScreen* {
for (const auto screen : QGuiApplication::screens()) {
if (position.moncrc == screenNameChecksum(screen->name())) {
const auto sum = Platform::ScreenNameChecksum(screen->name());
if (position.moncrc == sum) {
return screen;
}
}
return nullptr;
}();
if (!screen) {
return initial;
return initial.rect();
}
const auto frame = frameMargins();
const auto screenGeometry = screen->geometry();
@ -728,7 +714,7 @@ QRect MainWindow::countInitialGeometry(WindowPosition position) {
const auto w = spaceForInner.width();
const auto h = spaceForInner.height();
if (w < st::windowMinWidth || h < st::windowMinHeight) {
return initial;
return initial.rect();
}
if (position.x < x) position.x = x;
if (position.y < y) position.y = y;
@ -768,14 +754,14 @@ QRect MainWindow::countInitialGeometry(WindowPosition position) {
> screenGeometry.x() + screenGeometry.width())
|| (position.y + st::windowMinHeight
> screenGeometry.y() + screenGeometry.height())) {
return initial;
return initial.rect();
}
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);
return position.rect();
}
void MainWindow::initGeometry() {
@ -796,11 +782,6 @@ void MainWindow::positionUpdated() {
_positionUpdatedTimer.callOnce(kSaveWindowPositionTimeout);
}
int32 MainWindow::screenNameChecksum(const QString &name) const {
const auto bytes = name.toUtf8();
return base::crc32(bytes.constData(), bytes.size());
}
void MainWindow::setPositionInited() {
_positionInited = true;
}
@ -936,34 +917,10 @@ void MainWindow::savePosition(Qt::WindowState state) {
WindowPosition MainWindow::withScreenInPosition(
WindowPosition position) const {
const auto my = screen();
const auto chosen = my ? my : QGuiApplication::primaryScreen();
if (!chosen) {
return position;
}
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(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;
return PositionWithScreen(
position,
this,
{ st::windowMinWidth, st::windowMinHeight });
}
bool MainWindow::minimizeToTray() {
@ -1086,4 +1043,52 @@ MainWindow::~MainWindow() {
hide();
}
int32 DefaultScreenNameChecksum(const QString &name) {
const auto bytes = name.toUtf8();
return base::crc32(bytes.constData(), bytes.size());
}
WindowPosition PositionWithScreen(
WindowPosition position,
const QScreen *chosen,
QSize minimal) {
if (!chosen) {
return position;
}
const auto available = chosen->availableGeometry();
if (available.width() < minimal.width()
|| available.height() < minimal.height()) {
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(geometry.x()
).arg(geometry.y()
).arg(geometry.width()
).arg(geometry.height()));
position.x -= geometry.x();
position.y -= geometry.y();
position.moncrc = Platform::ScreenNameChecksum(chosen->name());
return position;
}
WindowPosition PositionWithScreen(
WindowPosition position,
not_null<const QWidget*> widget,
QSize minimal) {
const auto screen = widget->screen();
return PositionWithScreen(
position,
screen ? screen : QGuiApplication::primaryScreen(),
minimal);
}
} // namespace Window

View File

@ -134,6 +134,11 @@ public:
updateGlobalMenuHook();
}
[[nodiscard]] QRect countInitialGeometry(
Core::WindowPosition position,
Core::WindowPosition initial,
QSize minSize) const;
protected:
void leaveEventHook(QEvent *e) override;
@ -174,9 +179,6 @@ protected:
return false;
}
// This one is overriden in Windows for historical reasons.
virtual int32 screenNameChecksum(const QString &name) const;
void setPositionInited();
virtual QRect computeDesktopRect() const;
@ -218,4 +220,15 @@ private:
};
[[nodiscard]] int32 DefaultScreenNameChecksum(const QString &name);
[[nodiscard]] Core::WindowPosition PositionWithScreen(
Core::WindowPosition position,
const QScreen *chosen,
QSize minimal);
[[nodiscard]] Core::WindowPosition PositionWithScreen(
Core::WindowPosition position,
not_null<const QWidget*> widget,
QSize minimal);
} // namespace Window

@ -1 +1 @@
Subproject commit 3b69ec499ccc7f4208a6413fbeb6f5ebe84f3f55
Subproject commit 74ab66cfa9c05745ca513504940e59f6fd68eff3