From c9c0f070a91b89fefe2f62f47e240563e7cf344c Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Fri, 18 Oct 2019 14:40:30 +0200 Subject: [PATCH] edit mode action and dbus Summary: edit mode menu action edit mode dbus property for systemsettings containmentlayoutmanager goes out of edit mode only when the whole plasma app loses focus, so the panel controlled doesn't make it go out of it Test Plan: iaction shows in context menu, works property exposed on dbus works Reviewers: #plasma, #vdg, ngraham, GB_2, davidedmundson Reviewed By: #plasma, #vdg, ngraham, GB_2, davidedmundson Subscribers: GB_2, ngraham, davidedmundson, plasma-devel Tags: #plasma Maniphest Tasks: T10190, T11094, T10402 Differential Revision: https://phabricator.kde.org/D24264 --- .../appletslayout.cpp | 83 ++++++++++++++----- .../containmentlayoutmanager/appletslayout.h | 15 +++- .../itemcontainer.cpp | 19 +++-- containmentactions/contextmenu/menu.cpp | 8 +- shell/dbus/org.kde.PlasmaShell.xml | 1 + shell/shellcorona.cpp | 13 +++ 6 files changed, 108 insertions(+), 31 deletions(-) diff --git a/components/containmentlayoutmanager/appletslayout.cpp b/components/containmentlayoutmanager/appletslayout.cpp index 3e616dd71..a2f8ad765 100644 --- a/components/containmentlayoutmanager/appletslayout.cpp +++ b/components/containmentlayoutmanager/appletslayout.cpp @@ -93,28 +93,6 @@ AppletsLayout::AppletsLayout(QQuickItem *parent) polish(); } }); - - m_window = window(); - if (m_window) { - connect(m_window, &QWindow::activeChanged, this, [this]() { - if (!m_window->isActive()) { - setEditMode(false); - } - }); - } - connect(this, &QQuickItem::windowChanged, this, [this]() { - if (m_window) { - disconnect(m_window, &QWindow::activeChanged, this, nullptr); - } - m_window = window(); - if (m_window) { - connect(m_window, &QWindow::activeChanged, this, [this]() { - if (!m_window->isActive()) { - setEditMode(false); - } - }); - } - }); } AppletsLayout::~AppletsLayout() @@ -367,6 +345,23 @@ void AppletsLayout::setPlaceHolder(ItemContainer *placeHolder) emit placeHolderChanged(); } +QQuickItem *AppletsLayout::eventManagerToFilter() const +{ + return m_eventManagerToFilter; +} + +void AppletsLayout::setEventManagerToFilter(QQuickItem *item) +{ + if (m_eventManagerToFilter == item) { + return; + } + + m_eventManagerToFilter = item; + setFiltersChildMouseEvents(m_eventManagerToFilter); + emit eventManagerToFilterChanged(); +} + + void AppletsLayout::save() { m_saveLayoutTimer->start(); @@ -527,6 +522,39 @@ void AppletsLayout::componentComplete() } +bool AppletsLayout::childMouseEventFilter(QQuickItem *item, QEvent *event) +{ + if (item != m_eventManagerToFilter) { + return QQuickItem::childMouseEventFilter(item, event); + } + + switch (event->type()) { + case QEvent::MouseButtonPress: { + QMouseEvent *me = static_cast(event); + if (me->buttons() & Qt::LeftButton) { + mousePressEvent(me); + } + break; + } + case QEvent::MouseMove: { + QMouseEvent *me = static_cast(event); + mouseMoveEvent(me); + break; + } + case QEvent::MouseButtonRelease: { + QMouseEvent *me = static_cast(event); + mouseReleaseEvent(me); + break; + } + case QEvent::UngrabMouse: + mouseUngrabEvent(); + break; + default: + break; + } + + return QQuickItem::childMouseEventFilter(item, event); +} void AppletsLayout::mousePressEvent(QMouseEvent *event) { @@ -562,6 +590,12 @@ void AppletsLayout::mouseReleaseEvent(QMouseEvent *event) { if (m_editMode && m_mouseDownWasEditMode + // By only accepting synthetyzed events, this makes the + // close by tapping in any empty area only work with real + // touch events, as we want a different behavior between desktop + // and tablet mode + && (event->source() == Qt::MouseEventSynthesizedBySystem + || event->source() == Qt::MouseEventSynthesizedByQt) && QPointF(event->windowPos() - m_mouseDownPosition).manhattanLength() < QGuiApplication::styleHints()->startDragDistance()) { setEditMode(false); } @@ -578,6 +612,11 @@ void AppletsLayout::mouseReleaseEvent(QMouseEvent *event) } } +void AppletsLayout::mouseUngrabEvent() +{ + m_pressAndHoldTimer->stop(); +} + void AppletsLayout::appletAdded(QObject *applet, int x, int y) { PlasmaQuick::AppletQuickItem *appletItem = qobject_cast(applet); diff --git a/components/containmentlayoutmanager/appletslayout.h b/components/containmentlayoutmanager/appletslayout.h index 55c37612c..fe65dcc97 100644 --- a/components/containmentlayoutmanager/appletslayout.h +++ b/components/containmentlayoutmanager/appletslayout.h @@ -66,6 +66,13 @@ class AppletsLayout: public QQuickItem Q_PROPERTY(ItemContainer *placeHolder READ placeHolder WRITE setPlaceHolder NOTIFY placeHolderChanged); + /** + * if the applets layout contains some kind of main MouseArea, + * MouseEventListener or Flickable, we want to filter its events to make the + * long mouse press work + */ + Q_PROPERTY(QQuickItem *eventManagerToFilter READ eventManagerToFilter WRITE setEventManagerToFilter NOTIFY eventManagerToFilterChanged); + Q_PROPERTY(AppletsLayout::EditModeCondition editModeCondition READ editModeCondition WRITE setEditModeCondition NOTIFY editModeConditionChanged) Q_PROPERTY(bool editMode READ editMode WRITE setEditMode NOTIFY editModeChanged) @@ -123,6 +130,9 @@ public: ItemContainer *placeHolder() const; void setPlaceHolder(ItemContainer *placeHolder); + QQuickItem *eventManagerToFilter() const; + void setEventManagerToFilter(QQuickItem *item); + EditModeCondition editModeCondition() const; void setEditModeCondition(EditModeCondition condition); @@ -158,10 +168,12 @@ Q_SIGNALS: void acceptsAppletCallbackChanged(); void appletContainerComponentChanged(); void placeHolderChanged(); + void eventManagerToFilterChanged(); void editModeConditionChanged(); void editModeChanged(); protected: + bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; void updatePolish() override; void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; @@ -170,6 +182,7 @@ protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; + void mouseUngrabEvent() override; private Q_SLOTS: void appletAdded(QObject *applet, int x, int y); @@ -190,6 +203,7 @@ private: AbstractLayoutManager *m_layoutManager = nullptr; QPointer m_placeHolder; + QPointer m_eventManagerToFilter; QTimer *m_pressAndHoldTimer; QTimer *m_sizeSyncTimer; @@ -200,7 +214,6 @@ private: QHash m_containerForApplet; - QPointer m_window; QSizeF m_minimumItemSize; QSizeF m_defaultItemSize; QSizeF m_savedSize; diff --git a/components/containmentlayoutmanager/itemcontainer.cpp b/components/containmentlayoutmanager/itemcontainer.cpp index 6cb7dd18a..2cf0e6b21 100644 --- a/components/containmentlayoutmanager/itemcontainer.cpp +++ b/components/containmentlayoutmanager/itemcontainer.cpp @@ -106,8 +106,7 @@ void ItemContainer::setEditMode(bool editMode) m_editMode = editMode; - // Leave this decision to QML? - if (m_editModeCondition != AfterMouseOver || m_layout->editMode()) { + if (m_editModeCondition != AfterMouseOver || (m_layout && m_layout->editMode())) { m_contentItem->setEnabled(!editMode); } @@ -153,7 +152,7 @@ void ItemContainer::setEditModeCondition(EditModeCondition condition) m_editModeCondition = condition; - setAcceptHoverEvents(condition == AfterMouseOver); + setAcceptHoverEvents(condition == AfterMouseOver || (m_layout && m_layout->editMode())); emit editModeConditionChanged(); } @@ -182,6 +181,7 @@ void ItemContainer::setLayout(AppletsLayout *layout) if (m_layout) { disconnect(m_layout, &AppletsLayout::editModeConditionChanged, this, nullptr); + disconnect(m_layout, &AppletsLayout::editModeChanged, this, nullptr); if (m_editMode) { m_layout->hidePlaceHolder(); @@ -208,6 +208,9 @@ void ItemContainer::setLayout(AppletsLayout *layout) emit editModeConditionChanged(); } }); + connect(m_layout, &AppletsLayout::editModeChanged, this, [this]() { + setAcceptHoverEvents(m_editModeCondition == AfterMouseOver || m_layout->editMode()); + }); emit layoutChanged(); } @@ -625,7 +628,7 @@ void ItemContainer::hoverEnterEvent(QHoverEvent *event) { Q_UNUSED(event); - if (m_editModeCondition != AfterMouseOver) { + if (m_editModeCondition != AfterMouseOver && !m_layout->editMode()) { return; } @@ -633,14 +636,18 @@ void ItemContainer::hoverEnterEvent(QHoverEvent *event) m_closeEditModeTimer->stop(); } - m_editModeTimer->start(QGuiApplication::styleHints()->mousePressAndHoldInterval()); + if (m_layout->editMode()) { + setEditMode(true); + } else { + m_editModeTimer->start(QGuiApplication::styleHints()->mousePressAndHoldInterval()); + } } void ItemContainer::hoverLeaveEvent(QHoverEvent *event) { Q_UNUSED(event); - if (m_editModeCondition != AfterMouseOver) { + if (m_editModeCondition != AfterMouseOver && !m_layout->editMode()) { return; } diff --git a/containmentactions/contextmenu/menu.cpp b/containmentactions/contextmenu/menu.cpp index cfaf83453..243428790 100644 --- a/containmentactions/contextmenu/menu.cpp +++ b/containmentactions/contextmenu/menu.cpp @@ -71,11 +71,11 @@ void ContextMenu::restore(const KConfigGroup &config) if (c->containmentType() == Plasma::Types::PanelContainment || c->containmentType() == Plasma::Types::CustomPanelContainment) { - m_actionOrder << QStringLiteral("add widgets") << QStringLiteral("_add panel") << QStringLiteral("lock widgets") << QStringLiteral("_context") << QStringLiteral("configure") << QStringLiteral("remove"); + m_actionOrder << QStringLiteral("add widgets") << QStringLiteral("_add panel") << QStringLiteral("lock widgets") << QStringLiteral("edit mode") << QStringLiteral("_context") << QStringLiteral("configure") << QStringLiteral("remove"); } else { actions.insert(QStringLiteral("configure shortcuts"), false); m_actionOrder << QStringLiteral("_context") << QStringLiteral("_run_command") << QStringLiteral("add widgets") << QStringLiteral("_add panel") - << QStringLiteral("manage activities") << QStringLiteral("remove") << QStringLiteral("lock widgets") << QStringLiteral("_sep1") + << QStringLiteral("manage activities") << QStringLiteral("remove") << QStringLiteral("lock widgets") << QStringLiteral("edit mode") << QStringLiteral("_sep1") <corona()) { return c->corona()->actions()->action(QStringLiteral("lock widgets")); } + } else if (name == QLatin1String("edit mode")) { + if (c->corona()) { + return c->corona()->actions()->action(QStringLiteral("edit mode")); + } } else if (name == QLatin1String("manage activities")) { if (c->corona()) { return c->corona()->actions()->action(QStringLiteral("manage activities")); diff --git a/shell/dbus/org.kde.PlasmaShell.xml b/shell/dbus/org.kde.PlasmaShell.xml index f074e9b49..72e8ca5ef 100644 --- a/shell/dbus/org.kde.PlasmaShell.xml +++ b/shell/dbus/org.kde.PlasmaShell.xml @@ -1,6 +1,7 @@ + diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp index 6c95ecf31..a8e37417c 100644 --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -228,6 +228,19 @@ ShellCorona::ShellCorona(QObject *parent) KDirWatch::self()->addFile(m_configPath); connect(KDirWatch::self(), &KDirWatch::dirty, this, &ShellCorona::configurationChanged); connect(KDirWatch::self(), &KDirWatch::created, this, &ShellCorona::configurationChanged); + + connect(qApp, &QGuiApplication::focusWindowChanged, + this, [this] (QWindow *focusWindow) { + if (!focusWindow) { + setEditMode(false); + } + } + ); + connect(this, &ShellCorona::editModeChanged, + this, [this](bool edit) { + setDashboardShown(edit); + } + ); } ShellCorona::~ShellCorona()