diff --git a/components/mobileshell/qml/homescreen/HomeScreenWallpaperBlur.qml b/components/mobileshell/qml/homescreen/HomeScreenWallpaperBlur.qml new file mode 100644 index 00000000..04b73620 --- /dev/null +++ b/components/mobileshell/qml/homescreen/HomeScreenWallpaperBlur.qml @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2023-2025 Devin Lin +// SPDX-License-Identifier: LGPL-2.0-or-later + +import QtQuick +import QtQuick.Layouts +import Qt5Compat.GraphicalEffects + +Loader { + id: root + property real blurOpacity + property Item wallpaperItem + + sourceComponent: Item { + id: wallpaper + anchors.fill: parent + + // only take samples from wallpaper when we need the blur for performance + ShaderEffectSource { + id: controlledWallpaperSource + anchors.fill: parent + + live: blur.visible + hideSource: false + visible: false + sourceItem: root.wallpaperItem + } + + // wallpaper blur + // we attempted to use MultiEffect in the past, but it had very poor performance on the PinePhone + FastBlur { + id: blur + radius: 50 + cached: true + source: controlledWallpaperSource + anchors.fill: parent + visible: opacity > 0 + opacity: root.blurOpacity + } + } +} \ No newline at end of file diff --git a/containments/homescreens/folio/package/contents/ui/main.qml b/containments/homescreens/folio/package/contents/ui/main.qml index 065b4260..f12002f2 100644 --- a/containments/homescreens/folio/package/contents/ui/main.qml +++ b/containments/homescreens/folio/package/contents/ui/main.qml @@ -31,45 +31,20 @@ ContainmentItem { forceActiveFocus(); } - Loader { - id: wallpaperBlurLoader + MobileShell.HomeScreenWallpaperBlur { + id: wallpaperBlur active: folio.FolioSettings.showWallpaperBlur anchors.fill: parent + wallpaperItem: Plasmoid.wallpaperGraphicsObject - sourceComponent: Item { - id: wallpaper - anchors.fill: parent - - // only take samples from wallpaper when we need the blur for performance - ShaderEffectSource { - id: controlledWallpaperSource - anchors.fill: parent - - sourceItem: Plasmoid.wallpaperGraphicsObject - live: blur.visible - hideSource: false - visible: false - } - - // wallpaper blur - // we attempted to use MultiEffect in the past, but it had very poor performance on the PinePhone - FastBlur { - id: blur - radius: 50 - cached: true - source: controlledWallpaperSource - anchors.fill: parent - visible: opacity > 0 - opacity: Math.min(1, - Math.max( - 1 - homeScreen.contentOpacity, - folio.HomeScreenState.appDrawerOpenProgress * 2, // blur faster during swipe - folio.HomeScreenState.searchWidgetOpenProgress * 1.5, // blur faster during swipe - folio.HomeScreenState.folderOpenProgress - ) - ) - } - } + blurOpacity: Math.min(1, + Math.max( + 1 - homeScreen.contentOpacity, + folio.HomeScreenState.appDrawerOpenProgress * 2, // blur faster during swipe + folio.HomeScreenState.searchWidgetOpenProgress * 1.5, // blur faster during swipe + folio.HomeScreenState.folderOpenProgress + ) + ) } WindowPlugin.WindowMaximizedTracker { diff --git a/containments/homescreens/halcyon/CMakeLists.txt b/containments/homescreens/halcyon/CMakeLists.txt index 7661003e..4a670c78 100644 --- a/containments/homescreens/halcyon/CMakeLists.txt +++ b/containments/homescreens/halcyon/CMakeLists.txt @@ -5,6 +5,7 @@ add_definitions(-DTRANSLATION_DOMAIN=\"plasma_applet_org.kde.plasma.mobile.homes set(homescreen_SRCS homescreen.cpp + halcyonsettings.cpp ) add_library(org.kde.plasma.mobile.homescreen.halcyon MODULE ${homescreen_SRCS}) @@ -14,11 +15,11 @@ target_link_libraries(org.kde.plasma.mobile.homescreen.halcyon Qt::Qml Qt::Quick Plasma::Plasma + Plasma::KWaylandClient KF6::I18n KF6::Service KF6::KIOGui KF6::Notifications - Plasma::KWaylandClient KF6::WindowSystem ) diff --git a/containments/homescreens/halcyon/halcyonsettings.cpp b/containments/homescreens/halcyon/halcyonsettings.cpp new file mode 100644 index 00000000..d6114161 --- /dev/null +++ b/containments/homescreens/halcyon/halcyonsettings.cpp @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2025 Devin Lin +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "halcyonsettings.h" + +const QString CFG_KEY_SHOW_WALLPAPER_BLUR = QStringLiteral("showWallpaperBlur"); +const QString CFG_KEY_DOUBLE_TAP_TO_SLEEP = QStringLiteral("doubleTapToSleep"); + +HalcyonSettings::HalcyonSettings(QObject *parent, KConfigGroup config) + : QObject{parent} + , m_config{config} +{ + load(); +} + +bool HalcyonSettings::showWallpaperBlur() const +{ + return m_showWallpaperBlur; +} + +void HalcyonSettings::setShowWallpaperBlur(bool showWallpaperBlur) +{ + if (m_showWallpaperBlur != showWallpaperBlur) { + m_showWallpaperBlur = showWallpaperBlur; + Q_EMIT showWallpaperBlurChanged(); + save(); + } +} + +bool HalcyonSettings::doubleTapToSleep() const +{ + return m_doubleTapToSleep; +} + +void HalcyonSettings::setDoubleTapToSleep(bool doubleTapToSleep) +{ + if (m_doubleTapToSleep != doubleTapToSleep) { + m_doubleTapToSleep = doubleTapToSleep; + Q_EMIT doubleTapToSleepChanged(); + save(); + } +} + +void HalcyonSettings::save() +{ + m_config.writeEntry(CFG_KEY_SHOW_WALLPAPER_BLUR, m_showWallpaperBlur); + m_config.writeEntry(CFG_KEY_DOUBLE_TAP_TO_SLEEP, m_doubleTapToSleep); + + m_config.sync(); +} + +void HalcyonSettings::load() +{ + m_showWallpaperBlur = m_config.readEntry(CFG_KEY_SHOW_WALLPAPER_BLUR, false); + m_doubleTapToSleep = m_config.readEntry(CFG_KEY_DOUBLE_TAP_TO_SLEEP, true); +} \ No newline at end of file diff --git a/containments/homescreens/halcyon/halcyonsettings.h b/containments/homescreens/halcyon/halcyonsettings.h new file mode 100644 index 00000000..a3dc2665 --- /dev/null +++ b/containments/homescreens/halcyon/halcyonsettings.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2025 Devin Lin +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include + +class HalcyonSettings : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool showWallpaperBlur READ showWallpaperBlur WRITE setShowWallpaperBlur NOTIFY showWallpaperBlurChanged) + Q_PROPERTY(bool doubleTapToSleep READ doubleTapToSleep WRITE setDoubleTapToSleep NOTIFY doubleTapToSleepChanged) + +public: + HalcyonSettings(QObject *parent = nullptr, KConfigGroup config = {}); + + bool showWallpaperBlur() const; + void setShowWallpaperBlur(bool blurWallpaper); + + bool doubleTapToSleep() const; + void setDoubleTapToSleep(bool doubleTapToSleep); + +Q_SIGNALS: + void showWallpaperBlurChanged(); + void doubleTapToSleepChanged(); + +private: + void save(); + void load(); + + bool m_showWallpaperBlur{false}; + bool m_doubleTapToSleep{true}; + + KConfigGroup m_config; +}; \ No newline at end of file diff --git a/containments/homescreens/halcyon/homescreen.cpp b/containments/homescreens/halcyon/homescreen.cpp index 86beb986..13facc77 100644 --- a/containments/homescreens/halcyon/homescreen.cpp +++ b/containments/homescreens/halcyon/homescreen.cpp @@ -11,12 +11,18 @@ HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args) : Plasma::Containment{parent, data, args} + , m_settings{new HalcyonSettings{this, config()}} { setHasConfigurationInterface(true); } HomeScreen::~HomeScreen() = default; +HalcyonSettings *HomeScreen::settings() const +{ + return m_settings; +} + K_PLUGIN_CLASS(HomeScreen) #include "homescreen.moc" diff --git a/containments/homescreens/halcyon/homescreen.h b/containments/homescreens/halcyon/homescreen.h index 4e149e13..38a14667 100644 --- a/containments/homescreens/halcyon/homescreen.h +++ b/containments/homescreens/halcyon/homescreen.h @@ -5,14 +5,22 @@ #include +#include "halcyonsettings.h" + class HomeScreen : public Plasma::Containment { Q_OBJECT + Q_PROPERTY(HalcyonSettings *settings READ settings CONSTANT) public: HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args); ~HomeScreen() override; + HalcyonSettings *settings() const; + Q_SIGNALS: void showingDesktopChanged(bool showingDesktop); + +private: + HalcyonSettings *m_settings{nullptr}; }; diff --git a/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml b/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml index 52ff1c0a..74454bf0 100644 --- a/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml +++ b/containments/homescreens/halcyon/package/contents/ui/HomeScreen.qml @@ -13,6 +13,9 @@ import org.kde.draganddrop as DragDrop import org.kde.kirigami as Kirigami import org.kde.plasma.private.mobileshell.state as MobileShellState import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin +import org.kde.plasma.private.mobileshell as MobileShell + +import "settings" as Settings Item { id: root @@ -62,7 +65,7 @@ Item { } } - SettingsScreen { + Settings.SettingsScreen { id: settings bottomMargin: root.bottomMargin anchors.fill: parent @@ -104,6 +107,15 @@ Item { } onLongPressed: root.openConfigure() + onDoubleTapped: { + if (Plasmoid.settings.doubleTapToSleep) { + doubleTapToSleep.doubleTapped(); + } + } + } + + MobileShell.DoubleTapToSleep { + id: doubleTapToSleep } FavoritesView { diff --git a/containments/homescreens/halcyon/package/contents/ui/main.qml b/containments/homescreens/halcyon/package/contents/ui/main.qml index e63ae9fd..adcb2f88 100644 --- a/containments/homescreens/halcyon/package/contents/ui/main.qml +++ b/containments/homescreens/halcyon/package/contents/ui/main.qml @@ -56,11 +56,23 @@ ContainmentItem { screenGeometry: Plasmoid.containment.screenGeometry } + MobileShell.HomeScreenWallpaperBlur { + id: wallpaperBlur + active: Plasmoid.settings.showWallpaperBlur + anchors.fill: parent + wallpaperItem: Plasmoid.wallpaperGraphicsObject + + blurOpacity: Math.min(1, + Math.max(1 - homeScreen.contentOpacity, + halcyonHomeScreen.settingsOpenFactor + ) + ) + } + Rectangle { id: darkenBackground color: (halcyonHomeScreen.page == 1 ? Qt.rgba(0, 0, 0, 0.7) : Qt.rgba(0, 0, 0, 0.2)) anchors.fill: parent - z: -1 Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration } } @@ -71,7 +83,6 @@ ContainmentItem { color: Qt.rgba(0, 0, 0, 0.7) opacity: halcyonHomeScreen.settingsOpenFactor anchors.fill: parent - z: -1 Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration } } diff --git a/containments/homescreens/halcyon/package/contents/ui/SettingsScreen.qml b/containments/homescreens/halcyon/package/contents/ui/settings/SettingsScreen.qml similarity index 81% rename from containments/homescreens/halcyon/package/contents/ui/SettingsScreen.qml rename to containments/homescreens/halcyon/package/contents/ui/settings/SettingsScreen.qml index a80437b7..8b284062 100644 --- a/containments/homescreens/halcyon/package/contents/ui/SettingsScreen.qml +++ b/containments/homescreens/halcyon/package/contents/ui/settings/SettingsScreen.qml @@ -103,12 +103,40 @@ Item { onClicked: { root.homeScreen.settingsOpen = false; - root.homeScreen.openContainmentSettings(); + + if (settingsWindowLoader.active) { + // Ensure that if the window is already opened, it gets raised to the top + settingsWindowLoader.item.hide(); + settingsWindowLoader.item.showMaximized(); + } else { + settingsWindowLoader.active = true; + } } } } } + // Only load settings window when visible + Loader { + id: settingsWindowLoader + asynchronous: true + active: false + + onLoaded: item.showMaximized(); + + sourceComponent: SettingsWindow { + onVisibleChanged: { + if (!visible) { + settingsWindowLoader.active = false; + } + } + onRequestConfigureMenu: { + root.homeScreen.openContainmentSettings(); + } + } + } + + // Only load wallpaper selector when visible Loader { id: wallpaperSelectorLoader asynchronous: true diff --git a/containments/homescreens/halcyon/package/contents/ui/settings/SettingsWindow.qml b/containments/homescreens/halcyon/package/contents/ui/settings/SettingsWindow.qml new file mode 100644 index 00000000..ea3b8f36 --- /dev/null +++ b/containments/homescreens/halcyon/package/contents/ui/settings/SettingsWindow.qml @@ -0,0 +1,129 @@ +// SPDX-FileCopyrightText: 2023-2025 Devin Lin +// SPDX-License-Identifier: LGPL-2.0-or-later + +import QtQuick +import QtQuick.Window +import QtQuick.Layouts +import QtQuick.Dialogs +import QtQuick.Controls as QQC2 + +import org.kde.plasma.plasmoid +import org.kde.kirigami as Kirigami +import org.kde.kirigamiaddons.formcard as FormCard + +Window { + id: root + + flags: Qt.FramelessWindowHint + color: 'transparent' + + onVisibleChanged: { + if (visible) { + opacityAnim.to = 1; + opacityAnim.restart(); + } + } + + onClosing: (close) => { + if (applicationItem.opacity !== 0) { + close.accepted = false; + opacityAnim.to = 0; + opacityAnim.restart(); + } + } + + signal requestConfigureMenu() + + Kirigami.ApplicationItem { + id: applicationItem + anchors.fill: parent + + opacity: 0 + + NumberAnimation on opacity { + id: opacityAnim + duration: 200 + easing.type: Easing.OutCubic + onFinished: { + if (applicationItem.opacity === 0) { + root.close(); + } + } + } + + scale: 0.7 + 0.3 * applicationItem.opacity + + pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.ToolBar + pageStack.globalToolBar.showNavigationButtons: Kirigami.ApplicationHeaderStyle.NoNavigationButtons; + + pageStack.initialPage: Kirigami.ScrollablePage { + id: page + opacity: applicationItem.opacity + + titleDelegate: RowLayout { + QQC2.ToolButton { + Layout.leftMargin: -Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing + icon.name: "arrow-left" + onClicked: root.close() + } + + Kirigami.Heading { + level: 1 + text: page.title + } + } + + title: i18n("Homescreen Settings") + + topPadding: 0 + bottomPadding: 0 + leftPadding: 0 + rightPadding: 0 + + ColumnLayout { + + FormCard.FormHeader { + title: i18n("Homescreen") + } + + FormCard.FormCard { + FormCard.FormSwitchDelegate { + id: showWallpaperBlur + text: i18nc("@option:check", "Show wallpaper blur effect") + checked: Plasmoid.settings.showWallpaperBlur + onCheckedChanged: { + if (checked != Plasmoid.settings.showWallpaperBlur) { + Plasmoid.settings.showWallpaperBlur = checked; + } + } + } + + FormCard.FormDelegateSeparator { above: showWallpaperBlur; below: doubleTapToSleepSwitch } + + FormCard.FormSwitchDelegate { + id: doubleTapToSleepSwitch + text: i18n("Double tap to lock device") + checked: Plasmoid.settings.doubleTapToSleep + onCheckedChanged: { + if (checked != Plasmoid.settings.doubleTapToSleep) { + Plasmoid.settings.doubleTapToSleep = checked; + } + } + } + } + + FormCard.FormCard { + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.bottomMargin: Kirigami.Units.gridUnit + + FormCard.FormButtonDelegate { + id: containmentSettings + text: i18nc("@action:button", "Switch between homescreens and more wallpaper options") + icon.name: 'settings-configure' + onClicked: root.requestConfigureMenu() + } + } + } + } + } +}