implemented linux x11 moving

This commit is contained in:
Altair Wei 2021-09-20 00:08:43 +08:00
parent 93ac6f6ee3
commit a365499455
6 changed files with 121 additions and 5 deletions

View File

@ -50,6 +50,7 @@ else()
if(MACOS)
list(APPEND SOURCES utilities_macos.mm)
else()
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS X11Extras REQUIRED)
list(APPEND SOURCES utilities_linux.cpp)
endif()
endif()
@ -87,6 +88,14 @@ if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE
dwmapi
)
else()
if(MACOS)
#TODO
else()
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::X11Extras
)
endif()
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE

View File

@ -1,15 +1,16 @@
#include "flwindow.h"
#include "../../framelesshelper.h"
#include <QScreen>
FRAMELESSHELPER_USE_NAMESPACE
FLWindow::FLWindow(QWidget *parent) : QWidget(parent)
{
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
setWindowFlags(Qt::FramelessWindowHint);
setStyleSheet(QString::fromLatin1("background:blue"));
setAttribute(Qt::WA_ShowModal);
resize(500, 500);
move(screen()->geometry().center() - frameGeometry().center());
}
FLWindow::~FLWindow()
@ -21,7 +22,7 @@ void FLWindow::initFramelessWindow()
{
FramelessHelper* helper = new FramelessHelper(windowHandle());
helper->setResizeBorderThickness(8);
helper->setTitleBarHeight(20);
helper->setTitleBarHeight(40);
helper->setResizable(true);
helper->install();
}

View File

@ -240,6 +240,16 @@ void FramelessHelper::updateHoverStates(const QPoint& pos)
m_hoveredFrameSection = mapPosToFrameSection(pos);
}
void FramelessHelper::startMove(QMouseEvent* event)
{
#ifdef Q_OS_LINUX
Utilities::sendX11ButtonRelease(m_window, event->globalPos());
Utilities::startX11Moving(m_window, event->globalPos());
event->accept();
return;
#endif
}
bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
{
bool filterOut = false;
@ -263,7 +273,20 @@ bool FramelessHelper::eventFilter(QObject *object, QEvent *event)
}
case QEvent::NonClientAreaMouseButtonPress:
case QEvent::MouseButtonPress:
{
auto ev = static_cast<QMouseEvent *>(event);
if (isHoverResizeHandler()) {
// Start system resize
filterOut = true;
} else if (isInTitlebarArea(ev->pos())) {
// Start system move
startMove(ev);
filterOut = true;
}
break;
}
case QEvent::NonClientAreaMouseButtonRelease:
case QEvent::MouseButtonRelease:
break;

View File

@ -33,6 +33,7 @@
QT_BEGIN_NAMESPACE
QT_FORWARD_DECLARE_CLASS(QWindow)
QT_FORWARD_DECLARE_CLASS(QMouseEvent)
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
@ -81,6 +82,8 @@ public:
void updateMouse(const QPoint& pos);
void updateHoverStates(const QPoint& pos);
void startMove(QMouseEvent* event);
protected:
bool eventFilter(QObject *object, QEvent *event) override;

View File

@ -58,6 +58,11 @@ FRAMELESSHELPER_API void updateQtFrameMargins(QWindow *window, const bool enable
[[nodiscard]] FRAMELESSHELPER_API QString getSystemErrorMessage(const QString &function);
#endif
#ifdef Q_OS_LINUX
FRAMELESSHELPER_API void sendX11ButtonRelease(QWindow *w, const QPoint &pos);
FRAMELESSHELPER_API void startX11Moving(QWindow *w, const QPoint &pos);
#endif
}
FRAMELESSHELPER_END_NAMESPACE

View File

@ -25,9 +25,25 @@
#include "utilities.h"
#include <QtCore/qvariant.h>
#include <QtCore/qdebug.h>
#include <QtX11Extras/qx11info_x11.h>
#include <X11/Xlib.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
static constexpr int kDefaultResizeBorderThickness = 8;
static constexpr int kDefaultCaptionHeight = 23;
@ -106,7 +122,8 @@ bool Utilities::shouldAppsUseDarkMode()
ColorizationArea Utilities::getColorizationArea()
{
// ### TO BE IMPLEMENTED
return ColorizationArea::None;
//return ColorizationArea::None; // None has been defined as a macro in X11 headers.
return ColorizationArea::All;
}
bool Utilities::isThemeChanged(const void *data)
@ -132,4 +149,62 @@ bool Utilities::showSystemMenu(const WId winId, const QPointF &pos)
return false;
}
void Utilities::sendX11ButtonRelease(QWindow *w, const QPoint &pos)
{
QPoint clientPos = w->mapFromGlobal(pos);
Display *display = QX11Info::display();
int screen = QX11Info::appScreen();
unsigned long rootWindow = QX11Info::appRootWindow(screen);
XEvent event;
memset(&event, 0, sizeof (event));
event.xbutton.button = 0;
event.xbutton.same_screen = True;
event.xbutton.send_event = True;
Window window = w->winId();
event.xbutton.window = window;
event.xbutton.root = rootWindow;
event.xbutton.x_root = pos.x();
event.xbutton.y_root = pos.y();
event.xbutton.x = clientPos.x();
event.xbutton.y = clientPos.y();
event.xbutton.type = ButtonRelease;
event.xbutton.time = CurrentTime;
if (XSendEvent(display, window, True, ButtonReleaseMask, &event) == 0)
qWarning() << "Cant send ButtonRelease event.";
XFlush(display);
}
void Utilities::startX11Moving(QWindow *w, const QPoint &pos)
{
Display *display = QX11Info::display();
int screen = QX11Info::appScreen();
unsigned long rootWindow = QX11Info::appRootWindow(screen);
static Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", False);
XUngrabPointer(display, CurrentTime);
XEvent event;
memset(&event, 0x00, sizeof(event));
event.xclient.type = ClientMessage;
event.xclient.window = w->winId();
event.xclient.message_type = netMoveResize;
event.xclient.serial = 0;
event.xclient.display = display;
event.xclient.send_event = True;
event.xclient.format = 32;
event.xclient.data.l[0] = pos.x();
event.xclient.data.l[1] = pos.y();
event.xclient.data.l[2] = _NET_WM_MOVERESIZE_MOVE;
event.xclient.data.l[3] = Button1;
event.xclient.data.l[4] = 0; /* unused */
if (XSendEvent(display, rootWindow,
False, SubstructureRedirectMask | SubstructureNotifyMask, &event) == 0)
qWarning() << "Cant send Move event.";
XFlush(display);
}
FRAMELESSHELPER_END_NAMESPACE