1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
|
// 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.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;
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));
}
}
// 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 showingApp: windowMaximizedTracker.showingWindow && !showingStartupFeedback
readonly property color backgroundColor: topPanel.colorScopeColor
readonly property alias isCurrentWindowFullscreen: windowMaximizedTracker.isCurrentWindowFullscreen
onIsCurrentWindowFullscreenChanged: {
MobileShellState.ShellDBusClient.panelState = isCurrentWindowFullscreen ? "hidden" : "default";
}
WindowPlugin.WindowMaximizedTracker {
id: windowMaximizedTracker
screenGeometry: Plasmoid.containment.screenGeometry
}
// 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();
}
}
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
MobileShell.VolumeOSDProviderLoader.load();
// initialize notification popups
MobileShell.NotificationPopupProviderLoader.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.isCurrentWindowFullscreen
}
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 ? 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" ? 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
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
// 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;
}
}
}
}
|