Get Wayland window menu out of DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION

This commit is contained in:
Ilya Fedin 2023-09-21 08:11:32 +04:00 committed by John Preston
parent 88423818f8
commit caff63f284
4 changed files with 82 additions and 41 deletions

View file

@ -20,7 +20,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
using namespace QNativeInterface; using namespace QNativeInterface;
using namespace QNativeInterface::Private; using namespace QNativeInterface::Private;
using namespace base::Platform::Wayland; using namespace base::Platform::Wayland;
struct xdg_toplevel;
namespace Ui { namespace Ui {
namespace Platform { namespace Platform {
@ -83,30 +82,5 @@ bool WaylandIntegration::xdgDecorationSupported() {
return _private->xdgDecoration.has_value(); return _private->xdgDecoration.has_value();
} }
void WaylandIntegration::showWindowMenu(
not_null<QWidget*> widget,
const QPoint &point) {
const auto window = not_null(widget->windowHandle());
const auto native = qApp->nativeInterface<QWaylandApplication>();
const auto nativeWindow = window->nativeInterface<QWaylandWindow>();
if (!native || !nativeWindow) {
return;
}
const auto toplevel = nativeWindow->surfaceRole<xdg_toplevel>();
const auto seat = native->lastInputSeat();
if (!toplevel || !seat) {
return;
}
wl_proxy_marshal(
reinterpret_cast<wl_proxy*>(toplevel),
4, // XDG_TOPLEVEL_SHOW_WINDOW_MENU
seat,
native->lastInputSerial(),
point.x(),
point.y());
}
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui

View file

@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
class QWindow;
namespace Ui { namespace Ui {
namespace Platform { namespace Platform {
@ -20,7 +18,6 @@ public:
[[nodiscard]] static WaylandIntegration *Instance(); [[nodiscard]] static WaylandIntegration *Instance();
[[nodiscard]] bool xdgDecorationSupported(); [[nodiscard]] bool xdgDecorationSupported();
void showWindowMenu(not_null<QWidget*> widget, const QPoint &point);
private: private:
struct Private; struct Private;

View file

@ -30,10 +30,5 @@ bool WaylandIntegration::xdgDecorationSupported() {
return false; return false;
} }
void WaylandIntegration::showWindowMenu(
not_null<QWidget*> widget,
const QPoint &point) {
}
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui

View file

@ -7,8 +7,8 @@
#include "ui/platform/linux/ui_utility_linux.h" #include "ui/platform/linux/ui_utility_linux.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/platform/linux/base_linux_library.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "ui/platform/linux/ui_linux_wayland_integration.h"
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION #ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
#include "base/platform/linux/base_linux_xcb_utilities.h" #include "base/platform/linux/base_linux_xcb_utilities.h"
@ -19,6 +19,27 @@
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <qpa/qplatformwindow_p.h> #include <qpa/qplatformwindow_p.h>
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 Ui {
namespace Platform { namespace Platform {
namespace { namespace {
@ -396,6 +417,54 @@ void ShowXCBWindowMenu(not_null<QWidget*> widget, const QPoint &point) {
} }
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION #endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
void ShowWaylandWindowMenu(not_null<QWidget*> 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<QWaylandApplication>();
const auto nativeWindow = window->nativeInterface<QWaylandWindow>();
if (!native || !nativeWindow) {
return;
}
const auto toplevel = nativeWindow->surfaceRole<xdg_toplevel>();
const auto seat = native->lastInputSeat();
if (!toplevel || !seat) {
return;
}
wl_proxy_marshal_array(
reinterpret_cast<wl_proxy*>(toplevel),
4, // XDG_TOPLEVEL_SHOW_WINDOW_MENU
std::array{
wl_argument{ .o = reinterpret_cast<wl_object*>(seat) },
wl_argument{ .u = native->lastInputSerial() },
wl_argument{ .i = point.x() },
wl_argument{ .i = point.y() },
}.data());
}
#endif // Qt >= 6.5.0
} // namespace } // namespace
bool IsApplicationActive() { bool IsApplicationActive() {
@ -527,13 +596,19 @@ void UnsetWindowMargins(not_null<QWidget*> widget) {
} }
void ShowWindowMenu(not_null<QWidget*> widget, const QPoint &point) { void ShowWindowMenu(not_null<QWidget*> widget, const QPoint &point) {
if (const auto integration = WaylandIntegration::Instance()) { #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
integration->showWindowMenu(widget, point); if (::Platform::IsWayland()) {
} else if (::Platform::IsX11()) { ShowWaylandWindowMenu(widget, point);
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION return;
ShowXCBWindowMenu(widget, point);
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
} }
#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() { void RegisterChildPopupHiding() {