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 }