diff --git a/ui/platform/linux/ui_linux_wayland_integration.cpp b/ui/platform/linux/ui_linux_wayland_integration.cpp index b44df9e..b9436be 100644 --- a/ui/platform/linux/ui_linux_wayland_integration.cpp +++ b/ui/platform/linux/ui_linux_wayland_integration.cpp @@ -20,7 +20,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL using namespace QNativeInterface; using namespace QNativeInterface::Private; using namespace base::Platform::Wayland; -struct xdg_toplevel; namespace Ui { namespace Platform { @@ -83,30 +82,5 @@ bool WaylandIntegration::xdgDecorationSupported() { return _private->xdgDecoration.has_value(); } -void WaylandIntegration::showWindowMenu( - not_null widget, - const QPoint &point) { - const auto window = not_null(widget->windowHandle()); - const auto native = qApp->nativeInterface(); - const auto nativeWindow = window->nativeInterface(); - if (!native || !nativeWindow) { - return; - } - - const auto toplevel = nativeWindow->surfaceRole(); - const auto seat = native->lastInputSeat(); - if (!toplevel || !seat) { - return; - } - - wl_proxy_marshal( - reinterpret_cast(toplevel), - 4, // XDG_TOPLEVEL_SHOW_WINDOW_MENU - seat, - native->lastInputSerial(), - point.x(), - point.y()); -} - } // namespace Platform } // namespace Ui diff --git a/ui/platform/linux/ui_linux_wayland_integration.h b/ui/platform/linux/ui_linux_wayland_integration.h index 7d13631..62f1610 100644 --- a/ui/platform/linux/ui_linux_wayland_integration.h +++ b/ui/platform/linux/ui_linux_wayland_integration.h @@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -class QWindow; - namespace Ui { namespace Platform { @@ -20,7 +18,6 @@ public: [[nodiscard]] static WaylandIntegration *Instance(); [[nodiscard]] bool xdgDecorationSupported(); - void showWindowMenu(not_null widget, const QPoint &point); private: struct Private; diff --git a/ui/platform/linux/ui_linux_wayland_integration_dummy.cpp b/ui/platform/linux/ui_linux_wayland_integration_dummy.cpp index 171fc48..04f2a16 100644 --- a/ui/platform/linux/ui_linux_wayland_integration_dummy.cpp +++ b/ui/platform/linux/ui_linux_wayland_integration_dummy.cpp @@ -30,10 +30,5 @@ bool WaylandIntegration::xdgDecorationSupported() { return false; } -void WaylandIntegration::showWindowMenu( - not_null widget, - const QPoint &point) { -} - } // namespace Platform } // namespace Ui diff --git a/ui/platform/linux/ui_utility_linux.cpp b/ui/platform/linux/ui_utility_linux.cpp index da9fb4b..8a3cf9c 100644 --- a/ui/platform/linux/ui_utility_linux.cpp +++ b/ui/platform/linux/ui_utility_linux.cpp @@ -7,8 +7,8 @@ #include "ui/platform/linux/ui_utility_linux.h" #include "base/platform/base_platform_info.h" +#include "base/platform/linux/base_linux_library.h" #include "base/call_delayed.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" @@ -19,6 +19,27 @@ #include #include +extern "C" { + +typedef int32_t wl_fixed_t; +struct wl_object; +struct wl_array; +struct wl_proxy; +struct xdg_toplevel; + +union wl_argument { + int32_t i; /**< `int` */ + uint32_t u; /**< `uint` */ + wl_fixed_t f; /**< `fixed` */ + const char *s; /**< `string` */ + struct wl_object *o; /**< `object` */ + uint32_t n; /**< `new_id` */ + struct wl_array *a; /**< `array` */ + int32_t h; /**< `fd` */ +}; + +} + namespace Ui { namespace Platform { namespace { @@ -396,6 +417,54 @@ void ShowXCBWindowMenu(not_null widget, const QPoint &point) { } #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) +void ShowWaylandWindowMenu(not_null widget, const QPoint &point) { + static const auto wl_proxy_marshal_array = [] { + void (*result)( + struct wl_proxy *p, + uint32_t opcode, + union wl_argument *args) = nullptr; + + if (const auto lib = base::Platform::LoadLibrary( + "libwayland-client.so.0", + RTLD_NODELETE)) { + base::Platform::LoadSymbol(lib, "wl_proxy_marshal_array", result); + } + + return result; + }(); + + if (!wl_proxy_marshal_array) { + return; + } + + using namespace QNativeInterface; + using namespace QNativeInterface::Private; + const auto window = not_null(widget->windowHandle()); + const auto native = qApp->nativeInterface(); + const auto nativeWindow = window->nativeInterface(); + if (!native || !nativeWindow) { + return; + } + + const auto toplevel = nativeWindow->surfaceRole(); + const auto seat = native->lastInputSeat(); + if (!toplevel || !seat) { + return; + } + + wl_proxy_marshal_array( + reinterpret_cast(toplevel), + 4, // XDG_TOPLEVEL_SHOW_WINDOW_MENU + std::array{ + wl_argument{ .o = reinterpret_cast(seat) }, + wl_argument{ .u = native->lastInputSerial() }, + wl_argument{ .i = point.x() }, + wl_argument{ .i = point.y() }, + }.data()); +} +#endif // Qt >= 6.5.0 + } // namespace bool IsApplicationActive() { @@ -527,13 +596,19 @@ void UnsetWindowMargins(not_null widget) { } void ShowWindowMenu(not_null widget, const QPoint &point) { - if (const auto integration = WaylandIntegration::Instance()) { - integration->showWindowMenu(widget, point); - } else if (::Platform::IsX11()) { -#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION - ShowXCBWindowMenu(widget, point); -#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + if (::Platform::IsWayland()) { + ShowWaylandWindowMenu(widget, point); + return; } +#endif // Qt >= 6.5.0 + +#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION + if (::Platform::IsX11()) { + ShowXCBWindowMenu(widget, point); + return; + } +#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION } void RegisterChildPopupHiding() {