shift-shell/containments/panel/package/contents/ui/main.qml
Micah Stanley 9bd4f0b747 GestureNavigation: Screen Rotation Popup Button
Implementation of a popup button to rotate the screen while using gesture navigation.

The button is set to appear when the device rotates while auto rotation is off. Then the button will be visible for a short period of time before disappearing.
2025-04-21 22:09:14 +00:00

287 lines
10 KiB
QML

// SPDX-FileCopyrightText: 2021-2023 Devin Lin <devin@kde.org>
// SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQml.Models
import org.kde.kirigami as Kirigami
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
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.windowplugin as WindowPlugin
import org.kde.taskmanager as TaskManager
import org.kde.notificationmanager as NotificationManager
import org.kde.layershell 1.0 as LayerShell
ContainmentItem {
id: root
Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground
Plasmoid.status: PlasmaCore.Types.PassiveStatus // ensure that the panel never takes focus away from the running app
// filled in by the shell (Panel.qml) with the plasma-workspace PanelView
property var panel: null
onPanelChanged: setWindowProperties()
MobileShell.HapticsEffect {
id: haptics
}
readonly property real statusPanelHeight: MobileShell.Constants.topPanelHeight
readonly property real intendedWindowThickness: statusPanelHeight
// use a timer so we don't have to maximize for every single pixel
// - improves performance if the shell is run in a window, and can be resized
Timer {
id: maximizeTimer
running: false
interval: 100
onTriggered: root.panel.maximize()
}
function setWindowProperties() {
if (root.panel) {
root.panel.floating = false;
root.panel.maximize(); // maximize first, then we can apply offsets (otherwise they are overridden)
root.panel.thickness = statusPanelHeight;
root.panel.visibilityMode = ShellSettings.Settings.autoHidePanelsEnabled ? 3 : 0;
MobileShell.ShellUtil.setWindowLayer(root.panel, LayerShell.Window.LayerOverlay)
root.updateTouchArea();
}
}
// update the touch area when hidden to minimize the space the panel takes for touch input
function updateTouchArea() {
const hiddenTouchAreaThickness = Kirigami.Units.gridUnit;
if (statusPanel.state == "hidden") {
MobileShell.ShellUtil.setInputRegion(root.panel, Qt.rect(0, 0, root.panel.width, hiddenTouchAreaThickness));
} else {
MobileShell.ShellUtil.setInputRegion(root.panel, Qt.rect(0, 0, 0, 0));
}
}
Connections {
target: ShellSettings.Settings
function onAutoHidePanelsEnabled() {
root.setWindowProperties();
}
}
// only opaque if there are no maximized windows on this screen
readonly property bool showingStartupFeedback: MobileShellState.ShellDBusObject.startupFeedbackModel.activeWindowIsStartupFeedback && startupFeedbackColorAnimation.visible && windowMaximizedTracker.windowCount === 1
readonly property bool showingApp: windowMaximizedTracker.showingWindow && !showingStartupFeedback
readonly property color backgroundColor: topPanel.colorScopeColor
readonly property alias isCurrentWindowFullscreen: windowMaximizedTracker.isCurrentWindowFullscreen
readonly property bool fullscreen: isCurrentWindowFullscreen || (ShellSettings.Settings.autoHidePanelsEnabled && showingApp)
onFullscreenChanged: {
MobileShellState.ShellDBusClient.panelState = fullscreen ? "hidden" : "default";
}
WindowPlugin.WindowMaximizedTracker {
id: windowMaximizedTracker
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
Binding {
target: panel // assumed to be plasma-workspace "PanelView" component
property: "thickness"
value: MobileShell.Constants.topPanelHeight
}
//BEGIN API implementation
Connections {
target: MobileShellState.ShellDBusClient
function onOpenActionDrawerRequested() {
drawer.actionDrawer.open();
}
function onCloseActionDrawerRequested() {
drawer.actionDrawer.close();
}
function onDoNotDisturbChanged() {
if (drawer.actionDrawer.notificationsWidget.doNotDisturbModeEnabled !== MobileShellState.ShellDBusClient.doNotDisturb) {
drawer.actionDrawer.notificationsWidget.toggleDoNotDisturbMode();
}
}
}
Binding {
target: MobileShellState.ShellDBusClient
property: "isActionDrawerOpen"
value: drawer.visible
}
//END API implementation
Component.onCompleted: {
root.setWindowProperties();
// register dbus
MobileShellState.ShellDBusObject.registerObject();
// HACK: we need to initialize the DBus server somewhere, it might as well be here...
// Initialize the volume osd, and volume keys.
// Initialize notification popups.
// Initialize action popup buttons.
MobileShell.PopupProviderLoader.load();
}
MobileShell.StartupFeedbackPanelFill {
id: startupFeedbackColorAnimation
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
fullHeight: root.height
screen: Plasmoid.screen
maximizedTracker: windowMaximizedTracker
visible: !root.fullscreen
}
Rectangle {
id: statusPanel
anchors.fill: parent
Kirigami.Theme.colorSet: root.showingApp ? Kirigami.Theme.Header : Kirigami.Theme.Complementary
Kirigami.Theme.inherit: false
color: statusPanel.state == "default" && (root.showingApp || root.fullscreen) ? Kirigami.Theme.backgroundColor : "transparent"
property real offset: 0
// top panel component
MobileShell.StatusBar {
id: topPanel
anchors.fill: parent
showDropShadow: !root.showingApp
backgroundColor: statusPanel.state != "default" && root.showingApp ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.95) : "transparent"
transform: [
Translate {
y: statusPanel.offset
}
]
}
state: MobileShellState.ShellDBusClient.panelState
onStateChanged: {
if (statusPanel.state != "hidden") {
root.setWindowProperties();
hiddenTimer.restart();
}
}
Timer {
id: hiddenTimer
running: false
interval: 3000
onTriggered: {
if (statusPanel.state == "visible") {
MobileShellState.ShellDBusClient.panelState = "hidden";
}
}
}
states: [
State {
name: "default"
PropertyChanges {
target: statusPanel; offset: 0
}
},
State {
name: "visible"
PropertyChanges {
target: statusPanel; offset: 0
}
},
State {
name: "hidden"
PropertyChanges {
target: statusPanel; offset: -root.statusPanelHeight
}
}
]
transitions: Transition {
SequentialAnimation {
ParallelAnimation {
PropertyAnimation {
properties: "offset"; easing.type: statusPanel.state === "hidden" ? Easing.InExpo : Easing.OutExpo; duration: Kirigami.Units.longDuration
}
}
ScriptAction {
script: {
root.setWindowProperties();
}
}
}
}
}
// swiping area for swipe-down drawer
MobileShell.ActionDrawerOpenSurface {
id: swipeArea
actionDrawer: drawer.actionDrawer
anchors.fill: parent
readonly property alias drawerVisible: drawer.visible
readonly property alias offset: drawer.actionDrawer.offset
// if in a fullscreen app, the panels are visible, and the action drawer is opened
// set the panels to a hidden state
onDrawerVisibleChanged: {
if (statusPanel.state == "visible") {
MobileShellState.ShellDBusClient.panelState = "hidden";
}
}
}
// swipe-down drawer component
MobileShell.ActionDrawerWindow {
id: drawer
actionDrawer.notificationSettings: NotificationManager.Settings {}
actionDrawer.notificationModel: NotificationManager.Notifications {
showExpired: true
showDismissed: true
showJobs: drawer.actionDrawer.notificationSettings.jobsInNotifications
sortMode: NotificationManager.Notifications.SortByTypeAndUrgency
groupMode: NotificationManager.Notifications.GroupApplicationsFlat
groupLimit: 2
expandUnread: true
blacklistedDesktopEntries: drawer.actionDrawer.notificationSettings.historyBlacklistedApplications
blacklistedNotifyRcNames: drawer.actionDrawer.notificationSettings.historyBlacklistedServices
urgencies: {
var urgencies = NotificationManager.Notifications.CriticalUrgency
| NotificationManager.Notifications.NormalUrgency;
if (drawer.actionDrawer.notificationSettings.lowPriorityHistory) {
urgencies |= NotificationManager.Notifications.LowUrgency;
}
return urgencies;
}
}
}
}