From 2b51e0c30c87e8742e47dc0f34edf760171efd78 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Wed, 25 Jun 2025 22:39:36 +0200 Subject: [PATCH] homescreens/folio: Add options to turn off and lock the phone after a double tap on screen Linked to issue: https://invent.kde.org/teams/plasma-mobile/issues/-/issues/318 --- .../qml/homescreen/DoubleTapToSleep.qml | 66 +++++++++++++++++++ .../mobileshellstate/lockscreendbusclient.cpp | 9 +++ .../mobileshellstate/lockscreendbusclient.h | 1 + .../homescreens/folio/foliosettings.cpp | 18 +++++ .../homescreens/folio/foliosettings.h | 6 ++ .../package/contents/ui/FavouritesBar.qml | 6 ++ .../package/contents/ui/HomeScreenPage.qml | 6 ++ .../contents/ui/settings/SettingsWindow.qml | 13 ++++ 8 files changed, 125 insertions(+) create mode 100644 components/mobileshell/qml/homescreen/DoubleTapToSleep.qml diff --git a/components/mobileshell/qml/homescreen/DoubleTapToSleep.qml b/components/mobileshell/qml/homescreen/DoubleTapToSleep.qml new file mode 100644 index 00000000..8681f8da --- /dev/null +++ b/components/mobileshell/qml/homescreen/DoubleTapToSleep.qml @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2025 Florian RICHER +// SPDX-License-Identifier: LGPL-2.0-or-later + +import QtQuick + +import org.kde.plasma.private.mobileshell.dpmsplugin as DPMS +import org.kde.plasma.private.mobileshell.state as MobileShellState + +Item { + id: root + + property real doubleClickInterval: 400 + property int tapCount: 0 + property bool isSwiping: false + + signal doubleTapped() + + onDoubleTapped: { + MobileShellState.LockscreenDBusClient.lockScreen() + dpms.turnDpmsOff() + } + + DPMS.DPMSUtil { + id: dpms + } + + // Workaround for double tap detection without capture events for HomeScreen + Timer { + id: doubleClickTimer + interval: root.doubleClickInterval + onTriggered: { + root.tapCount = 0 + } + } + + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + + onReleased: { + mouse.accepted = false + + if (root.isSwiping) { + // Reset the isSwiping flag to re-enable double tap detection + root.isSwiping = false + return + } + + root.tapCount++; + if (root.tapCount === 2) { + root.doubleTapped() + } + + doubleClickTimer.restart() + } + + // If is swiping, we don't want to trigger the double tap + onPositionChanged: { + mouse.accepted = false + doubleClickTimer.stop() + root.tapCount = 0 + root.isSwiping = true + } + } +} + diff --git a/components/mobileshellstate/lockscreendbusclient.cpp b/components/mobileshellstate/lockscreendbusclient.cpp index 8d00502b..81bf09d3 100644 --- a/components/mobileshellstate/lockscreendbusclient.cpp +++ b/components/mobileshellstate/lockscreendbusclient.cpp @@ -33,6 +33,15 @@ bool LockscreenDBusClient::lockscreenActive() const return m_lockscreenActive; } +void LockscreenDBusClient::lockScreen() +{ + QDBusMessage request = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.ScreenSaver"), + QStringLiteral("/ScreenSaver"), + QStringLiteral("org.freedesktop.ScreenSaver"), + QStringLiteral("Lock")); + QDBusConnection::sessionBus().call(request); +} + void LockscreenDBusClient::slotLockscreenActiveChanged(bool active) { if (active != m_lockscreenActive) { diff --git a/components/mobileshellstate/lockscreendbusclient.h b/components/mobileshellstate/lockscreendbusclient.h index b277160e..233b7fff 100644 --- a/components/mobileshellstate/lockscreendbusclient.h +++ b/components/mobileshellstate/lockscreendbusclient.h @@ -20,6 +20,7 @@ public: explicit LockscreenDBusClient(QObject *parent = nullptr); bool lockscreenActive() const; + Q_INVOKABLE void lockScreen(); Q_SIGNALS: void lockscreenActiveChanged(); diff --git a/containments/homescreens/folio/foliosettings.cpp b/containments/homescreens/folio/foliosettings.cpp index 5956789c..3b1cbc09 100644 --- a/containments/homescreens/folio/foliosettings.cpp +++ b/containments/homescreens/folio/foliosettings.cpp @@ -19,6 +19,7 @@ const QString CFG_KEY_DELEGATE_ICON_SIZE = QStringLiteral("delegateIconSize"); const QString CFG_KEY_SHOW_FAVORITES_BAR_BACKGROUND = QStringLiteral("showFavoritesBarBackground"); const QString CFG_KEY_PAGE_TRANSITION_EFFECT = QStringLiteral("pageTransitionEffect"); const QString CFG_KEY_SHOW_WALLPAPER_BLUR = QStringLiteral("showWallpaperBlur"); +const QString CFG_KEY_DOUBLE_TAP_TO_SLEEP = QStringLiteral("doubleTapToSleep"); FolioSettings::FolioSettings(HomeScreen *parent) : QObject{parent} @@ -153,6 +154,20 @@ void FolioSettings::setShowWallpaperBlur(bool showWallpaperBlur) } } +bool FolioSettings::doubleTapToSleep() const +{ + return m_doubleTapToSleep; +} + +void FolioSettings::setDoubleTapToSleep(bool doubleTapToSleep) +{ + if (m_doubleTapToSleep != doubleTapToSleep) { + m_doubleTapToSleep = doubleTapToSleep; + Q_EMIT doubleTapToSleepChanged(); + save(); + } +} + void FolioSettings::save() { if (!m_homeScreen) { @@ -168,6 +183,7 @@ void FolioSettings::save() m_homeScreen->config().writeEntry(CFG_KEY_SHOW_FAVORITES_BAR_BACKGROUND, m_showFavouritesBarBackground); m_homeScreen->config().writeEntry(CFG_KEY_PAGE_TRANSITION_EFFECT, (int)m_pageTransitionEffect); m_homeScreen->config().writeEntry(CFG_KEY_SHOW_WALLPAPER_BLUR, m_showWallpaperBlur); + m_homeScreen->config().writeEntry(CFG_KEY_DOUBLE_TAP_TO_SLEEP, m_doubleTapToSleep); Q_EMIT m_homeScreen->configNeedsSaving(); } @@ -187,6 +203,7 @@ void FolioSettings::load() m_showFavouritesBarBackground = m_homeScreen->config().readEntry(CFG_KEY_SHOW_FAVORITES_BAR_BACKGROUND, true); m_pageTransitionEffect = static_cast(m_homeScreen->config().readEntry(CFG_KEY_PAGE_TRANSITION_EFFECT, (int)SlideTransition)); m_showWallpaperBlur = m_homeScreen->config().readEntry(CFG_KEY_SHOW_WALLPAPER_BLUR, true); + m_doubleTapToSleep = m_homeScreen->config().readEntry(CFG_KEY_DOUBLE_TAP_TO_SLEEP, true); Q_EMIT homeScreenRowsChanged(); Q_EMIT homeScreenColumnsChanged(); @@ -195,6 +212,7 @@ void FolioSettings::load() Q_EMIT lockLayoutChanged(); Q_EMIT delegateIconSizeChanged(); Q_EMIT showWallpaperBlurChanged(); + Q_EMIT doubleTapToSleepChanged(); } bool FolioSettings::saveLayoutToFile(QString path) diff --git a/containments/homescreens/folio/foliosettings.h b/containments/homescreens/folio/foliosettings.h index aa6529b1..1eb8e704 100644 --- a/containments/homescreens/folio/foliosettings.h +++ b/containments/homescreens/folio/foliosettings.h @@ -24,6 +24,7 @@ class FolioSettings : public QObject Q_PROPERTY( FolioSettings::PageTransitionEffect pageTransitionEffect READ pageTransitionEffect WRITE setPageTransitionEffect NOTIFY pageTransitionEffectChanged) Q_PROPERTY(bool showWallpaperBlur READ showWallpaperBlur WRITE setShowWallpaperBlur NOTIFY showWallpaperBlurChanged) + Q_PROPERTY(bool doubleTapToSleep READ doubleTapToSleep WRITE setDoubleTapToSleep NOTIFY doubleTapToSleepChanged) public: FolioSettings(HomeScreen *parent = nullptr); @@ -68,6 +69,9 @@ public: bool showWallpaperBlur() const; void setShowWallpaperBlur(bool showWallpaperBlur); + bool doubleTapToSleep() const; + void setDoubleTapToSleep(bool doubleTapToSleep); + Q_INVOKABLE void load(); Q_INVOKABLE bool saveLayoutToFile(QString path); @@ -83,6 +87,7 @@ Q_SIGNALS: void showFavouritesBarBackgroundChanged(); void pageTransitionEffectChanged(); void showWallpaperBlurChanged(); + void doubleTapToSleepChanged(); private: void save(); @@ -98,4 +103,5 @@ private: bool m_showFavouritesBarBackground{false}; PageTransitionEffect m_pageTransitionEffect{SlideTransition}; bool m_showWallpaperBlur{false}; + bool m_doubleTapToSleep{false}; }; diff --git a/containments/homescreens/folio/package/contents/ui/FavouritesBar.qml b/containments/homescreens/folio/package/contents/ui/FavouritesBar.qml index 46a231f9..9b90fb67 100644 --- a/containments/homescreens/folio/package/contents/ui/FavouritesBar.qml +++ b/containments/homescreens/folio/package/contents/ui/FavouritesBar.qml @@ -31,6 +31,12 @@ MouseArea { id: haptics } + MobileShell.DoubleTapToSleep { + id: doubleTapToSleep + enabled: folio.FolioSettings.doubleTapToSleep + anchors.fill: parent + } + Repeater { id: repeater model: folio.FavouritesModel diff --git a/containments/homescreens/folio/package/contents/ui/HomeScreenPage.qml b/containments/homescreens/folio/package/contents/ui/HomeScreenPage.qml index 9eb8218a..887bdb03 100644 --- a/containments/homescreens/folio/package/contents/ui/HomeScreenPage.qml +++ b/containments/homescreens/folio/package/contents/ui/HomeScreenPage.qml @@ -28,6 +28,12 @@ Item { id: haptics } + MobileShell.DoubleTapToSleep { + id: doubleTapToSleep + enabled: folio.FolioSettings.doubleTapToSleep + anchors.fill: parent + } + // background when in settings view (for rearranging pages) Rectangle { id: settingsViewBackground diff --git a/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml b/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml index 659d1cbc..c0de1a04 100644 --- a/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml +++ b/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml @@ -233,6 +233,19 @@ Window { onCurrentValueChanged: folio.FolioSettings.pageTransitionEffect = currentValue } + + FormCard.FormDelegateSeparator { above: pageTransitionCombobox; below: doubleTapToSleepSwitch } + + FormCard.FormSwitchDelegate { + id: doubleTapToSleepSwitch + text: i18n("Double tap to lock device") + checked: folio.FolioSettings.doubleTapToSleep + onCheckedChanged: { + if (checked != folio.FolioSettings.doubleTapToSleep) { + folio.FolioSettings.doubleTapToSleep = checked; + } + } + } } FormCard.FormHeader {