autotests: Add _NET_WM_MOVERESIZE tests
This commit is contained in:
parent
8892b16626
commit
6b1e2f24f4
3 changed files with 443 additions and 75 deletions
|
@ -54,7 +54,6 @@ private Q_SLOTS:
|
||||||
void testPointerMoveEnd_data();
|
void testPointerMoveEnd_data();
|
||||||
void testPointerMoveEnd();
|
void testPointerMoveEnd();
|
||||||
void testClientSideMove();
|
void testClientSideMove();
|
||||||
void testNetMove();
|
|
||||||
void testAdjustClientGeometryOfHiddenX11Panel_data();
|
void testAdjustClientGeometryOfHiddenX11Panel_data();
|
||||||
void testAdjustClientGeometryOfHiddenX11Panel();
|
void testAdjustClientGeometryOfHiddenX11Panel();
|
||||||
void testAdjustClientGeometryOfHiddenWaylandPanel_data();
|
void testAdjustClientGeometryOfHiddenWaylandPanel_data();
|
||||||
|
@ -536,76 +535,6 @@ void MoveResizeWindowTest::testClientSideMove()
|
||||||
QCOMPARE(pointerEnteredSpy.last().last().toPoint(), QPoint(50, 25));
|
QCOMPARE(pointerEnteredSpy.last().last().toPoint(), QPoint(50, 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveResizeWindowTest::testNetMove()
|
|
||||||
{
|
|
||||||
// this test verifies that a move request for an X11 window through NET API works
|
|
||||||
// create an xcb window
|
|
||||||
Test::XcbConnectionPtr c = Test::createX11Connection();
|
|
||||||
QVERIFY(!xcb_connection_has_error(c.get()));
|
|
||||||
|
|
||||||
xcb_window_t windowId = xcb_generate_id(c.get());
|
|
||||||
xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
|
|
||||||
0, 0, 100, 100,
|
|
||||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
|
|
||||||
xcb_size_hints_t hints;
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
xcb_icccm_size_hints_set_position(&hints, 1, 0, 0);
|
|
||||||
xcb_icccm_size_hints_set_size(&hints, 1, 100, 100);
|
|
||||||
xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
|
|
||||||
// let's set a no-border
|
|
||||||
NETWinInfo winInfo(c.get(), windowId, rootWindow(), NET::WMWindowType, NET::Properties2());
|
|
||||||
winInfo.setWindowType(NET::Override);
|
|
||||||
xcb_map_window(c.get(), windowId);
|
|
||||||
xcb_flush(c.get());
|
|
||||||
|
|
||||||
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
|
||||||
QVERIFY(windowCreatedSpy.wait());
|
|
||||||
X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
|
|
||||||
QVERIFY(window);
|
|
||||||
QCOMPARE(window->window(), windowId);
|
|
||||||
const QRectF origGeo = window->frameGeometry();
|
|
||||||
|
|
||||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
|
||||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
|
||||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
|
||||||
QVERIFY(!workspace()->moveResizeWindow());
|
|
||||||
|
|
||||||
// use NETRootInfo to trigger a move request
|
|
||||||
quint32 timestamp = 0;
|
|
||||||
Test::pointerMotion(window->frameGeometry().center(), timestamp++);
|
|
||||||
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
|
||||||
NETRootInfo root(c.get(), NET::Properties());
|
|
||||||
root.moveResizeRequest(windowId, origGeo.center().x(), origGeo.center().y(), NET::Move, XCB_BUTTON_INDEX_1);
|
|
||||||
xcb_flush(c.get());
|
|
||||||
|
|
||||||
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
|
||||||
QCOMPARE(workspace()->moveResizeWindow(), window);
|
|
||||||
QVERIFY(window->isInteractiveMove());
|
|
||||||
QCOMPARE(window->geometryRestore(), origGeo);
|
|
||||||
QCOMPARE(Cursors::self()->mouse()->pos(), origGeo.center());
|
|
||||||
|
|
||||||
// let's move a step
|
|
||||||
Test::pointerMotionRelative(QPoint(10, 10), timestamp++);
|
|
||||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
|
||||||
QCOMPARE(interactiveMoveResizeSteppedSpy.first().last(), origGeo.translated(10, 10));
|
|
||||||
|
|
||||||
// let's cancel the move resize again through the net API
|
|
||||||
root.moveResizeRequest(windowId, window->frameGeometry().center().x(), window->frameGeometry().center().y(), NET::MoveResizeCancel, XCB_BUTTON_INDEX_1);
|
|
||||||
xcb_flush(c.get());
|
|
||||||
QVERIFY(interactiveMoveResizeFinishedSpy.wait());
|
|
||||||
|
|
||||||
// and destroy the window again
|
|
||||||
xcb_unmap_window(c.get(), windowId);
|
|
||||||
xcb_destroy_window(c.get(), windowId);
|
|
||||||
xcb_flush(c.get());
|
|
||||||
c.reset();
|
|
||||||
|
|
||||||
QSignalSpy windowClosedSpy(window, &X11Window::closed);
|
|
||||||
QVERIFY(windowClosedSpy.wait());
|
|
||||||
|
|
||||||
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel_data()
|
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QRect>("panelGeometry");
|
QTest::addColumn<QRect>("panelGeometry");
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <KWayland/Client/surface.h>
|
#include <KWayland/Client/surface.h>
|
||||||
|
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
#include <netwm.h>
|
#include <netwm.h>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
|
|
||||||
|
@ -79,6 +80,17 @@ private Q_SLOTS:
|
||||||
void testOnAllDesktops();
|
void testOnAllDesktops();
|
||||||
void testInitialOnAllDesktops();
|
void testInitialOnAllDesktops();
|
||||||
void testChangeOnAllDesktops();
|
void testChangeOnAllDesktops();
|
||||||
|
void testNetWmKeyboardMove();
|
||||||
|
void testNetWmKeyboardMoveCancel();
|
||||||
|
void testNetWmKeyboardResize();
|
||||||
|
void testNetWmKeyboardResizeCancel();
|
||||||
|
void testNetWmButtonMove();
|
||||||
|
void testNetWmButtonMoveNotPressed();
|
||||||
|
void testNetWmButtonMoveCancel();
|
||||||
|
void testNetWmButtonSize_data();
|
||||||
|
void testNetWmButtonSize();
|
||||||
|
void testNetWmButtonSizeNotPressed();
|
||||||
|
void testNetWmButtonSizeCancel();
|
||||||
void testMinimumSize();
|
void testMinimumSize();
|
||||||
void testMaximumSize();
|
void testMaximumSize();
|
||||||
void testTrimCaption_data();
|
void testTrimCaption_data();
|
||||||
|
@ -1359,6 +1371,433 @@ void X11WindowTest::testChangeOnAllDesktops()
|
||||||
QCOMPARE(window->desktops(), (QList<VirtualDesktop *>{VirtualDesktopManager::self()->desktopForX11Id(1)}));
|
QCOMPARE(window->desktops(), (QList<VirtualDesktop *>{VirtualDesktopManager::self()->desktopForX11Id(1)}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmKeyboardMove()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can initiate a keyboard interactive move operation.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive move.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width() / 2), Xcb::toXNative(window->y() + window->height() / 2), NET::KeyboardMove, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveMove());
|
||||||
|
|
||||||
|
// Move the window to the right.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::keyboardKeyPressed(KEY_RIGHT, timestamp++);
|
||||||
|
Test::keyboardKeyReleased(KEY_RIGHT, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.translated(8, 0));
|
||||||
|
|
||||||
|
// Finish the interactive move.
|
||||||
|
Test::keyboardKeyPressed(KEY_ENTER, timestamp++);
|
||||||
|
Test::keyboardKeyReleased(KEY_ENTER, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.translated(8, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmKeyboardMoveCancel()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can initiate a keyboard interactive move operation and then cancel it.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive move.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width() / 2), Xcb::toXNative(window->y() + window->height() / 2), NET::KeyboardMove, XCB_BUTTON_INDEX_ANY);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveMove());
|
||||||
|
|
||||||
|
// Move the window to the right.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::keyboardKeyPressed(KEY_RIGHT, timestamp++);
|
||||||
|
Test::keyboardKeyReleased(KEY_RIGHT, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.translated(8, 0));
|
||||||
|
|
||||||
|
// Cancel the interactive move.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width() / 2), Xcb::toXNative(window->y() + window->height() / 2), NET::MoveResizeCancel, XCB_BUTTON_INDEX_ANY);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QVERIFY(interactiveMoveResizeFinishedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmKeyboardResize()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can initiate a keyboard interactive resize operation.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive resize.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width()), Xcb::toXNative(window->y() + window->height()), NET::KeyboardSize, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveResize());
|
||||||
|
|
||||||
|
// Move the window to the right, the frame geometry will be updated some time later.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::keyboardKeyPressed(KEY_RIGHT, timestamp++);
|
||||||
|
Test::keyboardKeyReleased(KEY_RIGHT, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QVERIFY(frameGeometryChangedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(0, 0, 8, 0));
|
||||||
|
|
||||||
|
// Finish the interactive move.
|
||||||
|
Test::keyboardKeyPressed(KEY_ENTER, timestamp++);
|
||||||
|
Test::keyboardKeyReleased(KEY_ENTER, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(0, 0, 8, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmKeyboardResizeCancel()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can initiate a keyboard interactive resize operation and then cancel it.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive resize.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width()), Xcb::toXNative(window->y() + window->height()), NET::KeyboardSize, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveResize());
|
||||||
|
|
||||||
|
// Move the window to the right, the frame geometry will be updated some time later.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::keyboardKeyPressed(KEY_RIGHT, timestamp++);
|
||||||
|
Test::keyboardKeyReleased(KEY_RIGHT, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QVERIFY(frameGeometryChangedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(0, 0, 8, 0));
|
||||||
|
|
||||||
|
// Cancel the interactive move.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width()), Xcb::toXNative(window->y() + window->height()), NET::MoveResizeCancel, XCB_BUTTON_INDEX_ANY);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QVERIFY(interactiveMoveResizeFinishedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmButtonMove()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can initiate an interactive move operation controlled by the pointer.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive move.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width() / 2), Xcb::toXNative(window->y() + window->height() / 2), NET::Move, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveMove());
|
||||||
|
|
||||||
|
// Move the window to the right.
|
||||||
|
Test::pointerMotionRelative(QPointF(8, 0), timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.translated(8, 0));
|
||||||
|
|
||||||
|
// Finish the interactive move.
|
||||||
|
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.translated(8, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmButtonMoveNotPressed()
|
||||||
|
{
|
||||||
|
// This test verifies that an interactive move operation won't be started if the specified button is not pressed.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive move.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width() / 2), Xcb::toXNative(window->y() + window->height() / 2), NET::Move, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QVERIFY(!interactiveMoveResizeStartedSpy.wait(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmButtonMoveCancel()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can initiate an interactive move operation controlled by the pointer and then cancel it.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive move.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||||
|
auto releaseButton = qScopeGuard([×tamp]() {
|
||||||
|
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||||
|
});
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width() / 2), Xcb::toXNative(window->y() + window->height() / 2), NET::Move, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveMove());
|
||||||
|
|
||||||
|
// Move the window to the right.
|
||||||
|
Test::pointerMotionRelative(QPointF(8, 0), timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.translated(8, 0));
|
||||||
|
|
||||||
|
// Cancel the interactive move.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x() + window->width() / 2), Xcb::toXNative(window->y() + window->height() / 2), NET::MoveResizeCancel, XCB_BUTTON_INDEX_ANY);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QVERIFY(interactiveMoveResizeFinishedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmButtonSize_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<Gravity>("gravity");
|
||||||
|
QTest::addColumn<NET::Direction>("direction");
|
||||||
|
|
||||||
|
QTest::addRow("top-left") << Gravity::TopLeft << NET::Direction::TopLeft;
|
||||||
|
QTest::addRow("top") << Gravity::Top << NET::Direction::Top;
|
||||||
|
QTest::addRow("top-right") << Gravity::TopRight << NET::Direction::TopRight;
|
||||||
|
QTest::addRow("right") << Gravity::Right << NET::Direction::Right;
|
||||||
|
QTest::addRow("bottom-right") << Gravity::BottomRight << NET::Direction::BottomRight;
|
||||||
|
QTest::addRow("bottom") << Gravity::Bottom << NET::Direction::Bottom;
|
||||||
|
QTest::addRow("bottom-left") << Gravity::BottomLeft << NET::Direction::BottomLeft;
|
||||||
|
QTest::addRow("left") << Gravity::Left << NET::Direction::Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QPointF directionToVector(NET::Direction direction, const QSizeF &size)
|
||||||
|
{
|
||||||
|
switch (direction) {
|
||||||
|
case NET::Direction::TopLeft:
|
||||||
|
return QPointF(-size.width(), -size.height());
|
||||||
|
case NET::Direction::Top:
|
||||||
|
return QPointF(0, -size.height());
|
||||||
|
case NET::Direction::TopRight:
|
||||||
|
return QPointF(size.width(), -size.height());
|
||||||
|
case NET::Direction::Right:
|
||||||
|
return QPointF(size.width(), 0);
|
||||||
|
case NET::Direction::BottomRight:
|
||||||
|
return QPointF(size.width(), size.height());
|
||||||
|
case NET::Direction::Bottom:
|
||||||
|
return QPointF(0, size.height());
|
||||||
|
case NET::Direction::BottomLeft:
|
||||||
|
return QPointF(-size.width(), size.height());
|
||||||
|
case NET::Direction::Left:
|
||||||
|
return QPointF(-size.width(), 0);
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QRectF expandRect(const QRectF &rect, NET::Direction direction, const QSizeF &amount)
|
||||||
|
{
|
||||||
|
switch (direction) {
|
||||||
|
case NET::Direction::TopLeft:
|
||||||
|
return rect.adjusted(-amount.width(), -amount.height(), 0, 0);
|
||||||
|
case NET::Direction::Top:
|
||||||
|
return rect.adjusted(0, -amount.height(), 0, 0);
|
||||||
|
case NET::Direction::TopRight:
|
||||||
|
return rect.adjusted(0, -amount.height(), amount.width(), 0);
|
||||||
|
case NET::Direction::Right:
|
||||||
|
return rect.adjusted(0, 0, amount.width(), 0);
|
||||||
|
case NET::Direction::BottomRight:
|
||||||
|
return rect.adjusted(0, 0, amount.width(), amount.height());
|
||||||
|
case NET::Direction::Bottom:
|
||||||
|
return rect.adjusted(0, 0, 0, amount.height());
|
||||||
|
case NET::Direction::BottomLeft:
|
||||||
|
return rect.adjusted(-amount.width(), 0, 0, amount.height());
|
||||||
|
case NET::Direction::Left:
|
||||||
|
return rect.adjusted(-amount.width(), 0, 0, 0);
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmButtonSize()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can initiate an interactive move operation controlled by the pointer.
|
||||||
|
|
||||||
|
QFETCH(NET::Direction, direction);
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive move.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
const QPointF initialPointer = window->frameGeometry().center() + directionToVector(direction, originalGeometry.size() * 0.5);
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||||
|
Test::pointerMotion(initialPointer, timestamp++);
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(initialPointer.x()), Xcb::toXNative(initialPointer.y()), direction, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveResize());
|
||||||
|
QTEST(window->interactiveMoveResizeGravity(), "gravity");
|
||||||
|
|
||||||
|
// Resize the window a tiny bit.
|
||||||
|
Test::pointerMotionRelative(directionToVector(direction, QSizeF(8, 8)), timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QVERIFY(frameGeometryChangedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), expandRect(originalGeometry, direction, QSizeF(8, 8)));
|
||||||
|
|
||||||
|
// Finish the interactive move.
|
||||||
|
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||||
|
QCOMPARE(window->frameGeometry(), expandRect(originalGeometry, direction, QSizeF(8, 8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmButtonSizeNotPressed()
|
||||||
|
{
|
||||||
|
// This test verifies that an interactive siize operation won't be started if the specified button is not pressed.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive move.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x()), Xcb::toXNative(window->y()), NET::TopLeft, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QVERIFY(!interactiveMoveResizeStartedSpy.wait(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11WindowTest::testNetWmButtonSizeCancel()
|
||||||
|
{
|
||||||
|
// This test verifies that a client can start an interactive resize and then cancel it.
|
||||||
|
|
||||||
|
// Create an xcb window.
|
||||||
|
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||||
|
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||||
|
X11Window *window = createWindow(c.get(), QRect(100, 100, 100, 200));
|
||||||
|
|
||||||
|
// Request interactive resize.
|
||||||
|
const QRectF originalGeometry = window->frameGeometry();
|
||||||
|
quint32 timestamp = 0;
|
||||||
|
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||||
|
auto releaseButton = qScopeGuard([×tamp]() {
|
||||||
|
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||||
|
});
|
||||||
|
Test::pointerMotion(originalGeometry.topLeft(), timestamp++);
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x()), Xcb::toXNative(window->y()), NET::TopLeft, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||||
|
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||||
|
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||||
|
QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged);
|
||||||
|
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||||
|
QVERIFY(window->isInteractiveResize());
|
||||||
|
|
||||||
|
// Resize the window a tiny bit.
|
||||||
|
Test::pointerMotionRelative(QPointF(-8, -8), timestamp++);
|
||||||
|
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||||
|
QVERIFY(frameGeometryChangedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(-8, -8, 0, 0));
|
||||||
|
|
||||||
|
// Cancel the interactive resize.
|
||||||
|
{
|
||||||
|
NETRootInfo root(c.get(), NET::Properties());
|
||||||
|
root.moveResizeRequest(window->window(), Xcb::toXNative(window->x()), Xcb::toXNative(window->y()), NET::MoveResizeCancel, XCB_BUTTON_INDEX_1);
|
||||||
|
xcb_flush(c.get());
|
||||||
|
}
|
||||||
|
QVERIFY(interactiveMoveResizeFinishedSpy.wait());
|
||||||
|
QCOMPARE(window->frameGeometry(), originalGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
void X11WindowTest::testMinimumSize()
|
void X11WindowTest::testMinimumSize()
|
||||||
{
|
{
|
||||||
// This test verifies that the minimum size constraint is correctly applied.
|
// This test verifies that the minimum size constraint is correctly applied.
|
||||||
|
|
|
@ -1115,6 +1115,10 @@ public:
|
||||||
{
|
{
|
||||||
return isInteractiveMoveResize() && interactiveMoveResizeGravity() != Gravity::None;
|
return isInteractiveMoveResize() && interactiveMoveResizeGravity() != Gravity::None;
|
||||||
}
|
}
|
||||||
|
Gravity interactiveMoveResizeGravity() const
|
||||||
|
{
|
||||||
|
return m_interactiveMoveResize.gravity;
|
||||||
|
}
|
||||||
QPointF interactiveMoveResizeAnchor() const
|
QPointF interactiveMoveResizeAnchor() const
|
||||||
{
|
{
|
||||||
return m_interactiveMoveResize.anchor;
|
return m_interactiveMoveResize.anchor;
|
||||||
|
@ -1618,10 +1622,6 @@ protected:
|
||||||
return m_interactiveMoveResize.initialGeometry;
|
return m_interactiveMoveResize.initialGeometry;
|
||||||
}
|
}
|
||||||
void setMoveResizeGeometry(const QRectF &geo);
|
void setMoveResizeGeometry(const QRectF &geo);
|
||||||
Gravity interactiveMoveResizeGravity() const
|
|
||||||
{
|
|
||||||
return m_interactiveMoveResize.gravity;
|
|
||||||
}
|
|
||||||
void setInteractiveMoveResizeGravity(Gravity gravity)
|
void setInteractiveMoveResizeGravity(Gravity gravity)
|
||||||
{
|
{
|
||||||
m_interactiveMoveResize.gravity = gravity;
|
m_interactiveMoveResize.gravity = gravity;
|
||||||
|
|
Loading…
Reference in a new issue