diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 18a2c486a8..9e1a8a8381 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -873,7 +873,6 @@ PRIVATE platform/linux/notifications_manager_linux.h platform/linux/specific_linux.cpp platform/linux/specific_linux.h - platform/linux/window_title_linux.h platform/mac/file_utilities_mac.mm platform/mac/file_utilities_mac.h platform/mac/launcher_mac.mm @@ -888,7 +887,6 @@ PRIVATE platform/mac/specific_mac_p.mm platform/mac/specific_mac_p.h platform/mac/window_title_mac.mm - platform/mac/window_title_mac.h platform/mac/touchbar/items/mac_formatter_item.h platform/mac/touchbar/items/mac_formatter_item.mm platform/mac/touchbar/items/mac_pinned_chats_item.h @@ -919,8 +917,6 @@ PRIVATE platform/win/notifications_manager_win.h platform/win/specific_win.cpp platform/win/specific_win.h - platform/win/window_title_win.cpp - platform/win/window_title_win.h platform/win/windows_app_user_model_id.cpp platform/win/windows_app_user_model_id.h platform/win/windows_dlls.cpp @@ -1099,9 +1095,6 @@ PRIVATE window/window_session_controller.h window/window_slide_animation.cpp window/window_slide_animation.h - window/window_title_qt.cpp - window/window_title_qt.h - window/window_title.h window/window_top_bar_wrap.h window/themes/window_theme.cpp window/themes/window_theme.h @@ -1140,13 +1133,6 @@ PRIVATE stdafx.h ) -if (NOT LINUX) - remove_target_sources(Telegram ${src_loc} - window/window_title_qt.cpp - window/window_title_qt.h - ) -endif() - if (DESKTOP_APP_DISABLE_DBUS_INTEGRATION) remove_target_sources(Telegram ${src_loc} platform/linux/linux_xdp_file_dialog.cpp diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index eb66c95191..005b9260f8 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -269,7 +269,7 @@ void Application::run() { const auto currentGeometry = _window->widget()->geometry(); _mediaView = std::make_unique(); - _window->widget()->setGeometry(currentGeometry); + _window->widget()->Ui::RpWidget::setGeometry(currentGeometry); DEBUG_LOG(("Application Info: showing.")); _window->finishFirstShow(); diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 05fcef5308..97ce78c9ae 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -41,7 +41,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_intro.h" #include "platform/platform_notifications_manager.h" #include "base/platform/base_platform_info.h" -#include "ui/platform/ui_platform_utility.h" #include "base/call_delayed.h" #include "base/variant.h" #include "window/notifications_manager.h" @@ -115,12 +114,7 @@ MainWindow::MainWindow(not_null controller) }, lifetime()); setAttribute(Qt::WA_NoSystemBackground); - - if (Ui::Platform::WindowExtentsSupported()) { - setAttribute(Qt::WA_TranslucentBackground); - } else { - setAttribute(Qt::WA_OpaquePaintEvent); - } + setAttribute(Qt::WA_OpaquePaintEvent); } void MainWindow::initHook() { @@ -226,10 +220,8 @@ void MainWindow::applyInitialWorkMode() { void MainWindow::finishFirstShow() { createTrayIconMenu(); - initShadows(); applyInitialWorkMode(); createGlobalMenu(); - firstShadowsUpdate(); windowDeactivateEvents( ) | rpl::start_with_next([=] { @@ -419,7 +411,7 @@ void MainWindow::showMainMenu() { ensureLayerCreated(); _layer->showMainMenu( - object_ptr(this, sessionController()), + object_ptr(body(), sessionController()), anim::type::normal); } diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp index 16db763d83..cc747a15a2 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp @@ -21,128 +21,73 @@ using namespace KWayland::Client; namespace Platform { namespace internal { -class WaylandIntegration::Private : public QObject { -public: - Private(); - - [[nodiscard]] Registry ®istry() { - return _registry; - } - - [[nodiscard]] XdgExporter *xdgExporter() { - return _xdgExporter.get(); - } - - [[nodiscard]] PlasmaShell *plasmaShell() { - return _plasmaShell.get(); - } - - [[nodiscard]] AppMenuManager *appMenuManager() { - return _appMenuManager.get(); - } - - [[nodiscard]] QEventLoop &interfacesLoop() { - return _interfacesLoop; - } - - [[nodiscard]] bool interfacesAnnounced() const { - return _interfacesAnnounced; - } - -private: - ConnectionThread _connection; - ConnectionThread *_applicationConnection = nullptr; - Registry _registry; - Registry _applicationRegistry; - std::unique_ptr _xdgExporter; - std::unique_ptr _plasmaShell; - std::unique_ptr _appMenuManager; - QEventLoop _interfacesLoop; - bool _interfacesAnnounced = false; +struct WaylandIntegration::Private { + std::unique_ptr connection; + Registry registry; + std::unique_ptr xdgExporter; + std::unique_ptr plasmaShell; + std::unique_ptr appMenuManager; }; -WaylandIntegration::Private::Private() -: _applicationConnection(ConnectionThread::fromApplication(this)) { - _applicationRegistry.create(_applicationConnection); - _applicationRegistry.setup(); - - connect( - _applicationConnection, - &ConnectionThread::connectionDied, - &_applicationRegistry, - &Registry::destroy); - - connect(&_connection, &ConnectionThread::connected, [=] { - LOG(("Successfully connected to Wayland server at socket: %1") - .arg(_connection.socketName())); - - _registry.create(&_connection); - _registry.setup(); - }); - - connect( - &_connection, - &ConnectionThread::connectionDied, - &_registry, - &Registry::destroy); - - connect(&_registry, &Registry::interfacesAnnounced, [=] { - _interfacesAnnounced = true; - if (_interfacesLoop.isRunning()) { - _interfacesLoop.quit(); - } - }); - - connect( - &_applicationRegistry, - &Registry::exporterUnstableV2Announced, - [=](uint name, uint version) { - _xdgExporter = std::unique_ptr{ - _applicationRegistry.createXdgExporter(name, version), - }; - - connect( - _applicationConnection, - &ConnectionThread::connectionDied, - _xdgExporter.get(), - &XdgExporter::destroy); - }); - - connect( - &_applicationRegistry, - &Registry::plasmaShellAnnounced, - [=](uint name, uint version) { - _plasmaShell = std::unique_ptr{ - _applicationRegistry.createPlasmaShell(name, version), - }; - - connect( - _applicationConnection, - &ConnectionThread::connectionDied, - _plasmaShell.get(), - &PlasmaShell::destroy); - }); - - connect( - &_applicationRegistry, - &Registry::appMenuAnnounced, - [=](uint name, uint version) { - _appMenuManager = std::unique_ptr{ - _applicationRegistry.createAppMenuManager(name, version), - }; - - connect( - _applicationConnection, - &ConnectionThread::connectionDied, - _appMenuManager.get(), - &AppMenuManager::destroy); - }); - - _connection.initConnection(); -} - WaylandIntegration::WaylandIntegration() : _private(std::make_unique()) { + _private->connection = std::unique_ptr{ + ConnectionThread::fromApplication(), + }; + + _private->registry.create(_private->connection.get()); + _private->registry.setup(); + + QObject::connect( + _private->connection.get(), + &ConnectionThread::connectionDied, + &_private->registry, + &Registry::destroy); + + QObject::connect( + &_private->registry, + &Registry::exporterUnstableV2Announced, + [=](uint name, uint version) { + _private->xdgExporter = std::unique_ptr{ + _private->registry.createXdgExporter(name, version), + }; + + QObject::connect( + _private->connection.get(), + &ConnectionThread::connectionDied, + _private->xdgExporter.get(), + &XdgExporter::destroy); + }); + + QObject::connect( + &_private->registry, + &Registry::plasmaShellAnnounced, + [=](uint name, uint version) { + _private->plasmaShell = std::unique_ptr{ + _private->registry.createPlasmaShell(name, version), + }; + + QObject::connect( + _private->connection.get(), + &ConnectionThread::connectionDied, + _private->plasmaShell.get(), + &PlasmaShell::destroy); + }); + + QObject::connect( + &_private->registry, + &Registry::appMenuAnnounced, + [=](uint name, uint version) { + _private->appMenuManager = std::unique_ptr{ + _private->registry.createAppMenuManager(name, version), + }; + + QObject::connect( + _private->connection.get(), + &ConnectionThread::connectionDied, + _private->appMenuManager.get(), + &AppMenuManager::destroy); + }); } WaylandIntegration::~WaylandIntegration() = default; @@ -153,20 +98,8 @@ WaylandIntegration *WaylandIntegration::Instance() { return &instance; } -void WaylandIntegration::waitForInterfaceAnnounce() { - Expects(!_private->interfacesLoop().isRunning()); - if (!_private->interfacesAnnounced()) { - _private->interfacesLoop().exec(); - } -} - -bool WaylandIntegration::supportsXdgDecoration() { - return _private->registry().hasInterface( - Registry::Interface::XdgDecorationUnstableV1); -} - QString WaylandIntegration::nativeHandle(QWindow *window) { - if (const auto exporter = _private->xdgExporter()) { + if (const auto exporter = _private->xdgExporter.get()) { if (const auto surface = Surface::fromWindow(window)) { if (const auto exported = exporter->exportTopLevel( surface, @@ -186,11 +119,11 @@ QString WaylandIntegration::nativeHandle(QWindow *window) { } bool WaylandIntegration::skipTaskbarSupported() { - return _private->plasmaShell(); + return _private->plasmaShell != nullptr; } void WaylandIntegration::skipTaskbar(QWindow *window, bool skip) { - const auto shell = _private->plasmaShell(); + const auto shell = _private->plasmaShell.get(); if (!shell) { return; } @@ -212,7 +145,7 @@ void WaylandIntegration::registerAppMenu( QWindow *window, const QString &serviceName, const QString &objectPath) { - const auto manager = _private->appMenuManager(); + const auto manager = _private->appMenuManager.get(); if (!manager) { return; } diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h index a37f10e34e..e6fa915cae 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.h @@ -13,8 +13,7 @@ namespace internal { class WaylandIntegration { public: [[nodiscard]] static WaylandIntegration *Instance(); - void waitForInterfaceAnnounce(); - [[nodiscard]] bool supportsXdgDecoration(); + [[nodiscard]] QString nativeHandle(QWindow *window); [[nodiscard]] bool skipTaskbarSupported(); void skipTaskbar(QWindow *window, bool skip); @@ -27,7 +26,7 @@ private: WaylandIntegration(); ~WaylandIntegration(); - class Private; + struct Private; const std::unique_ptr _private; }; diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp index 7ab26b1e2d..ffd6bace35 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration_dummy.cpp @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Platform { namespace internal { -class WaylandIntegration::Private { +struct WaylandIntegration::Private { }; WaylandIntegration::WaylandIntegration() { @@ -26,13 +26,6 @@ WaylandIntegration *WaylandIntegration::Instance() { return &instance; } -void WaylandIntegration::waitForInterfaceAnnounce() { -} - -bool WaylandIntegration::supportsXdgDecoration() { - return false; -} - QString WaylandIntegration::nativeHandle(QWindow *window) { return {}; } diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 2dcee5bb86..241a6ddaa7 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -971,7 +971,6 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) { } void MainWindow::unreadCounterChangedHook() { - setWindowTitle(titleText()); updateIconCounters(); } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 2247457e7c..eda7c0017b 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/platform/base_platform_info.h" #include "base/platform/linux/base_linux_glibmm_helper.h" #include "base/platform/linux/base_linux_gtk_integration.h" +#include "ui/platform/linux/ui_linux_wayland_integration.h" #include "platform/linux/linux_desktop_environment.h" #include "platform/linux/linux_gtk_integration.h" #include "platform/linux/linux_wayland_integration.h" @@ -60,6 +61,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL using namespace Platform; using BaseGtkIntegration = base::Platform::GtkIntegration; +using UiWaylandIntegration = Ui::Platform::WaylandIntegration; using Platform::internal::WaylandIntegration; using Platform::internal::GtkIntegration; @@ -799,7 +801,7 @@ void start() { } // wait for interface announce to know if native window frame is supported - if (const auto integration = WaylandIntegration::Instance()) { + if (const auto integration = UiWaylandIntegration::Instance()) { integration->waitForInterfaceAnnounce(); } diff --git a/Telegram/SourceFiles/platform/linux/window_title_linux.h b/Telegram/SourceFiles/platform/linux/window_title_linux.h deleted file mode 100644 index 3bfebc2360..0000000000 --- a/Telegram/SourceFiles/platform/linux/window_title_linux.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "platform/platform_window_title.h" -#include "platform/linux/linux_wayland_integration.h" -#include "base/object_ptr.h" - -namespace Window { -namespace Theme { - -int DefaultPreviewTitleHeight(); -void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth); - -} // namespace Theme -} // namespace Window - -namespace Platform { - -inline bool AllowNativeWindowFrameToggle() { - const auto waylandIntegration = internal::WaylandIntegration::Instance(); - return !waylandIntegration - || waylandIntegration->supportsXdgDecoration(); -} - -inline object_ptr CreateTitleWidget(QWidget *parent) { - return object_ptr(parent); -} - -inline bool NativeTitleRequiresShadow() { - return false; -} - -inline int PreviewTitleHeight() { - return Window::Theme::DefaultPreviewTitleHeight(); -} - -inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth) { - return Window::Theme::DefaultPreviewWindowFramePaint(preview, palette, body, outerWidth); -} - -} // namespace Platform diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.h b/Telegram/SourceFiles/platform/mac/main_window_mac.h index f81c1832ba..7588e863a4 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.h +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.h @@ -62,7 +62,6 @@ protected: void handleActiveChangedHook() override; void stateChangedHook(Qt::WindowState state) override; void initHook() override; - void titleVisibilityChangedHook() override; void unreadCounterChangedHook() override; bool hasTrayIcon() const override { @@ -80,9 +79,6 @@ protected: void psSetupTrayIcon(); virtual void placeSmallCounter(QImage &img, int size, int count, style::color bg, const QPoint &shift, style::color color) = 0; - QTimer psUpdatedPositionTimer; - - void initShadows() override; void closeWithoutDestroy() override; void createGlobalMenu() override; @@ -90,7 +86,6 @@ private: friend class Private; void hideAndDeactivate(); - void updateTitleCounter(); void updateIconCounters(); [[nodiscard]] QIcon generateIconForTray(int counter, bool muted) const; diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index aebe04d29e..5ef1318245 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -53,9 +53,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL - (void) darkModeChanged:(NSNotification *)aNotification; - (void) screenIsLocked:(NSNotification *)aNotification; - (void) screenIsUnlocked:(NSNotification *)aNotification; -- (void) windowWillEnterFullScreen:(NSNotification *)aNotification; -- (void) windowWillExitFullScreen:(NSNotification *)aNotification; -- (void) windowDidExitFullScreen:(NSNotification *)aNotification; @end // @interface MainWindowObserver @@ -67,43 +64,6 @@ namespace { // fullscreen mode, after that we'll hide the window no matter what. constexpr auto kHideAfterFullscreenTimeoutMs = 3000; -id FindClassInSubviews(NSView *parent, NSString *className) { - for (NSView *child in [parent subviews]) { - if ([child isKindOfClass:NSClassFromString(className)]) { - return child; - } else if (id inchild = FindClassInSubviews(child, className)) { - return inchild; - } - } - return nil; -} - -#ifndef OS_MAC_OLD - -class LayerCreationChecker : public QObject { -public: - LayerCreationChecker(NSView * __weak view, Fn callback) - : _weakView(view) - , _callback(std::move(callback)) { - QCoreApplication::instance()->installEventFilter(this); - } - -protected: - bool eventFilter(QObject *object, QEvent *event) override { - if (!_weakView || [_weakView layer] != nullptr) { - _callback(); - } - return QObject::eventFilter(object, event); - } - -private: - NSView * __weak _weakView = nil; - Fn _callback; - -}; - -#endif // OS_MAC_OLD - [[nodiscard]] QImage TrayIconBack(bool darkMode) { static const auto WithColor = [](QColor color) { return st::macTrayIcon.instance(color, 100); @@ -127,38 +87,16 @@ public: not_null controller, rpl::producer canApplyMarkdown); void setWindowBadge(const QString &str); - void setWindowTitle(const QString &str); - void updateNativeTitle(); - - void enableShadow(WId winId); - - void willEnterFullScreen(); - void willExitFullScreen(); - void didExitFullScreen(); bool clipboardHasText(); ~Private(); private: - void initCustomTitle(); - void refreshWeakTitleReferences(); - void enforceCorrectStyleMask(); - not_null _public; friend class MainWindow; -#ifdef OS_MAC_OLD - NSWindow *_nativeWindow = nil; - NSView *_nativeView = nil; -#else // OS_MAC_OLD NSWindow * __weak _nativeWindow = nil; NSView * __weak _nativeView = nil; - id __weak _nativeTitleWrapWeak = nil; - id __weak _nativeTitleWeak = nil; - std::unique_ptr _layerCreationChecker; -#endif // !OS_MAC_OLD - bool _useNativeTitle = false; - bool _inFullScreen = false; MainWindowObserver *_observer = nullptr; NSPasteboard *_generalPasteboard = nullptr; @@ -198,18 +136,6 @@ private: Core::App().setScreenIsLocked(false); } -- (void) windowWillEnterFullScreen:(NSNotification *)aNotification { - _private->willEnterFullScreen(); -} - -- (void) windowWillExitFullScreen:(NSNotification *)aNotification { - _private->willExitFullScreen(); -} - -- (void) windowDidExitFullScreen:(NSNotification *)aNotification { - _private->didExitFullScreen(); -} - @end // @implementation MainWindowObserver namespace Platform { @@ -256,15 +182,12 @@ void MainWindow::Private::setWindowBadge(const QString &str) { } } -void MainWindow::Private::setWindowTitle(const QString &str) { - _public->setWindowTitle(str); - updateNativeTitle(); -} - void MainWindow::Private::setNativeWindow(NSWindow *window, NSView *view) { _nativeWindow = window; _nativeView = view; - initCustomTitle(); + auto inner = [_nativeWindow contentLayoutRect]; + auto full = [_nativeView frame]; + _public->_customTitleHeight = qMax(qRound(full.size.height - inner.size.height), 0); } void MainWindow::Private::initTouchBar( @@ -288,119 +211,6 @@ void MainWindow::Private::initTouchBar( #endif } -void MainWindow::Private::initCustomTitle() { -#ifndef OS_MAC_OLD - if (![_nativeWindow respondsToSelector:@selector(contentLayoutRect)] - || ![_nativeWindow respondsToSelector:@selector(setTitlebarAppearsTransparent:)]) { - return; - } - [_nativeWindow setTitlebarAppearsTransparent:YES]; - - [[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:_nativeWindow]; - [[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:_nativeWindow]; - [[NSNotificationCenter defaultCenter] addObserver:_observer selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:_nativeWindow]; - - // Qt has bug with layer-backed widgets containing QOpenGLWidgets. - // See https://bugreports.qt.io/browse/QTBUG-64494 - // Emulate custom title instead (code below). - // - // Tried to backport a fix, testing. - [_nativeWindow setStyleMask:[_nativeWindow styleMask] | NSFullSizeContentViewWindowMask]; - auto inner = [_nativeWindow contentLayoutRect]; - auto full = [_nativeView frame]; - _public->_customTitleHeight = qMax(qRound(full.size.height - inner.size.height), 0); - - // Qt still has some bug with layer-backed widgets containing QOpenGLWidgets. - // See https://github.com/telegramdesktop/tdesktop/issues/4150 - // Tried to workaround it by catching the first moment we have CALayer created - // and explicitly setting contentsScale to window->backingScaleFactor there. - _layerCreationChecker = std::make_unique(_nativeView, [=] { - if (_nativeView && _nativeWindow) { - if (CALayer *layer = [_nativeView layer]) { - LOG(("Window Info: Setting layer scale factor to: %1").arg([_nativeWindow backingScaleFactor])); - [layer setContentsScale: [_nativeWindow backingScaleFactor]]; - _layerCreationChecker = nullptr; - } - } else { - _layerCreationChecker = nullptr; - } - }); - - // Disabled for now. - //_useNativeTitle = true; - //setWindowTitle(qsl("Telegram")); -#endif // !OS_MAC_OLD -} - -void MainWindow::Private::refreshWeakTitleReferences() { - if (!_nativeWindow) { - return; - } - -#ifndef OS_MAC_OLD - @autoreleasepool { - - if (NSView *parent = [[_nativeWindow contentView] superview]) { - if (id titleWrap = FindClassInSubviews(parent, Q2NSString(strTitleWrapClass()))) { - if ([titleWrap respondsToSelector:@selector(setBackgroundColor:)]) { - if (id title = FindClassInSubviews(titleWrap, Q2NSString(strTitleClass()))) { - if ([title respondsToSelector:@selector(setAttributedStringValue:)]) { - _nativeTitleWrapWeak = titleWrap; - _nativeTitleWeak = title; - } - } - } - } - } - - } -#endif // !OS_MAC_OLD -} - -void MainWindow::Private::updateNativeTitle() { - if (!_useNativeTitle) { - return; - } -#ifndef OS_MAC_OLD - if (!_nativeTitleWrapWeak || !_nativeTitleWeak) { - refreshWeakTitleReferences(); - } - if (_nativeTitleWrapWeak && _nativeTitleWeak) { - @autoreleasepool { - - auto convertColor = [](QColor color) { - return [NSColor colorWithDeviceRed:color.redF() green:color.greenF() blue:color.blueF() alpha:color.alphaF()]; - }; - auto adjustFg = [](const style::color &st) { - // Weird thing with NSTextField taking NSAttributedString with - // NSForegroundColorAttributeName set to colorWithDeviceRed:green:blue - // with components all equal to 128 - it ignores it and prints black text! - auto color = st->c; - return (color.red() == 128 && color.green() == 128 && color.blue() == 128) - ? QColor(129, 129, 129, color.alpha()) - : color; - }; - - auto active = _public->isActiveWindow(); - auto bgColor = (active ? st::titleBgActive : st::titleBg)->c; - auto fgColor = adjustFg(active ? st::titleFgActive : st::titleFg); - - auto bgConverted = convertColor(bgColor); - auto fgConverted = convertColor(fgColor); - [_nativeTitleWrapWeak setBackgroundColor:bgConverted]; - - auto title = Q2NSString(_public->windowTitle()); - NSDictionary *attributes = _inFullScreen - ? nil - : [NSDictionary dictionaryWithObjectsAndKeys: fgConverted, NSForegroundColorAttributeName, bgConverted, NSBackgroundColorAttributeName, nil]; - NSAttributedString *string = [[NSAttributedString alloc] initWithString:title attributes:attributes]; - [_nativeTitleWeak setAttributedStringValue:string]; - - } - } -#endif // !OS_MAC_OLD -} - bool MainWindow::Private::clipboardHasText() { auto currentChangeCount = static_cast([_generalPasteboard changeCount]); if (_generalPasteboardChangeCount != currentChangeCount) { @@ -410,32 +220,6 @@ bool MainWindow::Private::clipboardHasText() { return _generalPasteboardHasText; } -void MainWindow::Private::willEnterFullScreen() { - _inFullScreen = true; - _public->setTitleVisible(false); -} - -void MainWindow::Private::willExitFullScreen() { - _inFullScreen = false; - _public->setTitleVisible(true); - enforceCorrectStyleMask(); -} - -void MainWindow::Private::didExitFullScreen() { - enforceCorrectStyleMask(); -} - -void MainWindow::Private::enforceCorrectStyleMask() { - if (_nativeWindow && _public->_customTitleHeight > 0) { - [_nativeWindow setStyleMask:[_nativeWindow styleMask] | NSFullSizeContentViewWindowMask]; - } -} - -void MainWindow::Private::enableShadow(WId winId) { -// [[(NSView*)winId window] setStyleMask:NSBorderlessWindowMask]; -// [[(NSView*)winId window] setHasShadow:YES]; -} - MainWindow::Private::~Private() { [_observer release]; } @@ -449,11 +233,6 @@ MainWindow::MainWindow(not_null controller) #endif // !OS_MAC_OLD _hideAfterFullScreenTimer.setCallback([this] { hideAndDeactivate(); }); - - style::PaletteChanged( - ) | rpl::start_with_next([=] { - _private->updateNativeTitle(); - }, lifetime()); } void MainWindow::closeWithoutDestroy() { @@ -475,8 +254,6 @@ void MainWindow::stateChangedHook(Qt::WindowState state) { } void MainWindow::handleActiveChangedHook() { - InvokeQueued(this, [this] { _private->updateNativeTitle(); }); - // On macOS just remove trayIcon menu if the window is not active. // So we will activate the window on click instead of showing the menu. if (isActiveForTrayMenu()) { @@ -506,10 +283,6 @@ void MainWindow::initHook() { void MainWindow::updateWindowIcon() { } -void MainWindow::titleVisibilityChangedHook() { - updateTitleCounter(); -} - void MainWindow::hideAndDeactivate() { hide(); } @@ -591,12 +364,7 @@ void _placeCounter(QImage &img, int size, int count, style::color bg, style::col img.setDevicePixelRatio(savedRatio); } -void MainWindow::updateTitleCounter() { - _private->setWindowTitle(titleVisible() ? QString() : titleText()); -} - void MainWindow::unreadCounterChangedHook() { - updateTitleCounter(); updateIconCounters(); } @@ -649,10 +417,6 @@ QIcon MainWindow::generateIconForTray(int counter, bool muted) const { return result; } -void MainWindow::initShadows() { - _private->enableShadow(winId()); -} - void MainWindow::createGlobalMenu() { const auto ensureWindowShown = [=] { if (isHidden()) { diff --git a/Telegram/SourceFiles/platform/mac/window_title_mac.h b/Telegram/SourceFiles/platform/mac/window_title_mac.h deleted file mode 100644 index 924f7a440d..0000000000 --- a/Telegram/SourceFiles/platform/mac/window_title_mac.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "platform/platform_window_title.h" - -namespace Ui { -class PlainShadow; -} // namespace Ui - -namespace Platform { - -class MainWindow; - -class TitleWidget : public Window::TitleWidget { -public: - TitleWidget(MainWindow *parent, int height); - -protected: - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - void mouseDoubleClickEvent(QMouseEvent *e) override; - -private: - object_ptr _shadow; - QFont _font; - -}; - -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); - -} // namespace Platform diff --git a/Telegram/SourceFiles/platform/mac/window_title_mac.mm b/Telegram/SourceFiles/platform/mac/window_title_mac.mm index 6ccdcbd0e0..a332305301 100644 --- a/Telegram/SourceFiles/platform/mac/window_title_mac.mm +++ b/Telegram/SourceFiles/platform/mac/window_title_mac.mm @@ -5,83 +5,18 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "platform/mac/window_title_mac.h" +#include "platform/platform_window_title.h" -#include "mainwindow.h" -#include "ui/widgets/shadow.h" #include "ui/image/image_prepare.h" #include "core/application.h" #include "styles/style_window.h" #include "styles/style_media_view.h" -#include "platform/platform_main_window.h" #include "window/window_controller.h" #include -#include namespace Platform { -TitleWidget::TitleWidget(MainWindow *parent, int height) -: Window::TitleWidget(parent) -, _shadow(this, st::titleShadow) { - setAttribute(Qt::WA_OpaquePaintEvent); - resize(width(), height); - -#ifndef OS_MAC_OLD - QStringList families = { qsl(".SF NS Text"), qsl("Helvetica Neue") }; - for (auto family : families) { - _font.setFamily(family); - if (QFontInfo(_font).family() == _font.family()) { - break; - } - } -#endif // OS_MAC_OLD - - if (QFontInfo(_font).family() == _font.family()) { - _font.setPixelSize((height * 15) / 24); - } else { - _font = st::normalFont; - } - - Core::App().unreadBadgeChanges( - ) | rpl::start_with_next([=] { - update(); - }, lifetime()); -} - -void TitleWidget::paintEvent(QPaintEvent *e) { - Painter p(this); - - auto active = isActiveWindow(); - p.fillRect(rect(), active ? st::titleBgActive : st::titleBg); - - p.setFont(_font); - p.setPen(active ? st::titleFgActive : st::titleFg); - p.drawText(rect(), static_cast(parentWidget())->titleText(), style::al_center); -} - -void TitleWidget::resizeEvent(QResizeEvent *e) { - _shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth); -} - -void TitleWidget::mouseDoubleClickEvent(QMouseEvent *e) { - auto window = parentWidget(); - if (window->windowState() == Qt::WindowMaximized) { - window->setWindowState(Qt::WindowNoState); - } else { - window->setWindowState(Qt::WindowMaximized); - } -} - -object_ptr CreateTitleWidget(QWidget *parent) { - if (auto window = qobject_cast(parent)) { - if (auto height = window->getCustomTitleHeight()) { - return object_ptr(window, height); - } - } - return { nullptr }; -} - // All the window decorations preview is done without taking cScale() into // account, with 100% scale and without "px" dimensions, because thats // how it will look in real launched macOS app. diff --git a/Telegram/SourceFiles/platform/platform_window_title.h b/Telegram/SourceFiles/platform/platform_window_title.h index 8c70e8fa16..d0002f9a39 100644 --- a/Telegram/SourceFiles/platform/platform_window_title.h +++ b/Telegram/SourceFiles/platform/platform_window_title.h @@ -7,16 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "window/window_title.h" -#include "window/window_title_qt.h" #include "window/themes/window_theme_preview.h" -#include "base/object_ptr.h" +#include "base/platform/base_platform_info.h" namespace Platform { -bool AllowNativeWindowFrameToggle(); -object_ptr CreateTitleWidget(QWidget *parent); -bool NativeTitleRequiresShadow(); +inline bool NativeTitleRequiresShadow() { + return Platform::IsWindows(); +} int PreviewTitleHeight(); void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth); @@ -25,28 +23,10 @@ void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRe // Platform dependent implementations. -#ifdef Q_OS_MAC -#include "platform/mac/window_title_mac.h" -#elif defined Q_OS_WIN // Q_OS_MAC -#include "platform/win/window_title_win.h" -#elif defined Q_OS_UNIX // Q_OS_MAC || Q_OS_WIN -#include "platform/linux/window_title_linux.h" -#else // Q_OS_MAC || Q_OS_WIN || Q_OS_UNIX +#ifndef Q_OS_MAC namespace Platform { -inline bool AllowNativeWindowFrameToggle() { - return true; -} - -inline object_ptr CreateTitleWidget(QWidget *parent) { - return object_ptr(parent); -} - -inline bool NativeTitleRequiresShadow() { - return false; -} - inline int PreviewTitleHeight() { return Window::Theme::DefaultPreviewTitleHeight(); } @@ -57,4 +37,4 @@ inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palet } // namespace Platform -#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_UNIX +#endif // !Q_OS_MAC diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index c1895dad87..27e1bfbc86 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -43,8 +43,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL HICON qt_pixmapToWinHICON(const QPixmap &); -Q_DECLARE_METATYPE(QMargins); - namespace ViewManagement = ABI::Windows::UI::ViewManagement; namespace Platform { @@ -122,12 +120,6 @@ MainWindow::MainWindow(not_null controller) if (!kTaskbarCreatedMsgId) { kTaskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); } - style::PaletteChanged( - ) | rpl::start_with_next([=] { - if (_shadow) { - _shadow->setColor(st::windowShadowFg->c); - } - }, lifetime()); setupNativeWindowFrame(); using namespace rpl::mappers; @@ -163,15 +155,7 @@ void MainWindow::setupNativeWindowFrame() { std::move(nativeFrame), std::move(nightMode) ) | rpl::skip(1) | rpl::start_with_next([=](bool native, bool night) { - const auto nativeChanged = (_wasNativeFrame != native); - if (nativeChanged) { - _wasNativeFrame = native; - initShadows(); - } validateWindowTheme(native, night); - if (nativeChanged) { - fixMaximizedWindow(); - } }, lifetime()); } @@ -186,23 +170,12 @@ void MainWindow::TaskbarCreated() { } } -void MainWindow::shadowsUpdate( - Ui::Platform::WindowShadow::Changes changes, - WINDOWPOS *position) { - if (_shadow) { - _shadow->update(changes, position); - } -} - void MainWindow::shadowsActivate() { _hasActiveFrame = true; -// _shadow->setColor(_shActive); - shadowsUpdate(Ui::Platform::WindowShadow::Change::Activate); } void MainWindow::shadowsDeactivate() { _hasActiveFrame = false; -// _shadow->setColor(_shInactive); } void MainWindow::psShowTrayMenu() { @@ -327,7 +300,7 @@ bool MainWindow::initSizeFromSystem() { if (!screen) { return false; } - setGeometry(screen->availableGeometry()); + Ui::RpWidget::setGeometry(screen->availableGeometry()); return true; } @@ -356,7 +329,6 @@ bool MainWindow::isActiveForTrayMenu() { } void MainWindow::unreadCounterChangedHook() { - setWindowTitle(titleText()); updateIconCounters(); } @@ -437,147 +409,9 @@ void MainWindow::initHook() { } } - psInitSysMenu(); -} - -void MainWindow::initShadows() { - if (Core::App().settings().nativeWindowFrame()) { - _shadow.reset(); - } else { - _shadow.emplace(this, st::windowShadowFg->c); - } - updateCustomMargins(); - firstShadowsUpdate(); -} - -void MainWindow::firstShadowsUpdate() { - using Change = Ui::Platform::WindowShadow::Change; - if ((windowState() & (Qt::WindowMinimized | Qt::WindowMaximized)) - || isHidden()) { - shadowsUpdate(Change::Hidden); - } else { - shadowsUpdate(Change::Moved | Change::Resized | Change::Shown); - } -} - -void MainWindow::stateChangedHook(Qt::WindowState state) { - updateSystemMenu(state); -} - -void MainWindow::psInitSysMenu() { - Qt::WindowStates states = windowState(); - ps_menu = GetSystemMenu(ps_hWnd, FALSE); - updateSystemMenu(windowHandle()->windowState()); -} - -void MainWindow::updateSystemMenu(Qt::WindowState state) { - if (!ps_menu) return; - - int menuToDisable = SC_RESTORE; - if (state == Qt::WindowMaximized) { - menuToDisable = SC_MAXIMIZE; - } else if (state == Qt::WindowMinimized) { - menuToDisable = SC_MINIMIZE; - } - int itemCount = GetMenuItemCount(ps_menu); - for (int i = 0; i < itemCount; ++i) { - MENUITEMINFO itemInfo = { 0 }; - itemInfo.cbSize = sizeof(itemInfo); - itemInfo.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID; - if (GetMenuItemInfo(ps_menu, i, TRUE, &itemInfo)) { - if (itemInfo.fType & MFT_SEPARATOR) { - continue; - } - if (itemInfo.wID && !(itemInfo.fState & MFS_DEFAULT)) { - UINT fOldState = itemInfo.fState, fState = itemInfo.fState & ~MFS_DISABLED; - if (itemInfo.wID == SC_CLOSE) { - fState |= MFS_DEFAULT; - } else if (itemInfo.wID == menuToDisable || (itemInfo.wID != SC_MINIMIZE && itemInfo.wID != SC_MAXIMIZE && itemInfo.wID != SC_RESTORE)) { - fState |= MFS_DISABLED; - } - itemInfo.fMask = MIIM_STATE; - itemInfo.fState = fState; - if (!SetMenuItemInfo(ps_menu, i, TRUE, &itemInfo)) { - DEBUG_LOG(("PS Error: could not set state %1 to menu item %2, old state %3, error %4").arg(fState).arg(itemInfo.wID).arg(fOldState).arg(GetLastError())); - DestroyMenu(ps_menu); - ps_menu = 0; - break; - } - } - } else { - DEBUG_LOG(("PS Error: could not get state, menu item %1 of %2, error %3").arg(i).arg(itemCount).arg(GetLastError())); - DestroyMenu(ps_menu); - ps_menu = 0; - break; - } - } -} - -void MainWindow::updateCustomMargins() { - if (!ps_hWnd || _inUpdateMargins) { - return; - } - - _inUpdateMargins = true; - - const auto margins = computeCustomMargins(); - if (const auto native = QGuiApplication::platformNativeInterface()) { - native->setWindowProperty( - windowHandle()->handle(), - qsl("WindowsCustomMargins"), - QVariant::fromValue(margins)); - } - if (!_themeInited) { - _themeInited = true; - validateWindowTheme( - Core::App().settings().nativeWindowFrame(), - Window::Theme::IsNightMode()); - } - _inUpdateMargins = false; -} - -QMargins MainWindow::computeCustomMargins() { - if (Core::App().settings().nativeWindowFrame()) { - _deltaLeft = _deltaTop = _deltaRight = _deltaBottom = 0; - return QMargins(); - } - auto r = RECT(); - GetClientRect(ps_hWnd, &r); - - auto a = r; - const auto style = GetWindowLongPtr(ps_hWnd, GWL_STYLE); - const auto styleEx = GetWindowLongPtr(ps_hWnd, GWL_EXSTYLE); - AdjustWindowRectEx(&a, style, false, styleEx); - 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); - m = w; - - HMONITOR hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST); - if (hMonitor) { - MONITORINFO mi; - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - m = mi.rcWork; - } - - _deltaLeft = w.left - m.left; - _deltaTop = w.top - m.top; - _deltaRight = m.right - w.right; - _deltaBottom = m.bottom - w.bottom; - - margins.setLeft(margins.left() - _deltaLeft); - margins.setRight(margins.right() - _deltaRight); - margins.setBottom(margins.bottom() - _deltaBottom); - margins.setTop(margins.top() - _deltaTop); - } else if (_deltaLeft != 0 || _deltaTop != 0 || _deltaRight != 0 || _deltaBottom != 0) { - RECT w; - GetWindowRect(ps_hWnd, &w); - 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; + validateWindowTheme( + Core::App().settings().nativeWindowFrame(), + Window::Theme::IsNightMode()); } void MainWindow::validateWindowTheme(bool native, bool night) { @@ -673,25 +507,6 @@ void MainWindow::validateWindowTheme(bool native, bool night) { SendMessage(ps_hWnd, WM_NCACTIVATE, _hasActiveFrame ? 1 : 0, 0); } -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); - } - } -} - void MainWindow::showFromTrayMenu() { // If we try to activate() window before the trayIconMenu is hidden, // then the window will be shown in semi-active state (Qt bug). @@ -707,10 +522,6 @@ HWND MainWindow::psHwnd() const { return ps_hWnd; } -HMENU MainWindow::psMenu() const { - return ps_menu; -} - void MainWindow::psDestroyIcons() { if (ps_iconBig) { DestroyIcon(ps_iconBig); @@ -735,7 +546,6 @@ MainWindow::~MainWindow() { taskbarList.Reset(); } - if (ps_menu) DestroyMenu(ps_menu); psDestroyIcons(); if (ps_tbHider_hWnd) DestroyWindow(ps_tbHider_hWnd); diff --git a/Telegram/SourceFiles/platform/win/main_window_win.h b/Telegram/SourceFiles/platform/win/main_window_win.h index de82180759..dfc958d98a 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.h +++ b/Telegram/SourceFiles/platform/win/main_window_win.h @@ -8,12 +8,9 @@ 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" -#include - namespace Ui { class PopupMenu; } // namespace Ui @@ -27,11 +24,6 @@ public: void showFromTrayMenu() override; HWND psHwnd() const; - HMENU psMenu() const; - - void psInitSysMenu(); - void updateSystemMenu(Qt::WindowState state); - void updateCustomMargins(); void updateWindowIcon() override; bool isActiveForTrayMenu() override; @@ -46,16 +38,6 @@ public: // Custom shadows. void shadowsActivate(); void shadowsDeactivate(); - void shadowsUpdate( - Ui::Platform::WindowShadow::Changes changes, - WINDOWPOS *position = nullptr); - - int deltaLeft() const { - return _deltaLeft; - } - int deltaTop() const { - return _deltaTop; - } [[nodiscard]] bool hasTabletView() const; @@ -68,10 +50,6 @@ protected: int32 screenNameChecksum(const QString &name) const override; void unreadCounterChangedHook() override; - void initShadows() override; - void firstShadowsUpdate() override; - void stateChangedHook(Qt::WindowState state) override; - bool hasTrayIcon() const override { return trayIcon; } @@ -91,25 +69,16 @@ protected: QRect computeDesktopRect() const override; - QTimer psUpdatedPositionTimer; - private: struct Private; void setupNativeWindowFrame(); void updateIconCounters(); - QMargins computeCustomMargins(); void validateWindowTheme(bool native, bool night); void psDestroyIcons(); - void fixMaximizedWindow(); const std::unique_ptr _private; - std::optional _shadow; - - bool _themeInited = false; - bool _inUpdateMargins = false; - bool _wasNativeFrame = false; bool _hasActiveFrame = false; // Workarounds for activation from tray icon. @@ -118,16 +87,10 @@ private: HWND ps_hWnd = nullptr; HWND ps_tbHider_hWnd = nullptr; - HMENU ps_menu = nullptr; HICON ps_iconBig = nullptr; HICON ps_iconSmall = nullptr; HICON ps_iconOverlay = nullptr; - int _deltaLeft = 0; - int _deltaTop = 0; - int _deltaRight = 0; - int _deltaBottom = 0; - }; } // namespace Platform diff --git a/Telegram/SourceFiles/platform/win/window_title_win.cpp b/Telegram/SourceFiles/platform/win/window_title_win.cpp deleted file mode 100644 index 80df1d90d5..0000000000 --- a/Telegram/SourceFiles/platform/win/window_title_win.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "platform/win/window_title_win.h" - -#include "ui/widgets/buttons.h" -#include "ui/widgets/shadow.h" -#include "styles/style_window.h" - -#include - -namespace Platform { - -TitleWidget::TitleWidget(QWidget *parent) -: Window::TitleWidget(parent) -, _st(st::defaultWindowTitle) -, _minimize(this, _st.minimize) -, _maximizeRestore(this, _st.maximize) -, _close(this, _st.close) -, _shadow(this, st::titleShadow) -, _maximizedState(parent->window()->windowState() & Qt::WindowMaximized) { - _minimize->setClickedCallback([=] { - window()->setWindowState( - window()->windowState() | Qt::WindowMinimized); - _minimize->clearState(); - }); - _minimize->setPointerCursor(false); - _maximizeRestore->setClickedCallback([=] { - window()->setWindowState(_maximizedState - ? Qt::WindowNoState - : Qt::WindowMaximized); - _maximizeRestore->clearState(); - }); - _maximizeRestore->setPointerCursor(false); - _close->setClickedCallback([=] { - window()->close(); - _close->clearState(); - }); - _close->setPointerCursor(false); - - setAttribute(Qt::WA_OpaquePaintEvent); - resize(width(), _st.height); -} - -void TitleWidget::init() { - connect( - window()->windowHandle(), - &QWindow::windowStateChanged, - this, - [=](Qt::WindowState state) { windowStateChanged(state); }); - _maximizedState = (window()->windowState() & Qt::WindowMaximized); - _activeState = isActiveWindow(); - updateButtonsState(); -} - -void TitleWidget::paintEvent(QPaintEvent *e) { - auto active = isActiveWindow(); - if (_activeState != active) { - _activeState = active; - updateButtonsState(); - } - Painter(this).fillRect(rect(), active ? _st.bgActive : _st.bg); -} - -void TitleWidget::updateControlsPosition() { - auto right = 0; - _close->moveToRight(right, 0); right += _close->width(); - _maximizeRestore->moveToRight(right, 0); right += _maximizeRestore->width(); - _minimize->moveToRight(right, 0); -} - -void TitleWidget::resizeEvent(QResizeEvent *e) { - updateControlsPosition(); - _shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth); -} - -void TitleWidget::windowStateChanged(Qt::WindowState state) { - if (state == Qt::WindowMinimized) { - return; - } - - const auto maximized = (state == Qt::WindowMaximized); - if (_maximizedState != maximized) { - _maximizedState = maximized; - updateButtonsState(); - } -} - -void TitleWidget::updateButtonsState() { - _minimize->setIconOverride(_activeState - ? &_st.minimizeIconActive - : nullptr, - _activeState - ? &_st.minimizeIconActiveOver - : nullptr); - if (_maximizedState) { - _maximizeRestore->setIconOverride( - _activeState - ? &_st.restoreIconActive : &_st.restoreIcon, - _activeState - ? &_st.restoreIconActiveOver - : &_st.restoreIconOver); - } else { - _maximizeRestore->setIconOverride(_activeState - ? &_st.maximizeIconActive - : nullptr, - _activeState - ? &_st.maximizeIconActiveOver - : nullptr); - } - _close->setIconOverride(_activeState - ? &_st.closeIconActive - : nullptr, - _activeState - ? &_st.closeIconActiveOver - : nullptr); -} - -Window::HitTestResult TitleWidget::hitTest(const QPoint &p) const { - if (false - || (_minimize->geometry().contains(p)) - || (_maximizeRestore->geometry().contains(p)) - || (_close->geometry().contains(p)) - ) { - return Window::HitTestResult::SysButton; - } else if (rect().contains(p)) { - return Window::HitTestResult::Caption; - } - return Window::HitTestResult::None; -} - -} // namespace Platform diff --git a/Telegram/SourceFiles/platform/win/window_title_win.h b/Telegram/SourceFiles/platform/win/window_title_win.h deleted file mode 100644 index 9508e508b4..0000000000 --- a/Telegram/SourceFiles/platform/win/window_title_win.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "platform/platform_window_title.h" -#include "base/object_ptr.h" - -namespace style { -struct WindowTitle; -} // namespace style - -namespace Ui { -class IconButton; -class PlainShadow; -} // namespace Ui - -namespace Window { -namespace Theme { - -int DefaultPreviewTitleHeight(); -void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth); - -} // namespace Theme -} // namespace Window - -namespace Platform { - -class TitleWidget : public Window::TitleWidget { -public: - TitleWidget(QWidget *parent); - - void init() override; - - [[nodiscard]] Window::HitTestResult hitTest( - const QPoint &p) const override; - -protected: - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - -private: - void windowStateChanged(Qt::WindowState state = Qt::WindowNoState); - void updateButtonsState(); - void updateControlsPosition(); - - const style::WindowTitle &_st; - object_ptr _minimize; - object_ptr _maximizeRestore; - object_ptr _close; - object_ptr _shadow; - - bool _maximizedState = false; - bool _activeState = false; - -}; - -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(); -} - -inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRect body, int outerWidth) { - return Window::Theme::DefaultPreviewWindowFramePaint(preview, palette, body, outerWidth); -} - -} // namespace Platform diff --git a/Telegram/SourceFiles/platform/win/windows_dlls.cpp b/Telegram/SourceFiles/platform/win/windows_dlls.cpp index 7a461ca303..a9d11138f9 100644 --- a/Telegram/SourceFiles/platform/win/windows_dlls.cpp +++ b/Telegram/SourceFiles/platform/win/windows_dlls.cpp @@ -63,7 +63,6 @@ SafeIniter::SafeIniter() { LOAD_SYMBOL(LibPropSys, PSStringFromPropertyKey); const auto LibDwmApi = LoadLibrary(L"dwmapi.dll"); - LOAD_SYMBOL(LibDwmApi, DwmIsCompositionEnabled); LOAD_SYMBOL(LibDwmApi, DwmSetWindowAttribute); const auto LibPsApi = LoadLibrary(L"psapi.dll"); diff --git a/Telegram/SourceFiles/platform/win/windows_dlls.h b/Telegram/SourceFiles/platform/win/windows_dlls.h index c28c063844..18719727e9 100644 --- a/Telegram/SourceFiles/platform/win/windows_dlls.h +++ b/Telegram/SourceFiles/platform/win/windows_dlls.h @@ -96,8 +96,6 @@ inline HRESULT(__stdcall *PSStringFromPropertyKey)( // DWMAPI.DLL -inline HRESULT(__stdcall *DwmIsCompositionEnabled)( - _Out_ BOOL* pfEnabled); inline HRESULT(__stdcall *DwmSetWindowAttribute)( HWND hwnd, DWORD dwAttribute, diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp index eab91c48d5..4d0127bbb9 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -7,12 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "platform/win/windows_event_filter.h" -#include "platform/win/windows_dlls.h" #include "platform/win/specific_win.h" #include "core/sandbox.h" #include "core/core_settings.h" #include "core/application.h" -#include "ui/inactive_press.h" #include "mainwindow.h" #include "app.h" @@ -23,67 +21,6 @@ namespace { EventFilter *instance = nullptr; -int menuShown = 0, menuHidden = 0; - -bool IsCompositionEnabled() { - if (!Dlls::DwmIsCompositionEnabled) { - return false; - } - auto result = BOOL(FALSE); - const auto success = (Dlls::DwmIsCompositionEnabled(&result) == S_OK); - return success && result; -} - -HWND FindTaskbarWindow(LPRECT rcMon = nullptr) { - HWND hTaskbar = nullptr; - RECT rcTaskbar, rcMatch; - - while ((hTaskbar = FindWindowEx( - nullptr, - hTaskbar, - L"Shell_TrayWnd", - nullptr)) != nullptr) { - if (!rcMon) { - break; // OK, return first found - } - if (GetWindowRect(hTaskbar, &rcTaskbar) - && IntersectRect(&rcMatch, &rcTaskbar, rcMon)) { - break; // OK, taskbar match monitor - } - } - - return hTaskbar; -} - -bool IsTaskbarAutoHidden(LPRECT rcMon = nullptr, PUINT pEdge = nullptr) { - HWND hTaskbar = FindTaskbarWindow(rcMon); - if (!hTaskbar) { - if (pEdge) { - *pEdge = (UINT)-1; - } - return false; - } - - APPBARDATA state = {sizeof(state), hTaskbar}; - APPBARDATA pos = {sizeof(pos), hTaskbar}; - - LRESULT lState = SHAppBarMessage(ABM_GETSTATE, &state); - bool bAutoHidden = (lState & ABS_AUTOHIDE); - - if (SHAppBarMessage(ABM_GETTASKBARPOS, &pos)) { - if (pEdge) { - *pEdge = pos.uEdge; - } - } else { - LOG(("Failed to get taskbar pos")); - if (pEdge) { - *pEdge = ABE_BOTTOM; - } - } - - return bAutoHidden; -} - } // namespace EventFilter *EventFilter::CreateInstance(not_null window) { @@ -125,108 +62,18 @@ 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; - UINT uEdge = (UINT)-1; - if (IsTaskbarAutoHidden(&mi.rcMonitor, &uEdge)) { - switch (uEdge) { - case ABE_LEFT: r->left += 1; break; - case ABE_RIGHT: r->right -= 1; break; - case ABE_TOP: r->top += 1; break; - case ABE_BOTTOM: r->bottom -= 1; break; - } - } - } - } - } - 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, 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: { @@ -246,91 +93,25 @@ bool EventFilter::mainWindowEvent( } return false; case WM_ACTIVATE: { - if (LOWORD(wParam) == WA_CLICKACTIVE) { - Ui::MarkInactivePress(_window, true); - } if (LOWORD(wParam) != WA_INACTIVE) { _window->shadowsActivate(); } else { _window->shadowsDeactivate(); } - _window->update(); - } return false; - - case WM_WINDOWPOSCHANGING: - case WM_WINDOWPOSCHANGED: { - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - if (_window->hasTabletView() - || (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; - } - _window->windowHandle()->windowStateChanged(state); - } else { + if (wParam == SIZE_RESTORED && _window->windowState() == Qt::WindowNoState) { _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) { - POINTS p = MAKEPOINTS(lParam); - _window->updateSystemMenu(_window->windowHandle()->windowState()); - TrackPopupMenu(_window->psMenu(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, p.x, p.y, 0, hWnd, 0); - } - } return false; - - case WM_COMMAND: { - if (HIWORD(wParam)) { - return false; - } - int cmd = LOWORD(wParam); - switch (cmd) { - case SC_CLOSE: - _window->close(); - return true; - case SC_MINIMIZE: - _window->setWindowState( - _window->windowState() | Qt::WindowMinimized); - return true; - case SC_MAXIMIZE: - _window->setWindowState(Qt::WindowMaximized); - return true; - case SC_RESTORE: - _window->setWindowState(Qt::WindowNoState); - return true; - } - } return true; - case WM_SETTINGCHANGE: { Core::App().settings().setSystemDarkMode(Platform::IsDarkMode()); } return false; diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.h b/Telegram/SourceFiles/platform/win/windows_event_filter.h index de48509ff9..c313f29cf7 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.h +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.h @@ -26,13 +26,6 @@ public: private: explicit EventFilter(not_null window); - bool customWindowFrameEvent( - HWND hWnd, - UINT msg, - WPARAM wParam, - LPARAM lParam, - LRESULT *result); - not_null _window; }; diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index 0060c56fef..7eabb47e65 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -22,7 +22,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 "ui/platform/ui_platform_window.h" #include "base/platform/base_platform_info.h" #include "window/window_controller.h" #include "window/window_session_controller.h" @@ -406,7 +406,7 @@ void SetupSystemIntegrationContent( }, taskbar->lifetime()); } } - if (Platform::AllowNativeWindowFrameToggle()) { + if (Ui::Platform::NativeWindowFrameSupported()) { const auto nativeFrame = addCheckbox( tr::lng_settings_native_frame(), Core::App().settings().nativeWindowFrame()); diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 4c3eeca0db..40db1f0a26 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -9,9 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/localstorage.h" #include "platform/platform_specific.h" +#include "ui/platform/ui_platform_window.h" #include "platform/platform_window_title.h" #include "base/platform/base_platform_info.h" -#include "ui/platform/ui_platform_utility.h" #include "history/history.h" #include "window/window_session_controller.h" #include "window/window_lock_widgets.h" @@ -161,9 +161,8 @@ QIcon CreateIcon(Main::Session *session) { MainWindow::MainWindow(not_null controller) : _controller(controller) , _positionUpdatedTimer([=] { savePosition(); }) -, _outdated(CreateOutdatedBar(this)) -, _body(this) -, _titleText(qsl("Telegram")) { +, _outdated(CreateOutdatedBar(body())) +, _body(body()) { style::PaletteChanged( ) | rpl::start_with_next([=] { updatePalette(); @@ -266,8 +265,6 @@ QRect MainWindow::desktopRect() const { } void MainWindow::init() { - Expects(!windowHandle()); - createWinId(); initHook(); @@ -293,7 +290,7 @@ void MainWindow::init() { updatePalette(); - if (Platform::AllowNativeWindowFrameToggle()) { + if (Ui::Platform::NativeWindowFrameSupported()) { Core::App().settings().nativeWindowFrameChanges( ) | rpl::start_with_next([=](bool native) { refreshTitleWidget(); @@ -308,7 +305,6 @@ void MainWindow::init() { void MainWindow::handleStateChanged(Qt::WindowState state) { stateChangedHook(state); - updateShadowSize(); updateControlsGeometry(); if (state == Qt::WindowMinimized) { controller().updateIsActiveBlur(); @@ -381,27 +377,6 @@ void MainWindow::updatePalette() { setPalette(p); } -HitTestResult MainWindow::hitTest(const QPoint &p) const { - auto titleResult = _title ? _title->hitTest(p - _title->geometry().topLeft()) : Window::HitTestResult::None; - if (titleResult != Window::HitTestResult::None) { - return titleResult; - } else if (rect().contains(p)) { - return Window::HitTestResult::Client; - } - return Window::HitTestResult::None; -} - -bool MainWindow::hasShadow() const { - const auto center = geometry().center(); - return Ui::Platform::WindowExtentsSupported() - && Ui::Platform::TranslucentWindowsSupported(center) - && _title; -} - -QRect MainWindow::inner() const { - return rect().marginsRemoved(_padding); -} - int MainWindow::computeMinWidth() const { auto result = st::windowMinWidth; if (const auto session = _controller->sessionController()) { @@ -412,38 +387,32 @@ int MainWindow::computeMinWidth() const { if (_rightColumn) { result += _rightColumn->width(); } - return result + _padding.left() + _padding.right(); + return result; } int MainWindow::computeMinHeight() const { - const auto title = _title ? _title->height() : 0; const auto outdated = [&] { if (!_outdated) { return 0; } - _outdated->resizeToWidth(st::windowMinWidth - _padding.left() - _padding.right()); + _outdated->resizeToWidth(st::windowMinWidth); return _outdated->height(); }(); - return title + outdated + st::windowMinHeight + _padding.top() + _padding.bottom(); + return outdated + st::windowMinHeight; } void MainWindow::refreshTitleWidget() { - if (Platform::AllowNativeWindowFrameToggle() + if (Ui::Platform::NativeWindowFrameSupported() && Core::App().settings().nativeWindowFrame()) { - _title.destroy(); + setNativeFrame(true); if (Platform::NativeTitleRequiresShadow()) { _titleShadow.create(this); _titleShadow->show(); } - } else if ((_title = Platform::CreateTitleWidget(this))) { - _title->show(); - _title->init(); + } else { + setNativeFrame(false); _titleShadow.destroy(); } - - const auto withShadow = hasShadow(); - windowHandle()->setFlag(Qt::NoDropShadowWindowHint, withShadow); - setAttribute(Qt::WA_OpaquePaintEvent, !withShadow); } void MainWindow::updateMinimumSize() { @@ -451,21 +420,13 @@ void MainWindow::updateMinimumSize() { setMinimumHeight(computeMinHeight()); } -void MainWindow::updateShadowSize() { - _padding = hasShadow() && !isMaximized() - ? st::callShadow.extend - : style::margins(); -} - void MainWindow::recountGeometryConstraints() { - updateShadowSize(); updateMinimumSize(); updateControlsGeometry(); fixOrder(); } void MainWindow::initSize() { - updateShadowSize(); updateMinimumSize(); if (initSizeFromSystem()) { @@ -565,7 +526,6 @@ void MainWindow::initSize() { } } } - geometry += _padding; DEBUG_LOG(("Window Pos: Setting first %1, %2, %3, %4").arg(geometry.x()).arg(geometry.y()).arg(geometry.width()).arg(geometry.height())); setGeometry(geometry); } @@ -574,18 +534,6 @@ void MainWindow::positionUpdated() { _positionUpdatedTimer.callOnce(kSaveWindowPositionTimeout); } -bool MainWindow::titleVisible() const { - return _title && !_title->isHidden(); -} - -void MainWindow::setTitleVisible(bool visible) { - if (_title && (_title->isHidden() == visible)) { - _title->setVisible(visible); - updateControlsGeometry(); - } - titleVisibilityChangedHook(); -} - int32 MainWindow::screenNameChecksum(const QString &name) const { const auto bytes = name.toUtf8(); return base::crc32(bytes.constData(), bytes.size()); @@ -605,15 +553,7 @@ void MainWindow::attachToTrayIcon(not_null icon) { }); } -void MainWindow::paintEvent(QPaintEvent *e) { - if (hasShadow() && !isMaximized()) { - QPainter p(this); - Ui::Shadow::paint(p, inner(), width(), st::callShadow); - } -} - void MainWindow::resizeEvent(QResizeEvent *e) { - updateShadowSize(); updateControlsGeometry(); } @@ -626,14 +566,10 @@ void MainWindow::leaveEventHook(QEvent *e) { } void MainWindow::updateControlsGeometry() { - const auto inner = this->inner(); + const auto inner = body()->rect(); auto bodyLeft = inner.x(); auto bodyTop = inner.y(); auto bodyWidth = inner.width(); - if (_title && !_title->isHidden()) { - _title->setGeometry(inner.x(), bodyTop, inner.width(), _title->height()); - bodyTop += _title->height(); - } if (_titleShadow) { _titleShadow->setGeometry(inner.x(), bodyTop, inner.width(), st::lineWidth); } @@ -656,7 +592,7 @@ void MainWindow::updateUnreadCounter() { } const auto counter = Core::App().unreadBadge(); - _titleText = (counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram"); + setTitle((counter > 0) ? qsl("Telegram (%1)").arg(counter) : qsl("Telegram")); unreadCounterChangedHook(); } @@ -683,7 +619,7 @@ void MainWindow::savePosition(Qt::WindowState state) { realPosition.maximized = 1; DEBUG_LOG(("Window Pos: Saving maximized position.")); } else { - auto r = geometry().marginsRemoved(_padding); + auto r = body()->mapToGlobal(body()->rect()); realPosition.x = r.x(); realPosition.y = r.y(); realPosition.w = r.width() - (_rightColumn ? _rightColumn->width() : 0); @@ -774,7 +710,7 @@ void MainWindow::showRightColumn(object_ptr widget) { const auto wasRightWidth = _rightColumn ? _rightColumn->width() : 0; _rightColumn = std::move(widget); if (_rightColumn) { - _rightColumn->setParent(this); + _rightColumn->setParent(body()); _rightColumn->show(); _rightColumn->setFocus(); } else { @@ -799,12 +735,12 @@ void MainWindow::showRightColumn(object_ptr widget) { int MainWindow::maximalExtendBy() const { auto desktop = QDesktopWidget().availableGeometry(this); - return std::max(desktop.width() - inner().width(), 0); + return std::max(desktop.width() - body()->width(), 0); } bool MainWindow::canExtendNoMove(int extendBy) const { auto desktop = QDesktopWidget().availableGeometry(this); - auto inner = geometry().marginsRemoved(_padding); + auto inner = body()->mapToGlobal(body()->rect()); auto innerRight = (inner.x() + inner.width() + extendBy); auto desktopRight = (desktop.x() + desktop.width()); return innerRight <= desktopRight; @@ -812,7 +748,7 @@ bool MainWindow::canExtendNoMove(int extendBy) const { int MainWindow::tryToExtendWidthBy(int addToWidth) { auto desktop = QDesktopWidget().availableGeometry(this); - auto inner = geometry(); + auto inner = body()->mapToGlobal(body()->rect()); accumulate_min( addToWidth, std::max(desktop.width() - inner.width(), 0)); @@ -821,7 +757,7 @@ int MainWindow::tryToExtendWidthBy(int addToWidth) { inner.x(), desktop.x() + desktop.width() - newWidth); if (inner.x() != newLeft || inner.width() != newWidth) { - setGeometry(newLeft, inner.y(), newWidth, inner.height()); + setGeometry(QRect(newLeft, inner.y(), newWidth, inner.height())); } else { updateControlsGeometry(); } @@ -841,8 +777,6 @@ void MainWindow::launchDrag( } MainWindow::~MainWindow() { - _title.destroy(); - // Otherwise: // ~QWidget // QWidgetPrivate::close_helper diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index afc3650935..60562fc4d7 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -7,8 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "window/window_title.h" -#include "ui/rp_widget.h" +#include "ui/widgets/rp_window.h" #include "base/timer.h" #include "base/object_ptr.h" #include "core/core_settings.h" @@ -37,7 +36,7 @@ QImage LoadLogoNoMargin(); QIcon CreateIcon(Main::Session *session = nullptr); void ConvertIconToBlack(QImage &image); -class MainWindow : public Ui::RpWidget { +class MainWindow : public Ui::RpWindow { public: explicit MainWindow(not_null controller); virtual ~MainWindow(); @@ -60,7 +59,6 @@ public: [[nodiscard]] QRect desktopRect() const; void init(); - [[nodiscard]] HitTestResult hitTest(const QPoint &p) const; void updateIsActive(); @@ -77,12 +75,6 @@ public: } void positionUpdated(); - bool titleVisible() const; - void setTitleVisible(bool visible); - QString titleText() const { - return _titleText; - } - void reActivateWindow(); void showRightColumn(object_ptr widget); @@ -112,22 +104,18 @@ public: void clearWidgets(); - QRect inner() const; int computeMinWidth() const; int computeMinHeight() const; void recountGeometryConstraints(); virtual void updateControlsGeometry(); - bool hasShadow() const; - bool minimizeToTray(); void updateGlobalMenu() { updateGlobalMenuHook(); } protected: - void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; void leaveEventHook(QEvent *e) override; @@ -154,9 +142,6 @@ protected: virtual void stateChangedHook(Qt::WindowState state) { } - virtual void titleVisibilityChangedHook() { - } - virtual void unreadCounterChangedHook() { } @@ -180,10 +165,6 @@ protected: virtual void createGlobalMenu() { } - virtual void initShadows() { - } - virtual void firstShadowsUpdate() { - } virtual bool initSizeFromSystem() { return false; @@ -203,7 +184,6 @@ protected: private: void refreshTitleWidget(); void updateMinimumSize(); - void updateShadowSize(); void updatePalette(); void initSize(); @@ -214,7 +194,6 @@ private: base::Timer _positionUpdatedTimer; bool _positionInited = false; - object_ptr _title = { nullptr }; object_ptr _titleShadow = { nullptr }; object_ptr _outdated; object_ptr _body; @@ -222,8 +201,6 @@ private: QIcon _icon; bool _usingSupportIcon = false; - QString _titleText; - style::margins _padding; bool _isActive = false; diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index f9d352f642..2bd1e7849e 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "core/click_handler_types.h" #include "export/export_manager.h" +#include "ui/platform/ui_platform_window.h" #include "platform/platform_window_title.h" #include "main/main_account.h" #include "main/main_domain.h" @@ -267,7 +268,7 @@ void Controller::showSettings() { int Controller::verticalShadowTop() const { return (Platform::NativeTitleRequiresShadow() - && Platform::AllowNativeWindowFrameToggle() + && Ui::Platform::NativeWindowFrameSupported() && Core::App().settings().nativeWindowFrame()) ? st::lineWidth : 0; diff --git a/Telegram/SourceFiles/window/window_title.h b/Telegram/SourceFiles/window/window_title.h deleted file mode 100644 index 3226b37635..0000000000 --- a/Telegram/SourceFiles/window/window_title.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "ui/rp_widget.h" - -namespace Window { - -enum class HitTestResult { - None = 0, - Client, - SysButton, - Caption, - Top, - TopRight, - Right, - BottomRight, - Bottom, - BottomLeft, - Left, - TopLeft, -}; - -class TitleWidget : public Ui::RpWidget { -public: - using RpWidget::RpWidget; - - virtual void init() { - } - virtual HitTestResult hitTest(const QPoint &p) const { - return HitTestResult::None; - } - virtual QRect iconRect() const { - return QRect(); - } - -}; - -} // namespace Window diff --git a/Telegram/SourceFiles/window/window_title_qt.cpp b/Telegram/SourceFiles/window/window_title_qt.cpp deleted file mode 100644 index 9ca4ac1a84..0000000000 --- a/Telegram/SourceFiles/window/window_title_qt.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "window/window_title_qt.h" - -#include "ui/platform/ui_platform_utility.h" -#include "ui/widgets/buttons.h" -#include "ui/widgets/shadow.h" -#include "styles/style_widgets.h" -#include "styles/style_window.h" - -#include -#include -#include - -namespace Window { -namespace { - -[[nodiscard]] style::margins ShadowExtents() { - return st::callShadow.extend; -} - -template -void RemoveDuplicates(std::vector &v) { - auto end = v.end(); - for (auto it = v.begin(); it != end; ++it) { - end = std::remove(it + 1, end, *it); - } - - v.erase(end, v.end()); -} - -} // namespace - -TitleWidgetQt::TitleWidgetQt(QWidget *parent) -: TitleWidget(parent) -, _st(st::defaultWindowTitle) -, _minimize(this, _st.minimize) -, _maximizeRestore(this, _st.maximize) -, _close(this, _st.close) -, _shadow(this, st::titleShadow) -, _maximizedState(parent->window()->windowState() & Qt::WindowMaximized) { - _minimize->setClickedCallback([=] { - window()->setWindowState( - window()->windowState() | Qt::WindowMinimized); - _minimize->clearState(); - }); - _minimize->setPointerCursor(false); - _maximizeRestore->setClickedCallback([=] { - window()->setWindowState(_maximizedState - ? Qt::WindowNoState - : Qt::WindowMaximized); - _maximizeRestore->clearState(); - }); - _maximizeRestore->setPointerCursor(false); - _close->setClickedCallback([=] { - window()->close(); - _close->clearState(); - }); - _close->setPointerCursor(false); - - Ui::Platform::TitleControlsLayoutChanged( - ) | rpl::start_with_next([=] { - updateControlsPosition(); - }, lifetime()); - - QCoreApplication::instance()->installEventFilter(this); - - _windowWasFrameless = (window()->windowFlags() - & Qt::FramelessWindowHint) != 0; - - if (!_windowWasFrameless) { - toggleFramelessWindow(true); - } - - setAttribute(Qt::WA_OpaquePaintEvent); - resize(width(), _st.height); - - updateWindowExtents(); -} - -TitleWidgetQt::~TitleWidgetQt() { - restoreCursor(); - - if (!_windowWasFrameless) { - toggleFramelessWindow(false); - } - - if (_extentsSet) { - Ui::Platform::UnsetWindowExtents(window()->windowHandle()); - } -} - -void TitleWidgetQt::init() { - connect( - window()->windowHandle(), - &QWindow::windowStateChanged, - this, - [=](Qt::WindowState state) { windowStateChanged(state); }); - connect( - window()->windowHandle(), - &QWindow::visibleChanged, - this, - [=](bool visible) { visibleChanged(visible); }); - _maximizedState = (window()->windowState() & Qt::WindowMaximized); - _activeState = isActiveWindow(); - updateButtonsState(); -} - -bool TitleWidgetQt::hasShadow() const { - const auto center = window()->geometry().center(); - return Ui::Platform::WindowExtentsSupported() - && Ui::Platform::TranslucentWindowsSupported(center); -} - -Ui::IconButton *TitleWidgetQt::controlWidget(Control control) const { - switch (control) { - case Control::Minimize: return _minimize; - case Control::Maximize: return _maximizeRestore; - case Control::Close: return _close; - } - - return nullptr; -} - -void TitleWidgetQt::paintEvent(QPaintEvent *e) { - auto active = isActiveWindow(); - if (_activeState != active) { - _activeState = active; - updateButtonsState(); - } - Painter(this).fillRect(rect(), active ? _st.bgActive : _st.bg); -} - -void TitleWidgetQt::toggleFramelessWindow(bool enabled) { - window()->windowHandle()->setFlag(Qt::FramelessWindowHint, enabled); -} - -void TitleWidgetQt::updateWindowExtents() { - if (hasShadow()) { - Ui::Platform::SetWindowExtents( - window()->windowHandle(), - resizeArea()); - - _extentsSet = true; - } else if (_extentsSet) { - Ui::Platform::UnsetWindowExtents(window()->windowHandle()); - _extentsSet = false; - } -} - -void TitleWidgetQt::updateControlsPosition() { - const auto controlsLayout = Ui::Platform::TitleControlsLayout(); - const auto controlsLeft = controlsLayout.left; - const auto controlsRight = controlsLayout.right; - - const auto controlPresent = [&](Control control) { - return ranges::contains(controlsLeft, control) - || ranges::contains(controlsRight, control); - }; - - if (controlPresent(Control::Minimize)) { - _minimize->show(); - } else { - _minimize->hide(); - } - - if (controlPresent(Control::Maximize)) { - _maximizeRestore->show(); - } else { - _maximizeRestore->hide(); - } - - if (controlPresent(Control::Close)) { - _close->show(); - } else { - _close->hide(); - } - - updateControlsPositionBySide(controlsLeft, false); - updateControlsPositionBySide(controlsRight, true); -} - -void TitleWidgetQt::updateControlsPositionBySide( - const std::vector &controls, - bool right) { - auto preparedControls = right - ? (ranges::views::reverse(controls) | ranges::to_vector) - : controls; - - RemoveDuplicates(preparedControls); - - auto position = 0; - for (const auto &control : preparedControls) { - const auto widget = controlWidget(control); - if (!widget) { - continue; - } - - if (right) { - widget->moveToRight(position, 0); - } else { - widget->moveToLeft(position, 0); - } - - position += widget->width(); - } -} - -void TitleWidgetQt::resizeEvent(QResizeEvent *e) { - updateControlsPosition(); - _shadow->setGeometry(0, height() - st::lineWidth, width(), st::lineWidth); -} - -void TitleWidgetQt::mousePressEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton) { - _mousePressed = true; - } else if (e->button() == Qt::RightButton) { - Ui::Platform::ShowWindowMenu(window()->windowHandle()); - } -} - -void TitleWidgetQt::mouseReleaseEvent(QMouseEvent *e) { - if (e->button() == Qt::LeftButton) { - _mousePressed = false; - } -} - -void TitleWidgetQt::mouseMoveEvent(QMouseEvent *e) { - if (_mousePressed) { - window()->windowHandle()->startSystemMove(); - } -} - -void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) { - if (_maximizedState) { - window()->setWindowState(Qt::WindowNoState); - } else { - window()->setWindowState(Qt::WindowMaximized); - } -} - -bool TitleWidgetQt::eventFilter(QObject *obj, QEvent *e) { - if (e->type() == QEvent::MouseMove - || e->type() == QEvent::MouseButtonPress) { - if (obj->isWidgetType() - && window()->isAncestorOf(static_cast(obj))) { - const auto mouseEvent = static_cast(e); - const auto currentPoint = mouseEvent->windowPos().toPoint(); - const auto edges = edgesFromPos(currentPoint); - - if (e->type() == QEvent::MouseMove - && mouseEvent->buttons() == Qt::NoButton) { - if (_mousePressed) { - _mousePressed = false; - } - - updateCursor(edges); - } - - if (e->type() == QEvent::MouseButtonPress - && mouseEvent->button() == Qt::LeftButton - && edges) { - return window()->windowHandle()->startSystemResize(edges); - } - } - } else if (e->type() == QEvent::Leave) { - if (obj->isWidgetType() && window() == static_cast(obj)) { - restoreCursor(); - } - } else if (e->type() == QEvent::Move - || e->type() == QEvent::Resize) { - if (obj->isWidgetType() && window() == static_cast(obj)) { - updateWindowExtents(); - } - } - - return TitleWidget::eventFilter(obj, e); -} - -void TitleWidgetQt::windowStateChanged(Qt::WindowState state) { - if (state == Qt::WindowMinimized) { - return; - } - - const auto maximized = (state == Qt::WindowMaximized); - if (_maximizedState != maximized) { - _maximizedState = maximized; - updateButtonsState(); - updateWindowExtents(); - } -} - -void TitleWidgetQt::visibleChanged(bool visible) { - if (visible) { - updateWindowExtents(); - - // workaround a bug in Qt 5.12, works ok in Qt 5.15 - // https://github.com/telegramdesktop/tdesktop/issues/10119 - if (!_windowWasFrameless) { - toggleFramelessWindow(true); - } - } -} - -void TitleWidgetQt::updateButtonsState() { - _minimize->setIconOverride(_activeState - ? &_st.minimizeIconActive - : nullptr, - _activeState - ? &_st.minimizeIconActiveOver - : nullptr); - if (_maximizedState) { - _maximizeRestore->setIconOverride( - _activeState - ? &_st.restoreIconActive : &_st.restoreIcon, - _activeState - ? &_st.restoreIconActiveOver - : &_st.restoreIconOver); - } else { - _maximizeRestore->setIconOverride(_activeState - ? &_st.maximizeIconActive - : nullptr, - _activeState - ? &_st.maximizeIconActiveOver - : nullptr); - } - _close->setIconOverride(_activeState - ? &_st.closeIconActive - : nullptr, - _activeState - ? &_st.closeIconActiveOver - : nullptr); -} - -QMargins TitleWidgetQt::resizeArea() const { - if (_maximizedState) { - return QMargins(); - } else if (!hasShadow()) { - return QMargins( - st::windowResizeArea, - st::windowResizeArea, - st::windowResizeArea, - st::windowResizeArea); - } - - return ShadowExtents(); -} - -Qt::Edges TitleWidgetQt::edgesFromPos(const QPoint &pos) const { - const auto area = resizeArea(); - - if (area.isNull()) { - return Qt::Edges(); - } else if (pos.x() <= area.left()) { - if (pos.y() <= area.top()) { - return Qt::LeftEdge | Qt::TopEdge; - } else if (pos.y() >= (window()->height() - area.bottom())) { - return Qt::LeftEdge | Qt::BottomEdge; - } - - return Qt::LeftEdge; - } else if (pos.x() >= (window()->width() - area.right())) { - if (pos.y() <= area.top()) { - return Qt::RightEdge | Qt::TopEdge; - } else if (pos.y() >= (window()->height() - area.bottom())) { - return Qt::RightEdge | Qt::BottomEdge; - } - - return Qt::RightEdge; - } else if (pos.y() <= area.top()) { - return Qt::TopEdge; - } else if (pos.y() >= (window()->height() - area.bottom())) { - return Qt::BottomEdge; - } - - return Qt::Edges(); -} - -void TitleWidgetQt::updateCursor(Qt::Edges edges) { - if (!edges) { - restoreCursor(); - return; - } else if (!QGuiApplication::overrideCursor()) { - _cursorOverriden = false; - } - - if (!_cursorOverriden) { - _cursorOverriden = true; - QGuiApplication::setOverrideCursor(QCursor()); - } - - if (((edges & Qt::LeftEdge) && (edges & Qt::TopEdge)) - || ((edges & Qt::RightEdge) && (edges & Qt::BottomEdge))) { - QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeFDiagCursor)); - } else if (((edges & Qt::LeftEdge) && (edges & Qt::BottomEdge)) - || ((edges & Qt::RightEdge) && (edges & Qt::TopEdge))) { - QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeBDiagCursor)); - } else if ((edges & Qt::LeftEdge) || (edges & Qt::RightEdge)) { - QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeHorCursor)); - } else if ((edges & Qt::TopEdge) || (edges & Qt::BottomEdge)) { - QGuiApplication::changeOverrideCursor(QCursor(Qt::SizeVerCursor)); - } -} - -void TitleWidgetQt::restoreCursor() { - if (_cursorOverriden) { - _cursorOverriden = false; - QGuiApplication::restoreOverrideCursor(); - } -} - -} // namespace Window diff --git a/Telegram/SourceFiles/window/window_title_qt.h b/Telegram/SourceFiles/window/window_title_qt.h deleted file mode 100644 index 4767f045b1..0000000000 --- a/Telegram/SourceFiles/window/window_title_qt.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "window/window_title.h" -#include "ui/platform/ui_platform_window_title.h" -#include "base/object_ptr.h" - -namespace style { -struct WindowTitle; -} // namespace style - -namespace Ui { -class IconButton; -class PlainShadow; -} // namespace Ui - -namespace Window { - -class TitleWidgetQt : public TitleWidget { -public: - using Control = Ui::Platform::TitleControls::Control; - - TitleWidgetQt(QWidget *parent); - ~TitleWidgetQt(); - - void init() override; - -protected: - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void mouseDoubleClickEvent(QMouseEvent *e) override; - - bool eventFilter(QObject *obj, QEvent *e) override; - -private: - void windowStateChanged(Qt::WindowState state = Qt::WindowNoState); - void visibleChanged(bool visible); - void updateWindowExtents(); - void updateButtonsState(); - void updateControlsPosition(); - void updateControlsPositionBySide( - const std::vector &controls, - bool right); - - void toggleFramelessWindow(bool enabled); - bool hasShadow() const; - Ui::IconButton *controlWidget(Control control) const; - QMargins resizeArea() const; - Qt::Edges edgesFromPos(const QPoint &pos) const; - void updateCursor(Qt::Edges edges); - void restoreCursor(); - - const style::WindowTitle &_st; - object_ptr _minimize; - object_ptr _maximizeRestore; - object_ptr _close; - object_ptr _shadow; - - bool _maximizedState = false; - bool _activeState = false; - bool _windowWasFrameless = false; - bool _cursorOverriden = false; - bool _extentsSet = false; - bool _mousePressed = false; - -}; - -} // namespace Window