From 8136c2722bea31e284af7865b107b99fc179aef3 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Mon, 19 Mar 2018 12:05:57 +0100 Subject: [PATCH] [platforms/virtual] Add virtual output class Summary: This matches the DRM backend more closely and allows mid-test removal and addition of virtual outputs with different properties in the future. Test Plan: Before and after 93% tests passed. Reviewers: #kwin, graesslin Reviewed By: #kwin, graesslin Subscribers: graesslin, kwin, #kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D11351 --- autotests/integration/activities_test.cpp | 2 +- .../colorcorrect_nightcolor_test.cpp | 2 +- autotests/integration/debug_console_test.cpp | 2 +- .../integration/decoration_input_test.cpp | 2 +- .../integration/desktop_window_x11_test.cpp | 2 +- .../dont_crash_aurorae_destroy_deco.cpp | 2 +- .../integration/dont_crash_empty_deco.cpp | 2 +- .../integration/dont_crash_no_border.cpp | 2 +- .../dont_crash_useractions_menu.cpp | 2 +- .../integration/input_stacking_order.cpp | 2 +- autotests/integration/internal_window.cpp | 2 +- autotests/integration/lockscreen.cpp | 2 +- autotests/integration/maximize_test.cpp | 2 +- autotests/integration/plasma_surface_test.cpp | 3 +- autotests/integration/plasmawindow_test.cpp | 2 +- .../integration/pointer_constraints_test.cpp | 2 +- autotests/integration/pointer_input.cpp | 5 +- autotests/integration/quick_tiling_test.cpp | 2 +- autotests/integration/screen_changes_test.cpp | 6 +- .../screenedge_client_show_test.cpp | 2 +- autotests/integration/shade_test.cpp | 2 +- .../integration/shell_client_rules_test.cpp | 2 +- autotests/integration/shell_client_test.cpp | 2 +- autotests/integration/struts_test.cpp | 11 ++-- autotests/integration/touch_input_test.cpp | 2 +- autotests/integration/transient_placement.cpp | 2 +- autotests/integration/window_rules_test.cpp | 2 +- .../integration/window_selection_test.cpp | 2 +- autotests/integration/xclipboardsync_test.cpp | 2 +- autotests/integration/xwayland_input_test.cpp | 2 +- plugins/platforms/virtual/CMakeLists.txt | 1 + plugins/platforms/virtual/screens_virtual.cpp | 30 +++++----- plugins/platforms/virtual/screens_virtual.h | 1 - plugins/platforms/virtual/virtual_backend.cpp | 40 +++++++++++++- plugins/platforms/virtual/virtual_backend.h | 36 +++++------- plugins/platforms/virtual/virtual_output.cpp | 42 ++++++++++++++ plugins/platforms/virtual/virtual_output.h | 55 +++++++++++++++++++ 37 files changed, 203 insertions(+), 79 deletions(-) create mode 100644 plugins/platforms/virtual/virtual_output.cpp create mode 100644 plugins/platforms/virtual/virtual_output.h diff --git a/autotests/integration/activities_test.cpp b/autotests/integration/activities_test.cpp index 1acfead397..91c2385137 100644 --- a/autotests/integration/activities_test.cpp +++ b/autotests/integration/activities_test.cpp @@ -60,7 +60,7 @@ void ActivitiesTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->setUseKActivities(true); diff --git a/autotests/integration/colorcorrect_nightcolor_test.cpp b/autotests/integration/colorcorrect_nightcolor_test.cpp index ecc319c917..84571d6dfa 100644 --- a/autotests/integration/colorcorrect_nightcolor_test.cpp +++ b/autotests/integration/colorcorrect_nightcolor_test.cpp @@ -49,7 +49,7 @@ void ColorCorrectNightColorTest::initTestCase() { QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); diff --git a/autotests/integration/debug_console_test.cpp b/autotests/integration/debug_console_test.cpp index 3272abc476..399b6d0fba 100644 --- a/autotests/integration/debug_console_test.cpp +++ b/autotests/integration/debug_console_test.cpp @@ -62,7 +62,7 @@ void DebugConsoleTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/decoration_input_test.cpp b/autotests/integration/decoration_input_test.cpp index e15c716e6a..584d371ee1 100644 --- a/autotests/integration/decoration_input_test.cpp +++ b/autotests/integration/decoration_input_test.cpp @@ -131,7 +131,7 @@ void DecorationInputTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // change some options diff --git a/autotests/integration/desktop_window_x11_test.cpp b/autotests/integration/desktop_window_x11_test.cpp index ca5ceeb289..9d29c1fd09 100644 --- a/autotests/integration/desktop_window_x11_test.cpp +++ b/autotests/integration/desktop_window_x11_test.cpp @@ -58,7 +58,7 @@ void X11DesktopWindowTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/dont_crash_aurorae_destroy_deco.cpp b/autotests/integration/dont_crash_aurorae_destroy_deco.cpp index 4c712b649c..811728e2af 100644 --- a/autotests/integration/dont_crash_aurorae_destroy_deco.cpp +++ b/autotests/integration/dont_crash_aurorae_destroy_deco.cpp @@ -59,7 +59,7 @@ void DontCrashAuroraeDestroyDecoTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); diff --git a/autotests/integration/dont_crash_empty_deco.cpp b/autotests/integration/dont_crash_empty_deco.cpp index c8e117261f..d800ef13bf 100644 --- a/autotests/integration/dont_crash_empty_deco.cpp +++ b/autotests/integration/dont_crash_empty_deco.cpp @@ -56,7 +56,7 @@ void DontCrashEmptyDecorationTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // this test needs to enforce OpenGL compositing to get into the crashy condition diff --git a/autotests/integration/dont_crash_no_border.cpp b/autotests/integration/dont_crash_no_border.cpp index fc155ef92a..e08d6b3aa3 100644 --- a/autotests/integration/dont_crash_no_border.cpp +++ b/autotests/integration/dont_crash_no_border.cpp @@ -63,7 +63,7 @@ void DontCrashNoBorder::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); diff --git a/autotests/integration/dont_crash_useractions_menu.cpp b/autotests/integration/dont_crash_useractions_menu.cpp index 486669b043..31994b69ca 100644 --- a/autotests/integration/dont_crash_useractions_menu.cpp +++ b/autotests/integration/dont_crash_useractions_menu.cpp @@ -62,7 +62,7 @@ void TestDontCrashUseractionsMenu::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // force style to breeze as that's the one which triggered the crash diff --git a/autotests/integration/input_stacking_order.cpp b/autotests/integration/input_stacking_order.cpp index 7acc98e1c4..e4c3d39675 100644 --- a/autotests/integration/input_stacking_order.cpp +++ b/autotests/integration/input_stacking_order.cpp @@ -68,7 +68,7 @@ void InputStackingOrderTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp index 58bbb36873..a1fb1a6c42 100644 --- a/autotests/integration/internal_window.cpp +++ b/autotests/integration/internal_window.cpp @@ -175,7 +175,7 @@ void InternalWindowTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); diff --git a/autotests/integration/lockscreen.cpp b/autotests/integration/lockscreen.cpp index 1460c9736d..30ceafffdc 100644 --- a/autotests/integration/lockscreen.cpp +++ b/autotests/integration/lockscreen.cpp @@ -187,7 +187,7 @@ void LockScreenTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/maximize_test.cpp b/autotests/integration/maximize_test.cpp index 530a0c6a3f..2db9fece2d 100644 --- a/autotests/integration/maximize_test.cpp +++ b/autotests/integration/maximize_test.cpp @@ -61,7 +61,7 @@ void TestMaximized::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); diff --git a/autotests/integration/plasma_surface_test.cpp b/autotests/integration/plasma_surface_test.cpp index 5cbc32aa98..41a966510a 100644 --- a/autotests/integration/plasma_surface_test.cpp +++ b/autotests/integration/plasma_surface_test.cpp @@ -229,8 +229,9 @@ void PlasmaSurfaceTest::testOSDPlacement() QSignalSpy screensChangedSpy(screens(), &Screens::changed); QVERIFY(screensChangedSpy.isValid()); const QVector geometries{QRect(0, 0, 1280, 1024), QRect(1280, 0, 1280, 1024)}; - QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, + Q_ARG(int, 2), Q_ARG(QVector, geometries)); QVERIFY(screensChangedSpy.wait()); QCOMPARE(screensChangedSpy.count(), 1); diff --git a/autotests/integration/plasmawindow_test.cpp b/autotests/integration/plasmawindow_test.cpp index 87d52278a1..3cc9273691 100644 --- a/autotests/integration/plasmawindow_test.cpp +++ b/autotests/integration/plasmawindow_test.cpp @@ -75,7 +75,7 @@ void PlasmaWindowTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/pointer_constraints_test.cpp b/autotests/integration/pointer_constraints_test.cpp index a9896157db..41990ed02b 100644 --- a/autotests/integration/pointer_constraints_test.cpp +++ b/autotests/integration/pointer_constraints_test.cpp @@ -76,7 +76,7 @@ void TestPointerConstraints::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // set custom config which disables the OnScreenNotification diff --git a/autotests/integration/pointer_input.cpp b/autotests/integration/pointer_input.cpp index d308dae93c..48f1083675 100644 --- a/autotests/integration/pointer_input.cpp +++ b/autotests/integration/pointer_input.cpp @@ -92,7 +92,7 @@ void PointerInputTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); @@ -298,8 +298,9 @@ void PointerInputTest::testUpdateFocusAfterScreenChange() QSignalSpy screensChangedSpy(screens(), &Screens::changed); QVERIFY(screensChangedSpy.isValid()); // now let's remove the screen containing the cursor - QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, + Q_ARG(int, 1), Q_ARG(QVector, QVector{QRect(0, 0, 1280, 1024)})); QVERIFY(screensChangedSpy.wait()); QCOMPARE(screens()->count(), 1); diff --git a/autotests/integration/quick_tiling_test.cpp b/autotests/integration/quick_tiling_test.cpp index 20a7ed9bc7..f72e6ed6c9 100644 --- a/autotests/integration/quick_tiling_test.cpp +++ b/autotests/integration/quick_tiling_test.cpp @@ -98,7 +98,7 @@ void QuickTilingTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // set custom config which disables the Outline diff --git a/autotests/integration/screen_changes_test.cpp b/autotests/integration/screen_changes_test.cpp index bf33d6c31f..112bbe535a 100644 --- a/autotests/integration/screen_changes_test.cpp +++ b/autotests/integration/screen_changes_test.cpp @@ -96,8 +96,9 @@ void ScreenChangesTest::testScreenAddRemove() QSignalSpy screensChangedSpy(screens(), &Screens::changed); QVERIFY(screensChangedSpy.isValid()); const QVector geometries{QRect(0, 0, 1280, 1024), QRect(1280, 0, 1280, 1024)}; - QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, + Q_ARG(int, 2), Q_ARG(QVector, geometries)); QVERIFY(screensChangedSpy.wait()); QCOMPARE(screensChangedSpy.count(), 1); @@ -148,8 +149,9 @@ void ScreenChangesTest::testScreenAddRemove() QVERIFY(o2RemovedSpy.isValid()); const QVector geometries2{QRect(0, 0, 1280, 1024)}; - QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, + Q_ARG(int, 1), Q_ARG(QVector, geometries2)); QVERIFY(screensChangedSpy.wait()); QCOMPARE(screensChangedSpy.count(), 1); diff --git a/autotests/integration/screenedge_client_show_test.cpp b/autotests/integration/screenedge_client_show_test.cpp index a617e202ca..06bcbac02d 100644 --- a/autotests/integration/screenedge_client_show_test.cpp +++ b/autotests/integration/screenedge_client_show_test.cpp @@ -57,7 +57,7 @@ void ScreenEdgeClientShowTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // set custom config which disable touch edge diff --git a/autotests/integration/shade_test.cpp b/autotests/integration/shade_test.cpp index 84c3eb3cf1..787f654076 100644 --- a/autotests/integration/shade_test.cpp +++ b/autotests/integration/shade_test.cpp @@ -54,7 +54,7 @@ void ShadeTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/shell_client_rules_test.cpp b/autotests/integration/shell_client_rules_test.cpp index 250d97c4de..2321f79721 100644 --- a/autotests/integration/shell_client_rules_test.cpp +++ b/autotests/integration/shell_client_rules_test.cpp @@ -74,7 +74,7 @@ void TestShellClientRules::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/shell_client_test.cpp b/autotests/integration/shell_client_test.cpp index b5900895d1..c69291a2c5 100644 --- a/autotests/integration/shell_client_test.cpp +++ b/autotests/integration/shell_client_test.cpp @@ -102,7 +102,7 @@ void TestShellClient::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/struts_test.cpp b/autotests/integration/struts_test.cpp index 229437b782..b1cf00f7c0 100644 --- a/autotests/integration/struts_test.cpp +++ b/autotests/integration/struts_test.cpp @@ -74,7 +74,7 @@ void StrutsTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // set custom config which disables the Outline @@ -660,8 +660,9 @@ void StrutsTest::test363804() // this test verifies the condition described in BUG 363804 // two screens in a vertical setup, aligned to right border with panel on the bottom screen const QVector geometries{QRect(0, 0, 1920, 1080), QRect(554, 1080, 1366, 768)}; - QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, + Q_ARG(int, 2), Q_ARG(QVector, geometries)); QCOMPARE(screens()->geometry(0), geometries.at(0)); QCOMPARE(screens()->geometry(1), geometries.at(1)); @@ -739,8 +740,9 @@ void StrutsTest::testLeftScreenSmallerBottomAligned() // what this test in addition tests is whether a window larger than the left screen is not placed into // the dead area const QVector geometries{QRect(0, 282, 1366, 768), QRect(1366, 0, 1680, 1050)}; - QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, + Q_ARG(int, 2), Q_ARG(QVector, geometries)); QCOMPARE(screens()->geometry(0), geometries.at(0)); QCOMPARE(screens()->geometry(1), geometries.at(1)); @@ -850,8 +852,9 @@ void StrutsTest::testWindowMoveWithPanelBetweenScreens() // left screen must be smaller than right screen const QVector geometries{QRect(0, 282, 1366, 768), QRect(1366, 0, 1680, 1050)}; - QMetaObject::invokeMethod(kwinApp()->platform(), "outputGeometriesChanged", + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, + Q_ARG(int, 2), Q_ARG(QVector, geometries)); QCOMPARE(screens()->geometry(0), geometries.at(0)); QCOMPARE(screens()->geometry(1), geometries.at(1)); diff --git a/autotests/integration/touch_input_test.cpp b/autotests/integration/touch_input_test.cpp index c81c1fb70e..aee34c30e8 100644 --- a/autotests/integration/touch_input_test.cpp +++ b/autotests/integration/touch_input_test.cpp @@ -62,7 +62,7 @@ void TouchInputTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/transient_placement.cpp b/autotests/integration/transient_placement.cpp index f51082c029..ac8869a2a8 100644 --- a/autotests/integration/transient_placement.cpp +++ b/autotests/integration/transient_placement.cpp @@ -72,7 +72,7 @@ void TransientPlacementTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/window_rules_test.cpp b/autotests/integration/window_rules_test.cpp index 20baa15eb2..2bd14edc5e 100644 --- a/autotests/integration/window_rules_test.cpp +++ b/autotests/integration/window_rules_test.cpp @@ -57,7 +57,7 @@ void WindowRuleTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/window_selection_test.cpp b/autotests/integration/window_selection_test.cpp index a04cb77568..3b70a37a7a 100644 --- a/autotests/integration/window_selection_test.cpp +++ b/autotests/integration/window_selection_test.cpp @@ -69,7 +69,7 @@ void TestWindowSelection::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); qputenv("XKB_DEFAULT_RULES", "evdev"); diff --git a/autotests/integration/xclipboardsync_test.cpp b/autotests/integration/xclipboardsync_test.cpp index 212eee2175..ee9a5e6752 100644 --- a/autotests/integration/xclipboardsync_test.cpp +++ b/autotests/integration/xclipboardsync_test.cpp @@ -55,7 +55,7 @@ void XClipboardSyncTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/autotests/integration/xwayland_input_test.cpp b/autotests/integration/xwayland_input_test.cpp index 7de3cbd878..a88bc3a15d 100644 --- a/autotests/integration/xwayland_input_test.cpp +++ b/autotests/integration/xwayland_input_test.cpp @@ -57,7 +57,7 @@ void XWaylandInputTest::initTestCase() QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); - QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); diff --git a/plugins/platforms/virtual/CMakeLists.txt b/plugins/platforms/virtual/CMakeLists.txt index 673bfe3147..4f41b353e3 100644 --- a/plugins/platforms/virtual/CMakeLists.txt +++ b/plugins/platforms/virtual/CMakeLists.txt @@ -1,6 +1,7 @@ set(VIRTUAL_SOURCES egl_gbm_backend.cpp virtual_backend.cpp + virtual_output.cpp scene_qpainter_virtual_backend.cpp screens_virtual.cpp ) diff --git a/plugins/platforms/virtual/screens_virtual.cpp b/plugins/platforms/virtual/screens_virtual.cpp index 7cd2fdfb9a..49b3836c6f 100644 --- a/plugins/platforms/virtual/screens_virtual.cpp +++ b/plugins/platforms/virtual/screens_virtual.cpp @@ -19,6 +19,7 @@ along with this program. If not, see . *********************************************************************/ #include "screens_virtual.h" #include "virtual_backend.h" +#include "virtual_output.h" namespace KWin { @@ -35,28 +36,27 @@ void VirtualScreens::init() { updateCount(); KWin::Screens::init(); - connect(m_backend, &VirtualBackend::sizeChanged, - this, &VirtualScreens::startChangedTimer); - connect(m_backend, &VirtualBackend::outputGeometriesChanged, this, - [this] (const QVector &geometries) { - const int oldCount = m_geometries.count(); - m_geometries = geometries; - if (oldCount != m_geometries.count()) { - setCount(m_geometries.count()); + + connect(m_backend, &VirtualBackend::virtualOutputsSet, this, + [this] (bool countChanged) { + if (countChanged) { + setCount(m_backend->outputCount()); } else { emit changed(); } } ); + emit changed(); } QRect VirtualScreens::geometry(int screen) const { - if (screen >= m_geometries.count()) { + const auto outputs = m_backend->outputs(); + if (screen >= outputs.size()) { return QRect(); } - return m_geometries.at(screen); + return outputs.at(screen).geometry(); } QSize VirtualScreens::size(int screen) const @@ -66,11 +66,6 @@ QSize VirtualScreens::size(int screen) const void VirtualScreens::updateCount() { - m_geometries.clear(); - const QSize size = m_backend->size(); - for (int i = 0; i < m_backend->outputCount(); ++i) { - m_geometries.append(QRect(size.width() * i, 0, size.width(), size.height())); - } setCount(m_backend->outputCount()); } @@ -78,8 +73,9 @@ int VirtualScreens::number(const QPoint &pos) const { int bestScreen = 0; int minDistance = INT_MAX; - for (int i = 0; i < m_geometries.count(); ++i) { - const QRect &geo = m_geometries.at(i); + const auto outputs = m_backend->outputs(); + for (int i = 0; i < outputs.size(); ++i) { + const QRect &geo = outputs.at(i).geometry(); if (geo.contains(pos)) { return i; } diff --git a/plugins/platforms/virtual/screens_virtual.h b/plugins/platforms/virtual/screens_virtual.h index c5fdbb68f6..d7962257f8 100644 --- a/plugins/platforms/virtual/screens_virtual.h +++ b/plugins/platforms/virtual/screens_virtual.h @@ -41,7 +41,6 @@ public: private: void createOutputs(); VirtualBackend *m_backend; - QVector m_geometries; }; } diff --git a/plugins/platforms/virtual/virtual_backend.cpp b/plugins/platforms/virtual/virtual_backend.cpp index d41cd69886..1afc3d68a2 100644 --- a/plugins/platforms/virtual/virtual_backend.cpp +++ b/plugins/platforms/virtual/virtual_backend.cpp @@ -68,12 +68,25 @@ VirtualBackend::~VirtualBackend() void VirtualBackend::init() { + /* + * Some tests currently expect one output present at start, + * others set them explicitly. + * + * TODO: rewrite all tests to explicitly set the outputs. + */ + if (!m_outputs.size()) { + auto dummyOutput = VirtualOutput(this); + dummyOutput.m_geo = QRect(QPoint(0, 0), initialWindowSize()); + m_outputs = { dummyOutput }; + } + + setSoftWareCursor(true); - m_size = initialWindowSize(); setReady(true); waylandServer()->seat()->setHasPointer(true); waylandServer()->seat()->setHasKeyboard(true); waylandServer()->seat()->setHasTouch(true); + emit screensQueried(); } @@ -100,13 +113,34 @@ OpenGLBackend *VirtualBackend::createOpenGLBackend() return new EglGbmBackend(this); } +void VirtualBackend::setVirtualOutputs(int count, QVector geometries) +{ + Q_ASSERT(geometries.size() == 0 || geometries.size() == count); + + bool countChanged = m_outputs.size() != count; + m_outputs.resize(count); + + int sumWidth = 0; + for (int i = 0; i < count; i++) { + VirtualOutput& o = m_outputs[i]; + if (geometries.size()) { + o.m_geo = geometries.at(i); + } else if (!o.m_geo.isValid()) { + o.m_geo = QRect(QPoint(sumWidth, 0), initialWindowSize()); + sumWidth += o.m_geo.width(); + } + } + + emit virtualOutputsSet(countChanged); +} + int VirtualBackend::gammaRampSize(int screen) const { - return m_gammaSizes[screen]; + return m_outputs[screen].m_gammaSize; } bool VirtualBackend::setGammaRamp(int screen, ColorCorrect::GammaRamp &gamma) { Q_UNUSED(gamma); - return m_gammaResults[screen]; + return m_outputs[screen].m_gammaResult; } } diff --git a/plugins/platforms/virtual/virtual_backend.h b/plugins/platforms/virtual/virtual_backend.h index 6c2eae1521..c0baa698b6 100644 --- a/plugins/platforms/virtual/virtual_backend.h +++ b/plugins/platforms/virtual/virtual_backend.h @@ -20,11 +20,12 @@ along with this program. If not, see . #ifndef KWIN_VIRTUAL_BACKEND_H #define KWIN_VIRTUAL_BACKEND_H #include "platform.h" +#include "virtual_output.h" #include #include -#include +#include class QTemporaryDir; @@ -32,28 +33,24 @@ struct gbm_device; namespace KWin { -namespace ColorCorrect { -class Manager; -struct GammaRamp; -} - +struct ColorCorrect::GammaRamp; class KWIN_EXPORT VirtualBackend : public Platform { Q_OBJECT Q_INTERFACES(KWin::Platform) Q_PLUGIN_METADATA(IID "org.kde.kwin.Platform" FILE "virtual.json") - Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) + public: VirtualBackend(QObject *parent = nullptr); virtual ~VirtualBackend(); void init() override; - QSize size() const { - return m_size; - } int outputCount() const { - return m_outputCount; + return m_outputs.size(); + } + const QVector outputs() const { + return m_outputs; } qreal outputScale() const { return m_outputScale; @@ -68,11 +65,7 @@ public: QPainterBackend* createQPainterBackend() override; OpenGLBackend *createOpenGLBackend() override; - Q_INVOKABLE void setOutputCount(int count) { - m_outputCount = count; - m_gammaSizes = QVector(count, 200); - m_gammaResults = QVector(count, true); - } + Q_INVOKABLE void setVirtualOutputs(int count, QVector geometries = QVector()); Q_INVOKABLE void setOutputScale(qreal scale) { m_outputScale = scale; @@ -99,19 +92,16 @@ public: } Q_SIGNALS: - void sizeChanged(); - void outputGeometriesChanged(const QVector &geometries); + void virtualOutputsSet(bool countChanged); private: - QSize m_size; - int m_outputCount = 1; + QVector m_outputs; + qreal m_outputScale = 1; + QScopedPointer m_screenshotDir; int m_drmFd = -1; gbm_device *m_gbmDevice = nullptr; - - QVector m_gammaSizes = QVector(1, 200); - QVector m_gammaResults = QVector(1, true); }; } diff --git a/plugins/platforms/virtual/virtual_output.cpp b/plugins/platforms/virtual/virtual_output.cpp new file mode 100644 index 0000000000..e402f8ca4e --- /dev/null +++ b/plugins/platforms/virtual/virtual_output.cpp @@ -0,0 +1,42 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2018 Roman Gilg + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "virtual_output.h" + +namespace KWin +{ + +VirtualOutput::VirtualOutput(QObject *parent) + : QObject(parent) +{ +} + +VirtualOutput::VirtualOutput(const VirtualOutput &o) + : m_geo(o.m_geo), + m_outputScale(o.m_outputScale), + m_gammaSize(o.m_gammaSize), + m_gammaResult(o.m_gammaResult) +{ +} + +VirtualOutput::~VirtualOutput() +{ +} + +} diff --git a/plugins/platforms/virtual/virtual_output.h b/plugins/platforms/virtual/virtual_output.h new file mode 100644 index 0000000000..762ed1eb38 --- /dev/null +++ b/plugins/platforms/virtual/virtual_output.h @@ -0,0 +1,55 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2018 Roman Gilg + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KWIN_VIRTUAL_OUTPUT_H +#define KWIN_VIRTUAL_OUTPUT_H + +#include +#include + +namespace KWin +{ +class VirtualBackend; + +class VirtualOutput : public QObject +{ + Q_OBJECT + +public: + VirtualOutput(QObject *parent = nullptr); + VirtualOutput(const VirtualOutput &o); + virtual ~VirtualOutput(); + + QRect geometry() const { + return m_geo; + } + +private: + friend class VirtualBackend; + + QRect m_geo; + qreal m_outputScale = 1; + + int m_gammaSize = 200; + bool m_gammaResult = true; +}; + +} + +#endif