diff --git a/autotests/integration/decoration_input_test.cpp b/autotests/integration/decoration_input_test.cpp --- a/autotests/integration/decoration_input_test.cpp +++ b/autotests/integration/decoration_input_test.cpp @@ -170,9 +170,12 @@ QTest::newRow("topLeft") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::WlShell; QTest::newRow("top") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::WlShell; QTest::newRow("topRight") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::WlShell; - QTest::newRow("topLeft|xdg") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("top|xdg") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("topRight|xdg") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topLeft|xdgv5") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("top|xdgv5") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topRight|xdgv5") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topLeft|xdgv6") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("top|xdgv6") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("topRight|xdgv6") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV6; } void DecorationInputTest::testAxis() @@ -224,9 +227,12 @@ QTest::newRow("topLeft") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::WlShell; QTest::newRow("top") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::WlShell; QTest::newRow("topRight") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::WlShell; - QTest::newRow("topLeft|xdg") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("top|xdg") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("topRight|xdg") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topLeft|xdgv5") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("top|xdgv5") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topRight|xdgv5") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topLeft|xdgv6") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("top|xdgv6") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("topRight|xdgv6") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV6; } void KWin::DecorationInputTest::testDoubleClick() @@ -279,9 +285,13 @@ QTest::newRow("topLeft") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::WlShell; QTest::newRow("top") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::WlShell; QTest::newRow("topRight") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::WlShell; - QTest::newRow("topLeft|xdg") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("top|xdg") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("topRight|xdg") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topLeft|xdgv5") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("top|xdgv5") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topRight|xdgv5") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("topLeft|xdgv6") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("top|xdgv6") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("topRight|xdgv6") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV6; + } void KWin::DecorationInputTest::testDoubleTap() @@ -330,6 +340,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void DecorationInputTest::testHover() @@ -380,10 +391,14 @@ QTest::newRow("To left") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::WlShell; QTest::newRow("To bottom") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::WlShell; QTest::newRow("To top") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::WlShell; - QTest::newRow("To right|xdg") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0) << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("To left|xdg") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("To bottom|xdg") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("To top|xdg") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To right|xdgv5") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To left|xdgv5") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To bottom|xdgv5") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To top|xdgv5") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To right|xdgv6") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0) << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("To left|xdgv6") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("To bottom|xdgv6") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("To top|xdgv6") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::XdgShellV6; } void DecorationInputTest::testPressToMove() @@ -445,10 +460,14 @@ QTest::newRow("To left") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::WlShell; QTest::newRow("To bottom") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::WlShell; QTest::newRow("To top") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::WlShell; - QTest::newRow("To right|xdg") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0) << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("To left|xdg") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("To bottom|xdg") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::XdgShellV5; - QTest::newRow("To top|xdg") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To right|xdgv5") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To left|xdgv5") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To bottom|xdgv5") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To top|xdgv5") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("To right|xdgv6") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0) << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("To left|xdgv6") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0) << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("To bottom|xdgv6") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30) << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("To top|xdgv6") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30) << Test::ShellSurfaceType::XdgShellV6; } void DecorationInputTest::testTapToMove() @@ -508,10 +527,13 @@ QTest::newRow("wlShell - left") << Test::ShellSurfaceType::WlShell << Qt::LeftEdge << Qt::SizeHorCursor; QTest::newRow("xdgShellV5 - left") << Test::ShellSurfaceType::XdgShellV5 << Qt::LeftEdge << Qt::SizeHorCursor; + QTest::newRow("xdgShellV6 - left") << Test::ShellSurfaceType::XdgShellV6 << Qt::LeftEdge << Qt::SizeHorCursor; QTest::newRow("wlShell - right") << Test::ShellSurfaceType::WlShell << Qt::RightEdge << Qt::SizeHorCursor; QTest::newRow("xdgShellV5 - right") << Test::ShellSurfaceType::XdgShellV5 << Qt::RightEdge << Qt::SizeHorCursor; + QTest::newRow("xdgShellV6 - right") << Test::ShellSurfaceType::XdgShellV6 << Qt::RightEdge << Qt::SizeHorCursor; QTest::newRow("wlShell - bottom") << Test::ShellSurfaceType::WlShell << Qt::BottomEdge << Qt::SizeVerCursor; QTest::newRow("xdgShellV5 - bottom") << Test::ShellSurfaceType::XdgShellV5 << Qt::BottomEdge << Qt::SizeVerCursor; + QTest::newRow("xdgShellV6 - bottom") << Test::ShellSurfaceType::XdgShellV6 << Qt::BottomEdge << Qt::SizeVerCursor; } void DecorationInputTest::testResizeOutsideWindow() diff --git a/autotests/integration/dont_crash_no_border.cpp b/autotests/integration/dont_crash_no_border.cpp --- a/autotests/integration/dont_crash_no_border.cpp +++ b/autotests/integration/dont_crash_no_border.cpp @@ -101,6 +101,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void DontCrashNoBorder::testCreateWindow() diff --git a/autotests/integration/effects/fade_test.cpp b/autotests/integration/effects/fade_test.cpp --- a/autotests/integration/effects/fade_test.cpp +++ b/autotests/integration/effects/fade_test.cpp @@ -119,6 +119,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void FadeTest::testWindowCloseAfterWindowHidden() diff --git a/autotests/integration/helper/kill.cpp b/autotests/integration/helper/kill.cpp --- a/autotests/integration/helper/kill.cpp +++ b/autotests/integration/helper/kill.cpp @@ -18,7 +18,10 @@ along with this program. If not, see . *********************************************************************/ #include +#include +#include #include +#include int main(int argc, char *argv[]) { @@ -28,5 +31,14 @@ w.setGeometry(QRect(0, 0, 100, 200)); w.show(); + //after showing the window block the main thread + //1 as we want it to come after the singleshots in qApp construction + QTimer::singleShot(1, []() { + //block + while(true) { + sleep(100000); + } + }); + return app.exec(); } diff --git a/autotests/integration/kwin_wayland_test.h b/autotests/integration/kwin_wayland_test.h --- a/autotests/integration/kwin_wayland_test.h +++ b/autotests/integration/kwin_wayland_test.h @@ -118,7 +118,8 @@ KWayland::Client::Surface *createSurface(QObject *parent = nullptr); enum class ShellSurfaceType { WlShell, - XdgShellV5 + XdgShellV5, + XdgShellV6 }; QObject *createShellSurface(ShellSurfaceType type, KWayland::Client::Surface *surface, QObject *parent = nullptr); KWayland::Client::ShellSurface *createShellSurface(KWayland::Client::Surface *surface, QObject *parent = nullptr); diff --git a/autotests/integration/move_resize_window_test.cpp b/autotests/integration/move_resize_window_test.cpp --- a/autotests/integration/move_resize_window_test.cpp +++ b/autotests/integration/move_resize_window_test.cpp @@ -502,6 +502,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void MoveResizeWindowTest::testClientSideMove() diff --git a/autotests/integration/plasma_surface_test.cpp b/autotests/integration/plasma_surface_test.cpp --- a/autotests/integration/plasma_surface_test.cpp +++ b/autotests/integration/plasma_surface_test.cpp @@ -256,12 +256,16 @@ QTest::newRow("always visible - wlShell") << Test::ShellSurfaceType::WlShell << PlasmaShellSurface::PanelBehavior::AlwaysVisible << true << QRect(0, 50, 1280, 974) << KWin::DockLayer; QTest::newRow("always visible - xdgShellV5") << Test::ShellSurfaceType::XdgShellV5 << PlasmaShellSurface::PanelBehavior::AlwaysVisible << true << QRect(0, 50, 1280, 974) << KWin::DockLayer; + QTest::newRow("always visible - xdgShellV6") << Test::ShellSurfaceType::XdgShellV6 << PlasmaShellSurface::PanelBehavior::AlwaysVisible << true << QRect(0, 50, 1280, 974) << KWin::DockLayer; QTest::newRow("autohide - wlShell") << Test::ShellSurfaceType::WlShell << PlasmaShellSurface::PanelBehavior::AutoHide << false << QRect(0, 0, 1280, 1024) << KWin::AboveLayer; QTest::newRow("autohide - xdgShellV5") << Test::ShellSurfaceType::XdgShellV5 << PlasmaShellSurface::PanelBehavior::AutoHide << false << QRect(0, 0, 1280, 1024) << KWin::AboveLayer; + QTest::newRow("autohide - xdgShellV6") << Test::ShellSurfaceType::XdgShellV6 << PlasmaShellSurface::PanelBehavior::AutoHide << false << QRect(0, 0, 1280, 1024) << KWin::AboveLayer; QTest::newRow("windows can cover - wlShell") << Test::ShellSurfaceType::WlShell << PlasmaShellSurface::PanelBehavior::WindowsCanCover << false << QRect(0, 0, 1280, 1024) << KWin::NormalLayer; QTest::newRow("windows can cover - xdgShellV5") << Test::ShellSurfaceType::XdgShellV5 << PlasmaShellSurface::PanelBehavior::WindowsCanCover << false << QRect(0, 0, 1280, 1024) << KWin::NormalLayer; + QTest::newRow("windows can cover - xdgShellV6") << Test::ShellSurfaceType::XdgShellV6 << PlasmaShellSurface::PanelBehavior::WindowsCanCover << false << QRect(0, 0, 1280, 1024) << KWin::NormalLayer; QTest::newRow("windows go below - wlShell") << Test::ShellSurfaceType::WlShell << PlasmaShellSurface::PanelBehavior::WindowsGoBelow << false << QRect(0, 0, 1280, 1024) << KWin::DockLayer; QTest::newRow("windows go below - xdgShellV5") << Test::ShellSurfaceType::XdgShellV5 << PlasmaShellSurface::PanelBehavior::WindowsGoBelow << false << QRect(0, 0, 1280, 1024) << KWin::DockLayer; + QTest::newRow("windows go below - xdgShellV6") << Test::ShellSurfaceType::XdgShellV6 << PlasmaShellSurface::PanelBehavior::WindowsGoBelow << false << QRect(0, 0, 1280, 1024) << KWin::DockLayer; } void PlasmaSurfaceTest::testPanelTypeHasStrut() diff --git a/autotests/integration/pointer_constraints_test.cpp b/autotests/integration/pointer_constraints_test.cpp --- a/autotests/integration/pointer_constraints_test.cpp +++ b/autotests/integration/pointer_constraints_test.cpp @@ -129,6 +129,10 @@ QTest::newRow("XdgShellV5 - bottomRight") << Test::ShellSurfaceType::XdgShellV5 << bottomRight << 1 << 1; QTest::newRow("XdgShellV5 - topLeft") << Test::ShellSurfaceType::XdgShellV5 << topLeft << -1 << -1; QTest::newRow("XdgShellV5 - topRight") << Test::ShellSurfaceType::XdgShellV5 << topRight << 1 << -1; + QTest::newRow("XdgShellV6 - bottomLeft") << Test::ShellSurfaceType::XdgShellV6 << bottomLeft << -1 << 1; + QTest::newRow("XdgShellV6 - bottomRight") << Test::ShellSurfaceType::XdgShellV6 << bottomRight << 1 << 1; + QTest::newRow("XdgShellV6 - topLeft") << Test::ShellSurfaceType::XdgShellV6 << topLeft << -1 << -1; + QTest::newRow("XdgShellV6 - topRight") << Test::ShellSurfaceType::XdgShellV6 << topRight << 1 << -1; } void TestPointerConstraints::testConfinedPointer() @@ -255,6 +259,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestPointerConstraints::testLockedPointer() @@ -305,6 +310,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestPointerConstraints::testBreakConstrainedPointer() @@ -393,6 +399,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("XdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("XdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestPointerConstraints::testCloseWindowWithLockedPointer() diff --git a/autotests/integration/scene_qpainter_test.cpp b/autotests/integration/scene_qpainter_test.cpp --- a/autotests/integration/scene_qpainter_test.cpp +++ b/autotests/integration/scene_qpainter_test.cpp @@ -156,6 +156,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void SceneQPainterTest::testWindow() @@ -260,6 +261,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void SceneQPainterTest::testCompositorRestart() diff --git a/autotests/integration/shell_client_test.cpp b/autotests/integration/shell_client_test.cpp --- a/autotests/integration/shell_client_test.cpp +++ b/autotests/integration/shell_client_test.cpp @@ -75,8 +75,8 @@ void testDesktopFileName(); void testCaptionSimplified(); void testCaptionMultipleWindows(); - void testKillWindow_data(); - void testKillWindow(); + void testUnresponsiveWindow_data(); + void testUnresponsiveWindow(); void testX11WindowId_data(); void testX11WindowId(); }; @@ -120,6 +120,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestShellClient::testMapUnmapMap() @@ -281,6 +282,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestShellClient::testWindowOutputs() @@ -327,6 +329,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestShellClient::testMinimizeActiveWindow() @@ -368,9 +371,12 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell << ServerSideDecoration::Mode::Client; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5 << ServerSideDecoration::Mode::Client; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6 << ServerSideDecoration::Mode::Client; + QTest::newRow("wlShell - deco") << Test::ShellSurfaceType::WlShell << ServerSideDecoration::Mode::Server; QTest::newRow("xdgShellV5 - deco") << Test::ShellSurfaceType::XdgShellV5 << ServerSideDecoration::Mode::Server; + QTest::newRow("xdgShellV6 - deco") << Test::ShellSurfaceType::XdgShellV6 << ServerSideDecoration::Mode::Server; } void TestShellClient::testFullscreen() @@ -411,6 +417,7 @@ qobject_cast(shellSurface.data())->setFullscreen(); break; case Test::ShellSurfaceType::XdgShellV5: + case Test::ShellSurfaceType::XdgShellV6: qobject_cast(shellSurface.data())->setFullscreen(true); break; default: @@ -441,6 +448,7 @@ qobject_cast(shellSurface.data())->setToplevel(); break; case Test::ShellSurfaceType::XdgShellV5: + case Test::ShellSurfaceType::XdgShellV6: qobject_cast(shellSurface.data())->setFullscreen(false); break; default: @@ -465,9 +473,11 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell << ServerSideDecoration::Mode::Client; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5 << ServerSideDecoration::Mode::Client; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6 << ServerSideDecoration::Mode::Client; QTest::newRow("wlShell - deco") << Test::ShellSurfaceType::WlShell << ServerSideDecoration::Mode::Server; QTest::newRow("xdgShellV5 - deco") << Test::ShellSurfaceType::XdgShellV5 << ServerSideDecoration::Mode::Server; + QTest::newRow("xdgShellV6 - deco") << Test::ShellSurfaceType::XdgShellV6 << ServerSideDecoration::Mode::Server; } void TestShellClient::testMaximizedToFullscreen() @@ -506,6 +516,7 @@ qobject_cast(shellSurface.data())->setMaximized(); break; case Test::ShellSurfaceType::XdgShellV5: + case Test::ShellSurfaceType::XdgShellV6: qobject_cast(shellSurface.data())->setMaximized(true); break; default: @@ -524,6 +535,7 @@ qobject_cast(shellSurface.data())->setFullscreen(); break; case Test::ShellSurfaceType::XdgShellV5: + case Test::ShellSurfaceType::XdgShellV6: qobject_cast(shellSurface.data())->setFullscreen(true); break; default: @@ -556,6 +568,7 @@ qobject_cast(shellSurface.data())->setToplevel(); break; case Test::ShellSurfaceType::XdgShellV5: + case Test::ShellSurfaceType::XdgShellV6: qobject_cast(shellSurface.data())->setFullscreen(false); break; default: @@ -567,6 +580,7 @@ QCOMPARE(sizeChangeRequestedSpy.count(), 1); QEXPECT_FAIL("wlShell - deco", "With decoration incorrect geometry requested", Continue); QEXPECT_FAIL("xdgShellV5 - deco", "With decoration incorrect geometry requested", Continue); + QEXPECT_FAIL("xdgShellV6 - deco", "With decoration incorrect geometry requested", Continue); QCOMPARE(sizeChangeRequestedSpy.last().first().toSize(), QSize(100, 50)); // TODO: should switch to fullscreen once it's updated QVERIFY(!c->isFullScreen()); @@ -579,6 +593,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestShellClient::testWindowOpensLargerThanScreen() @@ -615,6 +630,7 @@ QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestShellClient::testHidden() @@ -741,15 +757,21 @@ QCOMPARE(c4->captionSuffix(), QStringLiteral(" <4>")); } -void TestShellClient::testKillWindow_data() +void TestShellClient::testUnresponsiveWindow_data() { + QTest::addColumn("shellInterface");//see env selection in qwaylandintegration.cpp QTest::addColumn("socketMode"); - QTest::newRow("display") << false; - QTest::newRow("socket") << true; + //wl-shell ping is not implemented + //QTest::newRow("wl-shell display") << "wl-shell" << false; + //QTest::newRow("wl-shell socket") << "wl-shell" << true; + QTest::newRow("xdgv5 display") << "xdg-shell-v5" << false; + QTest::newRow("xdgv5 socket") << "xdg-shell-v5" << true; + QTest::newRow("xdgv6 display") << "xdg-shell-v6" << false; + QTest::newRow("xdgv6 socket") << "xdg-shell-v6" << true; } -void TestShellClient::testKillWindow() +void TestShellClient::testUnresponsiveWindow() { // this test verifies that killWindow properly terminates a process // for this an external binary is launched @@ -760,7 +782,10 @@ QScopedPointer process(new QProcess); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + + QFETCH(QString, shellInterface); QFETCH(bool, socketMode); + env.insert("QT_WAYLAND_SHELL_INTEGRATION", shellInterface); if (socketMode) { int sx[2]; QVERIFY(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) >= 0); @@ -781,20 +806,46 @@ AbstractClient *killClient = nullptr; QVERIFY(shellClientAddedSpy.wait()); killClient = shellClientAddedSpy.first().first().value(); - QVERIFY(killClient); - QSignalSpy finishedSpy(process.data(), static_cast(&QProcess::finished)); - QVERIFY(finishedSpy.isValid()); - killClient->killWindow(); - QVERIFY(finishedSpy.wait()); - QVERIFY(!finishedSpy.isEmpty()); + QSignalSpy unresponsiveSpy(killClient, &AbstractClient::unresponsiveChanged); + QSignalSpy killedSpy(process.data(), static_cast(&QProcess::finished)); + QSignalSpy deletedSpy(killClient, &QObject::destroyed); + + qint64 startTime = QDateTime::currentMSecsSinceEpoch(); + + //wait for the process to be frozen + QTest::qWait(10); + + //pretend the user clicked the close button + killClient->closeWindow(); + + //client should not yet be marked unresponsive nor killed + QVERIFY(!killClient->unresponsive()); + QVERIFY(killedSpy.isEmpty()); + + QVERIFY(unresponsiveSpy.wait()); + //client should be marked unresponsive but not killed + auto elapsed1 = QDateTime::currentMSecsSinceEpoch() - startTime; + QVERIFY(elapsed1 > 900 && elapsed1 < 1200); //ping timer is 1s, but coarse timers on a test across two processes means we need a fuzzy compare + QVERIFY(killClient->unresponsive()); + QVERIFY(killedSpy.isEmpty()); + + QVERIFY(deletedSpy.wait()); + if (!socketMode) { + //process was killed - because we're across process this could happen in either order + QVERIFY(killedSpy.count() || killedSpy.wait()); + } + + auto elapsed2 = QDateTime::currentMSecsSinceEpoch() - startTime; + QVERIFY(elapsed2 > 1800); //second ping comes in a second later } void TestShellClient::testX11WindowId_data() { QTest::addColumn("type"); QTest::newRow("wlShell") << Test::ShellSurfaceType::WlShell; QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; } void TestShellClient::testX11WindowId() diff --git a/autotests/integration/test_helpers.cpp b/autotests/integration/test_helpers.cpp --- a/autotests/integration/test_helpers.cpp +++ b/autotests/integration/test_helpers.cpp @@ -62,6 +62,7 @@ ServerSideDecorationManager *decoration = nullptr; Shell *shell = nullptr; XdgShell *xdgShellV5 = nullptr; + XdgShell *xdgShellV6 = nullptr; ShmPool *shm = nullptr; Seat *seat = nullptr; PlasmaShell *plasmaShell = nullptr; @@ -148,6 +149,10 @@ if (!s_waylandConnection.xdgShellV5->isValid()) { return false; } + s_waylandConnection.xdgShellV6 = registry->createXdgShell(registry->interface(Registry::Interface::XdgShellUnstableV6).name, registry->interface(Registry::Interface::XdgShellUnstableV6).version); + if (!s_waylandConnection.xdgShellV6->isValid()) { + return false; + } if (flags.testFlag(AdditionalWaylandInterface::Seat)) { s_waylandConnection.seat = registry->createSeat(registry->interface(Registry::Interface::Seat).name, registry->interface(Registry::Interface::Seat).version); if (!s_waylandConnection.seat->isValid()) { @@ -204,6 +209,8 @@ s_waylandConnection.pointerConstraints = nullptr; delete s_waylandConnection.xdgShellV5; s_waylandConnection.xdgShellV5 = nullptr; + delete s_waylandConnection.xdgShellV6; + s_waylandConnection.xdgShellV6 = nullptr; delete s_waylandConnection.shell; s_waylandConnection.shell = nullptr; delete s_waylandConnection.shm; @@ -393,13 +400,28 @@ return s; } +XdgShellSurface *createXdgShellV6Surface(Surface *surface, QObject *parent) +{ + if (!s_waylandConnection.xdgShellV6) { + return nullptr; + } + auto s = s_waylandConnection.xdgShellV6->createSurface(surface, parent); + if (!s->isValid()) { + delete s; + return nullptr; + } + return s; +} + QObject *createShellSurface(ShellSurfaceType type, KWayland::Client::Surface *surface, QObject *parent) { switch (type) { case ShellSurfaceType::WlShell: return createShellSurface(surface, parent); case ShellSurfaceType::XdgShellV5: return createXdgShellV5Surface(surface, parent); + case ShellSurfaceType::XdgShellV6: + return createXdgShellV6Surface(surface, parent); default: Q_UNREACHABLE(); return nullptr; diff --git a/shell_client.h b/shell_client.h --- a/shell_client.h +++ b/shell_client.h @@ -37,6 +37,14 @@ namespace KWin { +/** + * @brief The reason for which the server pinged a client surface + */ +enum class PingReason { + CloseWindow = 0, + FocusWindow +}; + class KWIN_EXPORT ShellClient : public AbstractClient { Q_OBJECT @@ -218,6 +226,7 @@ bool m_transient = false; bool m_hidden = false; bool m_internal; + bool m_hasPopupGrab = false; qreal m_opacity = 1.0; class RequestGeometryBlocker { @@ -244,6 +253,7 @@ QRect m_blockedRequestGeometry; QString m_caption; QString m_captionSuffix; + QHash m_pingSerials; bool m_compositingSetup = false; }; diff --git a/shell_client.cpp b/shell_client.cpp --- a/shell_client.cpp +++ b/shell_client.cpp @@ -228,8 +228,48 @@ connect(s, &SurfaceInterface::destroyed, this, &ShellClient::destroyClient); if (m_shellSurface) { initSurface(m_shellSurface); + // TODO: verify grab serial + m_hasPopupGrab = m_shellSurface->isPopup(); } else if (m_xdgShellSurface) { initSurface(m_xdgShellSurface); + + auto global = static_cast(m_xdgShellSurface->global()); + connect(global, &XdgShellInterface::pingDelayed, + this, [this](qint32 serial) { + auto it = m_pingSerials.find(serial); + if (it != m_pingSerials.end()) { + qCDebug(KWIN_CORE) << "First ping timeout:" << caption(); + setUnresponsive(true); + } + }); + + connect(global, &XdgShellInterface::pingTimeout, + this, [this](qint32 serial) { + auto it = m_pingSerials.find(serial); + if (it != m_pingSerials.end()) { + if (it.value() == PingReason::CloseWindow) { + qCDebug(KWIN_CORE) << "Final ping timeout on a close attempt, asking to kill:" << caption(); + + //for internal windows, killing the window will delete this + QPointer guard(this); + killWindow(); + if (!guard) { + return; + } + } + m_pingSerials.erase(it); + } + }); + + connect(global, &XdgShellInterface::pongReceived, + this, [this](qint32 serial){ + auto it = m_pingSerials.find(serial); + if (it != m_pingSerials.end()) { + setUnresponsive(false); + m_pingSerials.erase(it); + } + }); + connect(m_xdgShellSurface, &XdgShellSurfaceInterface::windowMenuRequested, this, [this] (SeatInterface *seat, quint32 serial, const QPoint &surfacePos) { // TODO: check serial on seat @@ -249,10 +289,21 @@ } m_xdgShellSurface->configure(xdgSurfaceStates()); }; + configure(); connect(this, &AbstractClient::activeChanged, this, configure); connect(this, &AbstractClient::clientStartUserMovedResized, this, configure); connect(this, &AbstractClient::clientFinishUserMovedResized, this, configure); } else if (m_xdgShellPopup) { + connect(m_xdgShellPopup, &XdgShellPopupInterface::grabRequested, this, [this](SeatInterface *seat, quint32 serial) { + Q_UNUSED(seat) + Q_UNUSED(serial) + //TODO - should check the parent had focus + m_hasPopupGrab = true; + }); + + QRect position = QRect(m_xdgShellPopup->transientOffset(), m_xdgShellPopup->initialSize()); + m_xdgShellPopup->configure(position); + connect(m_xdgShellPopup, &XdgShellPopupInterface::destroyed, this, &ShellClient::destroyClient); } @@ -588,12 +639,11 @@ { if (m_xdgShellSurface && isCloseable()) { m_xdgShellSurface->close(); - return; - } - if (m_qtExtendedSurface && isCloseable()) { + const qint32 pingSerial = static_cast(m_xdgShellSurface->global())->ping(m_xdgShellSurface); + m_pingSerials.insert(pingSerial, PingReason::CloseWindow); + } else if (m_qtExtendedSurface && isCloseable()) { m_qtExtendedSurface->close(); - } - if (m_internalWindow) { + } else if (m_internalWindow) { m_internalWindow->hide(); } } @@ -846,6 +896,10 @@ void ShellClient::takeFocus() { if (rules()->checkAcceptFocus(wantsInput())) { + if (m_xdgShellSurface) { + const qint32 pingSerial = static_cast(m_xdgShellSurface->global())->ping(m_xdgShellSurface); + m_pingSerials.insert(pingSerial, PingReason::FocusWindow); + } setActive(true); } @@ -1032,6 +1086,15 @@ if (m_xdgShellSurface) { m_xdgShellSurface->configure(xdgSurfaceStates(), size); } + if (m_xdgShellPopup) { + auto parent = transientFor(); + if (parent) { + const QPoint globalClientContentPos = parent->geometry().topLeft() + parent->clientPos(); + const QPoint relativeOffset = rect.topLeft() -globalClientContentPos; + m_xdgShellPopup->configure(QRect(relativeOffset, rect.size())); + } + } + m_blockedRequestGeometry = QRect(); if (m_internal) { m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom()))); @@ -1414,6 +1477,9 @@ if (isLockScreen()) { return false; } + if (m_xdgShellPopup) { + return false; + } if (m_shellSurface) { if (m_shellSurface->isTransient() && !m_shellSurface->acceptsKeyboardFocus()) { return false; @@ -1520,18 +1586,17 @@ bool ShellClient::hasPopupGrab() const { - if (m_shellSurface) { - // TODO: verify grab serial - return m_shellSurface->isPopup(); - } - return false; + return m_hasPopupGrab; } void ShellClient::popupDone() { if (m_shellSurface) { m_shellSurface->popupDone(); } + if (m_xdgShellPopup) { + m_xdgShellPopup->popupDone(); + } } void ShellClient::updateClientOutputs() diff --git a/wayland_server.h b/wayland_server.h --- a/wayland_server.h +++ b/wayland_server.h @@ -205,6 +205,7 @@ KWayland::Server::SeatInterface *m_seat = nullptr; KWayland::Server::ShellInterface *m_shell = nullptr; KWayland::Server::XdgShellInterface *m_xdgShell = nullptr; + KWayland::Server::XdgShellInterface *m_xdgShell6 = nullptr; KWayland::Server::PlasmaShellInterface *m_plasmaShell = nullptr; KWayland::Server::PlasmaWindowManagementInterface *m_windowManagement = nullptr; KWayland::Server::QtSurfaceExtensionInterface *m_qtExtendedSurface = nullptr; diff --git a/wayland_server.cpp b/wayland_server.cpp --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -201,6 +201,13 @@ connect(m_xdgShell, &XdgShellInterface::surfaceCreated, this, &WaylandServer::createSurface); // TODO: verify seat and serial connect(m_xdgShell, &XdgShellInterface::popupCreated, this, &WaylandServer::createSurface); + + m_xdgShell6 = m_display->createXdgShell(XdgShellInterfaceVersion::UnstableV6, m_display); + m_xdgShell6->create(); + connect(m_xdgShell6, &XdgShellInterface::surfaceCreated, this, &WaylandServer::createSurface); + connect(m_xdgShell6, &XdgShellInterface::xdgPopupCreated, this, &WaylandServer::createSurface); + + m_display->createShm(); m_seat = m_display->createSeat(m_display); m_seat->create();