diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f7bc3e..9073bcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,8 @@ PRIVATE ui/platform/linux/ui_linux_wayland_integration.h ui/platform/linux/ui_window_linux.cpp ui/platform/linux/ui_window_linux.h + ui/platform/linux/ui_window_title_linux.cpp + ui/platform/linux/ui_window_title_linux.h ui/platform/linux/ui_utility_linux.cpp ui/platform/linux/ui_utility_linux.h ui/platform/mac/ui_window_mac.h @@ -134,7 +136,6 @@ PRIVATE ui/platform/ui_platform_window_title.h ui/platform/ui_platform_window.cpp ui/platform/ui_platform_window.h - ui/platform/ui_platform_utility.cpp ui/platform/ui_platform_utility.h ui/style/style_core.cpp ui/style/style_core.h diff --git a/ui/platform/linux/ui_utility_linux.cpp b/ui/platform/linux/ui_utility_linux.cpp index 76bb270..96c4059 100644 --- a/ui/platform/linux/ui_utility_linux.cpp +++ b/ui/platform/linux/ui_utility_linux.cpp @@ -7,15 +7,12 @@ #include "ui/platform/linux/ui_utility_linux.h" #include "base/platform/base_platform_info.h" -#include "base/platform/linux/base_linux_glibmm_helper.h" -#include "base/platform/linux/base_linux_xdp_utilities.h" #include "base/call_delayed.h" #include "base/const_string.h" #include "ui/platform/linux/ui_linux_wayland_integration.h" #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION #include "base/platform/linux/base_linux_xcb_utilities.h" -#include "base/platform/linux/base_linux_xsettings.h" #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION #include @@ -399,41 +396,6 @@ void ShowXCBWindowMenu(not_null widget, const QPoint &point) { } #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION -TitleControls::Control GtkKeywordToTitleControl(const QString &keyword) { - if (keyword == qstr("minimize")) { - return TitleControls::Control::Minimize; - } else if (keyword == qstr("maximize")) { - return TitleControls::Control::Maximize; - } else if (keyword == qstr("close")) { - return TitleControls::Control::Close; - } - - return TitleControls::Control::Unknown; -} - -TitleControls::Layout GtkKeywordsToTitleControlsLayout(const QString &keywords) { - const auto splitted = keywords.split(':'); - - std::vector controlsLeft; - ranges::transform( - splitted[0].split(','), - ranges::back_inserter(controlsLeft), - GtkKeywordToTitleControl); - - std::vector controlsRight; - if (splitted.size() > 1) { - ranges::transform( - splitted[1].split(','), - ranges::back_inserter(controlsRight), - GtkKeywordToTitleControl); - } - - return TitleControls::Layout{ - .left = controlsLeft, - .right = controlsRight - }; -} - } // namespace bool IsApplicationActive() { @@ -581,94 +543,5 @@ void GotApplicationActivateEvent() { PendingDeactivateEvent = false; } -namespace internal { - -TitleControls::Layout TitleControlsLayout() { - [[maybe_unused]] static const auto Inited = [] { -#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION - using base::Platform::XCB::XSettings; - if (const auto xSettings = XSettings::Instance()) { - xSettings->registerCallbackForProperty("Gtk/DecorationLayout", []( - xcb_connection_t *, - const QByteArray &, - const QVariant &, - void *) { - NotifyTitleControlsLayoutChanged(); - }, nullptr); - } -#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION - - using XDPSettingWatcher = base::Platform::XDP::SettingWatcher; - static const XDPSettingWatcher settingWatcher( - [=]( - const Glib::ustring &group, - const Glib::ustring &key, - const Glib::VariantBase &value) { - if (group == "org.gnome.desktop.wm.preferences" - && key == "button-layout") { - NotifyTitleControlsLayoutChanged(); - } - }); - - return true; - }(); - -#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION - const auto xSettingsResult = []() -> std::optional { - using base::Platform::XCB::XSettings; - const auto xSettings = XSettings::Instance(); - if (!xSettings) { - return std::nullopt; - } - - const auto decorationLayout = xSettings->setting("Gtk/DecorationLayout"); - if (!decorationLayout.isValid()) { - return std::nullopt; - } - - return GtkKeywordsToTitleControlsLayout(decorationLayout.toString()); - }(); - - if (xSettingsResult.has_value()) { - return *xSettingsResult; - } -#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION - - const auto portalResult = []() -> std::optional { - try { - using namespace base::Platform::XDP; - - const auto decorationLayout = ReadSetting( - "org.gnome.desktop.wm.preferences", - "button-layout"); - - if (!decorationLayout.has_value()) { - return std::nullopt; - } - - return GtkKeywordsToTitleControlsLayout( - QString::fromStdString( - base::Platform::GlibVariantCast( - *decorationLayout))); - } catch (...) { - } - - return std::nullopt; - }(); - - if (portalResult.has_value()) { - return *portalResult; - } - - return TitleControls::Layout{ - .right = { - TitleControls::Control::Minimize, - TitleControls::Control::Maximize, - TitleControls::Control::Close, - } - }; -} - -} // namespace internal } // namespace Platform } // namespace Ui diff --git a/ui/platform/linux/ui_window_title_linux.cpp b/ui/platform/linux/ui_window_title_linux.cpp new file mode 100644 index 0000000..eca5024 --- /dev/null +++ b/ui/platform/linux/ui_window_title_linux.cpp @@ -0,0 +1,146 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#include "ui/platform/linux/ui_window_title_linux.h" + +#include "base/platform/linux/base_linux_glibmm_helper.h" +#include "base/platform/linux/base_linux_xdp_utilities.h" + +#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION +#include "base/platform/linux/base_linux_xsettings.h" +#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION + +namespace Ui { +namespace Platform { +namespace internal { +namespace { + +TitleControls::Control GtkKeywordToTitleControl(const QString &keyword) { + if (keyword == qstr("minimize")) { + return TitleControls::Control::Minimize; + } else if (keyword == qstr("maximize")) { + return TitleControls::Control::Maximize; + } else if (keyword == qstr("close")) { + return TitleControls::Control::Close; + } + + return TitleControls::Control::Unknown; +} + +TitleControls::Layout GtkKeywordsToTitleControlsLayout(const QString &keywords) { + const auto splitted = keywords.split(':'); + + std::vector controlsLeft; + ranges::transform( + splitted[0].split(','), + ranges::back_inserter(controlsLeft), + GtkKeywordToTitleControl); + + std::vector controlsRight; + if (splitted.size() > 1) { + ranges::transform( + splitted[1].split(','), + ranges::back_inserter(controlsRight), + GtkKeywordToTitleControl); + } + + return TitleControls::Layout{ + .left = controlsLeft, + .right = controlsRight, + }; +} + +} // namespace + +TitleControls::Layout TitleControlsLayout() { + [[maybe_unused]] static const auto Inited = [] { +#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION + using base::Platform::XCB::XSettings; + if (const auto xSettings = XSettings::Instance()) { + xSettings->registerCallbackForProperty("Gtk/DecorationLayout", []( + xcb_connection_t *, + const QByteArray &, + const QVariant &, + void *) { + NotifyTitleControlsLayoutChanged(); + }, nullptr); + } +#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION + + using XDPSettingWatcher = base::Platform::XDP::SettingWatcher; + static const XDPSettingWatcher settingWatcher( + [=]( + const Glib::ustring &group, + const Glib::ustring &key, + const Glib::VariantBase &value) { + if (group == "org.gnome.desktop.wm.preferences" + && key == "button-layout") { + NotifyTitleControlsLayoutChanged(); + } + }); + + return true; + }(); + +#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION + const auto xSettingsResult = []() -> std::optional { + using base::Platform::XCB::XSettings; + const auto xSettings = XSettings::Instance(); + if (!xSettings) { + return std::nullopt; + } + + const auto decorationLayout = xSettings->setting("Gtk/DecorationLayout"); + if (!decorationLayout.isValid()) { + return std::nullopt; + } + + return GtkKeywordsToTitleControlsLayout(decorationLayout.toString()); + }(); + + if (xSettingsResult.has_value()) { + return *xSettingsResult; + } +#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION + + const auto portalResult = []() -> std::optional { + try { + using namespace base::Platform::XDP; + + const auto decorationLayout = ReadSetting( + "org.gnome.desktop.wm.preferences", + "button-layout"); + + if (!decorationLayout.has_value()) { + return std::nullopt; + } + + return GtkKeywordsToTitleControlsLayout( + QString::fromStdString( + base::Platform::GlibVariantCast( + *decorationLayout))); + } catch (...) { + } + + return std::nullopt; + }(); + + if (portalResult.has_value()) { + return *portalResult; + } + + return TitleControls::Layout{ + .right = { + TitleControls::Control::Minimize, + TitleControls::Control::Maximize, + TitleControls::Control::Close, + } + }; +} + +} // namespace internal +} // namespace Platform +} // namespace Ui diff --git a/ui/platform/linux/ui_window_title_linux.h b/ui/platform/linux/ui_window_title_linux.h new file mode 100644 index 0000000..0aa287b --- /dev/null +++ b/ui/platform/linux/ui_window_title_linux.h @@ -0,0 +1,9 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#pragma once + +#include "ui/platform/ui_platform_window_title.h" diff --git a/ui/platform/mac/ui_utility_mac.mm b/ui/platform/mac/ui_utility_mac.mm index 3c59a5f..8aa7475 100644 --- a/ui/platform/mac/ui_utility_mac.mm +++ b/ui/platform/mac/ui_utility_mac.mm @@ -157,18 +157,5 @@ bool SkipApplicationDeactivateEvent() { void GotApplicationActivateEvent() { } -namespace internal { - -TitleControls::Layout TitleControlsLayout() { - return TitleControls::Layout{ - .left = { - TitleControls::Control::Close, - TitleControls::Control::Minimize, - TitleControls::Control::Maximize, - } - }; -} - -} // namespace internal } // namespace Platform } // namespace Ui diff --git a/ui/platform/mac/ui_window_title_mac.mm b/ui/platform/mac/ui_window_title_mac.mm index 0511e82..d9de411 100644 --- a/ui/platform/mac/ui_window_title_mac.mm +++ b/ui/platform/mac/ui_window_title_mac.mm @@ -20,6 +20,19 @@ namespace Ui { namespace Platform { +namespace internal { + +TitleControls::Layout TitleControlsLayout() { + return TitleControls::Layout{ + .left = { + TitleControls::Control::Close, + TitleControls::Control::Minimize, + TitleControls::Control::Maximize, + } + }; +} + +} // namespace internal TitleWidget::TitleWidget(not_null parent, int height) : RpWidget(parent) diff --git a/ui/platform/ui_platform_utility.cpp b/ui/platform/ui_platform_utility.cpp deleted file mode 100644 index cdeec97..0000000 --- a/ui/platform/ui_platform_utility.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// This file is part of Desktop App Toolkit, -// a set of libraries for developing nice desktop applications. -// -// For license and copyright information please follow this link: -// https://github.com/desktop-app/legal/blob/master/LEGAL -// -#include "ui/platform/ui_platform_utility.h" - -namespace Ui { -namespace Platform { -namespace internal { -namespace { - -auto &CachedTitleControlsLayout() { - using Layout = TitleControls::Layout; - static rpl::variable Result = TitleControlsLayout(); - return Result; -}; - -} // namespace - -void NotifyTitleControlsLayoutChanged( - const std::optional &layout) { - CachedTitleControlsLayout() = layout ? *layout : TitleControlsLayout(); -} - -} // namespace internal - -TitleControls::Layout TitleControlsLayout() { - return internal::CachedTitleControlsLayout().current(); -} - -rpl::producer TitleControlsLayoutValue() { - return internal::CachedTitleControlsLayout().value(); -} - -rpl::producer TitleControlsLayoutChanged() { - return internal::CachedTitleControlsLayout().changes(); -} - -} // namespace Platform -} // namespace Ui diff --git a/ui/platform/ui_platform_utility.h b/ui/platform/ui_platform_utility.h index 64c8dd9..d9adad4 100644 --- a/ui/platform/ui_platform_utility.h +++ b/ui/platform/ui_platform_utility.h @@ -6,8 +6,6 @@ // #pragma once -#include "ui/platform/ui_platform_window_title.h" - class QPoint; class QPainter; class QPaintEvent; @@ -17,14 +15,6 @@ class PopupMenu; } // namespace Ui namespace Ui::Platform { -namespace internal { - -// Actual requestor, cached by the public interface -[[nodiscard]] TitleControls::Layout TitleControlsLayout(); -void NotifyTitleControlsLayoutChanged( - const std::optional &layout = std::nullopt); - -} // namespace internal [[nodiscard]] bool IsApplicationActive(); @@ -53,21 +43,6 @@ void SetWindowExtents(not_null widget, const QMargins &extents); void UnsetWindowExtents(not_null widget); void ShowWindowMenu(not_null widget, const QPoint &point); -[[nodiscard]] TitleControls::Layout TitleControlsLayout(); -[[nodiscard]] rpl::producer TitleControlsLayoutValue(); -[[nodiscard]] rpl::producer TitleControlsLayoutChanged(); -[[nodiscard]] bool TitleControlsOnLeft( - const TitleControls::Layout &layout = TitleControlsLayout()) { - if (ranges::contains(layout.left, TitleControl::Close)) { - return true; - } else if (ranges::contains(layout.right, TitleControl::Close)) { - return false; - } else if (layout.left.size() > layout.right.size()) { - return true; - } - return false; -} - void FixPopupMenuNativeEmojiPopup(not_null menu); // Workaround for a Qt/Wayland bug that hides the parent popup when diff --git a/ui/platform/ui_platform_window_title.cpp b/ui/platform/ui_platform_window_title.cpp index 4162364..ddb69a8 100644 --- a/ui/platform/ui_platform_window_title.cpp +++ b/ui/platform/ui_platform_window_title.cpp @@ -441,6 +441,36 @@ void TitleControls::updateButtonsState() { _buttons->updateState(_activeState, _maximizedState, *_st); } +namespace internal { +namespace { + +auto &CachedTitleControlsLayout() { + using Layout = TitleControls::Layout; + static rpl::variable Result = TitleControlsLayout(); + return Result; +}; + +} // namespace + +void NotifyTitleControlsLayoutChanged( + const std::optional &layout) { + CachedTitleControlsLayout() = layout ? *layout : TitleControlsLayout(); +} + +} // namespace internal + +TitleControls::Layout TitleControlsLayout() { + return internal::CachedTitleControlsLayout().current(); +} + +rpl::producer TitleControlsLayoutValue() { + return internal::CachedTitleControlsLayout().value(); +} + +rpl::producer TitleControlsLayoutChanged() { + return internal::CachedTitleControlsLayout().changes(); +} + DefaultTitleWidget::DefaultTitleWidget(not_null parent) : RpWidget(parent) , _controls(this, st::defaultWindowTitle) diff --git a/ui/platform/ui_platform_window_title.h b/ui/platform/ui_platform_window_title.h index 21b2108..a2612ab 100644 --- a/ui/platform/ui_platform_window_title.h +++ b/ui/platform/ui_platform_window_title.h @@ -154,6 +154,30 @@ private: }; +namespace internal { + +// Actual requestor, cached by the public interface +[[nodiscard]] TitleControls::Layout TitleControlsLayout(); +void NotifyTitleControlsLayoutChanged( + const std::optional &layout = std::nullopt); + +} // namespace internal + +[[nodiscard]] TitleControls::Layout TitleControlsLayout(); +[[nodiscard]] rpl::producer TitleControlsLayoutValue(); +[[nodiscard]] rpl::producer TitleControlsLayoutChanged(); +[[nodiscard]] bool TitleControlsOnLeft( + const TitleControls::Layout &layout = TitleControlsLayout()) { + if (ranges::contains(layout.left, TitleControl::Close)) { + return true; + } else if (ranges::contains(layout.right, TitleControl::Close)) { + return false; + } else if (layout.left.size() > layout.right.size()) { + return true; + } + return false; +} + class DefaultTitleWidget : public RpWidget { public: explicit DefaultTitleWidget(not_null parent); diff --git a/ui/platform/win/ui_utility_win.cpp b/ui/platform/win/ui_utility_win.cpp index e81b150..c9678c0 100644 --- a/ui/platform/win/ui_utility_win.cpp +++ b/ui/platform/win/ui_utility_win.cpp @@ -134,20 +134,6 @@ void ShowWindowMenu(not_null widget, const QPoint &point) { MAKELPARAM(p.x, p.y)); } -namespace internal { - -TitleControls::Layout TitleControlsLayout() { - return TitleControls::Layout{ - .right = { - TitleControls::Control::Minimize, - TitleControls::Control::Maximize, - TitleControls::Control::Close, - } - }; -} - -} // namespace internal - void FixPopupMenuNativeEmojiPopup(not_null menu) { // Windows native emoji selector, that can be called by Win+. shortcut, // is behaving strangely within an input field in a popup menu. diff --git a/ui/platform/win/ui_window_title_win.cpp b/ui/platform/win/ui_window_title_win.cpp index bce7acc..cb3d645 100644 --- a/ui/platform/win/ui_window_title_win.cpp +++ b/ui/platform/win/ui_window_title_win.cpp @@ -44,6 +44,20 @@ HRESULT(__stdcall *GetScaleFactorForMonitor)( } // namespace +namespace internal { + +TitleControls::Layout TitleControlsLayout() { + return TitleControls::Layout{ + .right = { + TitleControls::Control::Minimize, + TitleControls::Control::Maximize, + TitleControls::Control::Close, + } + }; +} + +} // namespace internal + struct TitleWidget::PaddingHelper { explicit PaddingHelper(QWidget *parent) : controlsParent(parent) { }