Try to use as less private APIs as possible to show window menu on Wayland

This commit is contained in:
Ilya Fedin 2022-04-11 01:44:05 +04:00 committed by John Preston
parent 362fbb6331
commit d5a37c74b1
2 changed files with 51 additions and 12 deletions

View file

@ -27,7 +27,7 @@ generate_emoji(lib_ui emoji.txt emoji_suggestions/emoji_autocomplete.json)
set_target_properties(lib_ui PROPERTIES AUTOMOC ON) set_target_properties(lib_ui PROPERTIES AUTOMOC ON)
target_prepare_qrc(lib_ui) target_prepare_qrc(lib_ui)
target_precompile_headers(lib_ui PRIVATE ${src_loc}/ui/ui_pch.h) target_precompile_headers(lib_ui PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${src_loc}/ui/ui_pch.h>)
nice_target_sources(lib_ui ${src_loc} nice_target_sources(lib_ui ${src_loc}
PRIVATE PRIVATE
${style_files} ${style_files}
@ -270,11 +270,26 @@ if (DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION)
elseif(LINUX) elseif(LINUX)
remove_target_sources(lib_ui ${src_loc} ui/platform/linux/ui_linux_wayland_integration_dummy.cpp) remove_target_sources(lib_ui ${src_loc} ui/platform/linux/ui_linux_wayland_integration_dummy.cpp)
if (DESKTOP_APP_QT6)
qt6_generate_wayland_protocol_client_sources(lib_ui
FILES
${third_party_loc}/wayland-protocols/stable/xdg-shell/xdg-shell.xml
)
else()
message(FATAL_ERROR "This piece of cmake code is not ported to Qt 5")
endif()
target_link_libraries(lib_ui target_link_libraries(lib_ui
PUBLIC PUBLIC
desktop-app::lib_waylandshells desktop-app::lib_waylandshells
desktop-app::external_kwayland desktop-app::external_kwayland
) )
if (DESKTOP_APP_USE_PACKAGED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(WAYLAND_CLIENT REQUIRED IMPORTED_TARGET wayland-client)
target_link_libraries(lib_ui PRIVATE PkgConfig::WAYLAND_CLIENT)
endif()
endif() endif()
target_include_directories(lib_ui target_include_directories(lib_ui

View file

@ -9,20 +9,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "waylandshells/xdg_shell.h" #include "waylandshells/xdg_shell.h"
#include "qwayland-xdg-shell.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <qpa/qplatformnativeinterface.h>
#include <private/qguiapplication_p.h>
#include <private/qhighdpiscaling_p.h>
// private headers are using keywords :( // private QtWaylandClient headers are using keywords :(
#ifdef QT_NO_KEYWORDS #ifdef QT_NO_KEYWORDS
#define signals Q_SIGNALS #define signals Q_SIGNALS
#define slots Q_SLOTS #define slots Q_SLOTS
#endif // QT_NO_KEYWORDS #endif // QT_NO_KEYWORDS
#include <private/qguiapplication_p.h>
#include <private/qwaylandintegration_p.h> #include <private/qwaylandintegration_p.h>
#include <private/qwaylanddisplay_p.h> #include <private/qwaylanddisplay_p.h>
#include <private/qwaylandwindow_p.h> #include <private/qwaylandwindow_p.h>
#include <private/qwaylandshellsurface_p.h> #include <private/qwaylandinputdevice_p.h>
#include <connection_thread.h> #include <connection_thread.h>
#include <registry.h> #include <registry.h>
@ -113,17 +117,37 @@ void WaylandIntegration::unsetWindowExtents(QWindow *window) {
} }
bool WaylandIntegration::showWindowMenu(QWindow *window) { bool WaylandIntegration::showWindowMenu(QWindow *window) {
if (const auto waylandWindow = static_cast<QWaylandWindow*>( const auto native = QGuiApplication::platformNativeInterface();
window->handle())) { if (!native) {
if (const auto seat = waylandWindow->display()->lastInputDevice()) { return false;
if (const auto shellSurface = waylandWindow->shellSurface()) {
return shellSurface->showWindowMenu(seat);
}
}
} }
const auto toplevel = reinterpret_cast<xdg_toplevel*>(
native->nativeResourceForWindow(QByteArray("xdg_toplevel"), window));
const auto seat = reinterpret_cast<wl_seat*>(
native->nativeResourceForIntegration(QByteArray("wl_seat")));
const auto serial = [&]() -> std::optional<uint32_t> {
const auto waylandWindow = static_cast<QWaylandWindow*>(
window->handle());
if (!waylandWindow) {
return std::nullopt;
}
return waylandWindow->display()->defaultInputDevice()->serial();
}();
if (!toplevel || !seat || !serial) {
return false; return false;
} }
const auto pos = QHighDpi::toNativePixels(
window->mapFromGlobal(QCursor::pos()),
window);
xdg_toplevel_show_window_menu(toplevel, seat, *serial, pos.x(), pos.y());
return true;
}
} // namespace Platform } // namespace Platform
} // namespace Ui } // namespace Ui