Shell: Add Setting to Auto Hide Panels so Applications Can Fill the Entire Device Screen Space

This merge request adds a new setting to auto hide the status and navigation panels so applications will be able to fill out the entire device screen area. Also, this adds a new quick settings toggle to quickly change this property.
This commit is contained in:
Micah Stanley 2025-04-21 15:56:33 +00:00
parent 036cc8502b
commit 842354bd70
11 changed files with 141 additions and 30 deletions

View file

@ -41,6 +41,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
Q_EMIT actionDrawerTopLeftModeChanged(); Q_EMIT actionDrawerTopLeftModeChanged();
Q_EMIT actionDrawerTopRightModeChanged(); Q_EMIT actionDrawerTopRightModeChanged();
Q_EMIT convergenceModeEnabledChanged(); Q_EMIT convergenceModeEnabledChanged();
Q_EMIT autoHidePanelsEnabledChanged();
Q_EMIT allowLogoutChanged(); Q_EMIT allowLogoutChanged();
} }
if (group.name() == LOCKSCREEN_CONFIG_GROUP) { if (group.name() == LOCKSCREEN_CONFIG_GROUP) {
@ -201,6 +202,19 @@ void MobileShellSettings::setConvergenceModeEnabled(bool enabled)
job->start(); job->start();
} }
bool MobileShellSettings::autoHidePanelsEnabled() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
return group.readEntry("autoHidePanelsEnabled", false);
}
void MobileShellSettings::setAutoHidePanelsEnabled(bool enabled)
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
group.writeEntry("autoHidePanelsEnabled", enabled, KConfigGroup::Notify);
m_config->sync();
}
void MobileShellSettings::updateNavigationBarsInPlasma(bool navigationPanelEnabled) void MobileShellSettings::updateNavigationBarsInPlasma(bool navigationPanelEnabled)
{ {
// Do not update panels when not in Plasma Mobile // Do not update panels when not in Plasma Mobile

View file

@ -45,6 +45,9 @@ class MobileShellSettings : public QObject
// convergence mode // convergence mode
Q_PROPERTY(bool convergenceModeEnabled READ convergenceModeEnabled WRITE setConvergenceModeEnabled NOTIFY convergenceModeEnabledChanged) Q_PROPERTY(bool convergenceModeEnabled READ convergenceModeEnabled WRITE setConvergenceModeEnabled NOTIFY convergenceModeEnabledChanged)
// Auto Hide Panels
Q_PROPERTY(bool autoHidePanelsEnabled READ autoHidePanelsEnabled WRITE setAutoHidePanelsEnabled NOTIFY autoHidePanelsEnabledChanged)
// logout dialog // logout dialog
Q_PROPERTY(bool allowLogout READ allowLogout READ allowLogout NOTIFY allowLogoutChanged) Q_PROPERTY(bool allowLogout READ allowLogout READ allowLogout NOTIFY allowLogoutChanged)
@ -219,6 +222,18 @@ public:
*/ */
void setConvergenceModeEnabled(bool enabled); void setConvergenceModeEnabled(bool enabled);
/**
* Whether Auto Hide Panels is enabled.
*/
bool autoHidePanelsEnabled() const;
/**
* Set whether Auto Hide Panels is enabled.
*
* @param enabled
*/
void setAutoHidePanelsEnabled(bool enabled);
/** /**
* Whether logout button is shown in the logout/shutdown dialog. * Whether logout button is shown in the logout/shutdown dialog.
*/ */
@ -262,6 +277,7 @@ Q_SIGNALS:
void actionDrawerTopLeftModeChanged(); void actionDrawerTopLeftModeChanged();
void actionDrawerTopRightModeChanged(); void actionDrawerTopRightModeChanged();
void convergenceModeEnabledChanged(); void convergenceModeEnabledChanged();
void autoHidePanelsEnabledChanged();
void allowLogoutChanged(); void allowLogoutChanged();
void lockscreenLeftButtonActionChanged(); void lockscreenLeftButtonActionChanged();
void lockscreenRightButtonActionChanged(); void lockscreenRightButtonActionChanged();

View file

@ -14,6 +14,7 @@ import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell.state as MobileShellState import org.kde.plasma.private.mobileshell.state as MobileShellState
import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin import org.kde.plasma.private.mobileshell.windowplugin as WindowPlugin
@ -51,6 +52,7 @@ ContainmentItem {
root.panel.floating = false; root.panel.floating = false;
root.panel.maximize(); // maximize first, then we can apply offsets (otherwise they are overridden) root.panel.maximize(); // maximize first, then we can apply offsets (otherwise they are overridden)
root.panel.thickness = statusPanelHeight; root.panel.thickness = statusPanelHeight;
root.panel.visibilityMode = ShellSettings.Settings.autoHidePanelsEnabled ? 3 : 0;
MobileShell.ShellUtil.setWindowLayer(root.panel, LayerShell.Window.LayerOverlay) MobileShell.ShellUtil.setWindowLayer(root.panel, LayerShell.Window.LayerOverlay)
root.updateTouchArea(); root.updateTouchArea();
} }
@ -67,18 +69,34 @@ ContainmentItem {
} }
} }
Connections {
target: ShellSettings.Settings
function onAutoHidePanelsEnabled() {
root.setWindowProperties();
}
}
// only opaque if there are no maximized windows on this screen // only opaque if there are no maximized windows on this screen
readonly property bool showingStartupFeedback: MobileShellState.ShellDBusObject.startupFeedbackModel.activeWindowIsStartupFeedback && windowMaximizedTracker.windowCount === 1 readonly property bool showingStartupFeedback: MobileShellState.ShellDBusObject.startupFeedbackModel.activeWindowIsStartupFeedback && startupFeedbackColorAnimation.visible && windowMaximizedTracker.windowCount === 1
readonly property bool showingApp: windowMaximizedTracker.showingWindow && !showingStartupFeedback readonly property bool showingApp: windowMaximizedTracker.showingWindow && !showingStartupFeedback
readonly property color backgroundColor: topPanel.colorScopeColor readonly property color backgroundColor: topPanel.colorScopeColor
readonly property alias isCurrentWindowFullscreen: windowMaximizedTracker.isCurrentWindowFullscreen readonly property alias isCurrentWindowFullscreen: windowMaximizedTracker.isCurrentWindowFullscreen
onIsCurrentWindowFullscreenChanged: { readonly property bool fullscreen: isCurrentWindowFullscreen || (ShellSettings.Settings.autoHidePanelsEnabled && showingApp)
MobileShellState.ShellDBusClient.panelState = isCurrentWindowFullscreen ? "hidden" : "default"; onFullscreenChanged: {
MobileShellState.ShellDBusClient.panelState = fullscreen ? "hidden" : "default";
} }
WindowPlugin.WindowMaximizedTracker { WindowPlugin.WindowMaximizedTracker {
id: windowMaximizedTracker id: windowMaximizedTracker
screenGeometry: Plasmoid.containment.screenGeometry screenGeometry: Plasmoid.containment.screenGeometry
onShowingWindowChanged: {
if (windowMaximizedTracker.showingWindow && MobileShellState.ShellDBusClient.isTaskSwitcherVisible && (ShellSettings.Settings.autoHidePanelsEnabled || fullscreen)) {
MobileShellState.ShellDBusClient.panelState = "hidden";
statusPanel.offset = -root.statusPanelHeight;
}
}
} }
// enforce thickness // enforce thickness
@ -138,7 +156,7 @@ ContainmentItem {
screen: Plasmoid.screen screen: Plasmoid.screen
maximizedTracker: windowMaximizedTracker maximizedTracker: windowMaximizedTracker
visible: !root.isCurrentWindowFullscreen visible: !root.fullscreen
} }
Rectangle { Rectangle {
@ -147,7 +165,7 @@ ContainmentItem {
Kirigami.Theme.colorSet: root.showingApp ? Kirigami.Theme.Header : Kirigami.Theme.Complementary Kirigami.Theme.colorSet: root.showingApp ? Kirigami.Theme.Header : Kirigami.Theme.Complementary
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
color: statusPanel.state == "default" && root.showingApp ? Kirigami.Theme.backgroundColor : "transparent" color: statusPanel.state == "default" && (root.showingApp || root.fullscreen) ? Kirigami.Theme.backgroundColor : "transparent"
property real offset: 0 property real offset: 0
@ -157,7 +175,7 @@ ContainmentItem {
anchors.fill: parent anchors.fill: parent
showDropShadow: !root.showingApp showDropShadow: !root.showingApp
backgroundColor: statusPanel.state != "default" ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) : "transparent" backgroundColor: statusPanel.state != "default" && root.showingApp ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) : "transparent"
transform: [ transform: [
Translate { Translate {
@ -210,7 +228,7 @@ ContainmentItem {
SequentialAnimation { SequentialAnimation {
ParallelAnimation { ParallelAnimation {
PropertyAnimation { PropertyAnimation {
properties: "offset"; easing.type: statusPanel.state == "hidden" ? Easing.InExpo : Easing.OutExpo; duration: Kirigami.Units.longDuration properties: "offset"; easing.type: statusPanel.state === "hidden" ? Easing.InExpo : Easing.OutExpo; duration: Kirigami.Units.longDuration
} }
} }
ScriptAction { ScriptAction {
@ -230,18 +248,6 @@ ContainmentItem {
readonly property alias drawerVisible: drawer.visible readonly property alias drawerVisible: drawer.visible
readonly property alias offset: drawer.actionDrawer.offset readonly property alias offset: drawer.actionDrawer.offset
property bool surfacePressed: false
onOffsetChanged: surfacePressed = false
// allow tapping to bring back up the status bar when it is hidden
onPressedChanged: {
if (!pressed && surfacePressed && root.isCurrentWindowFullscreen) {
haptics.buttonVibrate();
MobileShellState.ShellDBusClient.panelState = "visible";
} else {
surfacePressed = true;
}
}
// if in a fullscreen app, the panels are visible, and the action drawer is opened // if in a fullscreen app, the panels are visible, and the action drawer is opened
// set the panels to a hidden state // set the panels to a hidden state

View file

@ -26,7 +26,7 @@ MobileShell.NavigationPanel {
// - opaque if an app is shown or vkbd is shown // - opaque if an app is shown or vkbd is shown
// - translucent if the task switcher is open // - translucent if the task switcher is open
// - transparent if on the homescreen // - transparent if on the homescreen
backgroundColor: navbarState != "default" ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) : "transparent" backgroundColor: navbarState != "default" && opaqueBar ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) : "transparent"
foregroundColorGroup: opaqueBar ? Kirigami.Theme.Window : Kirigami.Theme.Complementary foregroundColorGroup: opaqueBar ? Kirigami.Theme.Window : Kirigami.Theme.Complementary
shadow: !opaqueBar shadow: !opaqueBar

View file

@ -85,6 +85,7 @@ ContainmentItem {
root.panel.offset = intendedWindowOffset; root.panel.offset = intendedWindowOffset;
root.panel.thickness = navigationPanelHeight; root.panel.thickness = navigationPanelHeight;
root.panel.location = intendedWindowLocation; root.panel.location = intendedWindowLocation;
root.panel.visibilityMode = ShellSettings.Settings.autoHidePanelsEnabled ? 3 : 0;
MobileShell.ShellUtil.setWindowLayer(root.panel, LayerShell.Window.LayerOverlay); MobileShell.ShellUtil.setWindowLayer(root.panel, LayerShell.Window.LayerOverlay);
root.updateTouchArea(); root.updateTouchArea();
} }
@ -124,17 +125,31 @@ ContainmentItem {
} }
} }
Connections {
target: ShellSettings.Settings
function onAutoHidePanelsEnabled() {
root.setWindowProperties();
}
}
Component.onCompleted: setWindowProperties(); Component.onCompleted: setWindowProperties();
// only opaque if there are no maximized windows on this screen // only opaque if there are no maximized windows on this screen
readonly property bool showingStartupFeedback: MobileShellState.ShellDBusObject.startupFeedbackModel.activeWindowIsStartupFeedback && windowMaximizedTracker.windowCount === 1 readonly property bool showingStartupFeedback: MobileShellState.ShellDBusObject.startupFeedbackModel.activeWindowIsStartupFeedback && startupFeedbackColorAnimation.visible && windowMaximizedTracker.windowCount === 1
readonly property bool opaqueBar: (windowMaximizedTracker.showingWindow || isCurrentWindowFullscreen) && !showingStartupFeedback readonly property bool opaqueBar: (windowMaximizedTracker.showingWindow || isCurrentWindowFullscreen) && !showingStartupFeedback
readonly property alias isCurrentWindowFullscreen: windowMaximizedTracker.isCurrentWindowFullscreen readonly property alias isCurrentWindowFullscreen: windowMaximizedTracker.isCurrentWindowFullscreen
readonly property bool fullscreen: isCurrentWindowFullscreen || (ShellSettings.Settings.autoHidePanelsEnabled && opaqueBar)
WindowPlugin.WindowMaximizedTracker { WindowPlugin.WindowMaximizedTracker {
id: windowMaximizedTracker id: windowMaximizedTracker
screenGeometry: Plasmoid.containment.screenGeometry screenGeometry: Plasmoid.containment.screenGeometry
onShowingWindowChanged: {
if (windowMaximizedTracker.showingWindow && MobileShellState.ShellDBusClient.isTaskSwitcherVisible && (ShellSettings.Settings.autoHidePanelsEnabled || fullscreen)) {
navigationPanel.offset = root.navigationPanelHeight;
}
}
} }
MobileShell.StartupFeedbackPanelFill { MobileShell.StartupFeedbackPanelFill {
@ -147,7 +162,7 @@ ContainmentItem {
screen: Plasmoid.screen screen: Plasmoid.screen
maximizedTracker: windowMaximizedTracker maximizedTracker: windowMaximizedTracker
visible: !root.isCurrentWindowFullscreen visible: !root.fullscreen
} }
Rectangle { Rectangle {
@ -208,7 +223,7 @@ ContainmentItem {
SequentialAnimation { SequentialAnimation {
ParallelAnimation { ParallelAnimation {
PropertyAnimation { PropertyAnimation {
properties: "offset"; easing.type: navigationPanel.state == "hidden" ? Easing.InExpo : Easing.OutExpo; duration: Kirigami.Units.longDuration properties: "offset"; easing.type: navigationPanel.state === "hidden" ? Easing.InExpo : Easing.OutExpo; duration: Kirigami.Units.longDuration
} }
} }
ScriptAction { ScriptAction {

View file

@ -47,6 +47,20 @@ KCM.SimpleKCM {
} }
} }
} }
FormCard.FormDelegateSeparator { above: shellVibrationsButton; below: animationsSwitch }
FormCard.FormSwitchDelegate {
id: autoHidePanels
text: i18n("Auto Hide Panels")
description: i18n("When active, status and navigation panels will auto hide, allowing applications to fill the entire screen space.")
checked: ShellSettings.Settings.autoHidePanelsEnabled
onCheckedChanged: {
if (checked != ShellSettings.Settings.autoHidePanelsEnabled) {
ShellSettings.Settings.autoHidePanelsEnabled = checked;
}
}
}
} }
FormCard.FormHeader { FormCard.FormHeader {

View file

@ -30,10 +30,12 @@ FocusScope {
readonly property QtObject effect: KWinComponents.SceneView.effect readonly property QtObject effect: KWinComponents.SceneView.effect
readonly property QtObject targetScreen: KWinComponents.SceneView.screen readonly property QtObject targetScreen: KWinComponents.SceneView.screen
readonly property real topMargin: MobileShell.Constants.topPanelHeight readonly property real navBottomMargin: MobileShell.Constants.navigationPanelOnSide(width, height) ? 0 : MobileShell.Constants.navigationPanelThickness
readonly property real bottomMargin: MobileShell.Constants.navigationPanelOnSide(width, height) ? 0 : MobileShell.Constants.navigationPanelThickness readonly property real navRightMargin: MobileShell.Constants.navigationPanelOnSide(width, height) ? MobileShell.Constants.navigationPanelThickness : 0
readonly property real topMargin: ShellSettings.Settings.autoHidePanelsEnabled ? 0 : MobileShell.Constants.topPanelHeight
readonly property real bottomMargin: ShellSettings.Settings.autoHidePanelsEnabled ? 0 : navBottomMargin
readonly property real leftMargin: 0 readonly property real leftMargin: 0
readonly property real rightMargin: MobileShell.Constants.navigationPanelOnSide(width, height) ? MobileShell.Constants.navigationPanelThickness : 0 readonly property real rightMargin: ShellSettings.Settings.autoHidePanelsEnabled ? 0 : navRightMargin
property var taskSwitcherHelpers: TaskSwitcherHelpers { property var taskSwitcherHelpers: TaskSwitcherHelpers {
taskSwitcher: root taskSwitcher: root
@ -481,7 +483,7 @@ FocusScope {
// navigation panel // navigation panel
MobileShell.NavigationPanel { MobileShell.NavigationPanel {
id: navigationPanel id: navigationPanel
z: 1 z: taskSwitcherHelpers.taskDrawerOpened && !taskSwitcherHelpers.currentlyBeingClosed ? 1 : 0
visible: ShellSettings.Settings.navigationPanelEnabled visible: ShellSettings.Settings.navigationPanelEnabled
backgroundColor: Qt.rgba(0, 0, 0, 0.1) backgroundColor: Qt.rgba(0, 0, 0, 0.1)
foregroundColorGroup: Kirigami.Theme.Complementary foregroundColorGroup: Kirigami.Theme.Complementary
@ -550,7 +552,7 @@ FocusScope {
} }
PropertyChanges { PropertyChanges {
target: navigationPanel target: navigationPanel
width: root.rightMargin width: navRightMargin
anchors.topMargin: root.topMargin anchors.topMargin: root.topMargin
} }
}, },
@ -568,7 +570,7 @@ FocusScope {
} }
PropertyChanges { PropertyChanges {
target: navigationPanel target: navigationPanel
height: root.bottomMargin height: navBottomMargin
} }
} }
] ]

View file

@ -8,6 +8,7 @@ plasma_install_package(bluetooth org.kde.plasma.quicksetting.bluetooth quicksett
plasma_install_package(caffeine org.kde.plasma.quicksetting.caffeine quicksettings) plasma_install_package(caffeine org.kde.plasma.quicksetting.caffeine quicksettings)
plasma_install_package(docked org.kde.plasma.quicksetting.docked quicksettings) plasma_install_package(docked org.kde.plasma.quicksetting.docked quicksettings)
plasma_install_package(donotdisturb org.kde.plasma.quicksetting.donotdisturb quicksettings) plasma_install_package(donotdisturb org.kde.plasma.quicksetting.donotdisturb quicksettings)
plasma_install_package(autohidepanels org.kde.plasma.quicksetting.autohidepanels quicksettings)
plasma_install_package(keyboardtoggle org.kde.plasma.quicksetting.keyboardtoggle quicksettings) plasma_install_package(keyboardtoggle org.kde.plasma.quicksetting.keyboardtoggle quicksettings)
plasma_install_package(mobiledata org.kde.plasma.quicksetting.mobiledata quicksettings) plasma_install_package(mobiledata org.kde.plasma.quicksetting.mobiledata quicksettings)
plasma_install_package(settingsapp org.kde.plasma.quicksetting.settingsapp quicksettings) plasma_install_package(settingsapp org.kde.plasma.quicksetting.settingsapp quicksettings)

View file

@ -0,0 +1,6 @@
#! /usr/bin/env bash
# SPDX-FileCopyrightText: 2025 Micah Stanley <stanleymicah@proton.me>
# SPDX-License-Identifier: GPL-2.0-or-later
$XGETTEXT `find . -name \*.js -o -name \*.qml -o -name \*.cpp` -o $podir/plasma_org.kde.plasma.quicksetting.autohidepanels.pot

View file

@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: 2025 Micah Stanley <stanleymicah@proton.me>
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS
QS.QuickSetting {
text: i18n("Auto Hide Panels")
icon: "view-fullscreen"
enabled: ShellSettings.Settings.autoHidePanelsEnabled
function toggle() {
ShellSettings.Settings.autoHidePanelsEnabled = !ShellSettings.Settings.autoHidePanelsEnabled;
}
}

View file

@ -0,0 +1,20 @@
{
"KPackageStructure": "KPackage/GenericQML",
"KPlugin": {
"Authors": [
{
"Email": "stanleymicah@proton.me",
"Name": "Micah Stanley",
"Name[x-test]": "xxMicah Stanleyxx"
}
],
"Description": "Auto Hide Panels quick setting for Plasma Mobile",
"Description[x-test]": "xxAuto Hide Panels quick setting for Plasma Mobilexx",
"Icon": "view-fullscreen",
"Id": "org.kde.plasma.quicksetting.autohidepanels",
"License": "GPL-2.0+",
"Name": "Auto Hide Panels",
"Name[x-test]": "xxAuto Hide Panelsxx",
"Website": "https://kde.org"
}
}