Warning, /plasma/plasma-mobile/shell/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     // NOTE: Plasma Mobile specific:
0025     Connections {
0026         target: root
0027         
0028         function onContainmentChanged() { 
0029             // HACK: add PanelView into the containment so that it can be used
0030             if (containment.panel !== undefined) {
0031                 containment.panel = panel;
0032             }
0033             if (containment.tabBar !== undefined) {
0034                 containment.tabBar = tabBar;
0035             }
0036         }
0037     }
0038 
0039     // NOTE: Below is taken straight out of Plasma Desktop so that we can 
0040     //       support desktop panels properly, try to keep it in sync:
0041     //       plasma-desktop/desktoppackage/contents/views/Panel.qml
0042 
0043     property Item containment
0044 
0045     property bool floatingPrefix: floatingPanelSvg.usedPrefix === "floating"
0046     readonly property bool verticalPanel: containment?.plasmoid?.formFactor === PlasmaCore.Types.Vertical
0047 
0048     readonly property real spacingAtMinSize: Math.round(Math.max(1, (verticalPanel ? root.width : root.height) - Kirigami.Units.iconSizes.smallMedium)/2)
0049     KSvg.FrameSvgItem {
0050         id: thickPanelSvg
0051         visible: false
0052         prefix: 'thick'
0053         imagePath: "widgets/panel-background"
0054     }
0055     KSvg.FrameSvgItem {
0056         id: floatingPanelSvg
0057         visible: false
0058         prefix: ['floating', '']
0059         imagePath: "widgets/panel-background"
0060     }
0061 
0062     readonly property bool topEdge: containment?.plasmoid?.location === PlasmaCore.Types.TopEdge
0063     readonly property bool leftEdge: containment?.plasmoid?.location === PlasmaCore.Types.LeftEdge
0064     readonly property bool rightEdge: containment?.plasmoid?.location === PlasmaCore.Types.RightEdge
0065     readonly property bool bottomEdge: containment?.plasmoid?.location === PlasmaCore.Types.BottomEdge
0066 
0067     readonly property int topPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.top + Kirigami.Units.smallSpacing, spacingAtMinSize));
0068     readonly property int bottomPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.bottom + Kirigami.Units.smallSpacing, spacingAtMinSize));
0069     readonly property int leftPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.left + Kirigami.Units.smallSpacing, spacingAtMinSize));
0070     readonly property int rightPadding: Math.round(Math.min(thickPanelSvg.fixedMargins.right + Kirigami.Units.smallSpacing, spacingAtMinSize));
0071 
0072     readonly property int fixedBottomFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.bottom : 8)
0073     readonly property int fixedLeftFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.left   : 8)
0074     readonly property int fixedRightFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.right  : 8)
0075     readonly property int fixedTopFloatingPadding: floating && (floatingPrefix ? floatingPanelSvg.fixedMargins.top    : 8)
0076 
0077     readonly property int bottomFloatingPadding: Math.round(fixedBottomFloatingPadding * floatingness)
0078     readonly property int leftFloatingPadding: Math.round(fixedLeftFloatingPadding * floatingness)
0079     readonly property int rightFloatingPadding: Math.round(fixedRightFloatingPadding * floatingness)
0080     readonly property int topFloatingPadding: Math.round(fixedTopFloatingPadding * floatingness)
0081 
0082     readonly property int minPanelHeight: translucentItem.minimumDrawingHeight
0083     readonly property int minPanelWidth: translucentItem.minimumDrawingWidth
0084 
0085     TaskManager.VirtualDesktopInfo {
0086         id: virtualDesktopInfo
0087     }
0088 
0089     TaskManager.ActivityInfo {
0090         id: activityInfo
0091     }
0092 
0093     property bool touchingWindow: visibleWindowsModel.count > 0
0094 
0095     TaskManager.TasksModel {
0096         id: visibleWindowsModel
0097         filterByVirtualDesktop: true
0098         filterByActivity: true
0099         filterByScreen: true
0100         filterByRegion: TaskManager.RegionFilterMode.Intersect
0101         filterHidden: true
0102         filterMinimized: true
0103 
0104         screenGeometry: panel.screenGeometry
0105         virtualDesktop: virtualDesktopInfo.currentDesktop
0106         activity: activityInfo.currentActivity
0107 
0108         groupMode: TaskManager.TasksModel.GroupDisabled
0109 
0110         Binding on regionGeometry {
0111             delayed: true
0112             property real verticalMargin: (fixedTopFloatingPadding + fixedBottomFloatingPadding) * (1 - floatingness)
0113             property real horizontalMargin: (fixedLeftFloatingPadding + fixedRightFloatingPadding) * (1 - floatingness)
0114             // This makes the panel de-float when a window is 6px from it or less.
0115             // 6px 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             value: floatingness, panel.width, panel.height, panel.x, panel.y, panel.geometryByDistance(6 + (verticalPanel ? horizontalMargin : verticalMargin))
0118         }
0119     }
0120 
0121     Connections {
0122         target: containment
0123         function onActivated() {
0124             // BUG 472909: status changes to PassiveStatus or ActiveStatus after applet shortcut is pressed for the second time
0125             if (containment.status === PlasmaCore.Types.PassiveStatus /*After pressing panel shortcut*/ || containment.status === PlasmaCore.Types.ActiveStatus) {
0126                 containment.status = PlasmaCore.Types.AcceptingInputStatus;
0127                 // BUG 472909: if applet shortcut is pressed, panel also gets activated, but status will change to RequiresAttentionStatus after applet has focus
0128             } else /* Panel has focus, or applet has focus */ {
0129                 containment.status = PlasmaCore.Types.PassiveStatus;
0130             }
0131         }
0132     }
0133 
0134     // 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
0135     property double floatingness
0136     // 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
0137     property double panelOpacity
0138     Behavior on floatingness {
0139         NumberAnimation {
0140             duration: Kirigami.Units.longDuration
0141             easing.type: Easing.OutCubic
0142         }
0143     }
0144     Behavior on panelOpacity {
0145         NumberAnimation {
0146             duration: Kirigami.Units.longDuration
0147             easing.type: Easing.OutCubic
0148         }
0149     }
0150 
0151     // This value is read from panelview.cpp and disables shadow for floating panels, as they'd be detached from the panel
0152     property bool hasShadows: floatingness < 0.5
0153     property var panelMask: floatingness === 0 ? (panelOpacity === 1 ? opaqueItem.mask : translucentItem.mask) : (panelOpacity === 1 ? floatingOpaqueItem.mask : floatingTranslucentItem.mask)
0154 
0155     // These two values are read from panelview.cpp and are used as an offset for the mask
0156     property int maskOffsetX: floatingTranslucentItem.x
0157     property int maskOffsetY: floatingTranslucentItem.y
0158 
0159     KSvg.FrameSvgItem {
0160         id: translucentItem
0161         visible: floatingness === 0 && panelOpacity !== 1
0162         enabledBorders: panel.enabledBorders
0163         anchors.fill: floatingTranslucentItem
0164         imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "widgets/panel-background"
0165     }
0166     KSvg.FrameSvgItem {
0167         id: floatingTranslucentItem
0168         visible: floatingness !== 0 && panelOpacity !== 1
0169         x: root.leftEdge ? fixedLeftFloatingPadding + fixedRightFloatingPadding * (1 - floatingness) : leftFloatingPadding
0170         y: root.topEdge ? fixedTopFloatingPadding + fixedBottomFloatingPadding * (1 - floatingness) : topFloatingPadding
0171         width: verticalPanel ? panel.thickness : parent.width - leftFloatingPadding - rightFloatingPadding
0172         height: verticalPanel ? parent.height - topFloatingPadding - bottomFloatingPadding : panel.thickness
0173 
0174         imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "widgets/panel-background"
0175     }
0176     KSvg.FrameSvgItem {
0177         id: floatingOpaqueItem
0178         visible: floatingness !== 0 && panelOpacity !== 0
0179         opacity: panelOpacity
0180         anchors.fill: floatingTranslucentItem
0181         imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
0182     }
0183     KSvg.FrameSvgItem {
0184         id: opaqueItem
0185         visible: panelOpacity !== 0 && floatingness === 0
0186         opacity: panelOpacity
0187         enabledBorders: panel.enabledBorders
0188         anchors.fill: floatingTranslucentItem
0189         imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
0190     }
0191     KSvg.FrameSvgItem {
0192         id: floatingShadow
0193         visible: !hasShadows
0194         z: -100
0195         imagePath: containment?.plasmoid?.backgroundHints === PlasmaCore.Types.NoBackground ? "" : "solid/widgets/panel-background"
0196         prefix: "shadow"
0197         anchors {
0198             fill: floatingTranslucentItem
0199             topMargin: -floatingShadow.margins.top
0200             leftMargin: -floatingShadow.margins.left
0201             rightMargin: -floatingShadow.margins.right
0202             bottomMargin: -floatingShadow.margins.bottom
0203         }
0204     }
0205 
0206     Keys.onEscapePressed: {
0207         root.parent.focus = false
0208     }
0209 
0210     property bool isOpaque: panel.opacityMode === Panel.Global.Opaque
0211     property bool isTransparent: panel.opacityMode === Panel.Global.Translucent
0212     property bool isAdaptive: panel.opacityMode === Panel.Global.Adaptive
0213     property bool floating: panel.floating
0214     readonly property bool screenCovered: !KWindowSystem.showingDesktop && touchingWindow && panel.visibilityMode == Panel.Global.NormalPanel
0215     property var stateTriggers: [floating, screenCovered, isOpaque, isAdaptive, isTransparent, KX11Extras.compositingActive]
0216     onStateTriggersChanged: {
0217         let opaqueApplets = false
0218         let floatingApplets = false
0219         if ((!floating || screenCovered) && (isOpaque || (screenCovered && isAdaptive))) {
0220             panelOpacity = 1
0221             opaqueApplets = true
0222             floatingness = 0
0223         } else if ((!floating || screenCovered) && (isTransparent || (!screenCovered && isAdaptive))) {
0224             panelOpacity = 0
0225             floatingness = 0
0226         } else if ((floating && !screenCovered) && (isTransparent || isAdaptive)) {
0227             panelOpacity = 0
0228             floatingness = 1
0229             floatingApplets = true
0230         } else if (floating && !screenCovered && isOpaque) {
0231             panelOpacity = 1
0232             opaqueApplets = true
0233             floatingness = 1
0234             floatingApplets = true
0235         }
0236         if (!KWindowSystem.isPlatformWayland && !KX11Extras.compositingActive) {
0237             opaqueApplets = false
0238             panelOpacity = 0
0239         }
0240         // Not using panelOpacity to check as it has a NumberAnimation, and it will thus
0241         // be still read as the initial value here, before the animation starts.
0242         if (containment) {
0243             if (opaqueApplets) {
0244                 containment.plasmoid.containmentDisplayHints |= PlasmaCore.Types.ContainmentPrefersOpaqueBackground
0245             } else {
0246                 containment.plasmoid.containmentDisplayHints &= ~PlasmaCore.Types.ContainmentPrefersOpaqueBackground
0247             }
0248             if (floatingApplets) {
0249                 containment.plasmoid.containmentDisplayHints |= PlasmaCore.Types.ContainmentPrefersFloatingApplets
0250             } else {
0251                 containment.plasmoid.containmentDisplayHints &= ~PlasmaCore.Types.ContainmentPrefersFloatingApplets
0252             }
0253         }
0254     }
0255 
0256     function adjustPrefix() {
0257         if (!containment) {
0258             return "";
0259         }
0260         var pre;
0261         switch (containment.plasmoid.location) {
0262         case PlasmaCore.Types.LeftEdge:
0263             pre = "west";
0264             break;
0265         case PlasmaCore.Types.TopEdge:
0266             pre = "north";
0267             break;
0268         case PlasmaCore.Types.RightEdge:
0269             pre = "east";
0270             break;
0271         case PlasmaCore.Types.BottomEdge:
0272             pre = "south";
0273             break;
0274         default:
0275             pre = "";
0276             break;
0277         }
0278         translucentItem.prefix = opaqueItem.prefix = floatingTranslucentItem.prefix = floatingOpaqueItem.prefix = [pre, ""];
0279     }
0280 
0281     onContainmentChanged: {
0282         if (!containment) {
0283             return;
0284         }
0285         containment.parent = containmentParent;
0286         containment.visible = true;
0287         containment.anchors.fill = containmentParent;
0288         containment.plasmoid.locationChanged.connect(adjustPrefix);
0289         adjustPrefix();
0290     }
0291 
0292     Binding {
0293         target: panel
0294         property: "length"
0295         when: containment
0296         delayed: true
0297         value: {
0298             if (!containment) {
0299                 return;
0300             }
0301             if (verticalPanel) {
0302                 return containment.Layout.preferredHeight
0303             } else {
0304                 return containment.Layout.preferredWidth
0305             }
0306         }
0307         restoreMode: Binding.RestoreBinding
0308     }
0309 
0310     Binding {
0311         target: panel
0312         property: "backgroundHints"
0313         when: containment
0314         value: {
0315             if (!containment) {
0316                 return;
0317             }
0318 
0319             return containment.plasmoid.backgroundHints;
0320         }
0321         restoreMode: Binding.RestoreBinding
0322     }
0323 
0324     KSvg.FrameSvgItem {
0325         id: tabBar
0326         x: root.verticalPanel || !panel.activeFocusItem
0327             ? 0
0328             : Math.max(panel.activeFocusItem.Kirigami.ScenePosition.x, panel.activeFocusItem.Kirigami.ScenePosition.x)
0329         y: root.verticalPanel && panel.activeFocusItem
0330             ? Math.max(panel.activeFocusItem.Kirigami.ScenePosition.y, panel.activeFocusItem.Kirigami.ScenePosition.y)
0331             : 0
0332 
0333         width: panel.activeFocusItem
0334             ? (root.verticalPanel ? root.width : Math.min(panel.activeFocusItem.width, panel.activeFocusItem.width))
0335             : 0
0336         height: panel.activeFocusItem
0337             ? (root.verticalPanel ?  Math.min(panel.activeFocusItem.height, panel.activeFocusItem.height) : root.height)
0338             : 0
0339 
0340         visible: panel.active && panel.activeFocusItem
0341 
0342         imagePath: "widgets/tabbar"
0343         prefix: {
0344             if (!root.containment) {
0345                 return "";
0346             }
0347             var prefix = ""
0348             switch (root.containment.plasmoid.location) {
0349                 case PlasmaCore.Types.LeftEdge:
0350                     prefix = "west-active-tab";
0351                     break;
0352                 case PlasmaCore.Types.TopEdge:
0353                     prefix = "north-active-tab";
0354                     break;
0355                 case PlasmaCore.Types.RightEdge:
0356                     prefix = "east-active-tab";
0357                     break;
0358                 default:
0359                     prefix = "south-active-tab";
0360             }
0361             if (!hasElementPrefix(prefix)) {
0362                 prefix = "active-tab";
0363             }
0364             return prefix;
0365         }
0366     }
0367     Item {
0368         id: containmentParent
0369         anchors.centerIn: isOpaque ? floatingOpaqueItem : floatingTranslucentItem
0370         width: root.verticalPanel ? panel.thickness : root.width - root.floatingness * (fixedLeftFloatingPadding + fixedRightFloatingPadding)
0371         height: root.verticalPanel ? root.height - root.floatingness * (fixedBottomFloatingPadding - fixedTopFloatingPadding) : panel.thickness
0372     }
0373 
0374 }