From 1680a4e9ebe9a21fcca559e6e6e29c8f4e83fd49 Mon Sep 17 00:00:00 2001 From: l10n daemon script Date: Tue, 13 Jun 2017 05:58:57 +0200 Subject: [PATCH 1/7] 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/frozenapp/package/metadata.desktop | 2 ++ 1 file changed, 2 insertions(+) diff --git a/effects/frozenapp/package/metadata.desktop b/effects/frozenapp/package/metadata.desktop index 8a7acbe1b1..1079fbbe93 100644 --- a/effects/frozenapp/package/metadata.desktop +++ b/effects/frozenapp/package/metadata.desktop @@ -2,6 +2,7 @@ Name=Desaturate Unresponsive Applications Name[ca]=Dessatura les aplicacions que no responen Name[ca@valencia]=Dessatura les aplicacions que no responen +Name[el]=Αποκορεσμός χρωμάτων μη αποκρινόμενων εφαρμογών Name[en_GB]=Desaturate Unresponsive Applications Name[es]=Desaturar las aplicaciones que no responden Name[fi]=Vähennä värikylläisyyttä sovelluksilta, jotka eivät vastaa @@ -26,6 +27,7 @@ Icon=preferences-system-windows-effect-frozenapp Comment=Desaturate windows of unresponsive (frozen) applications Comment[ca]=Dessatura les finestres de les aplicacions que no responen (congelades) Comment[ca@valencia]=Dessatura les finestres de les aplicacions que no responen (congelades) +Comment[el]=Αποκορεσμός χρωμάτων παραθύρων μη αποκρινόμενων (κολλημένων) εφαρμογών Comment[en_GB]=Desaturate windows of unresponsive (frozen) applications Comment[es]=Desaturar las ventanas de las aplicaciones que no responden (congeladas) Comment[fi]=Vähennä värikylläisyyttä sovelluksilta, jotka eivät vastaa (ovat jumittuneet) From cfe13c5a4ff75c8a1cb1ec9a7db9fb7e68eb8a5f Mon Sep 17 00:00:00 2001 From: Jonathan Riddell Date: Tue, 13 Jun 2017 18:31:37 +0100 Subject: [PATCH 2/7] Update version number for 5.10.2 GIT_SILENT --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3040b552ff..6a0cb688ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ project(KWIN) -set(PROJECT_VERSION "5.10.1") +set(PROJECT_VERSION "5.10.2") set(PROJECT_VERSION_MAJOR 5) cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) From 0df09a8cbbb1caa217c8deb59700bd12f27e45b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Sun, 18 Jun 2017 21:01:30 +0200 Subject: [PATCH 3/7] Better handle cases when the xkb keymap fails to be created Summary: If the keymap cannot be created a few pointers in Xkb are null. We should make sure to not call any xkbcommon functions on those null pointers and instead use proper fallbacks. This change introduces fixes for a few usages, but it's not unlikely that there are more cases. BUG: 381210 FIXED-IN: 5.10.3 Test Plan: Autotest added for the condition of the bug, which does not crash any more. Just starting the test found a few more crash cases. Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D6260 --- autotests/integration/CMakeLists.txt | 1 + .../keymap_creation_failure_test.cpp | 102 ++++++++++++++++++ xkb.cpp | 8 +- 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 autotests/integration/keymap_creation_failure_test.cpp diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt index 5f1d379925..60000224e0 100644 --- a/autotests/integration/CMakeLists.txt +++ b/autotests/integration/CMakeLists.txt @@ -43,6 +43,7 @@ integrationTest(NAME testGlobalShortcuts SRCS globalshortcuts_test.cpp) integrationTest(NAME testWindowSelection SRCS window_selection_test.cpp) integrationTest(NAME testPointerConstraints SRCS pointer_constraints_test.cpp) integrationTest(NAME testKeyboardLayout SRCS keyboard_layout_test.cpp) +integrationTest(NAME testKeymapCreationFailure SRCS keymap_creation_failure_test.cpp) if (XCB_ICCCM_FOUND) integrationTest(NAME testMoveResize SRCS move_resize_window_test.cpp LIBS XCB::ICCCM) diff --git a/autotests/integration/keymap_creation_failure_test.cpp b/autotests/integration/keymap_creation_failure_test.cpp new file mode 100644 index 0000000000..dd8d7b6411 --- /dev/null +++ b/autotests/integration/keymap_creation_failure_test.cpp @@ -0,0 +1,102 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright (C) 2017 Martin Flöser + +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 "kwin_wayland_test.h" +#include "keyboard_input.h" +#include "keyboard_layout.h" +#include "platform.h" +#include "shell_client.h" +#include "virtualdesktops.h" +#include "wayland_server.h" +#include "workspace.h" + +#include +#include + +#include + +using namespace KWin; +using namespace KWayland::Client; + +static const QString s_socketName = QStringLiteral("wayland_test_kwin_keymap_creation_failure-0"); + +class KeymapCreationFailureTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase(); + void init(); + void cleanup(); + + void testPointerButton(); +}; + +void KeymapCreationFailureTest::initTestCase() +{ + // situation for for BUG 381210 + // this will fail to create keymap + qputenv("XKB_DEFAULT_RULES", "no"); + qputenv("XKB_DEFAULT_MODEL", "no"); + qputenv("XKB_DEFAULT_LAYOUT", "no"); + qputenv("XKB_DEFAULT_VARIANT", "no"); + qputenv("XKB_DEFAULT_OPTIONS", "no"); + + qRegisterMetaType(); + qRegisterMetaType(); + QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); + QVERIFY(workspaceCreatedSpy.isValid()); + kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); + QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); + + kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); + kwinApp()->setKxkbConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); + KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout"); + layoutGroup.writeEntry("LayoutList", QStringLiteral("no")); + layoutGroup.writeEntry("Model", "no"); + layoutGroup.writeEntry("Options", "no"); + layoutGroup.sync(); + + kwinApp()->start(); + QVERIFY(workspaceCreatedSpy.wait()); + waylandServer()->initWorkspace(); +} + +void KeymapCreationFailureTest::init() +{ + QVERIFY(Test::setupWaylandConnection()); +} + +void KeymapCreationFailureTest::cleanup() +{ + Test::destroyWaylandConnection(); +} + +void KeymapCreationFailureTest::testPointerButton() +{ + // test case for BUG 381210 + // pressing a pointer button results in crash + + // now create the crashing condition + // which is sending in a pointer event + kwinApp()->platform()->pointerButtonPressed(BTN_LEFT, 0); + kwinApp()->platform()->pointerButtonReleased(BTN_LEFT, 1); +} + +WAYLANDTEST_MAIN(KeymapCreationFailureTest) +#include "keymap_creation_failure_test.moc" diff --git a/xkb.cpp b/xkb.cpp index f8dc6ed219..cdee22b68d 100644 --- a/xkb.cpp +++ b/xkb.cpp @@ -354,13 +354,16 @@ QString Xkb::layoutName() const QString Xkb::layoutName(xkb_layout_index_t layout) const { + if (!m_keymap) { + return QString{}; + } return QString::fromLocal8Bit(xkb_keymap_layout_get_name(m_keymap, layout)); } QMap Xkb::layoutNames() const { QMap layouts; - const auto size = xkb_keymap_num_layouts(m_keymap); + const auto size = m_keymap ? xkb_keymap_num_layouts(m_keymap) : 0u; for (xkb_layout_index_t i = 0; i < size; i++) { layouts.insert(i, layoutName(i)); } @@ -387,6 +390,9 @@ void Xkb::updateConsumedModifiers(uint32_t key) Qt::KeyboardModifiers Xkb::modifiersRelevantForGlobalShortcuts() const { + if (!m_state) { + return Qt::NoModifier; + } Qt::KeyboardModifiers mods = Qt::NoModifier; if (xkb_state_mod_index_is_active(m_state, m_shiftModifier, XKB_STATE_MODS_EFFECTIVE) == 1) { mods |= Qt::ShiftModifier; From a6dee74ee455d1da47dd5c9d55a84adbb5e1426a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Sun, 18 Jun 2017 14:23:33 +0200 Subject: [PATCH 4/7] Workaround Qt regression of no longer delivering events for the root window Summary: With qtbase 2b34aefcf02f09253473b096eb4faffd3e62b5f4 we do no longer get events reported for the X11 root window. Our keyboard handling in effects like PresentWindows and DesktopGrid relied on that. This change works around the regression by calling winId() on qApp->desktop() as suggested in the change. This is a short term solution for the 5.10 branch. This needs to be addressed properly by no longer relying on Qt in this area. KWin already does not rely on Qt for Wayland in that area and is able to compose the QKeyEvents. This should also be done on X11. It just needs some more hook up code for xkb, but that's needed anyway to improve modifier only shortcuts and friends. BUG: 360841 FIXED-IN: 5.10.3 Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D6258 --- effects.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/effects.cpp b/effects.cpp index d2c4768c04..8155de6b34 100644 --- a/effects.cpp +++ b/effects.cpp @@ -48,6 +48,7 @@ along with this program. If not, see . #include "kwinglutils.h" #include +#include #include @@ -599,6 +600,11 @@ bool EffectsHandlerImpl::grabKeyboard(Effect* effect) bool ret = grabXKeyboard(); if (!ret) return false; + // Workaround for Qt 5.9 regression introduced with 2b34aefcf02f09253473b096eb4faffd3e62b5f4 + // we no longer get any events for the root window, one needs to call winId() on the desktop window + // TODO: change effects event handling to create the appropriate QKeyEvent without relying on Qt + // as it's done already in the Wayland case. + qApp->desktop()->winId(); } keyboard_grab_effect = effect; return true; From c45e165514ec70314d721d6e0238431ab92bd441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Sun, 18 Jun 2017 13:36:27 +0200 Subject: [PATCH 5/7] Fix switch desktop through edge when moving window Summary: There was a regression introduced in ScreenEdges when introducing the activatesForPointer method. It considered the switch desktop on edge, but not the special case of switch desktop when moving windows. Due to that the edges did not activate when moving the window. This change addresses the regression and extends the autotest to ensure it's properly covered. BUG: 380440 FIXED-IN: 5.10.3 Test Plan: Manual testing and extended auto test Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D6257 --- autotests/mock_abstract_client.cpp | 11 +++++++++++ autotests/mock_abstract_client.h | 3 +++ autotests/mock_client.cpp | 5 ----- autotests/mock_client.h | 2 -- autotests/test_screen_edges.cpp | 21 +++++++++++++++++++++ screenedge.cpp | 6 ++++++ 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/autotests/mock_abstract_client.cpp b/autotests/mock_abstract_client.cpp index 20795fa899..d270f636e1 100644 --- a/autotests/mock_abstract_client.cpp +++ b/autotests/mock_abstract_client.cpp @@ -30,6 +30,7 @@ AbstractClient::AbstractClient(QObject *parent) , m_hiddenInternal(false) , m_keepBelow(false) , m_geometry() + , m_resize(false) { } @@ -103,4 +104,14 @@ void AbstractClient::setKeepBelow(bool keepBelow) emit keepBelowChanged(); } +bool AbstractClient::isResize() const +{ + return m_resize; +} + +void AbstractClient::setResize(bool set) +{ + m_resize = set; +} + } diff --git a/autotests/mock_abstract_client.h b/autotests/mock_abstract_client.h index a88f04f06b..8d7e825d75 100644 --- a/autotests/mock_abstract_client.h +++ b/autotests/mock_abstract_client.h @@ -47,6 +47,8 @@ public: void setHiddenInternal(bool set); void setGeometry(const QRect &rect); void setKeepBelow(bool); + bool isResize() const; + void setResize(bool set); virtual void showOnScreenEdge() = 0; Q_SIGNALS: @@ -60,6 +62,7 @@ private: bool m_hiddenInternal; bool m_keepBelow; QRect m_geometry; + bool m_resize; }; } diff --git a/autotests/mock_client.cpp b/autotests/mock_client.cpp index 97d7e0154f..88b5fa6698 100644 --- a/autotests/mock_client.cpp +++ b/autotests/mock_client.cpp @@ -35,9 +35,4 @@ void Client::showOnScreenEdge() setHiddenInternal(false); } -bool Client::isResize() const -{ - return false; -} - } diff --git a/autotests/mock_client.h b/autotests/mock_client.h index df62ecd62d..17db3c8c7b 100644 --- a/autotests/mock_client.h +++ b/autotests/mock_client.h @@ -34,8 +34,6 @@ class Client : public AbstractClient public: explicit Client(QObject *parent); virtual ~Client(); - - bool isResize() const; void showOnScreenEdge() override; }; diff --git a/autotests/test_screen_edges.cpp b/autotests/test_screen_edges.cpp index e26459e5c2..8411781044 100644 --- a/autotests/test_screen_edges.cpp +++ b/autotests/test_screen_edges.cpp @@ -392,6 +392,27 @@ void TestScreenEdges::testCreatingInitialEdges() QCOMPARE(e->activatesForTouchGesture(), false); QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1)); } + + // let's start a move of window. + Client client(workspace()); + workspace()->setMovingClient(&client); + for (int i = 0; i < 8; ++i) { + auto e = edges.at(i); + QVERIFY(!e->isReserved()); + QCOMPARE(e->activatesForPointer(), true); + QCOMPARE(e->activatesForTouchGesture(), false); + QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1)); + } + // not for resize + client.setResize(true); + for (int i = 0; i < 8; ++i) { + auto e = edges.at(i); + QVERIFY(!e->isReserved()); + QCOMPARE(e->activatesForPointer(), false); + QCOMPARE(e->activatesForTouchGesture(), false); + QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1)); + } + workspace()->setMovingClient(nullptr); } void TestScreenEdges::testCallback() diff --git a/screenedge.cpp b/screenedge.cpp index 589c1d03f2..7e4fc07212 100644 --- a/screenedge.cpp +++ b/screenedge.cpp @@ -183,6 +183,12 @@ bool Edge::activatesForPointer() const if (m_edges->isDesktopSwitching()) { return true; } + if (m_edges->isDesktopSwitchingMovingClients()) { + auto c = Workspace::self()->getMovingClient(); + if (c && !c->isResize()) { + return true; + } + } if (!m_callBacks.isEmpty()) { return true; } From 7a3c2926122603752916f8b6ecc00a3333528707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Mon, 19 Jun 2017 06:54:54 +0200 Subject: [PATCH 6/7] Fix switch desktop on screenedge while resizing a Wayland window Summary: Screenedges only allows to switch desktop while moving window, not while resizing. There was a special branch which only checked this for X11 windows but not for Wayland windows. This change removes a no longer needed cast from AbstractClient to Client so that the check whether a window is getting resized works for both X11 and Wayland clients. The cast was introduced in a time when AbstractClient did not yet support the isResize method. Reviewers: #kwin, #plasma Subscribers: plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D6264 --- screenedge.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/screenedge.cpp b/screenedge.cpp index 7e4fc07212..0b17a0e413 100644 --- a/screenedge.cpp +++ b/screenedge.cpp @@ -299,10 +299,7 @@ bool Edge::canActivate(const QPoint &cursorPos, const QDateTime &triggerTime) void Edge::handle(const QPoint &cursorPos) { AbstractClient *movingClient = Workspace::self()->getMovingClient(); - bool isResize = false; - if (Client *movingClientClient = qobject_cast(movingClient)) - isResize = movingClientClient->isResize(); - if ((edges()->isDesktopSwitchingMovingClients() && movingClient && !isResize) || + if ((edges()->isDesktopSwitchingMovingClients() && movingClient && !movingClient->isResize()) || (edges()->isDesktopSwitching() && isScreenEdge())) { // always switch desktops in case: // moving a Client and option for switch on client move is enabled From 3b9ccc65a3a853ee5212486f69918eddd4db1e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Mon, 19 Jun 2017 17:01:47 +0200 Subject: [PATCH 7/7] [tabbox] Fix casts to Client where it should be AbstractClient Summary: A few areas in TabBox perform casts from Toplevel to Client. By casting to Client instead of AbstractClient the Wayland windows are excluded. This change addresses the problem by changing the casts where possible. The only remaining cast to Client is for shading which is not (yet) supported for Wayland windows anyway. Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D6273 --- tabbox/tabbox.cpp | 40 +++++++++++++++++++++------------------- tabbox/tabbox.h | 4 ++-- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp index d6d3c7849a..1438dd6743 100644 --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -284,7 +284,7 @@ TabBoxClientList TabBoxHandlerImpl::stackingOrder() const ToplevelList stacking = Workspace::self()->stackingOrder(); TabBoxClientList ret; foreach (Toplevel *toplevel, stacking) { - if (Client *client = qobject_cast(toplevel)) { + if (auto client = qobject_cast(toplevel)) { ret.append(client->tabBoxClient()); } } @@ -331,7 +331,7 @@ void TabBoxHandlerImpl::shadeClient(TabBoxClient *c, bool b) const QWeakPointer TabBoxHandlerImpl::desktopClient() const { foreach (Toplevel *toplevel, Workspace::self()->stackingOrder()) { - Client *client = qobject_cast(toplevel); + auto client = qobject_cast(toplevel); if (client && client->isDesktop() && client->isOnCurrentDesktop() && client->screen() == screens()->current()) { return client->tabBoxClient(); } @@ -1319,7 +1319,7 @@ void TabBox::walkThroughDesktops(bool forward) void TabBox::CDEWalkThroughWindows(bool forward) { - Client* c = nullptr; + AbstractClient* c = nullptr; // this function find the first suitable client for unreasonable focus // policies - the topmost one, with some exceptions (can't be keepabove/below, // otherwise it gets stuck on them) @@ -1327,7 +1327,7 @@ void TabBox::CDEWalkThroughWindows(bool forward) for (int i = Workspace::self()->stackingOrder().size() - 1; i >= 0 ; --i) { - Client* it = qobject_cast(Workspace::self()->stackingOrder().at(i)); + auto it = qobject_cast(Workspace::self()->stackingOrder().at(i)); if (it && it->isOnCurrentActivity() && it->isOnCurrentDesktop() && !it->isSpecialWindow() && it->isShown(false) && it->wantsTabFocus() && !it->keepAbove() && !it->keepBelow()) { @@ -1335,14 +1335,14 @@ void TabBox::CDEWalkThroughWindows(bool forward) break; } } - Client* nc = c; + AbstractClient* nc = c; bool options_traverse_all; { KConfigGroup group(kwinApp()->config(), "TabBox"); options_traverse_all = group.readEntry("TraverseAll", false); } - Client* firstClient = nullptr; + AbstractClient* firstClient = nullptr; do { nc = forward ? nextClientStatic(nc) : previousClientStatic(nc); if (!firstClient) { @@ -1641,34 +1641,36 @@ int TabBox::previousDesktopStatic(int iDesktop) const auxiliary functions to travers all clients according to the static order. Useful for the CDE-style Alt-tab feature. */ -Client* TabBox::nextClientStatic(Client* c) const +AbstractClient* TabBox::nextClientStatic(AbstractClient* c) const { - if (!c || Workspace::self()->clientList().isEmpty()) + const auto &list = Workspace::self()->allClientList(); + if (!c || list.isEmpty()) return 0; - int pos = Workspace::self()->clientList().indexOf(c); + int pos = list.indexOf(c); if (pos == -1) - return Workspace::self()->clientList().first(); + return list.first(); ++pos; - if (pos == Workspace::self()->clientList().count()) - return Workspace::self()->clientList().first(); - return Workspace::self()->clientList()[ pos ]; + if (pos == list.count()) + return list.first(); + return list.at(pos); } /*! auxiliary functions to travers all clients according to the static order. Useful for the CDE-style Alt-tab feature. */ -Client* TabBox::previousClientStatic(Client* c) const +AbstractClient* TabBox::previousClientStatic(AbstractClient* c) const { - if (!c || Workspace::self()->clientList().isEmpty()) + const auto &list = Workspace::self()->allClientList(); + if (!c || list.isEmpty()) return 0; - int pos = Workspace::self()->clientList().indexOf(c); + int pos = list.indexOf(c); if (pos == -1) - return Workspace::self()->clientList().last(); + return list.last(); if (pos == 0) - return Workspace::self()->clientList().last(); + return list.last(); --pos; - return Workspace::self()->clientList()[ pos ]; + return list.at(pos); } bool TabBox::establishTabBoxGrab() diff --git a/tabbox/tabbox.h b/tabbox/tabbox.h index 012cd815da..3cb8c7cf76 100644 --- a/tabbox/tabbox.h +++ b/tabbox/tabbox.h @@ -176,8 +176,8 @@ public: void initShortcuts(); - Client* nextClientStatic(Client*) const; - Client* previousClientStatic(Client*) const; + AbstractClient* nextClientStatic(AbstractClient*) const; + AbstractClient* previousClientStatic(AbstractClient*) const; int nextDesktopStatic(int iDesktop) const; int previousDesktopStatic(int iDesktop) const; void keyPress(int key);