diff --git a/components/containmentlayoutmanager/appletslayout.h b/components/containmentlayoutmanager/appletslayout.h --- a/components/containmentlayoutmanager/appletslayout.h +++ b/components/containmentlayoutmanager/appletslayout.h @@ -66,6 +66,13 @@ 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 @@ ItemContainer *placeHolder() const; void setPlaceHolder(ItemContainer *placeHolder); + QQuickItem *eventManagerToFilter() const; + void setEventManagerToFilter(QQuickItem *item); + EditModeCondition editModeCondition() const; void setEditModeCondition(EditModeCondition condition); @@ -158,18 +168,21 @@ 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; //void classBegin() override; void componentComplete() override; 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 @@ AbstractLayoutManager *m_layoutManager = nullptr; QPointer m_placeHolder; + QPointer m_eventManagerToFilter; QTimer *m_pressAndHoldTimer; QTimer *m_sizeSyncTimer; @@ -200,7 +214,6 @@ QHash m_containerForApplet; - QPointer m_window; QSizeF m_minimumItemSize; QSizeF m_defaultItemSize; QSizeF m_savedSize; diff --git a/components/containmentlayoutmanager/appletslayout.cpp b/components/containmentlayoutmanager/appletslayout.cpp --- a/components/containmentlayoutmanager/appletslayout.cpp +++ b/components/containmentlayoutmanager/appletslayout.cpp @@ -93,28 +93,6 @@ 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 @@ 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 @@ } +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 @@ { 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::mouseUngrabEvent() +{ + m_pressAndHoldTimer->stop(); +} + void AppletsLayout::appletAdded(QObject *applet, int x, int y) { PlasmaQuick::AppletQuickItem *appletItem = qobject_cast(applet); diff --git a/components/containmentlayoutmanager/itemcontainer.cpp b/components/containmentlayoutmanager/itemcontainer.cpp --- a/components/containmentlayoutmanager/itemcontainer.cpp +++ b/components/containmentlayoutmanager/itemcontainer.cpp @@ -106,8 +106,7 @@ 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 @@ m_editModeCondition = condition; - setAcceptHoverEvents(condition == AfterMouseOver); + setAcceptHoverEvents(condition == AfterMouseOver || (m_layout && m_layout->editMode())); emit editModeConditionChanged(); } @@ -182,6 +181,7 @@ 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 @@ emit editModeConditionChanged(); } }); + connect(m_layout, &AppletsLayout::editModeChanged, this, [this]() { + setAcceptHoverEvents(m_editModeCondition == AfterMouseOver || m_layout->editMode()); + }); emit layoutChanged(); } @@ -625,22 +628,26 @@ { Q_UNUSED(event); - if (m_editModeCondition != AfterMouseOver) { + if (m_editModeCondition != AfterMouseOver && !m_layout->editMode()) { return; } if (m_closeEditModeTimer) { 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 --- a/containmentactions/contextmenu/menu.cpp +++ b/containmentactions/contextmenu/menu.cpp @@ -72,11 +72,11 @@ 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 --- 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 --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -216,6 +216,19 @@ 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()