Warning, /plasma/plasma-desktop/desktoppackage/contents/views/Panel.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 SPDX-FileCopyrightText: 2012 Marco Martin <mart@kde.org>
0003
0004 SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006
0007 import QtQuick 2.15
0008 import QtQuick.Window 2.15
0009 import QtQuick.Layouts 1.1
0010 import QtQml 2.15
0011
0012 import org.kde.plasma.core as PlasmaCore
0013 import org.kde.ksvg 1.0 as KSvg
0014 import org.kde.taskmanager 0.1 as TaskManager
0015 import org.kde.kwindowsystem 1.0
0016 import org.kde.kirigami 2.20 as Kirigami
0017 import org.kde.plasma.shell.panel 0.1 as Panel
0018
0019 import org.kde.plasma.plasmoid 2.0
0020
0021 Item {
0022 id: root
0023
0024 property Item containment
0025
0026 property bool floatingPrefix: floatingPanelSvg.usedPrefix === "floating"
0027 readonly property bool verticalPanel: containment?.plasmoid?.formFactor === PlasmaCore.Types.Vertical
0028
0029 readonly property real spacingAtMinSize: Math.round(Math.max(1, (verticalPanel ? root.width : root.height) - Kirigami.Units.iconSizes.smallMedium)/2)
0030 KSvg.FrameSvgItem {
0031 id: thickPanelSvg
0032 visible: false
0033 prefix: 'thick'
0034 imagePath: "widgets/panel-background"
0035 }
0036 KSvg.FrameSvgItem {
0037 id: floatingPanelSvg
0038 visible: false
0039 prefix: ['floating', '']
0040 imagePath: "widgets/panel-background"
0041 }
0042
0043 // NOTE: Many of the properties in this file are accessed directly in C++ PanelView!
0044 // If you change these, make sure to also correct the related code in panelview.cpp.
0045
0046 readonly property bool topEdge: containment?.plasmoid?.location === PlasmaCore.Types.TopEdge
0047 readonly property bool leftEdge: containment?.plasmoid?.location === PlasmaCore.Types.LeftEdge
0048 readonly property bool rightEdge: containment?.plasmoid?.location === PlasmaCore.Types.RightEdge
0049 readonly property bool bottomEdge: containment?.plasmoid?.location === PlasmaCore.Types.BottomEdge
0050
0051 readonly property int topPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.top + Kirigami.Units.smallSpacing, spacingAtMinSize));
0052 readonly property int bottomPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.bottom + Kirigami.Units.smallSpacing, spacingAtMinSize));
0053 readonly property int leftPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.left + Kirigami.Units.smallSpacing, spacingAtMinSize));
0054 readonly property int rightPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.right + Kirigami.Units.smallSpacing, spacingAtMinSize));
0055
0056 readonly property int fixedBottomFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.bottom : 8)
0057 readonly property int fixedLeftFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.left : 8)
0058 readonly property int fixedRightFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.right : 8)
0059 readonly property int fixedTopFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.top : 8)
0060
0061 readonly property int bottomFloatingPadding: Math.round(fixedBottomFloatingPadding * floatingness)
0062 readonly property int leftFloatingPadding: Math.round(fixedLeftFloatingPadding * floatingness)
0063 readonly property int rightFloatingPadding: Math.round(fixedRightFloatingPadding * floatingness)
0064 readonly property int topFloatingPadding: Math.round(fixedTopFloatingPadding * floatingness)
0065
0066 readonly property int minPanelHeight: translucentItem.minimumDrawingHeight
0067 readonly property int minPanelWidth: translucentItem.minimumDrawingWidth
0068
0069 TaskManager.VirtualDesktopInfo {
0070 id: virtualDesktopInfo
0071 }
0072
0073 TaskManager.ActivityInfo {
0074 id: activityInfo
0075 }
0076
0077 // We need to have a little gap between the raw visibleWindowsModel count
0078 // and actually determining if a window is touching.
0079 // This is because certain dialog windows start off with a position of (screenwidth/2, screenheight/2)
0080 // and they register as "touching" in the split-second before KWin can place them correctly.
0081 // This avoids the panel flashing if it is auto-hide etc and such a window is shown.
0082 // Examples of such windows: properties of a file on desktop, or portal "open with" dialog
0083 property bool touchingWindow: false
0084 property bool touchingWindowDirect: visibleWindowsModel.count > 0
0085 property bool showingDesktop: KWindowSystem.showingDesktop
0086 Timer {
0087 id: touchingWindowDebounceTimer
0088 interval: 10 // ms, I find that this value is enough while not causing unresponsiveness while dragging windows close
0089 onTriggered: root.touchingWindow = !KWindowSystem.showingDesktop && root.touchingWindowDirect
0090 }
0091 onTouchingWindowDirectChanged: touchingWindowDebounceTimer.start()
0092 onShowingDesktopChanged: touchingWindowDebounceTimer.start()
0093
0094 TaskManager.TasksModel {
0095 id: visibleWindowsModel
0096 filterByVirtualDesktop: true
0097 filterByActivity: true
0098 filterByScreen: false
0099 filterByRegion: TaskManager.RegionFilterMode.Intersect
0100 filterHidden: true
0101 filterMinimized: true
0102
0103 screenGeometry: panel.screenGeometry
0104 virtualDesktop: virtualDesktopInfo.currentDesktop
0105 activity: activityInfo.currentActivity
0106
0107 groupMode: TaskManager.TasksModel.GroupDisabled
0108
0109 Binding on regionGeometry {
0110 delayed: true
0111 property real verticalMargin: (fixedTopFloatingPadding + fixedBottomFloatingPadding) * (1 - floatingness)
0112 property real horizontalMargin: (fixedLeftFloatingPadding + fixedRightFloatingPadding) * (1 - floatingness)
0113
0114 // This makes the panel de-float when a window is 12px from it or less.
0115 // 12px is chosen to avoid any potential issue with kwin snapping behavior,
0116 // and it looks like the panel hides away from the active window.
0117 property int defloatDistance: 12 + (verticalPanel ? horizontalMargin : verticalMargin)
0118 // Instead, we will only dodge an active panel if the panel is covered by it,
0119 // i.e. if the window touches at least one pixel of the panel
0120 property int dodgeDistance: -1
0121 // We don't have to worry about dealing with both at the same time since
0122 // dodge-window panels never de-float.
0123
0124 value: floatingness, panel.width, panel.height, panel.x, panel.y, panel.geometryByDistance(panel.visibilityMode === Panel.Global.DodgeWindows ? dodgeDistance : defloatDistance)
0125 }
0126 }
0127
0128 Connections {
0129 target: root.containment?.plasmoid ?? null
0130 function onActivated() {
0131 if (root.containment.plasmoid.status === PlasmaCore.Types.AcceptingInputStatus) {
0132 root.containment.plasmoid.status = PlasmaCore.Types.PassiveStatus;
0133 } else {
0134 root.containment.plasmoid.status = PlasmaCore.Types.AcceptingInputStatus;
0135 }
0136 }
0137 }
0138
0139 // Floatingness is a value in [0, 1] that's multiplied to the floating margin; 0: not floating, 1: floating, between 0 and 1: animation between the two states
0140 property double floatingness
0141 // PanelOpacity is a value in [0, 1] that's used as the opacity of the opaque elements over the transparent ones; values between 0 and 1 are used for animations
0142 property double panelOpacity
0143 Behavior on floatingness {
0144 NumberAnimation {
0145 duration: Kirigami.Units.longDuration
0146 easing.type: Easing.OutCubic
0147 }
0148 }
0149 Behavior on panelOpacity {
0150 NumberAnimation {
0151 duration: Kirigami.Units.longDuration
0152 easing.type: Easing.OutCubic
0153 }
0154 }
0155
0156 // This value is read from panelview.cpp and disables shadow for floating panels, as they'd be detached from the panel
0157 property bool hasShadows: floatingness < 0.5
0158 property var panelMask: floatingness === 0 ? (panelOpacity === 1 ? opaqueItem.mask : translucentItem.mask) : (panelOpacity === 1 ? floatingOpaqueItem.mask : floatingTranslucentItem.mask)
0159
0160 // These two values are read from panelview.cpp and are used as an offset for the mask
0161 property int maskOffsetX: floatingTranslucentItem.x
0162 property int maskOffsetY: floatingTranslucentItem.y
0163
0164 KSvg.FrameSvgItem {
0165 id: translucentItem
0166 visible: floatingness === 0 && panelOpacity !== 1
0167 enabledBorders: panel.enabledBorders
0168 anchors.fill: floatingTranslucentItem
0169 imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "widgets/panel-background"
0170 }
0171 KSvg.FrameSvgItem {
0172 id: floatingTranslucentItem
0173 visible: floatingness !== 0 && panelOpacity !== 1
0174 x: root.leftEdge ? fixedLeftFloatingPadding + fixedRightFloatingPadding * (1 - floatingness) : leftFloatingPadding
0175 y: root.topEdge ? fixedTopFloatingPadding + fixedBottomFloatingPadding * (1 - floatingness) : topFloatingPadding
0176 width: verticalPanel ? panel.thickness : parent.width - leftFloatingPadding - rightFloatingPadding
0177 height: verticalPanel ? parent.height - topFloatingPadding - bottomFloatingPadding : panel.thickness
0178
0179 imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "widgets/panel-background"
0180 }
0181 KSvg.FrameSvgItem {
0182 id: floatingOpaqueItem
0183 visible: floatingness !== 0 && panelOpacity !== 0
0184 opacity: panelOpacity
0185 anchors.fill: floatingTranslucentItem
0186 imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
0187 }
0188 KSvg.FrameSvgItem {
0189 id: opaqueItem
0190 visible: panelOpacity !== 0 && floatingness === 0
0191 opacity: panelOpacity
0192 enabledBorders: panel.enabledBorders
0193 anchors.fill: floatingTranslucentItem
0194 imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
0195 }
0196 KSvg.FrameSvgItem {
0197 id: floatingShadow
0198 visible: !hasShadows
0199 z: -100
0200 imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
0201 prefix: "shadow"
0202 anchors {
0203 fill: floatingTranslucentItem
0204 topMargin: -floatingShadow.margins.top
0205 leftMargin: -floatingShadow.margins.left
0206 rightMargin: -floatingShadow.margins.right
0207 bottomMargin: -floatingShadow.margins.bottom
0208 }
0209 }
0210
0211 Keys.onEscapePressed: {
0212 root.parent.focus = false
0213 }
0214
0215 property bool isOpaque: panel.opacityMode === Panel.Global.Opaque
0216 property bool isTransparent: panel.opacityMode === Panel.Global.Translucent
0217 property bool isAdaptive: panel.opacityMode === Panel.Global.Adaptive
0218 property bool floating: panel.floating
0219 property bool hasCompositing: KWindowSystem.isPlatformX11 ? KX11Extras.compositingActive : true
0220 readonly property bool screenCovered: touchingWindow && panel.visibilityMode == Panel.Global.NormalPanel
0221 property var stateTriggers: [floating, screenCovered, isOpaque, isAdaptive, isTransparent, hasCompositing, containment]
0222 onStateTriggersChanged: {
0223 let opaqueApplets = false
0224 let floatingApplets = false
0225 if ((!floating || screenCovered) && (isOpaque || (screenCovered && isAdaptive))) {
0226 panelOpacity = 1
0227 opaqueApplets = true
0228 floatingness = 0
0229 } else if ((!floating || screenCovered) && (isTransparent || (!screenCovered && isAdaptive))) {
0230 panelOpacity = 0
0231 floatingness = 0
0232 } else if ((floating && !screenCovered) && (isTransparent || isAdaptive)) {
0233 panelOpacity = 0
0234 floatingness = 1
0235 floatingApplets = true
0236 } else if (floating && !screenCovered && isOpaque) {
0237 panelOpacity = 1
0238 opaqueApplets = true
0239 floatingness = 1
0240 floatingApplets = true
0241 }
0242 if (!KWindowSystem.isPlatformWayland && !KX11Extras.compositingActive) {
0243 opaqueApplets = false
0244 panelOpacity = 0
0245 }
0246 // Not using panelOpacity to check as it has a NumberAnimation, and it will thus
0247 // be still read as the initial value here, before the animation starts.
0248 if (containment) {
0249 if (opaqueApplets) {
0250 containment.plasmoid.containmentDisplayHints |= PlasmaCore.Types.ContainmentPrefersOpaqueBackground
0251 } else {
0252 containment.plasmoid.containmentDisplayHints &= ~PlasmaCore.Types.ContainmentPrefersOpaqueBackground
0253 }
0254 if (floatingApplets) {
0255 containment.plasmoid.containmentDisplayHints |= PlasmaCore.Types.ContainmentPrefersFloatingApplets
0256 } else {
0257 containment.plasmoid.containmentDisplayHints &= ~PlasmaCore.Types.ContainmentPrefersFloatingApplets
0258 }
0259 }
0260 }
0261
0262 function adjustPrefix() {
0263 if (!containment) {
0264 return "";
0265 }
0266 var pre;
0267 switch (containment.plasmoid.location) {
0268 case PlasmaCore.Types.LeftEdge:
0269 pre = "west";
0270 break;
0271 case PlasmaCore.Types.TopEdge:
0272 pre = "north";
0273 break;
0274 case PlasmaCore.Types.RightEdge:
0275 pre = "east";
0276 break;
0277 case PlasmaCore.Types.BottomEdge:
0278 pre = "south";
0279 break;
0280 default:
0281 pre = "";
0282 break;
0283 }
0284 translucentItem.prefix = opaqueItem.prefix = floatingTranslucentItem.prefix = floatingOpaqueItem.prefix = [pre, ""];
0285 }
0286
0287 onContainmentChanged: {
0288 if (!containment) {
0289 return;
0290 }
0291 containment.parent = containmentParent;
0292 containment.visible = true;
0293 containment.anchors.fill = containmentParent;
0294 containment.plasmoid.locationChanged.connect(adjustPrefix);
0295 adjustPrefix();
0296 }
0297
0298 Binding {
0299 target: panel
0300 property: "length"
0301 when: containment
0302 value: {
0303 if (!containment) {
0304 return;
0305 }
0306 if (verticalPanel) {
0307 return containment.Layout.preferredHeight
0308 } else {
0309 return containment.Layout.preferredWidth
0310 }
0311 }
0312 restoreMode: Binding.RestoreBinding
0313 }
0314
0315 Binding {
0316 target: panel
0317 property: "backgroundHints"
0318 when: containment
0319 value: {
0320 if (!containment) {
0321 return;
0322 }
0323
0324 return containment.plasmoid.backgroundHints;
0325 }
0326 restoreMode: Binding.RestoreBinding
0327 }
0328
0329 KSvg.FrameSvgItem {
0330 x: root.verticalPanel || !panel.activeFocusItem
0331 ? 0
0332 : Math.max(panel.activeFocusItem.Kirigami.ScenePosition.x, panel.activeFocusItem.Kirigami.ScenePosition.x)
0333 y: root.verticalPanel && panel.activeFocusItem
0334 ? Math.max(panel.activeFocusItem.Kirigami.ScenePosition.y, panel.activeFocusItem.Kirigami.ScenePosition.y)
0335 : 0
0336
0337 width: panel.activeFocusItem
0338 ? (root.verticalPanel ? root.width : Math.min(panel.activeFocusItem.width, panel.activeFocusItem.width))
0339 : 0
0340 height: panel.activeFocusItem
0341 ? (root.verticalPanel ? Math.min(panel.activeFocusItem.height, panel.activeFocusItem.height) : root.height)
0342 : 0
0343
0344 visible: panel.active && panel.activeFocusItem
0345
0346 imagePath: "widgets/tabbar"
0347 prefix: {
0348 if (!root.containment) {
0349 return "";
0350 }
0351 var prefix = ""
0352 switch (root.containment.plasmoid.location) {
0353 case PlasmaCore.Types.LeftEdge:
0354 prefix = "west-active-tab";
0355 break;
0356 case PlasmaCore.Types.TopEdge:
0357 prefix = "north-active-tab";
0358 break;
0359 case PlasmaCore.Types.RightEdge:
0360 prefix = "east-active-tab";
0361 break;
0362 default:
0363 prefix = "south-active-tab";
0364 }
0365 if (!hasElementPrefix(prefix)) {
0366 prefix = "active-tab";
0367 }
0368 return prefix;
0369 }
0370 }
0371 Item {
0372 id: containmentParent
0373 anchors.centerIn: isOpaque ? floatingOpaqueItem : floatingTranslucentItem
0374 width: root.verticalPanel ? panel.thickness : root.width - fixedLeftFloatingPadding - fixedRightFloatingPadding
0375 height: root.verticalPanel ? root.height - fixedBottomFloatingPadding - fixedTopFloatingPadding : panel.thickness
0376 }
0377 }