diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 61592e775..7de3eb572 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -338,6 +338,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_update_fail" = "Update check failed :("; "lng_settings_workmode_tray" = "Show tray icon"; "lng_settings_workmode_window" = "Show taskbar icon"; +"lng_settings_native_frame" = "Use system window frame"; "lng_settings_auto_start" = "Launch Telegram when system starts"; "lng_settings_start_min" = "Launch minimized"; "lng_settings_add_sendto" = "Place Telegram in \"Send to\" menu"; @@ -2444,7 +2445,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "ktg_net_speed_boost_big" = "Big"; "ktg_settings_system" = "System"; -"ktg_settings_use_native_decorations" = "Native window decorations"; "ktg_settings_other" = "Other"; "ktg_profile_copy_id" = "Copy ID"; diff --git a/Telegram/Resources/langs/rewrites/en.json b/Telegram/Resources/langs/rewrites/en.json index fd4a941fe..6b7804b9e 100644 --- a/Telegram/Resources/langs/rewrites/en.json +++ b/Telegram/Resources/langs/rewrites/en.json @@ -67,7 +67,6 @@ "ktg_net_speed_boost_medium": "Medium", "ktg_net_speed_boost_big": "Big", "ktg_settings_system": "System", - "ktg_settings_use_native_decorations": "Native window decorations", "ktg_settings_other": "Other", "ktg_profile_copy_id": "Copy ID", "ktg_profile_bot_id": "Bot ID", diff --git a/Telegram/Resources/langs/rewrites/pl.json b/Telegram/Resources/langs/rewrites/pl.json index 719688518..8ce3b667e 100644 --- a/Telegram/Resources/langs/rewrites/pl.json +++ b/Telegram/Resources/langs/rewrites/pl.json @@ -67,7 +67,6 @@ "ktg_net_speed_boost_medium": "Średnie", "ktg_net_speed_boost_big": "Duże", "ktg_settings_system": "System", - "ktg_settings_use_native_decorations": "Natywne dekoracje okna", "ktg_settings_other": "Inne", "ktg_profile_copy_id": "Kopiuj ID", "ktg_profile_bot_id": "ID Bota", diff --git a/Telegram/Resources/langs/rewrites/ru.json b/Telegram/Resources/langs/rewrites/ru.json index e4eac04ac..219f3d172 100644 --- a/Telegram/Resources/langs/rewrites/ru.json +++ b/Telegram/Resources/langs/rewrites/ru.json @@ -66,7 +66,6 @@ "ktg_net_speed_boost_medium": "Среднее", "ktg_net_speed_boost_big": "Высокое", "ktg_settings_system": "Система", - "ktg_settings_use_native_decorations": "Системная рамка окна", "ktg_settings_other": "Прочие", "ktg_profile_copy_id": "Копировать ID", "ktg_profile_bot_id": "ID бота", diff --git a/Telegram/Resources/langs/rewrites/tr.json b/Telegram/Resources/langs/rewrites/tr.json index 39069fabd..b5bdd42c1 100644 --- a/Telegram/Resources/langs/rewrites/tr.json +++ b/Telegram/Resources/langs/rewrites/tr.json @@ -67,7 +67,6 @@ "ktg_net_speed_boost_medium": "orta", "ktg_net_speed_boost_big": "Güçlü", "ktg_settings_system": "sistem", - "ktg_settings_use_native_decorations": "Yerel pencere süslemeleri", "ktg_settings_other": "Başka", "ktg_profile_copy_id": "ID kopyala", "ktg_profile_bot_id": "Bot ID", diff --git a/Telegram/Resources/langs/rewrites/uk.json b/Telegram/Resources/langs/rewrites/uk.json index 64824f3ce..8c04cd56c 100644 --- a/Telegram/Resources/langs/rewrites/uk.json +++ b/Telegram/Resources/langs/rewrites/uk.json @@ -66,7 +66,6 @@ "ktg_net_speed_boost_medium": "Середнє", "ktg_net_speed_boost_big": "Високе", "ktg_settings_system": "Система", - "ktg_settings_use_native_decorations": "Системна рамка вікна", "ktg_settings_other": "Інші", "ktg_profile_copy_id": "Копіювати ID", "ktg_profile_bot_id": "ID бота", diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index a20191a2b..bf7544073 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -9,7 +9,7 @@ + Version="2.1.18.0" /> Telegram Desktop Telegram FZ-LLC diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index 3863a0ba7..48e71950a 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,1,17,0 - PRODUCTVERSION 2,1,17,0 + FILEVERSION 2,1,18,0 + PRODUCTVERSION 2,1,18,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -62,10 +62,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop" - VALUE "FileVersion", "2.1.17.0" + VALUE "FileVersion", "2.1.18.0" VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "2.1.17.0" + VALUE "ProductVersion", "2.1.18.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 25630bcad..6c71d6a0b 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,1,17,0 - PRODUCTVERSION 2,1,17,0 + FILEVERSION 2,1,18,0 + PRODUCTVERSION 2,1,18,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -53,10 +53,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram FZ-LLC" VALUE "FileDescription", "Telegram Desktop Updater" - VALUE "FileVersion", "2.1.17.0" + VALUE "FileVersion", "2.1.18.0" VALUE "LegalCopyright", "Copyright (C) 2014-2020" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "2.1.17.0" + VALUE "ProductVersion", "2.1.18.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 6d1543889..fc7c3c6a8 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -85,7 +85,6 @@ namespace App { void setLaunchState(LaunchState state); void restart(); - constexpr auto kFileSizeLimit = 1500 * 1024 * 1024; // Load files up to 1500mb constexpr auto kImageSizeLimit = 64 * 1024 * 1024; // Open images up to 64mb jpg/png/gif QImage readImage(QByteArray data, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr); QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0); diff --git a/Telegram/SourceFiles/core/changelogs.cpp b/Telegram/SourceFiles/core/changelogs.cpp index aa328f84e..ee6e25e8b 100644 --- a/Telegram/SourceFiles/core/changelogs.cpp +++ b/Telegram/SourceFiles/core/changelogs.cpp @@ -61,7 +61,17 @@ std::map BetaLogs() { "- Fix high definition GIF animations opening in media viewer.\n" "- Multiple crash fixes." - } + }, + { + 2001018, + "- Fix a possible crash in Picture-in-Picture video player.\n" + + "- Fix copying links from message texts.\n" + + "- Raise file size limit to 2000 MB.\n" + + "- Allow using system window frame in Windows and Linux." + }, }; }; diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 23c5d0eaf..1988fec58 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -105,7 +105,8 @@ QByteArray Settings::serialize() const { 1000000)) << qint32(_thirdColumnWidth.current()) << qint32(_thirdSectionExtendedBy) - << qint32(_notifyFromAll ? 1 : 0); + << qint32(_notifyFromAll ? 1 : 0) + << qint32(_nativeWindowFrame.current() ? 1 : 0); } return result; } @@ -169,6 +170,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { qint32 thirdColumnWidth = _thirdColumnWidth.current(); qint32 thirdSectionExtendedBy = _thirdSectionExtendedBy; qint32 notifyFromAll = _notifyFromAll ? 1 : 0; + qint32 nativeWindowFrame = _nativeWindowFrame.current() ? 1 : 0; stream >> themesAccentColors; if (!stream.atEnd()) { @@ -243,6 +245,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { >> notifyFromAll; dialogsWidthRatio = snap(dialogsWidthRatioInt / 1000000., 0., 1.); } + if (!stream.atEnd()) { + stream >> nativeWindowFrame; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for Core::Settings::constructFromSerialized()")); @@ -335,6 +340,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { _tabbedSelectorSectionEnabled = false; } _notifyFromAll = (notifyFromAll == 1); + _nativeWindowFrame = (nativeWindowFrame == 1); } bool Settings::chatWide() const { diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index b8eae179e..144b4977c 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -407,6 +407,15 @@ public: [[nodiscard]] bool notifyFromAll() const { return _notifyFromAll; } + void setNativeWindowFrame(bool value) { + _nativeWindowFrame = value; + } + [[nodiscard]] bool nativeWindowFrame() const { + return _nativeWindowFrame.current(); + } + [[nodiscard]] rpl::producer nativeWindowFrameChanges() const { + return _nativeWindowFrame.changes(); + } [[nodiscard]] static bool ThirdColumnByDefault(); [[nodiscard]] float64 DefaultDialogsWidthRatio(); @@ -474,6 +483,7 @@ private: rpl::variable _dialogsWidthRatio; // per-window rpl::variable _thirdColumnWidth = kDefaultThirdColumnWidth; // p-w bool _notifyFromAll = true; + rpl::variable _nativeWindowFrame = false; bool _tabbedReplacedWithInfo = false; // per-window rpl::event_stream _tabbedReplacedWithInfoValue; // per-window diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index 2b1ab8843..a6c4a60c8 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -23,7 +23,7 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs; constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs; constexpr auto AppName = "Kotatogram Desktop"_cs; constexpr auto AppFile = "Kotatogram"_cs; -constexpr auto AppVersion = 2001017; -constexpr auto AppVersionStr = "2.1.17"; +constexpr auto AppVersion = 2001018; +constexpr auto AppVersionStr = "2.1.18"; constexpr auto AppBetaVersion = true; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; diff --git a/Telegram/SourceFiles/data/data_auto_download.h b/Telegram/SourceFiles/data/data_auto_download.h index ab2a6fe4e..37c21a620 100644 --- a/Telegram/SourceFiles/data/data_auto_download.h +++ b/Telegram/SourceFiles/data/data_auto_download.h @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Data { namespace AutoDownload { -constexpr auto kMaxBytesLimit = 3000 * 512 * 1024; +constexpr auto kMaxBytesLimit = 4000 * 512 * 1024; enum class Source { User = 0x00, diff --git a/Telegram/SourceFiles/export/export_api_wrap.cpp b/Telegram/SourceFiles/export/export_api_wrap.cpp index 1476b8ccc..c509f2a54 100644 --- a/Telegram/SourceFiles/export/export_api_wrap.cpp +++ b/Telegram/SourceFiles/export/export_api_wrap.cpp @@ -27,7 +27,7 @@ constexpr auto kFileNextRequestDelay = crl::time(20); constexpr auto kChatsSliceLimit = 100; constexpr auto kMessagesSliceLimit = 100; constexpr auto kTopPeerSliceLimit = 100; -constexpr auto kFileMaxSize = 1500 * 1024 * 1024; +constexpr auto kFileMaxSize = 2000 * 1024 * 1024; constexpr auto kLocationCacheSize = 100'000; struct LocationKey { diff --git a/Telegram/SourceFiles/export/export_settings.cpp b/Telegram/SourceFiles/export/export_settings.cpp index 8c3ae84d0..58d92ce4a 100644 --- a/Telegram/SourceFiles/export/export_settings.cpp +++ b/Telegram/SourceFiles/export/export_settings.cpp @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Export { namespace { -constexpr auto kMaxFileSize = 1500 * 1024 * 1024; +constexpr auto kMaxFileSize = 2000 * 1024 * 1024; } // namespace diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp index e9dbc40af..c06e8e38c 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.cpp +++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp @@ -88,21 +88,18 @@ int SizeLimitByIndex(int index) { const auto megabytes = [&] { if (index <= 10) { return index; - } - else if (index <= 30) { + } else if (index <= 30) { return 10 + (index - 10) * 2; - } - else if (index <= 40) { + } else if (index <= 40) { return 50 + (index - 30) * 5; - } - else if (index <= 60) { + } else if (index <= 60) { return 100 + (index - 40) * 10; - } - else if (index <= 70) { + } else if (index <= 70) { return 300 + (index - 60) * 20; - } - else { - return 500 + (index - 70) * 100; + } else if (index <= 80) { + return 500 + (index - 70) * 50; + } else { + return 1000 + (index - 80) * 100; } }(); return megabytes * kMegabyte; diff --git a/Telegram/SourceFiles/export/view/export_view_settings.h b/Telegram/SourceFiles/export/view/export_view_settings.h index 083828aeb..d8dc59224 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.h +++ b/Telegram/SourceFiles/export/view/export_view_settings.h @@ -25,7 +25,7 @@ class Session; namespace Export { namespace View { -constexpr auto kSizeValueCount = 80; +constexpr auto kSizeValueCount = 90; int SizeLimitByIndex(int index); class SettingsWidget : public Ui::RpWidget { diff --git a/Telegram/SourceFiles/kotato/settings_menu.cpp b/Telegram/SourceFiles/kotato/settings_menu.cpp index 47e88bd55..0b23863f9 100644 --- a/Telegram/SourceFiles/kotato/settings_menu.cpp +++ b/Telegram/SourceFiles/kotato/settings_menu.cpp @@ -437,12 +437,12 @@ void SetupKotatoSystem( AddSkip(container); AddSubsectionTitle(container, tr::ktg_settings_system()); -#if defined Q_OS_WIN || defined Q_OS_MAC || QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED +#if defined Q_OS_MAC const auto useNativeDecorationsToggled = Ui::CreateChild>( container.get()); AddButton( container, - tr::ktg_settings_use_native_decorations(), + tr::lng_settings_native_frame(), st::settingsButton )->toggleOn( useNativeDecorationsToggled->events_starting_with_copy(cUseNativeDecorations()) @@ -464,7 +464,7 @@ void SetupKotatoSystem( confirmed, cancelled)); }, container->lifetime()); -#endif // Q_OS_WIN || Q_OS_MAC || Qt >= 5.15 || DESKTOP_APP_QT_PATCHED +#endif // Q_OS_MAC AddButton( container, diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 60f4e9bd0..714a96ed0 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -2185,13 +2185,19 @@ void MainWidget::updateControlsGeometry() { auto mainSectionWidth = width() - dialogsWidth - thirdSectionWidth; _dialogs->setGeometryWithTopMoved({ 0, 0, dialogsWidth, height() }, _contentScrollAddToY); - _sideShadow->setGeometryToLeft(dialogsWidth, 0, st::lineWidth, height()); + const auto shadowTop = _controller->window().verticalShadowTop(); + const auto shadowHeight = height() - shadowTop; + _sideShadow->setGeometryToLeft( + dialogsWidth, + shadowTop, + st::lineWidth, + shadowHeight); if (_thirdShadow) { _thirdShadow->setGeometryToLeft( width() - thirdSectionWidth - st::lineWidth, - 0, + shadowTop, st::lineWidth, - height()); + shadowHeight); } if (_callTopBar) { _callTopBar->resizeToWidth(mainSectionWidth); diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index fda60d0b7..63c30a66c 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -63,8 +63,6 @@ public: void checkHistoryActivation(); - void fixOrder(); - void sendPaths(); QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) override; @@ -79,6 +77,7 @@ public: void showMainMenu(); void updateTrayMenu(bool force = false) override; + void fixOrder() override; void showSpecialLayer( object_ptr layer, diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_loader_local.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_loader_local.cpp index d3791830f..a18ac399c 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_loader_local.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_loader_local.cpp @@ -16,7 +16,7 @@ namespace Streaming { namespace { // This is the maximum file size in Telegram API. -constexpr auto kMaxFileSize = 3000 * 512 * 1024; +constexpr auto kMaxFileSize = 4000 * 512 * 1024; int ValidateLocalSize(int64 size) { return (size > 0 && size <= kMaxFileSize) ? int(size) : 0; diff --git a/Telegram/SourceFiles/media/view/media_view_pip.cpp b/Telegram/SourceFiles/media/view/media_view_pip.cpp index 7394753b8..06b35504e 100644 --- a/Telegram/SourceFiles/media/view/media_view_pip.cpp +++ b/Telegram/SourceFiles/media/view/media_view_pip.cpp @@ -598,6 +598,7 @@ void PipPanel::mousePressEvent(QMouseEvent *e) { if (e->button() != Qt::LeftButton) { return; } + updateOverState(e->pos()); _pressState = _overState; _pressPoint = e->globalPos(); } diff --git a/Telegram/SourceFiles/platform/linux/window_title_linux.h b/Telegram/SourceFiles/platform/linux/window_title_linux.h index 19b2e9d06..c9e58bbe6 100644 --- a/Telegram/SourceFiles/platform/linux/window_title_linux.h +++ b/Telegram/SourceFiles/platform/linux/window_title_linux.h @@ -22,14 +22,22 @@ void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palet namespace Platform { -inline object_ptr CreateTitleWidget(QWidget *parent) { +inline bool AllowNativeWindowFrameToggle() { #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED - if (!DesktopEnvironment::IsUnity()) { - return object_ptr(parent); - } + return !DesktopEnvironment::IsUnity(); +#else // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED + return false; #endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED +} - return { nullptr }; +inline object_ptr CreateTitleWidget(QWidget *parent) { + return AllowNativeWindowFrameToggle() + ? object_ptr(parent) + : object_ptr{ nullptr }; +} + +inline bool NativeTitleRequiresShadow() { + return false; } inline int PreviewTitleHeight() { diff --git a/Telegram/SourceFiles/platform/mac/window_title_mac.h b/Telegram/SourceFiles/platform/mac/window_title_mac.h index bf7370c08..924f7a440 100644 --- a/Telegram/SourceFiles/platform/mac/window_title_mac.h +++ b/Telegram/SourceFiles/platform/mac/window_title_mac.h @@ -32,8 +32,16 @@ private: }; +inline bool AllowNativeWindowFrameToggle() { + return false; +} + object_ptr CreateTitleWidget(QWidget *parent); +inline bool NativeTitleRequiresShadow() { + return false; +} + int PreviewTitleHeight(); void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth); diff --git a/Telegram/SourceFiles/platform/platform_window_title.h b/Telegram/SourceFiles/platform/platform_window_title.h index 1af12c825..cd6b3a631 100644 --- a/Telegram/SourceFiles/platform/platform_window_title.h +++ b/Telegram/SourceFiles/platform/platform_window_title.h @@ -14,7 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Platform { +bool AllowNativeWindowFrameToggle(); object_ptr CreateTitleWidget(QWidget *parent); +bool NativeTitleRequiresShadow(); int PreviewTitleHeight(); void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth); @@ -33,12 +35,22 @@ void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRe namespace Platform { -inline object_ptr CreateTitleWidget(QWidget *parent) { +inline bool AllowNativeWindowFrameToggle() { #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED - return object_ptr(parent); + return true; +#else // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED + return false; #endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED +} - return { nullptr }; +inline object_ptr CreateTitleWidget(QWidget *parent) { + return AllowNativeWindowFrameToggle() + ? object_ptr(parent) + : object_ptr{ nullptr }; +} + +inline bool NativeTitleRequiresShadow() { + return false; } inline int PreviewTitleHeight() { diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index ef0ecbbd6..736993a20 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -38,28 +38,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define max(a, b) ((a) < (b) ? (b) : (a)) -#include -#undef min -#undef max - -// WM_POINTER support from Windows 8 onwards (WINVER >= 0x0602) -#ifndef WM_POINTERUPDATE -# define WM_NCPOINTERUPDATE 0x0241 -# define WM_NCPOINTERDOWN 0x0242 -# define WM_NCPOINTERUP 0x0243 -# define WM_POINTERUPDATE 0x0245 -# define WM_POINTERDOWN 0x0246 -# define WM_POINTERUP 0x0247 -# define WM_POINTERENTER 0x0249 -# define WM_POINTERLEAVE 0x024A -# define WM_POINTERACTIVATE 0x024B -# define WM_POINTERCAPTURECHANGED 0x024C -# define WM_POINTERWHEEL 0x024E -# define WM_POINTERHWHEEL 0x024F -#endif // WM_POINTERUPDATE - HICON qt_pixmapToWinHICON(const QPixmap &); using namespace Microsoft::WRL; @@ -112,515 +90,6 @@ HWND createTaskbarHider() { return hWnd; } -enum { - _PsInitHor = 0x01, - _PsInitVer = 0x02, -}; - -int32 _psSize = 0; -class _PsShadowWindows { -public: - - using Change = MainWindow::ShadowsChange; - using Changes = MainWindow::ShadowsChanges; - - _PsShadowWindows() : screenDC(0), noKeyColor(RGB(255, 255, 255)) { - for (int i = 0; i < 4; ++i) { - dcs[i] = 0; - bitmaps[i] = 0; - hwnds[i] = 0; - } - } - - void setColor(QColor c) { - r = c.red(); - g = c.green(); - b = c.blue(); - - if (!hwnds[0]) return; - Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); - for (int i = 0; i < 4; ++i) { - Gdiplus::Graphics graphics(dcs[i]); - graphics.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - if ((i % 2) && _h || !(i % 2) && _w) { - graphics.FillRectangle(&brush, 0, 0, (i % 2) ? _size : _w, (i % 2) ? _h : _size); - } - } - initCorners(); - - _x = _y = _w = _h = 0; - update(Change::Moved | Change::Resized); - } - - bool init(not_null window, QColor c) { - _window = window; - _fullsize = st::windowShadow.width(); - _shift = st::windowShadowShift; - auto cornersImage = QImage(_fullsize, _fullsize, QImage::Format_ARGB32_Premultiplied); - { - Painter p(&cornersImage); - p.setCompositionMode(QPainter::CompositionMode_Source); - st::windowShadow.paint(p, 0, 0, _fullsize, QColor(0, 0, 0)); - } - if (rtl()) cornersImage = cornersImage.mirrored(true, false); - - _metaSize = _fullsize + 2 * _shift; - _alphas.reserve(_metaSize); - _colors.reserve(_metaSize * _metaSize); - for (int32 j = 0; j < _metaSize; ++j) { - for (int32 i = 0; i < _metaSize; ++i) { - _colors.push_back((i < 2 * _shift || j < 2 * _shift) ? 1 : qMax(BYTE(1), BYTE(cornersImage.pixel(QPoint(i - 2 * _shift, j - 2 * _shift)) >> 24))); - } - } - uchar prev = 0; - for (int32 i = 0; i < _metaSize; ++i) { - uchar a = _colors[(_metaSize - 1) * _metaSize + i]; - if (a < prev) break; - - _alphas.push_back(a); - prev = a; - } - _psSize = _size = _alphas.size() - 2 * _shift; - - setColor(c); - - Gdiplus::GdiplusStartupInput gdiplusStartupInput; - ULONG_PTR gdiplusToken; - Gdiplus::Status gdiRes = Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); - - if (gdiRes != Gdiplus::Ok) { - LOG(("Application Error: could not init GDI+, error: %1").arg((int)gdiRes)); - return false; - } - blend.AlphaFormat = AC_SRC_ALPHA; - blend.SourceConstantAlpha = 255; - blend.BlendFlags = 0; - blend.BlendOp = AC_SRC_OVER; - - screenDC = GetDC(0); - if (!screenDC) { - LOG(("Application Error: could not GetDC(0), error: %2").arg(GetLastError())); - return false; - } - - const auto avail = QApplication::desktop()->availableGeometry(); - max_w = avail.width(); - accumulate_max(max_w, st::windowMinWidth); - max_h = avail.height(); - accumulate_max(max_h, st::defaultWindowTitle.height + st::windowMinHeight); - - HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); - HWND hwnd = _window ? _window->psHwnd() : nullptr; - - for (int i = 0; i < 4; ++i) { - QString cn = QString("KotatogramShadow%1").arg(i); - LPCWSTR _cn = (LPCWSTR)cn.utf16(); - WNDCLASSEX wc; - - wc.cbSize = sizeof(wc); - wc.style = 0; - wc.lpfnWndProc = wndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = appinst; - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = 0; - wc.lpszMenuName = NULL; - wc.lpszClassName = _cn; - wc.hIconSm = 0; - if (!RegisterClassEx(&wc)) { - LOG(("Application Error: could not register shadow window class %1, error: %2").arg(i).arg(GetLastError())); - destroy(); - return false; - } - - hwnds[i] = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0); - if (!hwnds[i]) { - LOG(("Application Error: could not create shadow window class %1, error: %2").arg(i).arg(GetLastError())); - destroy(); - return false; - } - SetWindowLongPtr(hwnds[i], GWLP_HWNDPARENT, (LONG)hwnd); - - dcs[i] = CreateCompatibleDC(screenDC); - if (!dcs[i]) { - LOG(("Application Error: could not create dc for shadow window class %1, error: %2").arg(i).arg(GetLastError())); - destroy(); - return false; - } - - bitmaps[i] = CreateCompatibleBitmap(screenDC, (i % 2) ? _size : max_w, (i % 2) ? max_h : _size); - if (!bitmaps[i]) { - LOG(("Application Error: could not create bitmap for shadow window class %1, error: %2").arg(i).arg(GetLastError())); - destroy(); - return false; - } - - SelectObject(dcs[i], bitmaps[i]); - } - - QStringList alphasForLog; - for_const (auto alpha, _alphas) { - alphasForLog.append(QString::number(alpha)); - } - LOG(("Window Shadow: %1").arg(alphasForLog.join(", "))); - - initCorners(); - return true; - } - - void initCorners(int directions = (_PsInitHor | _PsInitVer)) { - bool hor = (directions & _PsInitHor), ver = (directions & _PsInitVer); - Gdiplus::Graphics graphics0(dcs[0]), graphics1(dcs[1]), graphics2(dcs[2]), graphics3(dcs[3]); - graphics0.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - graphics1.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - graphics2.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - graphics3.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - - Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); - if (hor) graphics0.FillRectangle(&brush, 0, 0, _fullsize - (_size - _shift), 2 * _shift); - - if (ver) { - graphics1.FillRectangle(&brush, 0, 0, _size, 2 * _shift); - graphics3.FillRectangle(&brush, 0, 0, _size, 2 * _shift); - graphics1.FillRectangle(&brush, _size - _shift, 2 * _shift, _shift, _fullsize); - graphics3.FillRectangle(&brush, 0, 2 * _shift, _shift, _fullsize); - } - - if (hor) { - for (int j = 2 * _shift; j < _size; ++j) { - for (int k = 0; k < _fullsize - (_size - _shift); ++k) { - brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b)); - graphics0.FillRectangle(&brush, k, j, 1, 1); - graphics2.FillRectangle(&brush, k, _size - (j - 2 * _shift) - 1, 1, 1); - } - } - for (int j = _size; j < _size + 2 * _shift; ++j) { - for (int k = 0; k < _fullsize - (_size - _shift); ++k) { - brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b)); - graphics2.FillRectangle(&brush, k, _size - (j - 2 * _shift) - 1, 1, 1); - } - } - } - if (ver) { - for (int j = 2 * _shift; j < _fullsize + 2 * _shift; ++j) { - for (int k = _shift; k < _size; ++k) { - brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + (k + _shift)], r, g, b)); - graphics1.FillRectangle(&brush, _size - k - 1, j, 1, 1); - graphics3.FillRectangle(&brush, k, j, 1, 1); - } - } - } - } - void verCorners(int h, Gdiplus::Graphics *pgraphics1, Gdiplus::Graphics *pgraphics3) { - Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); - pgraphics1->FillRectangle(&brush, _size - _shift, h - _fullsize, _shift, _fullsize); - pgraphics3->FillRectangle(&brush, 0, h - _fullsize, _shift, _fullsize); - for (int j = 0; j < _fullsize; ++j) { - for (int k = _shift; k < _size; ++k) { - brush.SetColor(Gdiplus::Color(_colors[(j + 2 * _shift) * _metaSize + k + _shift], r, g, b)); - pgraphics1->FillRectangle(&brush, _size - k - 1, h - j - 1, 1, 1); - pgraphics3->FillRectangle(&brush, k, h - j - 1, 1, 1); - } - } - } - void horCorners(int w, Gdiplus::Graphics *pgraphics0, Gdiplus::Graphics *pgraphics2) { - Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); - pgraphics0->FillRectangle(&brush, w - 2 * _size - (_fullsize - (_size - _shift)), 0, _fullsize - (_size - _shift), 2 * _shift); - for (int j = 2 * _shift; j < _size; ++j) { - for (int k = 0; k < _fullsize - (_size - _shift); ++k) { - brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b)); - pgraphics0->FillRectangle(&brush, w - 2 * _size - k - 1, j, 1, 1); - pgraphics2->FillRectangle(&brush, w - 2 * _size - k - 1, _size - (j - 2 * _shift) - 1, 1, 1); - } - } - for (int j = _size; j < _size + 2 * _shift; ++j) { - for (int k = 0; k < _fullsize - (_size - _shift); ++k) { - brush.SetColor(Gdiplus::Color(_colors[j * _metaSize + k + (_size + _shift)], r, g, b)); - pgraphics2->FillRectangle(&brush, w - 2 * _size - k - 1, _size - (j - 2 * _shift) - 1, 1, 1); - } - } - } - - void update(Changes changes, WINDOWPOS *pos = 0) { - HWND hwnd = _window ? _window->psHwnd() : 0; - if (!hwnd || !hwnds[0]) return; - - if (changes == Changes(Change::Activate)) { - for (int i = 0; i < 4; ++i) { - SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } - return; - } - - if (changes & Change::Hidden) { - if (!hidden) { - for (int i = 0; i < 4; ++i) { - hidden = true; - ShowWindow(hwnds[i], SW_HIDE); - } - } - return; - } - if (!_window->positionInited()) return; - - int x = _x, y = _y, w = _w, h = _h; - if (pos && (!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE) || !(pos->flags & SWP_NOREPOSITION))) { - if (!(pos->flags & SWP_NOMOVE)) { - x = pos->x - _size; - y = pos->y - _size; - } else if (pos->flags & SWP_NOSIZE) { - for (int i = 0; i < 4; ++i) { - SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - } - return; - } - if (!(pos->flags & SWP_NOSIZE)) { - w = pos->cx + 2 * _size; - h = pos->cy + 2 * _size; - } - } else { - RECT r; - GetWindowRect(hwnd, &r); - x = r.left - _size; - y = r.top - _size; - w = r.right + _size - x; - h = r.bottom + _size - y; - } - if (h < 2 * _fullsize + 2 * _shift) { - h = 2 * _fullsize + 2 * _shift; - } - if (w < 2 * (_fullsize + _shift)) { - w = 2 * (_fullsize + _shift); - } - - if (w != _w) { - int from = (_w > 2 * (_fullsize + _shift)) ? (_w - _size - _fullsize - _shift) : (_fullsize - (_size - _shift)); - int to = w - _size - _fullsize - _shift; - if (w > max_w) { - from = _fullsize - (_size - _shift); - max_w *= 2; - for (int i = 0; i < 4; i += 2) { - DeleteObject(bitmaps[i]); - bitmaps[i] = CreateCompatibleBitmap(screenDC, max_w, _size); - SelectObject(dcs[i], bitmaps[i]); - } - initCorners(_PsInitHor); - } - Gdiplus::Graphics graphics0(dcs[0]), graphics2(dcs[2]); - graphics0.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - graphics2.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); - if (to > from) { - graphics0.FillRectangle(&brush, from, 0, to - from, 2 * _shift); - for (int i = 2 * _shift; i < _size; ++i) { - Gdiplus::Pen pen(Gdiplus::Color(_alphas[i], r, g, b)); - graphics0.DrawLine(&pen, from, i, to, i); - graphics2.DrawLine(&pen, from, _size - (i - 2 * _shift) - 1, to, _size - (i - 2 * _shift) - 1); - } - for (int i = _size; i < _size + 2 * _shift; ++i) { - Gdiplus::Pen pen(Gdiplus::Color(_alphas[i], r, g, b)); - graphics2.DrawLine(&pen, from, _size - (i - 2 * _shift) - 1, to, _size - (i - 2 * _shift) - 1); - } - } - if (_w > w) { - graphics0.FillRectangle(&brush, w - _size - _fullsize - _shift, 0, _fullsize - (_size - _shift), _size); - graphics2.FillRectangle(&brush, w - _size - _fullsize - _shift, 0, _fullsize - (_size - _shift), _size); - } - horCorners(w, &graphics0, &graphics2); - POINT p0 = { x + _size, y }, p2 = { x + _size, y + h - _size }, f = { 0, 0 }; - SIZE s = { w - 2 * _size, _size }; - updateWindow(0, &p0, &s); - updateWindow(2, &p2, &s); - } else if (x != _x || y != _y) { - POINT p0 = { x + _size, y }, p2 = { x + _size, y + h - _size }; - updateWindow(0, &p0); - updateWindow(2, &p2); - } else if (h != _h) { - POINT p2 = { x + _size, y + h - _size }; - updateWindow(2, &p2); - } - - if (h != _h) { - int from = (_h > 2 * _fullsize + 2 * _shift) ? (_h - _fullsize) : (_fullsize + 2 * _shift); - int to = h - _fullsize; - if (h > max_h) { - from = (_fullsize + 2 * _shift); - max_h *= 2; - for (int i = 1; i < 4; i += 2) { - DeleteObject(bitmaps[i]); - bitmaps[i] = CreateCompatibleBitmap(dcs[i], _size, max_h); - SelectObject(dcs[i], bitmaps[i]); - } - initCorners(_PsInitVer); - } - Gdiplus::Graphics graphics1(dcs[1]), graphics3(dcs[3]); - graphics1.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - graphics3.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); - - Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); - if (to > from) { - graphics1.FillRectangle(&brush, _size - _shift, from, _shift, to - from); - graphics3.FillRectangle(&brush, 0, from, _shift, to - from); - for (int i = 2 * _shift; i < _size + _shift; ++i) { - Gdiplus::Pen pen(Gdiplus::Color(_alphas[i], r, g, b)); - graphics1.DrawLine(&pen, _size + _shift - i - 1, from, _size + _shift - i - 1, to); - graphics3.DrawLine(&pen, i - _shift, from, i - _shift, to); - } - } - if (_h > h) { - graphics1.FillRectangle(&brush, 0, h - _fullsize, _size, _fullsize); - graphics3.FillRectangle(&brush, 0, h - _fullsize, _size, _fullsize); - } - verCorners(h, &graphics1, &graphics3); - - POINT p1 = { x + w - _size, y }, p3 = { x, y }, f = { 0, 0 }; - SIZE s = { _size, h }; - updateWindow(1, &p1, &s); - updateWindow(3, &p3, &s); - } else if (x != _x || y != _y) { - POINT p1 = { x + w - _size, y }, p3 = { x, y }; - updateWindow(1, &p1); - updateWindow(3, &p3); - } else if (w != _w) { - POINT p1 = { x + w - _size, y }; - updateWindow(1, &p1); - } - _x = x; - _y = y; - _w = w; - _h = h; - - if (hidden && (changes & Change::Shown)) { - for (int i = 0; i < 4; ++i) { - SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE); - } - hidden = false; - } - } - - void updateWindow(int i, POINT *p, SIZE *s = 0) { - static POINT f = { 0, 0 }; - if (s) { - UpdateLayeredWindow(hwnds[i], (s ? screenDC : 0), p, s, (s ? dcs[i] : 0), (s ? (&f) : 0), noKeyColor, &blend, ULW_ALPHA); - } else { - SetWindowPos(hwnds[i], 0, p->x, p->y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); - } - } - - void destroy() { - for (int i = 0; i < 4; ++i) { - if (dcs[i]) DeleteDC(dcs[i]); - if (bitmaps[i]) DeleteObject(bitmaps[i]); - if (hwnds[i]) DestroyWindow(hwnds[i]); - dcs[i] = 0; - bitmaps[i] = 0; - hwnds[i] = 0; - } - if (screenDC) ReleaseDC(0, screenDC); - } - - MainWindow *window() const { - return _window; - } - -private: - - int _x = 0, _y = 0, _w = 0, _h = 0; - int _metaSize = 0, _fullsize = 0, _size = 0, _shift = 0; - QVector _alphas, _colors; - - MainWindow *_window = nullptr; - bool hidden = true; - - HWND hwnds[4]; - HDC dcs[4], screenDC; - HBITMAP bitmaps[4]; - int max_w = 0, max_h = 0; - BLENDFUNCTION blend; - - BYTE r = 0, g = 0, b = 0; - COLORREF noKeyColor; - - static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - -}; -_PsShadowWindows _psShadowWindows; - -LRESULT CALLBACK _PsShadowWindows::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - const auto window = _psShadowWindows.window(); - if (!window || !window->shadowsWorking()) { - return DefWindowProc(hwnd, msg, wParam, lParam); - } - - int i; - for (i = 0; i < 4; ++i) { - if (_psShadowWindows.hwnds[i] && hwnd == _psShadowWindows.hwnds[i]) { - break; - } - } - if (i == 4) return DefWindowProc(hwnd, msg, wParam, lParam); - - switch (msg) { - case WM_CLOSE: - window->close(); - break; - - case WM_NCHITTEST: { - int32 xPos = GET_X_LPARAM(lParam), yPos = GET_Y_LPARAM(lParam); - switch (i) { - case 0: return HTTOP; - case 1: return (yPos < _psShadowWindows._y + _psSize) ? HTTOPRIGHT : ((yPos >= _psShadowWindows._y + _psShadowWindows._h - _psSize) ? HTBOTTOMRIGHT : HTRIGHT); - case 2: return HTBOTTOM; - case 3: return (yPos < _psShadowWindows._y + _psSize) ? HTTOPLEFT : ((yPos >= _psShadowWindows._y + _psShadowWindows._h - _psSize) ? HTBOTTOMLEFT : HTLEFT); - } - return HTTRANSPARENT; - } break; - - case WM_NCACTIVATE: return DefWindowProc(hwnd, msg, wParam, lParam); - case WM_NCLBUTTONDOWN: - case WM_NCLBUTTONUP: - case WM_NCLBUTTONDBLCLK: - case WM_NCMBUTTONDOWN: - case WM_NCMBUTTONUP: - case WM_NCMBUTTONDBLCLK: - case WM_NCRBUTTONDOWN: - case WM_NCRBUTTONUP: - case WM_NCRBUTTONDBLCLK: - case WM_NCXBUTTONDOWN: - case WM_NCXBUTTONUP: - case WM_NCXBUTTONDBLCLK: - case WM_NCMOUSEHOVER: - case WM_NCMOUSELEAVE: - case WM_NCMOUSEMOVE: - case WM_NCPOINTERUPDATE: - case WM_NCPOINTERDOWN: - case WM_NCPOINTERUP: - if (window && window->psHwnd()) { - if (msg == WM_NCLBUTTONDOWN) { - ::SetForegroundWindow(window->psHwnd()); - } - LRESULT res = SendMessage(window->psHwnd(), msg, wParam, lParam); - return res; - } - return 0; - break; - case WM_ACTIVATE: - if (window && window->psHwnd() && wParam == WA_ACTIVE) { - if ((HWND)lParam != window->psHwnd()) { - ::SetForegroundWindow(hwnd); - ::SetWindowPos(window->psHwnd(), hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - } - } - return DefWindowProc(hwnd, msg, wParam, lParam); - break; - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } - return 0; -} - ComPtr taskbarList; bool handleSessionNotification = false; @@ -638,13 +107,17 @@ MainWindow::MainWindow(not_null controller) if (!_taskbarCreatedMsgId) { _taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); } - if (!UseNativeDecorations()) { - subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) { - if (update.paletteChanged()) { - _psShadowWindows.setColor(st::windowShadowFg->c); - } - }); - } + subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) { + if (_shadow && update.paletteChanged()) { + _shadow->setColor(st::windowShadowFg->c); + } + }); + Core::App().settings().nativeWindowFrameChanges( + ) | rpl::start_with_next([=] { + initShadows(); + validateWindowTheme(); + fixMaximizedWindow(); + }, lifetime()); } void MainWindow::TaskbarCreated() { @@ -654,23 +127,21 @@ void MainWindow::TaskbarCreated() { } } -void MainWindow::shadowsUpdate(ShadowsChanges changes, WINDOWPOS *position) { - if (!UseNativeDecorations()) { - _psShadowWindows.update(changes, position); +void MainWindow::shadowsUpdate( + Ui::Platform::WindowShadow::Changes changes, + WINDOWPOS *position) { + if (_shadow) { + _shadow->update(changes, position); } } void MainWindow::shadowsActivate() { - if (!UseNativeDecorations()) { -// _psShadowWindows.setColor(_shActive); - shadowsUpdate(ShadowsChange::Activate); - } +// _shadow->setColor(_shActive); + shadowsUpdate(Ui::Platform::WindowShadow::Change::Activate); } void MainWindow::shadowsDeactivate() { -// if (!UseNativeDecorations()) { -// _psShadowWindows.setColor(_shInactive); -// } +// _shadow->setColor(_shInactive); } void MainWindow::psShowTrayMenu() { @@ -768,6 +239,10 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { } } +void MainWindow::updateWindowIcon() { + updateIconCounters(); +} + void MainWindow::unreadCounterChangedHook() { setWindowTitle(titleText()); updateIconCounters(); @@ -840,17 +315,22 @@ void MainWindow::initHook() { } void MainWindow::initShadows() { - if (!UseNativeDecorations()) { - _psShadowWindows.init(this, st::windowShadowFg->c); - _shadowsWorking = true; - psUpdateMargins(); - shadowsUpdate(ShadowsChange::Hidden); + if (Core::App().settings().nativeWindowFrame()) { + _shadow.reset(); + } else { + _shadow.emplace(this, st::windowShadowFg->c); } + updateCustomMargins(); + firstShadowsUpdate(); } void MainWindow::firstShadowsUpdate() { - if (!UseNativeDecorations() && !(windowState() & Qt::WindowMinimized) && !isHidden()) { - shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized | ShadowsChange::Shown); + using Change = Ui::Platform::WindowShadow::Change; + if ((windowState() & (Qt::WindowMinimized | Qt::WindowMaximized)) + || isHidden()) { + shadowsUpdate(Change::Hidden); + } else { + shadowsUpdate(Change::Moved | Change::Resized | Change::Shown); } } @@ -907,19 +387,40 @@ void MainWindow::updateSystemMenu(Qt::WindowState state) { } } -void MainWindow::psUpdateMargins() { - if (!ps_hWnd || _inUpdateMargins) return; +void MainWindow::updateCustomMargins() { + if (!ps_hWnd || _inUpdateMargins) { + return; + } _inUpdateMargins = true; - RECT r, a; + const auto margins = computeCustomMargins(); + if (const auto native = QGuiApplication::platformNativeInterface()) { + native->setWindowProperty( + windowHandle()->handle(), + qsl("WindowsCustomMargins"), + QVariant::fromValue(margins)); + } + if (!_themeInited) { + _themeInited = true; + validateWindowTheme(); + } + _inUpdateMargins = false; +} +QMargins MainWindow::computeCustomMargins() { + if (Core::App().settings().nativeWindowFrame()) { + _deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0; + return QMargins(); + } + auto r = RECT(); GetClientRect(ps_hWnd, &r); - a = r; - LONG style = GetWindowLongPtr(ps_hWnd, GWL_STYLE), styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE); + auto a = r; + const auto style = GetWindowLongPtr(ps_hWnd, GWL_STYLE); + const auto styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE); AdjustWindowRectEx(&a, style, false, styleEx); - QMargins margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom); + auto margins = QMargins(a.left - r.left, a.top - r.top, r.right - a.right, r.bottom - a.bottom); if (style & WS_MAXIMIZE) { RECT w, m; GetWindowRect(ps_hWnd, &w); @@ -948,23 +449,39 @@ void MainWindow::psUpdateMargins() { SetWindowPos(ps_hWnd, 0, 0, 0, w.right - w.left - _deltaLeft - _deltaRight, w.bottom - w.top - _deltaBottom - _deltaTop, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION); _deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0; } + return margins; +} - if (const auto native = QGuiApplication::platformNativeInterface()) { - native->setWindowProperty( - windowHandle()->handle(), - qsl("WindowsCustomMargins"), - QVariant::fromValue(margins)); +void MainWindow::validateWindowTheme() { + if (IsWindows8OrGreater()) { + return; + } else if (Dlls::SetWindowTheme != nullptr) { + if (Core::App().settings().nativeWindowFrame()) { + Dlls::SetWindowTheme(ps_hWnd, nullptr, nullptr); + } else { + Dlls::SetWindowTheme(ps_hWnd, L" ", L" "); + } + QApplication::setStyle(QStyleFactory::create(qsl("Windows"))); } - if (!_themeInited) { - _themeInited = true; - if (!IsWindows8OrGreater()) { - if (Dlls::SetWindowTheme != nullptr) { - Dlls::SetWindowTheme(ps_hWnd, L" ", L" "); - QApplication::setStyle(QStyleFactory::create(qsl("Windows"))); - } +} + +void MainWindow::fixMaximizedWindow() { + auto r = RECT(); + GetClientRect(ps_hWnd, &r); + const auto style = GetWindowLongPtr(ps_hWnd, GWL_STYLE); + const auto styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE); + AdjustWindowRectEx(&r, style, false, styleEx); + if (style & WS_MAXIMIZE) { + auto w = RECT(); + GetWindowRect(ps_hWnd, &w); + if (const auto hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST)) { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + const auto m = mi.rcWork; + SetWindowPos(ps_hWnd, 0, 0, 0, m.right - m.left - _deltaLeft - _deltaRight, m.bottom - m.top - _deltaTop - _deltaBottom, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION); } } - _inUpdateMargins = false; } HWND MainWindow::psHwnd() const { @@ -1000,10 +517,6 @@ MainWindow::~MainWindow() { if (ps_menu) DestroyMenu(ps_menu); psDestroyIcons(); - if (!UseNativeDecorations()) { - _shadowsWorking = false; - _psShadowWindows.destroy(); - } if (ps_tbHider_hWnd) DestroyWindow(ps_tbHider_hWnd); EventFilter::Destroy(); diff --git a/Telegram/SourceFiles/platform/win/main_window_win.h b/Telegram/SourceFiles/platform/win/main_window_win.h index f599de881..d534f81e7 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.h +++ b/Telegram/SourceFiles/platform/win/main_window_win.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "platform/platform_main_window.h" +#include "ui/platform/win/ui_window_shadow_win.h" #include "base/platform/win/base_windows_h.h" #include "base/flags.h" @@ -30,7 +31,9 @@ public: void psInitSysMenu(); void updateSystemMenu(Qt::WindowState state); - void psUpdateMargins(); + void updateCustomMargins(); + + void updateWindowIcon() override; void psRefreshTaskbarIcon(); @@ -42,22 +45,11 @@ public: static void TaskbarCreated(); // Custom shadows. - enum class ShadowsChange { - Moved = (1 << 0), - Resized = (1 << 1), - Shown = (1 << 2), - Hidden = (1 << 3), - Activate = (1 << 4), - }; - using ShadowsChanges = base::flags; - friend inline constexpr auto is_flag_type(ShadowsChange) { return true; }; - - bool shadowsWorking() const { - return _shadowsWorking; - } void shadowsActivate(); void shadowsDeactivate(); - void shadowsUpdate(ShadowsChanges changes, WINDOWPOS *position = nullptr); + void shadowsUpdate( + Ui::Platform::WindowShadow::Changes changes, + WINDOWPOS *position = nullptr); int deltaLeft() const { return _deltaLeft; @@ -99,12 +91,15 @@ protected: private: void updateIconCounters(); - + QMargins computeCustomMargins(); + void validateWindowTheme(); void psDestroyIcons(); + void fixMaximizedWindow(); static UINT _taskbarCreatedMsgId; - bool _shadowsWorking = false; + std::optional _shadow; + bool _themeInited = false; bool _inUpdateMargins = false; diff --git a/Telegram/SourceFiles/platform/win/window_title_win.h b/Telegram/SourceFiles/platform/win/window_title_win.h index 3423857a7..9508e508b 100644 --- a/Telegram/SourceFiles/platform/win/window_title_win.h +++ b/Telegram/SourceFiles/platform/win/window_title_win.h @@ -59,10 +59,18 @@ private: }; +inline bool AllowNativeWindowFrameToggle() { + return true; +} + inline object_ptr CreateTitleWidget(QWidget *parent) { return object_ptr(parent); } +inline bool NativeTitleRequiresShadow() { + return true; +} + inline int PreviewTitleHeight() { return Window::Theme::DefaultPreviewTitleHeight(); } diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp index 8a79abf64..6f0d8f901 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -78,56 +78,13 @@ bool EventFilter::nativeEventFilter( }); } -bool EventFilter::mainWindowEvent( +bool EventFilter::customWindowFrameEvent( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result) { - using ShadowsChange = MainWindow::ShadowsChange; - - if (const auto tbCreatedMsgId = Platform::MainWindow::TaskbarCreatedMsgId()) { - if (msg == tbCreatedMsgId) { - Platform::MainWindow::TaskbarCreated(); - } - } - - if (UseNativeDecorations()) { - return false; - } - switch (msg) { - - case WM_TIMECHANGE: { - Core::App().checkAutoLockIn(100); - } return false; - - case WM_WTSSESSION_CHANGE: { - if (wParam == WTS_SESSION_LOGOFF || wParam == WTS_SESSION_LOCK) { - setSessionLoggedOff(true); - } else if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK) { - setSessionLoggedOff(false); - } - } return false; - - case WM_DESTROY: { - App::quit(); - } return false; - - case WM_ACTIVATE: { - if (LOWORD(wParam) == WA_CLICKACTIVE) { - Ui::MarkInactivePress(_window, true); - } - if (LOWORD(wParam) != WA_INACTIVE) { - _window->shadowsActivate(); - } else { - _window->shadowsDeactivate(); - } - if (Global::started()) { - _window->update(); - } - } return false; - case WM_NCPAINT: { if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; if (result) *result = 0; @@ -162,47 +119,6 @@ bool EventFilter::mainWindowEvent( } } return true; - case WM_WINDOWPOSCHANGING: - case WM_WINDOWPOSCHANGED: { - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - if (GetWindowPlacement(hWnd, &wp) && (wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) { - _window->shadowsUpdate(ShadowsChange::Hidden); - } else { - _window->shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized, (WINDOWPOS*)lParam); - } - } return false; - - case WM_SIZE: { - if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) { - if (wParam != SIZE_RESTORED || _window->windowState() != Qt::WindowNoState) { - Qt::WindowState state = Qt::WindowNoState; - if (wParam == SIZE_MAXIMIZED) { - state = Qt::WindowMaximized; - } else if (wParam == SIZE_MINIMIZED) { - state = Qt::WindowMinimized; - } - emit _window->windowHandle()->windowStateChanged(state); - } else { - _window->positionUpdated(); - } - _window->psUpdateMargins(); - MainWindow::ShadowsChanges changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? ShadowsChange::Hidden : (ShadowsChange::Resized | ShadowsChange::Shown); - _window->shadowsUpdate(changes); - } - } return false; - - case WM_SHOWWINDOW: { - LONG style = GetWindowLongPtr(hWnd, GWL_STYLE); - auto changes = ShadowsChange::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? ShadowsChange::Shown : ShadowsChange::Hidden); - _window->shadowsUpdate(changes); - } return false; - - case WM_MOVE: { - _window->shadowsUpdate(ShadowsChange::Moved); - _window->positionUpdated(); - } return false; - case WM_NCHITTEST: { if (!result) return false; @@ -230,6 +146,103 @@ bool EventFilter::mainWindowEvent( case WM_NCRBUTTONUP: { SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); } return true; + } + + return false; +} + +bool EventFilter::mainWindowEvent( + HWND hWnd, + UINT msg, + WPARAM wParam, + LPARAM lParam, + LRESULT *result) { + using Change = Ui::Platform::WindowShadow::Change; + + if (const auto tbCreatedMsgId = Platform::MainWindow::TaskbarCreatedMsgId()) { + if (msg == tbCreatedMsgId) { + Platform::MainWindow::TaskbarCreated(); + } + } + + if (!Core::App().settings().nativeWindowFrame()) { + if (customWindowFrameEvent(hWnd, msg, wParam, lParam, result)) { + return true; + } + } + + switch (msg) { + + case WM_TIMECHANGE: { + Core::App().checkAutoLockIn(100); + } return false; + + case WM_WTSSESSION_CHANGE: { + if (wParam == WTS_SESSION_LOGOFF || wParam == WTS_SESSION_LOCK) { + setSessionLoggedOff(true); + } else if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK) { + setSessionLoggedOff(false); + } + } return false; + + case WM_DESTROY: { + App::quit(); + } return false; + + case WM_ACTIVATE: { + if (LOWORD(wParam) == WA_CLICKACTIVE) { + Ui::MarkInactivePress(_window, true); + } + if (LOWORD(wParam) != WA_INACTIVE) { + _window->shadowsActivate(); + } else { + _window->shadowsDeactivate(); + } + if (Global::started()) { + _window->update(); + } + } return false; + + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: { + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + if (GetWindowPlacement(hWnd, &wp) && (wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) { + _window->shadowsUpdate(Change::Hidden); + } else { + _window->shadowsUpdate(Change::Moved | Change::Resized, (WINDOWPOS*)lParam); + } + } return false; + + case WM_SIZE: { + if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) { + if (wParam != SIZE_RESTORED || _window->windowState() != Qt::WindowNoState) { + Qt::WindowState state = Qt::WindowNoState; + if (wParam == SIZE_MAXIMIZED) { + state = Qt::WindowMaximized; + } else if (wParam == SIZE_MINIMIZED) { + state = Qt::WindowMinimized; + } + emit _window->windowHandle()->windowStateChanged(state); + } else { + _window->positionUpdated(); + } + _window->updateCustomMargins(); + const auto changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? Change::Hidden : (Change::Resized | Change::Shown); + _window->shadowsUpdate(changes); + } + } return false; + + case WM_SHOWWINDOW: { + LONG style = GetWindowLongPtr(hWnd, GWL_STYLE); + const auto changes = Change::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? Change::Shown : Change::Hidden); + _window->shadowsUpdate(changes); + } return false; + + case WM_MOVE: { + _window->shadowsUpdate(Change::Moved); + _window->positionUpdated(); + } return false; case WM_SYSCOMMAND: { if (wParam == SC_MOUSEMENU) { diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.h b/Telegram/SourceFiles/platform/win/windows_event_filter.h index 84ac63093..a0dbd9d1e 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.h +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.h @@ -34,6 +34,13 @@ public: private: explicit EventFilter(not_null window); + bool customWindowFrameEvent( + HWND hWnd, + UINT msg, + WPARAM wParam, + LPARAM lParam, + LRESULT *result); + not_null _window; bool _sessionLoggedOff = false; diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index 13aea7e84..7a822cd95 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/about_box.h" #include "boxes/confirm_box.h" #include "platform/platform_specific.h" +#include "platform/platform_window_title.h" #include "base/platform/base_platform_info.h" #include "window/window_session_controller.h" #include "lang/lang_keys.h" @@ -407,6 +408,20 @@ void SetupTrayContent(not_null container) { }, taskbar->lifetime()); } + if (Platform::AllowNativeWindowFrameToggle()) { + const auto nativeFrame = addCheckbox( + "Use system window frame", + Core::App().settings().nativeWindowFrame()); + + nativeFrame->checkedChanges( + ) | rpl::filter([](bool checked) { + return (checked != Core::App().settings().nativeWindowFrame()); + }) | rpl::start_with_next([=](bool checked) { + Core::App().settings().setNativeWindowFrame(checked); + Core::App().saveSettingsDelayed(); + }, nativeFrame->lifetime()); + } + if (Platform::AutostartSupported()) { const auto minimizedToggled = [] { return cStartMinimized() && !Global::LocalPasscode(); diff --git a/Telegram/SourceFiles/storage/localimageloader.cpp b/Telegram/SourceFiles/storage/localimageloader.cpp index be4083834..d06ff0456 100644 --- a/Telegram/SourceFiles/storage/localimageloader.cpp +++ b/Telegram/SourceFiles/storage/localimageloader.cpp @@ -776,7 +776,7 @@ void FileLoadTask::process() { } _result->filesize = (int32)qMin(filesize, qint64(INT_MAX)); - if (!filesize || filesize > App::kFileSizeLimit) { + if (!filesize || filesize > kFileSizeLimit) { return; } @@ -963,7 +963,7 @@ void FileLoadTask::finish() { tr::lng_send_image_empty(tr::now, lt_name, _filepath)), Ui::LayerOption::KeepOther); removeFromAlbum(); - } else if (_result->filesize > App::kFileSizeLimit) { + } else if (_result->filesize > kFileSizeLimit) { Ui::show( Box( tr::lng_send_image_too_large(tr::now, lt_name, _filepath)), diff --git a/Telegram/SourceFiles/storage/localimageloader.h b/Telegram/SourceFiles/storage/localimageloader.h index 009d032db..200e46d0a 100644 --- a/Telegram/SourceFiles/storage/localimageloader.h +++ b/Telegram/SourceFiles/storage/localimageloader.h @@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/variant.h" #include "api/api_common.h" +constexpr auto kFileSizeLimit = 2000 * 1024 * 1024; // Load files up to 1500mb + enum class CompressConfirm { Auto, Yes, diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index 2a05a4837..42a6c8355 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -190,7 +190,7 @@ MimeDataState ComputeMimeDataState(const QMimeData *data) { } const auto filesize = info.size(); - if (filesize > App::kFileSizeLimit) { + if (filesize > kFileSizeLimit) { return MimeDataState::None; } else if (allAreSmallImages) { if (filesize > App::kImageSizeLimit) { @@ -237,7 +237,7 @@ PreparedList PrepareMediaList(const QStringList &files, int previewWidth) { PreparedList::Error::EmptyFile, file }; - } else if (filesize > App::kFileSizeLimit) { + } else if (filesize > kFileSizeLimit) { return { PreparedList::Error::TooLargeFile, file diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index d0f83c6f3..0fde90a9b 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/crc32hash.h" #include "base/call_delayed.h" #include "ui/toast/toast.h" +#include "ui/widgets/shadow.h" #include "ui/ui_utility.h" #include "apiwrap.h" #include "mainwindow.h" @@ -265,9 +266,14 @@ void MainWindow::init() { updatePalette(); - if (!UseNativeDecorations() && (_title = Platform::CreateTitleWidget(this))) { - _title->init(); + if (Platform::AllowNativeWindowFrameToggle()) { + Core::App().settings().nativeWindowFrameChanges( + ) | rpl::start_with_next([=](bool native) { + refreshTitleWidget(); + recountGeometryConstraints(); + }, lifetime()); } + refreshTitleWidget(); initSize(); updateUnreadCounter(); @@ -340,9 +346,34 @@ int MainWindow::computeMinHeight() const { return title + outdated + st::windowMinHeight; } -void MainWindow::initSize() { +void MainWindow::refreshTitleWidget() { + if (Platform::AllowNativeWindowFrameToggle() + && Core::App().settings().nativeWindowFrame()) { + _title.destroy(); + if (Platform::NativeTitleRequiresShadow()) { + _titleShadow.create(this); + _titleShadow->show(); + } + } else if ((_title = Platform::CreateTitleWidget(this))) { + _title->show(); + _title->init(); + _titleShadow.destroy(); + } +} + +void MainWindow::updateMinimumSize() { setMinimumWidth(computeMinWidth()); setMinimumHeight(computeMinHeight()); +} + +void MainWindow::recountGeometryConstraints() { + updateMinimumSize(); + updateControlsGeometry(); + fixOrder(); +} + +void MainWindow::initSize() { + updateMinimumSize(); auto position = cWindowPos(); DEBUG_LOG(("Window Pos: Initializing first %1, %2, %3, %4 (maximized %5)").arg(position.x).arg(position.y).arg(position.w).arg(position.h).arg(Logs::b(position.maximized))); @@ -455,6 +486,9 @@ void MainWindow::updateControlsGeometry() { _title->setGeometry(0, bodyTop, width(), _title->height()); bodyTop += _title->height(); } + if (_titleShadow) { + _titleShadow->setGeometry(0, bodyTop, width(), st::lineWidth); + } if (_outdated) { Ui::SendPendingMoveResizeEvents(_outdated.data()); _outdated->resizeToWidth(width()); @@ -637,6 +671,8 @@ void MainWindow::launchDrag(std::unique_ptr data) { } } -MainWindow::~MainWindow() = default; +MainWindow::~MainWindow() { + _title.destroy(); +} } // namespace Window diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index 30dee3d1f..5d09511cb 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -21,6 +21,7 @@ class Account; namespace Ui { class BoxContent; +class PlainShadow; } // namespace Ui namespace Window { @@ -81,6 +82,8 @@ public: virtual void updateTrayMenu(bool force = false) { } + virtual void fixOrder() { + } virtual ~MainWindow(); @@ -102,6 +105,7 @@ public: int computeMinWidth() const; int computeMinHeight() const; + void recountGeometryConstraints(); virtual void updateControlsGeometry(); public slots: @@ -174,6 +178,8 @@ protected: void updateUnreadCounter(); private: + void refreshTitleWidget(); + void updateMinimumSize(); void updatePalette(); void initSize(); @@ -185,6 +191,7 @@ private: bool _positionInited = false; object_ptr _title = { nullptr }; + object_ptr _titleShadow = { nullptr }; object_ptr _outdated; object_ptr _body; object_ptr _rightColumn = { nullptr }; diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index fce4b134d..a4fcc127c 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_updates.h" #include "core/application.h" #include "core/click_handler_types.h" +#include "platform/platform_window_title.h" #include "main/main_account.h" #include "main/main_domain.h" #include "main/main_session.h" @@ -241,6 +242,13 @@ void Controller::showSettings() { _widget.showSettings(); } +int Controller::verticalShadowTop() const { + return (Platform::NativeTitleRequiresShadow() + && Core::App().settings().nativeWindowFrame()) + ? st::lineWidth + : 0; +} + void Controller::showToast(const QString &text) { Ui::Toast::Show(_widget.bodyWidget(), text); } @@ -257,9 +265,7 @@ void Controller::showRightColumn(object_ptr widget) { } void Controller::sideBarChanged() { - _widget.setMinimumWidth(_widget.computeMinWidth()); - _widget.updateControlsGeometry(); - _widget.fixOrder(); + _widget.recountGeometryConstraints(); } void Controller::activate() { diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index e5f14096f..05c6e02fd 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -48,6 +48,8 @@ public: void showSettings(); + [[nodiscard]] int verticalShadowTop() const; + template QPointer show( object_ptr content, diff --git a/Telegram/SourceFiles/window/window_title_qt.cpp b/Telegram/SourceFiles/window/window_title_qt.cpp index e9417d03c..555a87355 100644 --- a/Telegram/SourceFiles/window/window_title_qt.cpp +++ b/Telegram/SourceFiles/window/window_title_qt.cpp @@ -10,11 +10,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/widgets/shadow.h" #include "styles/style_window.h" +#include "base/call_delayed.h" #include #include namespace Window { +namespace { + +// If we toggle frameless window hint in maximized window, and +// show it back too quickly, the mouse position inside the window +// won't be correct (from Qt-s point of view) until we Alt-Tab from +// that window. If we show the window back with this delay it works. +constexpr auto kShowAfterFramelessToggleDelay = crl::time(1000); + +} // namespace TitleWidgetQt::TitleWidgetQt(QWidget *parent) : TitleWidget(parent) @@ -45,11 +55,35 @@ TitleWidgetQt::TitleWidgetQt(QWidget *parent) QCoreApplication::instance()->installEventFilter(this); - window()->setWindowFlag(Qt::FramelessWindowHint, true); + _windowWasFrameless = (window()->windowFlags() & Qt::FramelessWindowHint) != 0; + if (!_windowWasFrameless) { + toggleFramelessWindow(true); + } setAttribute(Qt::WA_OpaquePaintEvent); resize(width(), _st.height); } +TitleWidgetQt::~TitleWidgetQt() { + restoreCursor(); + if (!_windowWasFrameless) { + toggleFramelessWindow(false); + } +} + +void TitleWidgetQt::toggleFramelessWindow(bool enabled) { + // setWindowFlag calls setParent(parentWidget(), newFlags), which + // always calls hide() explicitly, we have to show() the window back. + const auto top = window(); + const auto hidden = top->isHidden(); + top->setWindowFlag(Qt::FramelessWindowHint, enabled); + if (!hidden) { + base::call_delayed( + kShowAfterFramelessToggleDelay, + top, + [=] { top->show(); }); + } +} + void TitleWidgetQt::init() { connect( window()->windowHandle(), @@ -103,7 +137,7 @@ void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) { bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) { if (e->type() == QEvent::MouseMove || e->type() == QEvent::MouseButtonPress) { - if(window()->isAncestorOf(static_cast(obj))) { + if (window()->isAncestorOf(static_cast(obj))) { const auto mouseEvent = static_cast(e); const auto edges = edgesFromPos(mouseEvent->windowPos().toPoint()); @@ -111,7 +145,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) { updateCursor(edges); } - if(e->type() == QEvent::MouseButtonPress + if (e->type() == QEvent::MouseButtonPress && mouseEvent->button() == Qt::LeftButton && window()->windowState() != Qt::WindowMaximized) { return startResize(edges); @@ -119,9 +153,7 @@ bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) { } } else if (e->type() == QEvent::Leave) { if (window() == static_cast(obj)) { - while (QGuiApplication::overrideCursor()) { - QGuiApplication::restoreOverrideCursor(); - } + restoreCursor(); } } @@ -196,14 +228,22 @@ Qt::Edges TitleWidgetQt::edgesFromPos(const QPoint &pos) { } } +void TitleWidgetQt::restoreCursor() { + if (_cursorOverriden) { + _cursorOverriden = false; + QGuiApplication::restoreOverrideCursor(); + } +} + void TitleWidgetQt::updateCursor(Qt::Edges edges) { if (!edges || window()->windowState() == Qt::WindowMaximized) { - while (QGuiApplication::overrideCursor()) { - QGuiApplication::restoreOverrideCursor(); - } - + restoreCursor(); return; } else if (!QGuiApplication::overrideCursor()) { + _cursorOverriden = false; + } + if (!_cursorOverriden) { + _cursorOverriden = true; QGuiApplication::setOverrideCursor(QCursor()); } diff --git a/Telegram/SourceFiles/window/window_title_qt.h b/Telegram/SourceFiles/window/window_title_qt.h index 68d4dcbce..67a80945a 100644 --- a/Telegram/SourceFiles/window/window_title_qt.h +++ b/Telegram/SourceFiles/window/window_title_qt.h @@ -24,6 +24,7 @@ namespace Window { class TitleWidgetQt : public TitleWidget { public: TitleWidgetQt(QWidget *parent); + ~TitleWidgetQt(); void init() override; @@ -40,8 +41,10 @@ private: void updateButtonsState(); void updateControlsPosition(); + void toggleFramelessWindow(bool enabled); Qt::Edges edgesFromPos(const QPoint &pos); void updateCursor(Qt::Edges edges); + void restoreCursor(); bool startResize(Qt::Edges edges); const style::WindowTitle &_st; @@ -52,6 +55,8 @@ private: bool _maximizedState = false; bool _activeState = false; + bool _windowWasFrameless = false; + bool _cursorOverriden = false; }; diff --git a/Telegram/build/version b/Telegram/build/version index 9c3b3678c..85b4d4726 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,7 +1,7 @@ -AppVersion 2001017 +AppVersion 2001018 AppVersionStrMajor 2.1 -AppVersionStrSmall 2.1.17 -AppVersionStr 2.1.17 +AppVersionStrSmall 2.1.18 +AppVersionStr 2.1.18 BetaChannel 1 AlphaVersion 0 -AppVersionOriginal 2.1.17.beta +AppVersionOriginal 2.1.18.beta diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 11a39d9d9..c262a0931 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 11a39d9d941e4cd1c60a0c97352cbf89700f42fc +Subproject commit c262a0931e4b32ff156aa12cb2657c8cdd444c69 diff --git a/changelog.txt b/changelog.txt index f09a71aae..bc25a3a85 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,10 @@ +2.1.18 beta (08.07.20) + +- Fix a possible crash in Picture-in-Picture video player. +- Fix copying links from message texts. +- Raise file size limit to 2000 MB. +- Allow using system window frame in Windows and Linux. + 2.1.17 beta (02.07.20) - Fix messages editing in a non-active account.