Add support for custom titlebar on Linux with Qt < 5.15
This commit is contained in:
parent
2fd5771c3d
commit
b587328fed
|
@ -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)
|
||||
|
|
|
@ -24,8 +24,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QVersionNumber>
|
||||
#include <QtGui/QWindow>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
#include <private/qwaylanddisplay_p.h>
|
||||
#include <private/qwaylandwindow_p.h>
|
||||
#include <private/qwaylandshellsurface_p.h>
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
|
@ -36,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/screensaver.h>
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -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<crl::time> 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<xcb_connection_t*>(
|
||||
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<const char*>(&xev));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StartWaylandMove(QWindow *window) {
|
||||
if (const auto waylandWindow = static_cast<QWaylandWindow*>(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<QWaylandWindow*>(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 {
|
||||
|
|
|
@ -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<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
|
||||
return AllowNativeWindowFrameToggle()
|
||||
? object_ptr<Window::TitleWidgetQt>(parent)
|
||||
: object_ptr<Window::TitleWidgetQt>{ nullptr };
|
||||
return object_ptr<Window::TitleWidgetQt>(parent);
|
||||
}
|
||||
|
||||
inline bool NativeTitleRequiresShadow() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user