diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index b01c1f1d80..2c8b1e308e 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -49,6 +49,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rect.h" #include "ui/integration.h" #include "core/application.h" +#include "core/core_settings.h" #include "lang/lang_keys.h" #include "main/session/session_show.h" #include "main/main_session.h" @@ -59,6 +60,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/power_save_blocker.h" #include "media/streaming/media_streaming_utility.h" #include "window/main_window.h" +#include "window/window_controller.h" #include "webrtc/webrtc_environment.h" #include "webrtc/webrtc_video_track.h" #include "styles/style_calls.h" @@ -169,6 +171,30 @@ bool Panel::isActive() const { return window()->isActiveWindow() && isVisible(); } +QRect Panel::panelGeometry() const { + const auto saved = Core::App().settings().callPanelPosition(); + const auto adjusted = Core::AdjustToScale(saved, u"Call"_q); + const auto center = Core::App().getPointForCallPanelCenter(); + const auto simple = QRect(0, 0, st::callWidth, st::callHeight); + const auto initial = simple.translated(center - simple.center()); + auto result = initial; + if (const auto window = Core::App().activeWindow()) { + const auto initialPosition = Core::WindowPosition{ + .moncrc = 0, + .scale = cScale(), + .x = initial.x(), + .y = initial.y(), + .w = initial.width(), + .h = initial.height(), + }; + result = window->widget()->countInitialGeometry( + adjusted, + initialPosition, + { st::callWidthMin, st::callHeightMin }); + } + return result; +} + ConferencePanelMigration Panel::migrationInfo() const { return ConferencePanelMigration{ .window = _window }; } @@ -207,6 +233,41 @@ void Panel::replaceCall(not_null call) { updateControlsGeometry(); } +void Panel::savePanelGeometry() { + if (!window()->windowHandle()) { + return; + } + const auto state = window()->windowHandle()->windowState(); + if (state == Qt::WindowMinimized) { + return; + } + const auto &savedPosition = Core::App().settings().callPanelPosition(); + auto realPosition = savedPosition; + if (state == Qt::WindowMaximized) { + realPosition.maximized = 1; + realPosition.moncrc = 0; + } else { + auto r = window()->body()->mapToGlobal(window()->body()->rect()); + 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; + } + realPosition = ::Window::PositionWithScreen( + realPosition, + window(), + { st::callWidthMin, st::callHeightMin }); + if (realPosition.w >= st::callWidthMin + && realPosition.h >= st::callHeightMin + && realPosition != savedPosition) { + Core::App().settings().setCallPanelPosition(realPosition); + Core::App().saveSettingsDelayed(); + } +} + void Panel::initWindow() { window()->setAttribute(Qt::WA_OpaquePaintEvent); window()->setAttribute(Qt::WA_NoSystemBackground); @@ -946,12 +1007,15 @@ rpl::lifetime &Panel::lifetime() { } void Panel::initGeometry() { - const auto center = Core::App().getPointForCallPanelCenter(); - const auto initRect = QRect(0, 0, st::callWidth, st::callHeight); - window()->setGeometry(initRect.translated(center - initRect.center())); + window()->setGeometry(panelGeometry()); window()->setMinimumSize({ st::callWidthMin, st::callHeightMin }); window()->show(); updateControlsGeometry(); + + _geometryLifetime = window()->geometryValue( + ) | rpl::skip(1) | rpl::on_next([=](QRect r) { + savePanelGeometry(); + }); } void Panel::initMediaDeviceToggles() { diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index 66716a76be..aaed848f7f 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -79,6 +79,7 @@ public: [[nodiscard]] not_null user() const; [[nodiscard]] bool isVisible() const; [[nodiscard]] bool isActive() const; + [[nodiscard]] QRect panelGeometry() const; [[nodiscard]] ConferencePanelMigration migrationInfo() const; @@ -86,6 +87,7 @@ public: void minimize(); void toggleFullScreen(); void replaceCall(not_null call); + void savePanelGeometry(); void closeBeforeDestroy(bool windowIsReused = false); QWidget *chooseSourceParent() override; @@ -218,6 +220,7 @@ private: std::unique_ptr _background; + rpl::lifetime _geometryLifetime; rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index e60324915b..0a9cc941c4 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -155,6 +155,8 @@ QByteArray Settings::serialize() const { LogPosition(_mediaViewPosition, u"Viewer"_q); const auto ivPosition = Serialize(_ivPosition); LogPosition(_ivPosition, u"IV"_q); + const auto callPanelPosition = Serialize(_callPanelPosition); + LogPosition(_callPanelPosition, u"CallPanel"_q); const auto proxy = _proxy.serialize(); const auto skipLanguages = _skipTranslationLanguages.current(); @@ -242,7 +244,8 @@ QByteArray Settings::serialize() const { + Serialize::bytearraySize(_tonsiteStorageToken) + sizeof(qint32) * 8 + sizeof(ushort) - + sizeof(qint32); // _notificationsDisplayChecksum + + sizeof(qint32) // _notificationsDisplayChecksum + + Serialize::bytearraySize(callPanelPosition); auto result = QByteArray(); result.reserve(size); @@ -406,7 +409,8 @@ QByteArray Settings::serialize() const { << qint32(_systemDarkModeEnabled.current() ? 1 : 0) << qint32(_quickDialogAction) << _notificationsVolume - << _notificationsDisplayChecksum; + << _notificationsDisplayChecksum + << callPanelPosition; } Ensures(result.size() == size); @@ -527,6 +531,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { qint32 trayIconMonochrome = (_trayIconMonochrome.current() ? 1 : 0); qint32 ttlVoiceClickTooltipHidden = _ttlVoiceClickTooltipHidden.current() ? 1 : 0; QByteArray ivPosition; + QByteArray callPanelPosition; QString customFontFamily = _customFontFamily; qint32 systemUnlockEnabled = _systemUnlockEnabled ? 1 : 0; qint32 weatherInCelsius = !_weatherInCelsius ? 0 : *_weatherInCelsius ? 1 : 2; @@ -875,6 +880,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { if (!stream.atEnd()) { stream >> notificationsDisplayChecksum; } + if (!stream.atEnd()) { + stream >> callPanelPosition; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for Core::Settings::constructFromSerialized()")); @@ -1086,6 +1094,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { if (!ivPosition.isEmpty()) { _ivPosition = Deserialize(ivPosition); } + if (!callPanelPosition.isEmpty()) { + _callPanelPosition = Deserialize(callPanelPosition); + } _customFontFamily = customFontFamily; _systemUnlockEnabled = (systemUnlockEnabled == 1); _weatherInCelsius = !weatherInCelsius diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index 0a78d2c22c..8c57e359cb 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -903,6 +903,13 @@ public: _ivPosition = position; } + [[nodiscard]] const WindowPosition &callPanelPosition() const { + return _callPanelPosition; + } + void setCallPanelPosition(const WindowPosition &position) { + _callPanelPosition = position; + } + [[nodiscard]] QString customFontFamily() const { return _customFontFamily; } @@ -1085,6 +1092,7 @@ private: rpl::variable _storiesClickTooltipHidden = false; rpl::variable _ttlVoiceClickTooltipHidden = false; WindowPosition _ivPosition; + WindowPosition _callPanelPosition; QString _customFontFamily; bool _systemUnlockEnabled = false; std::optional _weatherInCelsius;