From c2bc7d4d04ca7a551f804d4149e942867b7c41ed Mon Sep 17 00:00:00 2001 From: l10n daemon script Date: Fri, 10 Feb 2017 07:31:10 +0100 Subject: [PATCH 1/4] SVN_SILENT made messages (.desktop file) - always resolve ours In case of conflict in i18n, keep the version of the branch "ours" To resolve a particular conflict, "git checkout --ours path/to/file.desktop" --- effects/morphingpopups/package/metadata.desktop | 1 + 1 file changed, 1 insertion(+) diff --git a/effects/morphingpopups/package/metadata.desktop b/effects/morphingpopups/package/metadata.desktop index 6464bcdce3..6814f6e8ee 100644 --- a/effects/morphingpopups/package/metadata.desktop +++ b/effects/morphingpopups/package/metadata.desktop @@ -37,6 +37,7 @@ Name=Morphing popups Name[ca]=Missatges emergents en metamorfosi Name[ca@valencia]=Missatges emergents en metamorfosi Name[da]=Sammensmeltende pop-op'er +Name[el]=Αναδυόμενα morphing Name[en_GB]=Morphing popups Name[es]=Transformación de ventanas emergentes Name[et]=Moonduvad hüpikdialoogid From 29179f115c81ff7128bb5430cb27ef7b65f46b33 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Fri, 10 Feb 2017 10:52:48 +0100 Subject: [PATCH 2/4] Avoid a crash on Kwin decoration KCM teardown Summary: As described in https://bugreports.qt.io/browse/QTBUG-57714 exposing a QWidget as a context item to QtQuick can crash. Especially as the engine's context property gets deleted whilst deleting the parent item. This patch reworks the code so that the models are exposed to QML directly rather than going through a QWidget. CCBUG: 373628 Test Plan: Pressing back whilst in the decoration KCM used to crash every time, now it doesn't. I still have the buttons. Reviewers: #plasma, graesslin Reviewed By: #plasma, graesslin Subscribers: graesslin, cfeck, plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D4533 --- kcmkwin/kwindecoration/kcm.cpp | 20 ++++---------------- kcmkwin/kwindecoration/kcm.h | 7 ------- kcmkwin/kwindecoration/qml/Buttons.qml | 6 +++--- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/kcmkwin/kwindecoration/kcm.cpp b/kcmkwin/kwindecoration/kcm.cpp index 035bc8b2aa..231b3e6a80 100644 --- a/kcmkwin/kwindecoration/kcm.cpp +++ b/kcmkwin/kwindecoration/kcm.cpp @@ -100,7 +100,10 @@ ConfigurationModule::ConfigurationModule(QWidget *parent, const QVariantList &ar m_quickView->rootContext()->setContextProperty(QStringLiteral("decorationsModel"), m_proxyModel); updateColors(); m_quickView->rootContext()->setContextProperty("_borderSizesIndex", 3); // 3 is normal - m_quickView->rootContext()->setContextProperty("configurationModule", this); + m_quickView->rootContext()->setContextProperty("leftButtons", m_leftButtons); + m_quickView->rootContext()->setContextProperty("rightButtons", m_rightButtons); + m_quickView->rootContext()->setContextProperty("availableButtons", m_availableButtons); + m_quickView->rootContext()->setContextProperty("titleFont", QFontDatabase::systemFont(QFontDatabase::TitleFont)); m_quickView->setResizeMode(QQuickView::SizeRootObjectToView); m_quickView->setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/kcm_kwindecoration/main.qml")))); @@ -406,21 +409,6 @@ void ConfigurationModule::showKNS(const QString &config) delete downloadDialog; } -QAbstractItemModel *ConfigurationModule::leftButtons() const -{ - return m_leftButtons; -} - -QAbstractItemModel *ConfigurationModule::rightButtons() const -{ - return m_rightButtons; -} - -QAbstractItemModel *ConfigurationModule::availableButtons() const -{ - return m_availableButtons; -} - bool ConfigurationModule::eventFilter(QObject *watched, QEvent *e) { if (watched != m_ui) { diff --git a/kcmkwin/kwindecoration/kcm.h b/kcmkwin/kwindecoration/kcm.h index 1d7ee73784..99fa431143 100644 --- a/kcmkwin/kwindecoration/kcm.h +++ b/kcmkwin/kwindecoration/kcm.h @@ -47,17 +47,10 @@ public: class ConfigurationModule : public KCModule { Q_OBJECT - Q_PROPERTY(QAbstractItemModel* leftButtons READ leftButtons CONSTANT) - Q_PROPERTY(QAbstractItemModel* rightButtons READ rightButtons CONSTANT) - Q_PROPERTY(QAbstractItemModel* availableButtons READ availableButtons CONSTANT) public: explicit ConfigurationModule(QWidget *parent = nullptr, const QVariantList &args = QVariantList()); virtual ~ConfigurationModule(); - QAbstractItemModel *leftButtons() const; - QAbstractItemModel *rightButtons() const; - QAbstractItemModel *availableButtons() const; - bool eventFilter(QObject *watched, QEvent *e) override; public Q_SLOTS: diff --git a/kcmkwin/kwindecoration/qml/Buttons.qml b/kcmkwin/kwindecoration/qml/Buttons.qml index 2e6487306d..64ab0f9be3 100644 --- a/kcmkwin/kwindecoration/qml/Buttons.qml +++ b/kcmkwin/kwindecoration/qml/Buttons.qml @@ -63,7 +63,7 @@ Item { id: leftButtonsView anchors.left: parent.left; height: buttonPreviewRow.height - model: configurationModule.leftButtons + model: leftButtons key: "decoButtonLeft" } Item { @@ -81,7 +81,7 @@ Item { id: rightButtonsView anchors.right: parent.right; height: buttonPreviewRow.height - model: configurationModule.rightButtons + model: rightButtons key: "decoButtonRight" } DropArea { @@ -144,7 +144,7 @@ Item { GridView { id: availableGrid Layout.fillWidth: true - model: configurationModule.availableButtons + model: availableButtons interactive: false cellWidth: iconLabel.implicitWidth cellHeight: units.iconSizes.small + iCannotBelieveIDoThis.implicitHeight + 4*units.smallSpacing From e9155286e8155f22ac7277d1a7ccabac986c6e51 Mon Sep 17 00:00:00 2001 From: l10n daemon script Date: Sun, 12 Feb 2017 07:29:42 +0100 Subject: [PATCH 3/4] SVN_SILENT made messages (.desktop file) - always resolve ours In case of conflict in i18n, keep the version of the branch "ours" To resolve a particular conflict, "git checkout --ours path/to/file.desktop" --- kcmkwin/kwincompositing/kwineffect.knsrc | 1 + kcmkwin/kwinscripts/kwinscripts.knsrc | 1 + kcmkwin/kwintabbox/kwinswitcher.knsrc | 1 + packageplugins/scripts/kwin-packagestructure-scripts.desktop | 1 + .../windowswitcher/kwin-packagestructure-windowswitcher.desktop | 1 + plugins/kdecorations/aurorae/src/aurorae.knsrc | 1 + 6 files changed, 6 insertions(+) diff --git a/kcmkwin/kwincompositing/kwineffect.knsrc b/kcmkwin/kwincompositing/kwineffect.knsrc index f206e0d512..79eacf103d 100644 --- a/kcmkwin/kwincompositing/kwineffect.knsrc +++ b/kcmkwin/kwincompositing/kwineffect.knsrc @@ -2,6 +2,7 @@ Name=Window Manager Effects Name[ca]=Efectes del gestor de finestres Name[ca@valencia]=Efectes del gestor de finestres +Name[da]=Vindueshåndteringseffekter Name[de]=Fensterverwaltungs-Effekte Name[el]=Εφέ διαχειριστή παραθύρων Name[en_GB]=Window Manager Effects diff --git a/kcmkwin/kwinscripts/kwinscripts.knsrc b/kcmkwin/kwinscripts/kwinscripts.knsrc index a95dff9be9..df1cba27d8 100644 --- a/kcmkwin/kwinscripts/kwinscripts.knsrc +++ b/kcmkwin/kwinscripts/kwinscripts.knsrc @@ -2,6 +2,7 @@ Name=Window Manager Scripts Name[ca]=Scripts del gestor de finestres Name[ca@valencia]=Scripts del gestor de finestres +Name[da]=Vindueshåndteringsscripts Name[de]=Fensterverwaltungs-Skripte Name[el]=Σενάρια διαχειριστή παραθύρων Name[en_GB]=Window Manager Scripts diff --git a/kcmkwin/kwintabbox/kwinswitcher.knsrc b/kcmkwin/kwintabbox/kwinswitcher.knsrc index 2fa4e6ffbe..b4f324e399 100644 --- a/kcmkwin/kwintabbox/kwinswitcher.knsrc +++ b/kcmkwin/kwintabbox/kwinswitcher.knsrc @@ -2,6 +2,7 @@ Name=Window Manager Switching Layouts Name[ca]=Disposicions del commutador del gestor de finestres Name[ca@valencia]=Disposicions del commutador del gestor de finestres +Name[da]=Skifterlayouts til vindueshåndtering Name[de]=Wechsel-Layout für Fensterverwaltung Name[el]=Διατάξεις εναλλαγής διαχειριστή παραθύρων Name[en_GB]=Window Manager Switching Layouts diff --git a/packageplugins/scripts/kwin-packagestructure-scripts.desktop b/packageplugins/scripts/kwin-packagestructure-scripts.desktop index 8847f44c0f..de4ce2c729 100644 --- a/packageplugins/scripts/kwin-packagestructure-scripts.desktop +++ b/packageplugins/scripts/kwin-packagestructure-scripts.desktop @@ -2,6 +2,7 @@ Name=KWin Script Name[ca]=Script del KWin Name[ca@valencia]=Script del KWin +Name[da]=KWin-script Name[el]=Σενάριο KWin Name[en_GB]=KWin Script Name[es]=Guion de KWin diff --git a/packageplugins/windowswitcher/kwin-packagestructure-windowswitcher.desktop b/packageplugins/windowswitcher/kwin-packagestructure-windowswitcher.desktop index 5789929d38..f168d38cd6 100644 --- a/packageplugins/windowswitcher/kwin-packagestructure-windowswitcher.desktop +++ b/packageplugins/windowswitcher/kwin-packagestructure-windowswitcher.desktop @@ -2,6 +2,7 @@ Name=KWin Window Switcher Name[ca]=Commutador de finestres del KWin Name[ca@valencia]=Commutador de finestres del KWin +Name[da]=KWin vinduesskifter Name[el]=Εφαρμογή εναλλαγής παραθύρων Kwin Name[en_GB]=KWin Window Switcher Name[es]=Cambiador de ventanas de KWin diff --git a/plugins/kdecorations/aurorae/src/aurorae.knsrc b/plugins/kdecorations/aurorae/src/aurorae.knsrc index f874d63d6b..50e5daabd5 100644 --- a/plugins/kdecorations/aurorae/src/aurorae.knsrc +++ b/plugins/kdecorations/aurorae/src/aurorae.knsrc @@ -2,6 +2,7 @@ Name=Aurorae Window Decorations Name[ca]=Decoracions de finestra Aurorae Name[ca@valencia]=Decoracions de finestra Aurorae +Name[da]=Aurorae vinduesdekorationer Name[de]=Aurorae-Fensterdekoration Name[el]=Διακοσμήσεις παραθύρου Aurorae Name[en_GB]=Aurorae Window Decorations From 8b4f284249f1ff6a52b7148c0536164c42ceaa73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 14 Feb 2017 07:29:38 +0100 Subject: [PATCH 4/4] [autotests] Add test case for quick tiling on X11 Exposes our regressions of X11 quick tiling when a window is vertically maximized. CCBUG: 376155 --- autotests/integration/CMakeLists.txt | 2 +- autotests/integration/quick_tiling_test.cpp | 183 ++++++++++++++++++++ 2 files changed, 184 insertions(+), 1 deletion(-) diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt index 6134011749..9d367a24a3 100644 --- a/autotests/integration/CMakeLists.txt +++ b/autotests/integration/CMakeLists.txt @@ -16,7 +16,6 @@ endfunction() integrationTest(NAME testStart SRCS start_test.cpp) integrationTest(NAME testTransientNoInput SRCS transient_no_input_test.cpp) -integrationTest(NAME testQuickTiling SRCS quick_tiling_test.cpp) integrationTest(NAME testDontCrashGlxgears SRCS dont_crash_glxgears.cpp) integrationTest(NAME testLockScreen SRCS lockscreen.cpp) integrationTest(NAME testDecorationInput SRCS decoration_input_test.cpp) @@ -55,6 +54,7 @@ if (XCB_ICCCM_FOUND) integrationTest(NAME testXwaylandInput SRCS xwayland_input_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testWindowRules SRCS window_rules_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testX11Client SRCS x11_client_test.cpp LIBS XCB::ICCCM) + integrationTest(NAME testQuickTiling SRCS quick_tiling_test.cpp LIBS XCB::ICCCM) if (KWIN_BUILD_ACTIVITIES) integrationTest(NAME testActivities SRCS activities_test.cpp LIBS XCB::ICCCM) diff --git a/autotests/integration/quick_tiling_test.cpp b/autotests/integration/quick_tiling_test.cpp index 9456ee655f..f5068108b0 100644 --- a/autotests/integration/quick_tiling_test.cpp +++ b/autotests/integration/quick_tiling_test.cpp @@ -20,6 +20,7 @@ along with this program. If not, see . #include "kwin_wayland_test.h" #include "platform.h" #include "abstract_client.h" +#include "client.h" #include "cursor.h" #include "screens.h" #include "wayland_server.h" @@ -31,6 +32,9 @@ along with this program. If not, see . #include #include +#include +#include + #include Q_DECLARE_METATYPE(KWin::AbstractClient::QuickTileMode) @@ -56,6 +60,10 @@ private Q_SLOTS: void testQuickTilingKeyboardMove(); void testQuickTilingPointerMove_data(); void testQuickTilingPointerMove(); + void testX11QuickTiling_data(); + void testX11QuickTiling(); + void testX11QuickTilingAfterVertMaximize_data(); + void testX11QuickTilingAfterVertMaximize(); private: KWayland::Client::ConnectionThread *m_connection = nullptr; @@ -406,6 +414,181 @@ void QuickTilingTest::testQuickTilingPointerMove() QTEST(c->quickTileMode(), "expectedMode"); } +struct XcbConnectionDeleter +{ + static inline void cleanup(xcb_connection_t *pointer) + { + xcb_disconnect(pointer); + } +}; + +void QuickTilingTest::testX11QuickTiling_data() +{ + QTest::addColumn("mode"); + QTest::addColumn("expectedGeometry"); + +#define FLAG(name) AbstractClient::QuickTileMode(AbstractClient::QuickTile##name) + + QTest::newRow("left") << FLAG(Left) << QRect(0, 0, 640, 1024); + QTest::newRow("top") << FLAG(Top) << QRect(0, 0, 1280, 512); + QTest::newRow("right") << FLAG(Right) << QRect(640, 0, 640, 1024); + QTest::newRow("bottom") << FLAG(Bottom) << QRect(0, 512, 1280, 512); + + QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRect(0, 0, 640, 512); + QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRect(640, 0, 640, 512); + QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRect(0, 512, 640, 512); + QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRect(640, 512, 640, 512); + + QTest::newRow("maximize") << FLAG(Maximize) << QRect(0, 0, 1280, 1024); + +#undef FLAG +} +void QuickTilingTest::testX11QuickTiling() +{ + QScopedPointer c(xcb_connect(nullptr, nullptr)); + QVERIFY(!xcb_connection_has_error(c.data())); + const QRect windowGeometry(0, 0, 100, 200); + xcb_window_t w = xcb_generate_id(c.data()); + xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w, rootWindow(), + windowGeometry.x(), + windowGeometry.y(), + windowGeometry.width(), + windowGeometry.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, windowGeometry.x(), windowGeometry.y()); + xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); + xcb_icccm_set_wm_normal_hints(c.data(), w, &hints); + xcb_map_window(c.data(), w); + xcb_flush(c.data()); + + // we should get a client for it + QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded); + QVERIFY(windowCreatedSpy.isValid()); + QVERIFY(windowCreatedSpy.wait()); + Client *client = windowCreatedSpy.first().first().value(); + QVERIFY(client); + QCOMPARE(client->window(), w); + + // now quick tile + QSignalSpy quickTileChangedSpy(client, &AbstractClient::quickTileModeChanged); + QVERIFY(quickTileChangedSpy.isValid()); + const QRect origGeo = client->geometry(); + QFETCH(AbstractClient::QuickTileMode, mode); + client->setQuickTileMode(mode, true); + QCOMPARE(client->quickTileMode(), mode); + QTEST(client->geometry(), "expectedGeometry"); + QCOMPARE(client->geometryRestore(), origGeo); + QEXPECT_FAIL("maximize", "For maximize we get two changed signals", Continue); + QCOMPARE(quickTileChangedSpy.count(), 1); + + // and destroy the window again + xcb_unmap_window(c.data(), w); + xcb_destroy_window(c.data(), w); + xcb_flush(c.data()); + c.reset(); + + QSignalSpy windowClosedSpy(client, &Client::windowClosed); + QVERIFY(windowClosedSpy.isValid()); + QVERIFY(windowClosedSpy.wait()); +} + +void QuickTilingTest::testX11QuickTilingAfterVertMaximize_data() +{ + QTest::addColumn("mode"); + QTest::addColumn("expectedGeometry"); + +#define FLAG(name) AbstractClient::QuickTileMode(AbstractClient::QuickTile##name) + + QTest::newRow("left") << FLAG(Left) << QRect(0, 0, 640, 1024); + QTest::newRow("top") << FLAG(Top) << QRect(0, 0, 1280, 512); + QTest::newRow("right") << FLAG(Right) << QRect(640, 0, 640, 1024); + QTest::newRow("bottom") << FLAG(Bottom) << QRect(0, 512, 1280, 512); + + QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRect(0, 0, 640, 512); + QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRect(640, 0, 640, 512); + QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRect(0, 512, 640, 512); + QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRect(640, 512, 640, 512); + + QTest::newRow("maximize") << FLAG(Maximize) << QRect(0, 0, 1280, 1024); + +#undef FLAG +} + +void QuickTilingTest::testX11QuickTilingAfterVertMaximize() +{ + QScopedPointer c(xcb_connect(nullptr, nullptr)); + QVERIFY(!xcb_connection_has_error(c.data())); + const QRect windowGeometry(0, 0, 100, 200); + xcb_window_t w = xcb_generate_id(c.data()); + xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w, rootWindow(), + windowGeometry.x(), + windowGeometry.y(), + windowGeometry.width(), + windowGeometry.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, windowGeometry.x(), windowGeometry.y()); + xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); + xcb_icccm_set_wm_normal_hints(c.data(), w, &hints); + xcb_map_window(c.data(), w); + xcb_flush(c.data()); + + // we should get a client for it + QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded); + QVERIFY(windowCreatedSpy.isValid()); + QVERIFY(windowCreatedSpy.wait()); + Client *client = windowCreatedSpy.first().first().value(); + QVERIFY(client); + QCOMPARE(client->window(), w); + + const QRect origGeo = client->geometry(); + QCOMPARE(client->maximizeMode(), MaximizeRestore); + // vertically maximize the window + client->maximize(client->maximizeMode() ^ MaximizeVertical); + QCOMPARE(client->geometry().width(), origGeo.width()); + QCOMPARE(client->height(), screens()->size(client->screen()).height()); + QCOMPARE(client->geometryRestore(), origGeo); + + // now quick tile + QSignalSpy quickTileChangedSpy(client, &AbstractClient::quickTileModeChanged); + QVERIFY(quickTileChangedSpy.isValid()); + QFETCH(AbstractClient::QuickTileMode, mode); + client->setQuickTileMode(mode, true); + QEXPECT_FAIL("left", "Quick tiling not working", Continue); + QEXPECT_FAIL("right", "Quick tiling not working", Continue); + QEXPECT_FAIL("top", "Quick tiling not working", Continue); + QEXPECT_FAIL("bottom", "Quick tiling not working", Continue); + QEXPECT_FAIL("top left", "Quick tiling not working", Continue); + QEXPECT_FAIL("top right", "Quick tiling not working", Continue); + QEXPECT_FAIL("bottom left", "Quick tiling not working", Continue); + QEXPECT_FAIL("bottom right", "Quick tiling not working", Continue); + QCOMPARE(client->quickTileMode(), mode); + QEXPECT_FAIL("left", "Quick tiling not working", Continue); + QEXPECT_FAIL("right", "Quick tiling not working", Continue); + QEXPECT_FAIL("top", "Quick tiling not working", Continue); + QEXPECT_FAIL("bottom", "Quick tiling not working", Continue); + QEXPECT_FAIL("top left", "Quick tiling not working", Continue); + QEXPECT_FAIL("top right", "Quick tiling not working", Continue); + QEXPECT_FAIL("bottom left", "Quick tiling not working", Continue); + QEXPECT_FAIL("bottom right", "Quick tiling not working", Continue); + QTEST(client->geometry(), "expectedGeometry"); + QEXPECT_FAIL("", "We get two changed events", Continue); + QCOMPARE(quickTileChangedSpy.count(), 1); + + // and destroy the window again + xcb_unmap_window(c.data(), w); + xcb_destroy_window(c.data(), w); + xcb_flush(c.data()); + c.reset(); + + QSignalSpy windowClosedSpy(client, &Client::windowClosed); + QVERIFY(windowClosedSpy.isValid()); + QVERIFY(windowClosedSpy.wait()); +} + } WAYLANDTEST_MAIN(KWin::QuickTilingTest)