Do not snap to windows of the Dock type

We do not snap to docks (i.e. panels) since the ones we
actually want to snap to (i.e. always visible ones) will
restrict the workspace area, and the window will snap to
that, effectively snapping to the panel too. Explicitedly
avoiding panel snapping solves any possible issue of
floating panels, since they change their size when a window
gets near them.
This commit is contained in:
Niccolò Venerandi 2024-05-17 09:17:24 +00:00 committed by Vlad Zahorodnii
parent de88370577
commit b59ba5b9b7
2 changed files with 8 additions and 164 deletions

View file

@ -54,10 +54,6 @@ private Q_SLOTS:
void testPointerMoveEnd_data();
void testPointerMoveEnd();
void testClientSideMove();
void testAdjustClientGeometryOfHiddenX11Panel_data();
void testAdjustClientGeometryOfHiddenX11Panel();
void testAdjustClientGeometryOfHiddenWaylandPanel_data();
void testAdjustClientGeometryOfHiddenWaylandPanel();
void testResizeForVirtualKeyboard_data();
void testResizeForVirtualKeyboard();
void testResizeForVirtualKeyboardWithMaximize();
@ -535,165 +531,6 @@ void MoveResizeWindowTest::testClientSideMove()
QCOMPARE(pointerEnteredSpy.last().last().toPoint(), QPoint(50, 25));
}
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel_data()
{
QTest::addColumn<QRect>("panelGeometry");
QTest::addColumn<QPoint>("targetPoint");
QTest::addColumn<QPoint>("expectedAdjustedPoint");
QTest::addColumn<quint32>("hideLocation");
QTest::newRow("top") << QRect(0, 0, 100, 20) << QPoint(50, 25) << QPoint(50, 20) << 0u;
QTest::newRow("bottom") << QRect(0, 1024 - 20, 100, 20) << QPoint(50, 1024 - 25 - 50) << QPoint(50, 1024 - 20 - 50) << 2u;
QTest::newRow("left") << QRect(0, 0, 20, 100) << QPoint(25, 50) << QPoint(20, 50) << 3u;
QTest::newRow("right") << QRect(1280 - 20, 0, 20, 100) << QPoint(1280 - 25 - 100, 50) << QPoint(1280 - 20 - 100, 50) << 1u;
}
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel()
{
// this test verifies that auto hiding panels are ignored when adjusting client geometry
// see BUG 365892
// first create our panel
Test::XcbConnectionPtr c = Test::createX11Connection();
QVERIFY(!xcb_connection_has_error(c.get()));
xcb_window_t windowId = xcb_generate_id(c.get());
QFETCH(QRect, panelGeometry);
xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
panelGeometry.x(), panelGeometry.y(), panelGeometry.width(), panelGeometry.height(),
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, panelGeometry.x(), panelGeometry.y());
xcb_icccm_size_hints_set_size(&hints, 1, panelGeometry.width(), panelGeometry.height());
xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
NETWinInfo winInfo(c.get(), windowId, rootWindow(), NET::WMWindowType, NET::Properties2());
winInfo.setWindowType(NET::Dock);
xcb_map_window(c.get(), windowId);
xcb_flush(c.get());
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
QVERIFY(windowCreatedSpy.wait());
X11Window *panel = windowCreatedSpy.first().first().value<X11Window *>();
QVERIFY(panel);
QCOMPARE(panel->window(), windowId);
QCOMPARE(panel->frameGeometry(), panelGeometry);
QVERIFY(panel->isDock());
// let's create a window
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
QVERIFY(surface != nullptr);
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
QVERIFY(shellSurface != nullptr);
auto testWindow = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
QVERIFY(testWindow);
QVERIFY(testWindow->isMovable());
// panel is not yet hidden, we should snap against it
QFETCH(QPoint, targetPoint);
QTEST(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false).toPoint(), "expectedAdjustedPoint");
// now let's hide the panel
QSignalSpy panelHiddenSpy(panel, &Window::hiddenChanged);
QFETCH(quint32, hideLocation);
xcb_change_property(c.get(), XCB_PROP_MODE_REPLACE, windowId, atoms->kde_screen_edge_show, XCB_ATOM_CARDINAL, 32, 1, &hideLocation);
xcb_flush(c.get());
QVERIFY(panelHiddenSpy.wait());
// now try to snap again
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
// and destroy the panel again
xcb_unmap_window(c.get(), windowId);
xcb_destroy_window(c.get(), windowId);
xcb_flush(c.get());
c.reset();
QSignalSpy panelClosedSpy(panel, &X11Window::closed);
QVERIFY(panelClosedSpy.wait());
// snap once more
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
// and close
QSignalSpy windowClosedSpy(testWindow, &Window::closed);
shellSurface.reset();
surface.reset();
QVERIFY(windowClosedSpy.wait());
}
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenWaylandPanel_data()
{
QTest::addColumn<uint32_t>("anchor");
QTest::addColumn<QRect>("panelGeometry");
QTest::addColumn<QPoint>("targetPoint");
QTest::addColumn<QPoint>("expectedAdjustedPoint");
QTest::newRow("top") << uint32_t(Test::LayerSurfaceV1::anchor_top) << QRect(0, 0, 1280, 20) << QPoint(50, 25) << QPoint(50, 20);
QTest::newRow("bottom") << uint32_t(Test::LayerSurfaceV1::anchor_bottom) << QRect(0, 1024 - 20, 1280, 20) << QPoint(50, 1024 - 25 - 50) << QPoint(50, 1024 - 20 - 50);
QTest::newRow("left") << uint32_t(Test::LayerSurfaceV1::anchor_left) << QRect(0, 0, 20, 1024) << QPoint(25, 50) << QPoint(20, 50);
QTest::newRow("right") << uint32_t(Test::LayerSurfaceV1::anchor_right) << QRect(1280 - 20, 0, 20, 1024) << QPoint(1280 - 25 - 100, 50) << QPoint(1280 - 20 - 100, 50);
}
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenWaylandPanel()
{
// this test verifies that hidden panels are ignored when adjusting client geometry
// see BUG 365892
// first create our panel
std::unique_ptr<KWayland::Client::Surface> panelSurface(Test::createSurface());
std::unique_ptr<Test::LayerSurfaceV1> panelShellSurface(Test::createLayerSurfaceV1(panelSurface.get(), QStringLiteral("dock")));
QFETCH(QRect, panelGeometry);
QFETCH(uint32_t, anchor);
panelShellSurface->set_anchor(anchor);
panelShellSurface->set_size(panelGeometry.width(), panelGeometry.height());
panelSurface->commit(KWayland::Client::Surface::CommitFlag::None);
// let's render
QSignalSpy panelConfigureRequestedSpy(panelShellSurface.get(), &Test::LayerSurfaceV1::configureRequested);
QVERIFY(panelConfigureRequestedSpy.wait());
auto panel = Test::renderAndWaitForShown(panelSurface.get(), panelConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
QVERIFY(panel);
QCOMPARE(panel->frameGeometry(), panelGeometry);
QVERIFY(panel->isDock());
// let's create a window
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
QVERIFY(surface != nullptr);
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
QVERIFY(shellSurface != nullptr);
auto testWindow = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
QVERIFY(testWindow);
QVERIFY(testWindow->isMovable());
// panel is not yet hidden, we should snap against it
QFETCH(QPoint, targetPoint);
QTEST(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false).toPoint(), "expectedAdjustedPoint");
// now let's hide the panel
panel->setHidden(true);
// now try to snap again
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
// and destroy the panel again
QSignalSpy panelClosedSpy(panel, &Window::closed);
panelShellSurface.reset();
panelSurface.reset();
QVERIFY(panelClosedSpy.wait());
// snap once more
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
// and close
QSignalSpy windowClosedSpy(testWindow, &Window::closed);
shellSurface.reset();
surface.reset();
QVERIFY(windowClosedSpy.wait());
}
void MoveResizeWindowTest::testResizeForVirtualKeyboard_data()
{
QTest::addColumn<QRect>("windowRect");

View file

@ -2719,7 +2719,14 @@ QPointF Workspace::adjustWindowPosition(const Window *window, QPointF pos, bool
if (!(*l)->isOnCurrentActivity()) {
continue; // wrong activity
}
if ((*l)->isUnmanaged() || (*l)->isDesktop() || (*l)->isSplash() || (*l)->isNotification() || (*l)->isCriticalNotification() || (*l)->isOnScreenDisplay() || (*l)->isAppletPopup()) {
// We do not snap to docks (i.e. panels) since the ones we actually want to snap to
// (i.e. always visible ones) will restrict the workspace area, and the window will
// snap to that, effectively snapping to the panel too. Explicitly avoiding panel
// snapping solves any possible issue of floating panels, since they change their
// size when a window gets near them.
if ((*l)->isUnmanaged() || (*l)->isDesktop() || (*l)->isSplash() || (*l)->isNotification() || (*l)->isCriticalNotification() || (*l)->isOnScreenDisplay() || (*l)->isAppletPopup() || (*l)->isDock()) {
continue;
}