diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 4463fd890c..b34fb28a0c 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -127,6 +127,16 @@ PRIVATE desktop-app::external_openal ) +if (LINUX AND DESKTOP_APP_USE_PACKAGED) + find_package(PkgConfig REQUIRED) + pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client) + + target_include_directories(Telegram + PRIVATE + ${WAYLAND_CLIENT_INCLUDE_DIRS} + ) +endif() + if (LINUX) if (DESKTOP_APP_USE_PACKAGED) find_package(PkgConfig REQUIRED) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index e9426dce3c..ba9a8835e0 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -24,8 +24,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include #include +#include +#include +#include + #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include #include @@ -36,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +#include #include #include @@ -48,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL using namespace Platform; using Platform::File::internal::EscapeShell; +using QtWaylandClient::QWaylandWindow; namespace Platform { namespace { @@ -394,6 +401,144 @@ std::optional MutterDBusLastUserInputTime() { } #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION +uint XCBMoveResizeFromEdges(Qt::Edges edges) { + if (edges == (Qt::TopEdge | Qt::LeftEdge)) + return 0; + if (edges == Qt::TopEdge) + return 1; + if (edges == (Qt::TopEdge | Qt::RightEdge)) + return 2; + if (edges == Qt::RightEdge) + return 3; + if (edges == (Qt::RightEdge | Qt::BottomEdge)) + return 4; + if (edges == Qt::BottomEdge) + return 5; + if (edges == (Qt::BottomEdge | Qt::LeftEdge)) + return 6; + if (edges == Qt::LeftEdge) + return 7; + + return 0; +} + +enum wl_shell_surface_resize WlResizeFromEdges(Qt::Edges edges) { + if (edges == (Qt::TopEdge | Qt::LeftEdge)) + return WL_SHELL_SURFACE_RESIZE_TOP_LEFT; + if (edges == Qt::TopEdge) + return WL_SHELL_SURFACE_RESIZE_TOP; + if (edges == (Qt::TopEdge | Qt::RightEdge)) + return WL_SHELL_SURFACE_RESIZE_TOP_RIGHT; + if (edges == Qt::RightEdge) + return WL_SHELL_SURFACE_RESIZE_RIGHT; + if (edges == (Qt::RightEdge | Qt::BottomEdge)) + return WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT; + if (edges == Qt::BottomEdge) + return WL_SHELL_SURFACE_RESIZE_BOTTOM; + if (edges == (Qt::BottomEdge | Qt::LeftEdge)) + return WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT; + if (edges == Qt::LeftEdge) + return WL_SHELL_SURFACE_RESIZE_LEFT; + + return WL_SHELL_SURFACE_RESIZE_NONE; +} + +bool StartXCBMoveResize(QWindow *window, int edges) { + const auto native = QGuiApplication::platformNativeInterface(); + + if (!native) { + return false; + } + + const auto connection = reinterpret_cast( + native->nativeResourceForIntegration(QByteArray("connection"))); + + if (!connection) { + return false; + } + + const auto screen = xcb_setup_roots_iterator( + xcb_get_setup(connection)).data; + + if (!screen) { + return false; + } + + const auto moveResizeCookie = xcb_intern_atom(connection, + 0, + strlen("_NET_WM_MOVERESIZE"), + "_NET_WM_MOVERESIZE"); + + auto moveResizeReply = xcb_intern_atom_reply( + connection, + moveResizeCookie, + nullptr); + + if (!moveResizeReply) { + return false; + } + + const auto moveResize = moveResizeReply->atom; + free(moveResizeReply); + + const auto globalPos = QCursor::pos(); + + xcb_client_message_event_t xev; + xev.response_type = XCB_CLIENT_MESSAGE; + xev.type = moveResize; + xev.sequence = 0; + xev.window = window->winId(); + xev.format = 32; + xev.data.data32[0] = globalPos.x(); + xev.data.data32[1] = globalPos.y(); + xev.data.data32[2] = (edges == 16) + ? 8 // move + : XCBMoveResizeFromEdges(Qt::Edges(edges)); + xev.data.data32[3] = XCB_BUTTON_INDEX_1; + xev.data.data32[4] = 0; + + xcb_ungrab_pointer(connection, XCB_CURRENT_TIME); + xcb_send_event(connection, + false, + screen->root, + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, + reinterpret_cast(&xev)); + + return true; +} + +bool StartWaylandMove(QWindow *window) { + if (const auto waylandWindow = static_cast(window->handle())) { + if (const auto seat = waylandWindow->display()->lastInputDevice()) { + if (const auto shellSurface = waylandWindow->shellSurface()) { + return shellSurface->move(seat); + } + } + } + + return false; +} + +bool StartWaylandResize(QWindow *window, Qt::Edges edges) { + if (const auto waylandWindow = static_cast(window->handle())) { + if (const auto seat = waylandWindow->display()->lastInputDevice()) { + if (const auto shellSurface = waylandWindow->shellSurface()) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED + return shellSurface->resize(seat, edges); +#elif QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) || defined DESKTOP_APP_QT_PATCHED // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED + shellSurface->resize(seat, edges); + return true; +#else // Qt >= 5.13 || DESKTOP_APP_QT_PATCHED + shellSurface->resize(seat, WlResizeFromEdges(edges)); + return true; +#endif // Qt < 5.13 && !DESKTOP_APP_QT_PATCHED + } + } + } + + return false; +} + } // namespace void SetApplicationIcon(const QIcon &icon) { @@ -745,6 +890,22 @@ void FallbackFontConfigCheckEnd() { QFile(FallbackFontConfigCheckPath()).remove(); } +bool StartSystemMove(QWindow *window) { + if (IsWayland()) { + return StartWaylandMove(window); + } else { + return StartXCBMoveResize(window, 16); + } +} + +bool StartSystemResize(QWindow *window, Qt::Edges edges) { + if (IsWayland()) { + return StartWaylandResize(window, edges); + } else { + return StartXCBMoveResize(window, edges); + } +} + } // namespace Platform namespace { diff --git a/Telegram/SourceFiles/platform/linux/window_title_linux.h b/Telegram/SourceFiles/platform/linux/window_title_linux.h index c9e58bbe64..7574f8b33d 100644 --- a/Telegram/SourceFiles/platform/linux/window_title_linux.h +++ b/Telegram/SourceFiles/platform/linux/window_title_linux.h @@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "platform/platform_window_title.h" -#include "platform/linux/linux_desktop_environment.h" #include "base/object_ptr.h" namespace Window { @@ -23,17 +22,11 @@ void DefaultPreviewWindowFramePaint(QImage &preview, const style::palette &palet namespace Platform { inline bool AllowNativeWindowFrameToggle() { -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED - return !DesktopEnvironment::IsUnity(); -#else // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED - return false; -#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED + return true; } inline object_ptr CreateTitleWidget(QWidget *parent) { - return AllowNativeWindowFrameToggle() - ? object_ptr(parent) - : object_ptr{ nullptr }; + return object_ptr(parent); } inline bool NativeTitleRequiresShadow() { diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h index fc591e9687..0d3b90c0b2 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac.h @@ -28,6 +28,14 @@ inline QImage GetImageFromClipboard() { return {}; } +inline bool StartSystemMove(QWindow *window) { + return false; +} + +inline bool StartSystemResize(QWindow *window, Qt::Edges edges) { + return false; +} + namespace ThirdParty { inline void start() { diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index c05e717cef..5172e88e87 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -44,6 +44,8 @@ bool OpenSystemSettings(SystemSettingsType type); void IgnoreApplicationActivationRightNow(); bool AutostartSupported(); QImage GetImageFromClipboard(); +bool StartSystemMove(QWindow *window); +bool StartSystemResize(QWindow *window, Qt::Edges edges); namespace ThirdParty { diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h index eb70f1e134..b6961100e7 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.h +++ b/Telegram/SourceFiles/platform/win/specific_win.h @@ -32,6 +32,14 @@ inline QImage GetImageFromClipboard() { return {}; } +inline bool StartSystemMove(QWindow *window) { + return false; +} + +inline bool StartSystemResize(QWindow *window, Qt::Edges edges) { + return false; +} + namespace ThirdParty { void start(); diff --git a/Telegram/SourceFiles/window/window_title_qt.cpp b/Telegram/SourceFiles/window/window_title_qt.cpp index 555a87355b..c14472b3d2 100644 --- a/Telegram/SourceFiles/window/window_title_qt.cpp +++ b/Telegram/SourceFiles/window/window_title_qt.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "window/window_title_qt.h" +#include "platform/platform_specific.h" #include "ui/widgets/buttons.h" #include "ui/widgets/shadow.h" #include "styles/style_window.h" @@ -121,9 +122,7 @@ void TitleWidgetQt::mousePressEvent(QMouseEvent *e) { return; } -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED - window()->windowHandle()->startSystemMove(); -#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED + startMove(); } void TitleWidgetQt::mouseDoubleClickEvent(QMouseEvent *e) { @@ -260,14 +259,34 @@ void TitleWidgetQt::updateCursor(Qt::Edges edges) { } } -bool TitleWidgetQt::startResize(Qt::Edges edges) { +bool TitleWidgetQt::startMove() { + if (Platform::StartSystemMove(window()->windowHandle())) { + return true; + } + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED - if (edges) { - return window()->windowHandle()->startSystemResize(edges); + if (window()->windowHandle()->startSystemMove()) { + return true; } #endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED return false; } +bool TitleWidgetQt::startResize(Qt::Edges edges) { + if (edges) { + if (Platform::StartSystemResize(window()->windowHandle(), edges)) { + return true; + } + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) || defined DESKTOP_APP_QT_PATCHED + if (window()->windowHandle()->startSystemResize(edges)) { + return true; + } +#endif // Qt >= 5.15 || DESKTOP_APP_QT_PATCHED + } + + return false; +} + } // namespace Window diff --git a/Telegram/SourceFiles/window/window_title_qt.h b/Telegram/SourceFiles/window/window_title_qt.h index 67a80945aa..3b90489cb3 100644 --- a/Telegram/SourceFiles/window/window_title_qt.h +++ b/Telegram/SourceFiles/window/window_title_qt.h @@ -45,6 +45,7 @@ private: Qt::Edges edgesFromPos(const QPoint &pos); void updateCursor(Qt::Edges edges); void restoreCursor(); + bool startMove(); bool startResize(Qt::Edges edges); const style::WindowTitle &_st;