From fdd9ed53d9a67089764d2879754c511f58da889e Mon Sep 17 00:00:00 2001 From: Ismael Asensio Date: Sat, 16 May 2020 01:02:46 +0200 Subject: [PATCH 1/4] [kcm/kwinrules] Fix Placement setting Summary: Since the port to KConfigXT, the setting "placement" is stored using the enum value, instead of a string equivalent. This updates the kcm model to be able to communicate this property with the config schema. BUG: 421586 FIXED-IN: 5.19.0 Test Plan: - In a rule set the "Initial Placement" property - The value is stored in `~/.config/kwinrulesrc` - Close/reopen the kcm. The placement value is correctly loaded. Reviewers: #kwin, #plasma, zzag Reviewed By: #kwin, #plasma, zzag Subscribers: zzag, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D29790 --- kcmkwin/kwinrules/rulesmodel.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/kcmkwin/kwinrules/rulesmodel.cpp b/kcmkwin/kwinrules/rulesmodel.cpp index bdf1309e45..2d0ee7a4ae 100644 --- a/kcmkwin/kwinrules/rulesmodel.cpp +++ b/kcmkwin/kwinrules/rulesmodel.cpp @@ -740,18 +740,17 @@ QList RulesModel::activitiesModelData() const QList RulesModel::placementModelData() const { - // From "placement.h" : Placement rule is stored as a string, not the enum value static const auto modelData = QList { - { Placement::policyToString(Placement::Default), i18n("Default") }, - { Placement::policyToString(Placement::NoPlacement), i18n("No Placement") }, - { Placement::policyToString(Placement::Smart), i18n("Minimal Overlapping") }, - { Placement::policyToString(Placement::Maximizing), i18n("Maximized") }, - { Placement::policyToString(Placement::Cascade), i18n("Cascaded") }, - { Placement::policyToString(Placement::Centered), i18n("Centered") }, - { Placement::policyToString(Placement::Random), i18n("Random") }, - { Placement::policyToString(Placement::ZeroCornered), i18n("In Top-Left Corner") }, - { Placement::policyToString(Placement::UnderMouse), i18n("Under Mouse") }, - { Placement::policyToString(Placement::OnMainWindow), i18n("On Main Window") } + { Placement::Default, i18n("Default") }, + { Placement::NoPlacement, i18n("No Placement") }, + { Placement::Smart, i18n("Minimal Overlapping") }, + { Placement::Maximizing, i18n("Maximized") }, + { Placement::Cascade, i18n("Cascaded") }, + { Placement::Centered, i18n("Centered") }, + { Placement::Random, i18n("Random") }, + { Placement::ZeroCornered, i18n("In Top-Left Corner") }, + { Placement::UnderMouse, i18n("Under Mouse") }, + { Placement::OnMainWindow, i18n("On Main Window") } }; return modelData; } From bd5e34f5b44e6baf46b1f994dd7c6d66a243d366 Mon Sep 17 00:00:00 2001 From: Ismael Asensio Date: Sun, 17 May 2020 03:34:21 +0200 Subject: [PATCH 2/4] [kcm/kwinrules] Detect virtual desktops in Wayland The list of virtual desktops is retrieved using a DBus method, instead of `KWindowSystem`, to make it work both in Wayland (as well as X11). FIXED-IN: 5.20 BUG: 416165 --- kcmkwin/kwinrules/CMakeLists.txt | 1 + kcmkwin/kwinrules/ruleitem.cpp | 4 ++-- kcmkwin/kwinrules/rulesmodel.cpp | 41 +++++++++++++++++++++++++++++--- kcmkwin/kwinrules/rulesmodel.h | 7 +++++- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/kcmkwin/kwinrules/CMakeLists.txt b/kcmkwin/kwinrules/CMakeLists.txt index 7027b1ffec..dc6e935f21 100644 --- a/kcmkwin/kwinrules/CMakeLists.txt +++ b/kcmkwin/kwinrules/CMakeLists.txt @@ -11,6 +11,7 @@ set(kwinrules_SRCS ../../rules.cpp ../../placement.cpp ../../utils.cpp + ../../virtualdesktopsdbustypes.cpp kwinsrc.cpp optionsmodel.cpp ruleitem.cpp diff --git a/kcmkwin/kwinrules/ruleitem.cpp b/kcmkwin/kwinrules/ruleitem.cpp index a4efce7f10..ff8047e71d 100644 --- a/kcmkwin/kwinrules/ruleitem.cpp +++ b/kcmkwin/kwinrules/ruleitem.cpp @@ -119,7 +119,7 @@ RuleItem::Type RuleItem::type() const QVariant RuleItem::value() const { - if (m_type == Option) { + if (m_options && m_type == Option) { return m_options->value(); } return m_value; @@ -127,7 +127,7 @@ QVariant RuleItem::value() const void RuleItem::setValue(QVariant value) { - if (m_type == Option) { + if (m_options && m_type == Option) { m_options->setValue(value); } m_value = typedValue(value, m_type); diff --git a/kcmkwin/kwinrules/rulesmodel.cpp b/kcmkwin/kwinrules/rulesmodel.cpp index 2d0ee7a4ae..daa17a0c03 100644 --- a/kcmkwin/kwinrules/rulesmodel.cpp +++ b/kcmkwin/kwinrules/rulesmodel.cpp @@ -45,6 +45,9 @@ RulesModel::RulesModel(QObject *parent) qmlRegisterUncreatableType("org.kde.kcms.kwinrules", 1, 0, "RulesModel", QStringLiteral("Do not create objects of type RulesModel")); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + populateRuleList(); } @@ -421,6 +424,10 @@ void RulesModel::populateRuleList() QIcon::fromTheme("virtual-desktops"))); desktop->setOptionsData(virtualDesktopsModelData()); + connect(this, &RulesModel::virtualDesktopsUpdated, + this, [this] { m_rules["desktop"]->setOptionsData(virtualDesktopsModelData()); }); + updateVirtualDesktops(); + #ifdef KWIN_BUILD_ACTIVITIES m_activities = new KActivities::Consumer(this); @@ -700,10 +707,10 @@ QList RulesModel::windowTypesModelData() const QList RulesModel::virtualDesktopsModelData() const { QList modelData; - for (int desktopId = 1; desktopId <= KWindowSystem::numberOfDesktops(); ++desktopId) { + for (const DBusDesktopDataStruct &desktop : m_virtualDesktops) { modelData << OptionsModel::Data{ - desktopId, - QString::number(desktopId).rightJustified(2) + QStringLiteral(": ") + KWindowSystem::desktopName(desktopId), + desktop.position + 1, // "desktop" setting uses the desktop position (int) starting at 1 + QString::number(desktop.position + 1).rightJustified(2) + QStringLiteral(": ") + desktop.name, QIcon::fromTheme("virtual-desktops") }; } @@ -815,4 +822,32 @@ void RulesModel::selectX11Window() ); } +void RulesModel::updateVirtualDesktops() +{ + QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), + QStringLiteral("/VirtualDesktopManager"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("Get")); + message.setArguments(QVariantList{ + QStringLiteral("org.kde.KWin.VirtualDesktopManager"), + QStringLiteral("desktops") + }); + + QDBusPendingReply async = QDBusConnection::sessionBus().asyncCall(message); + + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this); + connect(callWatcher, &QDBusPendingCallWatcher::finished, this, + [this](QDBusPendingCallWatcher *self) { + QDBusPendingReply reply = *self; + self->deleteLater(); + if (!reply.isValid()) { + return; + } + m_virtualDesktops = qdbus_cast(reply.value()); + emit virtualDesktopsUpdated(); + } + ); +} + + } //namespace diff --git a/kcmkwin/kwinrules/rulesmodel.h b/kcmkwin/kwinrules/rulesmodel.h index 3de0736845..a62cff5525 100644 --- a/kcmkwin/kwinrules/rulesmodel.h +++ b/kcmkwin/kwinrules/rulesmodel.h @@ -22,8 +22,9 @@ #define KWIN_RULES_MODEL_H #include "ruleitem.h" -#include "rulesettings.h" #include +#include +#include #include #include @@ -96,6 +97,8 @@ signals: void warningMessageChanged(); void suggestionsChanged(); + void virtualDesktopsUpdated(); + private: void populateRuleList(); bool wmclassWarning() const; @@ -103,6 +106,7 @@ private: QString defaultDescription() const; static const QHash x11PropertyHash(); + void updateVirtualDesktops(); QList windowTypesModelData() const; QList virtualDesktopsModelData() const; @@ -117,6 +121,7 @@ private slots: private: QList m_ruleList; QHash m_rules; + DBusDesktopDataVector m_virtualDesktops; #ifdef KWIN_BUILD_ACTIVITIES KActivities::Consumer *m_activities; #endif From 7569bdf6a35277d80dc1625a4bcff75762884d4b Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 19 May 2020 13:53:18 +0300 Subject: [PATCH 3/4] [scene] Re-build window quads after creating a WindowPixmap In order to generate window quads for a window, the scene needs a valid WindowPixmap tree. If it's time to render the window, the scene will build window quads for the contents, the server-side window decoration, the drop-shadow and cache the resulting window quads. With this way of generating window quads, we need the window pixmap tree to be valid, or else no contents window quads will be generated. While the window pixmap tree is guaranteed to be valid at the time of generation of window quads for Wayland and X11 clients, this is not the case for Xwayland clients. When an Xwayland client is created, some time may pass between the moment it's been created and the moment when a regular wayland surface has been associated with the xwayland window. If the compositor decides to render the Xwayland client in that short period of time, the window quads cache won't have window quads cache. In order to work around the weird asynchronous behavior of Xwayland clients, this change makes the scene discard the window quad cache when a new window pixmap has been created. This will ensure that the current window quads are always in sync with the current window pixmap tree. --- scene.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scene.cpp b/scene.cpp index 7b0a2fc09d..d798998092 100644 --- a/scene.cpp +++ b/scene.cpp @@ -1132,8 +1132,9 @@ void WindowPixmap::create() if (kwinApp()->shouldUseWaylandForCompositing()) { // use Buffer update(); - if (!isRoot() && isValid()) { + if (isRoot() && isValid()) { m_window->unreferencePreviousPixmap(); + m_window->invalidateQuadsCache(); } return; } @@ -1164,6 +1165,7 @@ void WindowPixmap::create() m_pixmapSize = bufferGeometry.size(); m_contentsRect = QRect(toplevel()->clientPos(), toplevel()->clientSize()); m_window->unreferencePreviousPixmap(); + m_window->invalidateQuadsCache(); } void WindowPixmap::update() From b2df11bf7e59d57240afcdf88b352d49799d9922 Mon Sep 17 00:00:00 2001 From: Bhushan Shah Date: Wed, 20 May 2020 19:56:15 +0530 Subject: [PATCH 4/4] [platforms/drm] show cursor only when it is enabled In previous code we used to update/show cursor even when the pointer device was present, e.g mobile device. Guard it behind the cursor enabled check. BUG: 418977 FIXED-IN: 5.19.0 --- plugins/platforms/drm/drm_backend.h | 4 ++++ plugins/platforms/drm/drm_output.cpp | 17 +++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/plugins/platforms/drm/drm_backend.h b/plugins/platforms/drm/drm_backend.h index 545865187f..93333279a6 100644 --- a/plugins/platforms/drm/drm_backend.h +++ b/plugins/platforms/drm/drm_backend.h @@ -132,6 +132,10 @@ public: QString supportInformation() const override; + bool isCursorEnabled() const { + return m_cursorEnabled; + }; + public Q_SLOTS: void turnOutputsOn(); diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp index 0d3ee97788..66ffbe06aa 100644 --- a/plugins/platforms/drm/drm_output.cpp +++ b/plugins/platforms/drm/drm_output.cpp @@ -709,9 +709,12 @@ void DrmOutput::updateTransform(Transform transform) } m_modesetRequested = true; - // the cursor might need to get rotated - updateCursor(); - showCursor(); + // show cursor only if is enabled, i.e if pointer device is presentP + if (m_backend->isCursorEnabled()) { + // the cursor might need to get rotated + updateCursor(); + showCursor(); + } } void DrmOutput::updateMode(int modeIndex) @@ -867,9 +870,11 @@ bool DrmOutput::presentAtomically(DrmBuffer *buffer) m_primaryPlane->setTransformation(m_lastWorkingState.planeTransformations); } m_modesetRequested = true; - // the cursor might need to get rotated - updateCursor(); - showCursor(); + if (m_backend->isCursorEnabled()) { + // the cursor might need to get rotated + updateCursor(); + showCursor(); + } // TODO: forward to OutputInterface and OutputDeviceInterface setWaylandMode(); emit screens()->changed();