diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 7787db0a05..ca96cce888 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"; diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 23c5d0eaf7..1988fec580 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 b8eae179e2..144b4977c4 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/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index a6f20da2f4..efe872c44d 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -2177,13 +2177,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 15f3815f2a..4ca8e07f4b 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/platform/linux/window_title_linux.h b/Telegram/SourceFiles/platform/linux/window_title_linux.h index 19b2e9d069..c9e58bbe64 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 bf7370c084..924f7a440d 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 1af12c8256..cd6b3a631b 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 dd2b44a7e6..0f2d114d12 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -112,6 +112,12 @@ MainWindow::MainWindow(not_null controller) _shadow->setColor(st::windowShadowFg->c); } }); + Core::App().settings().nativeWindowFrameChanges( + ) | rpl::start_with_next([=] { + initShadows(); + validateWindowTheme(); + fixMaximizedWindow(); + }, lifetime()); } void MainWindow::TaskbarCreated() { @@ -231,6 +237,10 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { } } +void MainWindow::updateWindowIcon() { + updateIconCounters(); +} + void MainWindow::unreadCounterChangedHook() { setWindowTitle(titleText()); updateIconCounters(); @@ -294,18 +304,24 @@ void MainWindow::initHook() { } psInitSysMenu(); - - _shadow.emplace(this, st::windowShadowFg->c); } void MainWindow::initShadows() { - psUpdateMargins(); - shadowsUpdate(Ui::Platform::WindowShadow::Change::Hidden); + if (Core::App().settings().nativeWindowFrame()) { + _shadow.reset(); + } else { + _shadow.emplace(this, st::windowShadowFg->c); + } + updateCustomMargins(); + firstShadowsUpdate(); } void MainWindow::firstShadowsUpdate() { - if (!(windowState() & Qt::WindowMinimized) && !isHidden()) { - using Change = Ui::Platform::WindowShadow::Change; + using Change = Ui::Platform::WindowShadow::Change; + if ((windowState() & (Qt::WindowMinimized | Qt::WindowMaximized)) + || isHidden()) { + shadowsUpdate(Change::Hidden); + } else { shadowsUpdate(Change::Moved | Change::Resized | Change::Shown); } } @@ -363,19 +379,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); @@ -404,23 +441,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 { diff --git a/Telegram/SourceFiles/platform/win/main_window_win.h b/Telegram/SourceFiles/platform/win/main_window_win.h index 938565a0b6..d534f81e7b 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.h +++ b/Telegram/SourceFiles/platform/win/main_window_win.h @@ -31,7 +31,9 @@ public: void psInitSysMenu(); void updateSystemMenu(Qt::WindowState state); - void psUpdateMargins(); + void updateCustomMargins(); + + void updateWindowIcon() override; void psRefreshTaskbarIcon(); @@ -89,8 +91,10 @@ protected: private: void updateIconCounters(); - + QMargins computeCustomMargins(); + void validateWindowTheme(); void psDestroyIcons(); + void fixMaximizedWindow(); static UINT _taskbarCreatedMsgId; diff --git a/Telegram/SourceFiles/platform/win/window_title_win.h b/Telegram/SourceFiles/platform/win/window_title_win.h index 3423857a79..9508e508b4 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 53b79ecdd3..6f0d8f901c 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -78,6 +78,79 @@ bool EventFilter::nativeEventFilter( }); } +bool EventFilter::customWindowFrameEvent( + HWND hWnd, + UINT msg, + WPARAM wParam, + LPARAM lParam, + LRESULT *result) { + switch (msg) { + case WM_NCPAINT: { + if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; + if (result) *result = 0; + } return true; + + case WM_NCCALCSIZE: { + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + if (GetWindowPlacement(hWnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED) { + LPNCCALCSIZE_PARAMS params = (LPNCCALCSIZE_PARAMS)lParam; + LPRECT r = (wParam == TRUE) ? ¶ms->rgrc[0] : (LPRECT)lParam; + HMONITOR hMonitor = MonitorFromPoint({ (r->left + r->right) / 2, (r->top + r->bottom) / 2 }, MONITOR_DEFAULTTONEAREST); + if (hMonitor) { + MONITORINFO mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfo(hMonitor, &mi)) { + *r = mi.rcWork; + } + } + } + if (result) *result = 0; + return true; + } + + case WM_NCACTIVATE: { + if (IsCompositionEnabled()) { + const auto res = DefWindowProc(hWnd, msg, wParam, -1); + if (result) *result = res; + } else { + // Thanks https://github.com/melak47/BorderlessWindow + if (result) *result = 1; + } + } return true; + + case WM_NCHITTEST: { + if (!result) return false; + + POINTS p = MAKEPOINTS(lParam); + RECT r; + GetWindowRect(hWnd, &r); + auto res = _window->hitTest(QPoint(p.x - r.left + _window->deltaLeft(), p.y - r.top + _window->deltaTop())); + switch (res) { + case Window::HitTestResult::Client: + case Window::HitTestResult::SysButton: *result = HTCLIENT; break; + case Window::HitTestResult::Caption: *result = HTCAPTION; break; + case Window::HitTestResult::Top: *result = HTTOP; break; + case Window::HitTestResult::TopRight: *result = HTTOPRIGHT; break; + case Window::HitTestResult::Right: *result = HTRIGHT; break; + case Window::HitTestResult::BottomRight: *result = HTBOTTOMRIGHT; break; + case Window::HitTestResult::Bottom: *result = HTBOTTOM; break; + case Window::HitTestResult::BottomLeft: *result = HTBOTTOMLEFT; break; + case Window::HitTestResult::Left: *result = HTLEFT; break; + case Window::HitTestResult::TopLeft: *result = HTTOPLEFT; break; + case Window::HitTestResult::None: + default: *result = HTTRANSPARENT; break; + }; + } return true; + + case WM_NCRBUTTONUP: { + SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); + } return true; + } + + return false; +} + bool EventFilter::mainWindowEvent( HWND hWnd, UINT msg, @@ -92,6 +165,12 @@ bool EventFilter::mainWindowEvent( } } + if (!Core::App().settings().nativeWindowFrame()) { + if (customWindowFrameEvent(hWnd, msg, wParam, lParam, result)) { + return true; + } + } + switch (msg) { case WM_TIMECHANGE: { @@ -124,40 +203,6 @@ bool EventFilter::mainWindowEvent( } } return false; - case WM_NCPAINT: { - if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; - if (result) *result = 0; - } return true; - - case WM_NCCALCSIZE: { - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - if (GetWindowPlacement(hWnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED) { - LPNCCALCSIZE_PARAMS params = (LPNCCALCSIZE_PARAMS)lParam; - LPRECT r = (wParam == TRUE) ? ¶ms->rgrc[0] : (LPRECT)lParam; - HMONITOR hMonitor = MonitorFromPoint({ (r->left + r->right) / 2, (r->top + r->bottom) / 2 }, MONITOR_DEFAULTTONEAREST); - if (hMonitor) { - MONITORINFO mi; - mi.cbSize = sizeof(mi); - if (GetMonitorInfo(hMonitor, &mi)) { - *r = mi.rcWork; - } - } - } - if (result) *result = 0; - return true; - } - - case WM_NCACTIVATE: { - if (IsCompositionEnabled()) { - const auto res = DefWindowProc(hWnd, msg, wParam, -1); - if (result) *result = res; - } else { - // Thanks https://github.com/melak47/BorderlessWindow - if (result) *result = 1; - } - } return true; - case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: { WINDOWPLACEMENT wp; @@ -182,7 +227,7 @@ bool EventFilter::mainWindowEvent( } else { _window->positionUpdated(); } - _window->psUpdateMargins(); + _window->updateCustomMargins(); const auto changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? Change::Hidden : (Change::Resized | Change::Shown); _window->shadowsUpdate(changes); } @@ -199,34 +244,6 @@ bool EventFilter::mainWindowEvent( _window->positionUpdated(); } return false; - case WM_NCHITTEST: { - if (!result) return false; - - POINTS p = MAKEPOINTS(lParam); - RECT r; - GetWindowRect(hWnd, &r); - auto res = _window->hitTest(QPoint(p.x - r.left + _window->deltaLeft(), p.y - r.top + _window->deltaTop())); - switch (res) { - case Window::HitTestResult::Client: - case Window::HitTestResult::SysButton: *result = HTCLIENT; break; - case Window::HitTestResult::Caption: *result = HTCAPTION; break; - case Window::HitTestResult::Top: *result = HTTOP; break; - case Window::HitTestResult::TopRight: *result = HTTOPRIGHT; break; - case Window::HitTestResult::Right: *result = HTRIGHT; break; - case Window::HitTestResult::BottomRight: *result = HTBOTTOMRIGHT; break; - case Window::HitTestResult::Bottom: *result = HTBOTTOM; break; - case Window::HitTestResult::BottomLeft: *result = HTBOTTOMLEFT; break; - case Window::HitTestResult::Left: *result = HTLEFT; break; - case Window::HitTestResult::TopLeft: *result = HTTOPLEFT; break; - case Window::HitTestResult::None: - default: *result = HTTRANSPARENT; break; - }; - } return true; - - case WM_NCRBUTTONUP: { - SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); - } return true; - case WM_SYSCOMMAND: { if (wParam == SC_MOUSEMENU) { POINTS p = MAKEPOINTS(lParam); diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.h b/Telegram/SourceFiles/platform/win/windows_event_filter.h index 84ac63093c..a0dbd9d1e0 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 5cd4af4575..7be2af484f 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/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index ff9b77f178..895c7c437b 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" @@ -236,9 +237,14 @@ void MainWindow::init() { updatePalette(); - if ((_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(); @@ -311,9 +317,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))); @@ -425,6 +456,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()); diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index 52f5d58658..ceb6cdedac 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 { @@ -80,6 +81,8 @@ public: virtual void updateTrayMenu(bool force = false) { } + virtual void fixOrder() { + } virtual ~MainWindow(); @@ -101,6 +104,7 @@ public: int computeMinWidth() const; int computeMinHeight() const; + void recountGeometryConstraints(); virtual void updateControlsGeometry(); public slots: @@ -173,6 +177,8 @@ protected: void updateUnreadCounter(); private: + void refreshTitleWidget(); + void updateMinimumSize(); void updatePalette(); void initSize(); @@ -184,6 +190,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 5868680279..479f645536 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" @@ -239,6 +240,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); } @@ -255,9 +263,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 e5f14096fe..05c6e02fd5 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/lib_ui b/Telegram/lib_ui index 09918f0133..aed9fe649b 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 09918f0133ce0070000b9ca2a798057e6ad8bd5d +Subproject commit aed9fe649bc150d8f4c1404b61c6b8bd56192d1b