Warning, /plasma/latte-dock/containment/package/contents/ui/VisibilityManager.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmailbox.org> 0003 SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com> 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 import QtQuick 2.1 0008 import QtQuick.Window 2.2 0009 0010 import org.kde.plasma.core 2.0 as PlasmaCore 0011 import org.kde.plasma.plasmoid 2.0 0012 0013 import org.kde.latte.core 0.2 as LatteCore 0014 import org.kde.latte.private.containment 0.1 as LatteContainment 0015 0016 Item{ 0017 id: manager 0018 anchors.fill: parent 0019 0020 property QtObject window 0021 0022 property bool isFloatingInClientSide: !root.behaveAsPlasmaPanel 0023 && screenEdgeMarginEnabled 0024 && !root.floatingInternalGapIsForced 0025 && !inSlidingIn 0026 && !inSlidingOut 0027 0028 property int animationSpeed: LatteCore.WindowSystem.compositingActive ? 0029 (root.editMode ? 400 : animations.speedFactor.current * 1.62 * animations.duration.large) : 0 0030 0031 property bool inClientSideScreenEdgeSliding: root.behaveAsDockWithMask && hideThickScreenGap 0032 property bool inNormalState: ((animations.needBothAxis.count === 0) && (animations.needLength.count === 0)) 0033 || (latteView && latteView.visibility.isHidden && !latteView.visibility.containsMouse && animations.needThickness.count === 0) 0034 property bool inRelocationAnimation: latteView && latteView.positioner && latteView.positioner.inRelocationAnimation 0035 0036 property bool inSlidingIn: false //necessary because of its init structure 0037 property alias inSlidingOut: slidingAnimationAutoHiddenOut.running 0038 property bool inRelocationHiding: false 0039 0040 readonly property bool isSinkedEventEnabled: !(parabolic.isEnabled && (animations.needBothAxis.count>0 || animations.needLength.count>0)) 0041 && myView.isShownFully 0042 0043 property int length: root.isVertical ? Screen.height : Screen.width //screenGeometry.height : screenGeometry.width 0044 0045 property int slidingOutToPos: { 0046 if (root.behaveAsPlasmaPanel) { 0047 var edgeMargin = screenEdgeMarginEnabled ? plasmoid.configuration.screenEdgeMargin : 0 0048 var thickmarg = latteView.visibility.isSidebar ? 0 : 1; 0049 0050 return root.isHorizontal ? root.height + edgeMargin - thickmarg : root.width + edgeMargin - thickmarg; 0051 } else { 0052 var topOrLeftEdge = ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)); 0053 return (topOrLeftEdge ? -metrics.mask.thickness.normal : metrics.mask.thickness.normal); 0054 } 0055 } 0056 0057 //! when Latte behaves as Plasma panel 0058 property int thicknessAsPanel: metrics.totals.thickness 0059 0060 property Item layouts: null 0061 0062 property bool updateIsEnabled: autosize.inCalculatedIconSize && !inSlidingIn && !inSlidingOut && !inRelocationHiding 0063 0064 Connections{ 0065 target: background.totals 0066 onVisualLengthChanged: updateMaskArea(); 0067 onVisualThicknessChanged: updateMaskArea(); 0068 } 0069 0070 Connections{ 0071 target: background.shadows 0072 onHeadThicknessChanged: updateMaskArea(); 0073 } 0074 0075 Connections{ 0076 target: latteView ? latteView : null 0077 onXChanged: updateMaskArea(); 0078 onYChanged: updateMaskArea() 0079 onWidthChanged: updateMaskArea(); 0080 onHeightChanged: updateMaskArea(); 0081 } 0082 0083 Connections{ 0084 target: animations.needBothAxis 0085 onCountChanged: updateMaskArea(); 0086 } 0087 0088 Connections{ 0089 target: animations.needLength 0090 onCountChanged: updateMaskArea(); 0091 } 0092 0093 Connections{ 0094 target: animations.needThickness 0095 onCountChanged: updateMaskArea(); 0096 } 0097 0098 Connections{ 0099 target: layoutsManager 0100 onCurrentLayoutIsSwitching: { 0101 if (LatteCore.WindowSystem.compositingActive && latteView && latteView.layout && latteView.layout.name === layoutName) { 0102 parabolic.sglClearZoom(); 0103 } 0104 } 0105 } 0106 0107 Connections { 0108 target: metrics.mask.thickness 0109 onMaxZoomedChanged: updateMaskArea() 0110 } 0111 0112 Connections { 0113 target: root.myView 0114 onInRelocationAnimationChanged: { 0115 if (!root.myView.inRelocationAnimation) { 0116 manager.updateMaskArea(); 0117 } 0118 } 0119 } 0120 0121 Connections { 0122 target: latteView ? latteView.effects : null 0123 onRectChanged: manager.updateMaskArea() 0124 } 0125 0126 Connections{ 0127 target: themeExtended ? themeExtended : null 0128 onThemeChanged: latteView.effects.forceMaskRedraw(); 0129 } 0130 0131 Connections { 0132 target: LatteCore.WindowSystem 0133 onCompositingActiveChanged: { 0134 manager.updateMaskArea(); 0135 } 0136 } 0137 0138 onIsFloatingInClientSideChanged: updateMaskArea(); 0139 0140 onInNormalStateChanged: { 0141 if (inNormalState) { 0142 updateMaskArea(); 0143 } 0144 } 0145 0146 onInSlidingInChanged: { 0147 if (latteView && !inSlidingIn && latteView.positioner.inRelocationShowing) { 0148 latteView.positioner.inRelocationShowing = false; 0149 } 0150 } 0151 0152 onUpdateIsEnabledChanged: { 0153 if (updateIsEnabled) { 0154 updateMaskArea(); 0155 } 0156 } 0157 0158 function slotContainsMouseChanged() { 0159 if(latteView.visibility.containsMouse && latteView.visibility.mode !== LatteCore.Types.SidebarOnDemand) { 0160 updateMaskArea(); 0161 0162 if (slidingAnimationAutoHiddenOut.running && !inRelocationHiding) { 0163 slotMustBeShown(); 0164 } 0165 } 0166 } 0167 0168 function slotMustBeShown() { 0169 if (root.inStartup) { 0170 slidingAnimationAutoHiddenIn.init(); 0171 return; 0172 } 0173 0174 //! WindowsCanCover case 0175 if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { 0176 latteView.visibility.setViewOnFrontLayer(); 0177 } 0178 0179 if (!latteView.visibility.isHidden && latteView.positioner.inSlideAnimation) { 0180 // Do not update when Positioner mid-slide animation takes place, for example: 0181 // 1. Latte panel is hiding its floating gap for maximized window 0182 // 2. the user clicks on an applet popup. 0183 // 3. Applet popups showing/hiding are triggering hidingIsBlockedChanged() signals. 0184 // 4. hidingIsBlockedChanged() signals create mustBeShown events when visibility::hidingIsBlocked() is not enabled. 0185 return; 0186 } 0187 0188 //! Normal Dodge/AutoHide case 0189 if (!slidingAnimationAutoHiddenIn.running 0190 && !inRelocationHiding 0191 && (latteView.visibility.isHidden || slidingAnimationAutoHiddenOut.running /*it is not already shown or is trying to hide*/)){ 0192 slidingAnimationAutoHiddenIn.init(); 0193 } 0194 } 0195 0196 function slotMustBeHide() { 0197 if (root.inStartup) { 0198 slidingAnimationAutoHiddenOut.init(); 0199 return; 0200 } 0201 0202 if (inSlidingIn && !inRelocationHiding) { 0203 /*consider hiding after sliding in has finished*/ 0204 return; 0205 } 0206 0207 if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { 0208 latteView.visibility.setViewOnBackLayer(); 0209 return; 0210 } 0211 0212 //! Normal Dodge/AutoHide case 0213 if (!slidingAnimationAutoHiddenOut.running 0214 && !latteView.visibility.blockHiding 0215 && (!latteView.visibility.containsMouse || latteView.visibility.mode === LatteCore.Types.SidebarOnDemand /*for SidebarOnDemand mouse should be ignored on hiding*/) 0216 && (!latteView.visibility.isHidden || slidingAnimationAutoHiddenIn.running /*it is not already hidden or is trying to show*/)) { 0217 slidingAnimationAutoHiddenOut.init(); 0218 } 0219 } 0220 0221 //! functions used for sliding out/in during location/screen changes 0222 function slotHideDockDuringLocationChange() { 0223 inRelocationHiding = true; 0224 0225 if(!slidingAnimationAutoHiddenOut.running) { 0226 slidingAnimationAutoHiddenOut.init(); 0227 } 0228 } 0229 0230 function slotShowDockAfterLocationChange() { 0231 slidingAnimationAutoHiddenIn.init(); 0232 } 0233 0234 function sendHideDockDuringLocationChangeFinished(){ 0235 latteView.positioner.hidingForRelocationFinished(); 0236 } 0237 0238 function sendSlidingOutAnimationEnded() { 0239 latteView.visibility.hide(); 0240 latteView.visibility.isHidden = true; 0241 0242 if (debug.maskEnabled) { 0243 console.log("hiding animation ended..."); 0244 } 0245 0246 sendHideDockDuringLocationChangeFinished(); 0247 } 0248 0249 ///test maskArea 0250 function updateMaskArea() { 0251 if (!latteView || !root.viewIsAvailable) { 0252 return; 0253 } 0254 0255 var localX = 0; 0256 var localY = 0; 0257 0258 // debug maskArea criteria 0259 if (debug.maskEnabled) { 0260 console.log(animations.needBothAxis.count + ", " + animations.needLength.count + ", " + 0261 animations.needThickness.count + ", " + latteView.visibility.isHidden); 0262 } 0263 0264 //console.log("reached updating geometry ::: "+dock.maskArea); 0265 0266 0267 if (!latteView.visibility.isHidden && updateIsEnabled && inNormalState) { 0268 //! Important: Local Geometry must not be updated when view ISHIDDEN 0269 //! because it breaks Dodge(s) modes in such case 0270 0271 var localGeometry = Qt.rect(0, 0, root.width, root.height); 0272 0273 //the shadows size must be removed from the maskArea 0274 //before updating the localDockGeometry 0275 if (!latteView.behaveAsPlasmaPanel) { 0276 var cleanThickness = metrics.totals.thickness; 0277 var edgeMargin = metrics.mask.screenEdge; 0278 0279 if (plasmoid.location === PlasmaCore.Types.TopEdge) { 0280 localGeometry.x = latteView.effects.rect.x; // from effects area 0281 localGeometry.width = latteView.effects.rect.width; // from effects area 0282 0283 localGeometry.y = edgeMargin; 0284 localGeometry.height = cleanThickness; 0285 } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { 0286 localGeometry.x = latteView.effects.rect.x; // from effects area 0287 localGeometry.width = latteView.effects.rect.width; // from effects area 0288 0289 localGeometry.y = root.height - cleanThickness - edgeMargin; 0290 localGeometry.height = cleanThickness; 0291 } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { 0292 localGeometry.y = latteView.effects.rect.y; // from effects area 0293 localGeometry.height = latteView.effects.rect.height; // from effects area 0294 0295 localGeometry.x = edgeMargin; 0296 localGeometry.width = cleanThickness; 0297 } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { 0298 localGeometry.y = latteView.effects.rect.y; // from effects area 0299 localGeometry.height = latteView.effects.rect.height; // from effects area 0300 0301 localGeometry.x = root.width - cleanThickness - edgeMargin; 0302 localGeometry.width = cleanThickness; 0303 } 0304 0305 //set the boundaries for latteView local geometry 0306 //qBound = qMax(min, qMin(value, max)). 0307 0308 localGeometry.x = Math.max(0, Math.min(localGeometry.x, latteView.width)); 0309 localGeometry.y = Math.max(0, Math.min(localGeometry.y, latteView.height)); 0310 localGeometry.width = Math.min(localGeometry.width, latteView.width); 0311 localGeometry.height = Math.min(localGeometry.height, latteView.height); 0312 } 0313 0314 //console.log("update geometry ::: "+localGeometry); 0315 latteView.localGeometry = localGeometry; 0316 } 0317 0318 //! Input Mask 0319 if (updateIsEnabled) { 0320 updateInputGeometry(); 0321 } 0322 } 0323 0324 function updateInputGeometry() { 0325 // VisibilityManager.qml tries to workaround faulty onEntered() signals from ParabolicMouseArea 0326 // by specifying inputThickness when ParabolicEffect is applied. (inputThickness->animated scenario) 0327 var animated = (animations.needBothAxis.count>0); 0328 0329 if (!LatteCore.WindowSystem.compositingActive || latteView.behaveAsPlasmaPanel) { 0330 //! clear input mask 0331 latteView.effects.inputMask = Qt.rect(0, 0, -1, -1); 0332 } else { 0333 var floatingInternalGapAcceptsInput = behaveAsDockWithMask && floatingInternalGapIsForced; 0334 var inputThickness; 0335 0336 if (latteView.visibility.isHidden) { 0337 inputThickness = metrics.mask.thickness.hidden; 0338 } else if (root.hasFloatingGapInputEventsDisabled) { 0339 inputThickness = animated ? metrics.mask.thickness.zoomedForItems - metrics.margins.screenEdge : metrics.totals.thickness; 0340 } else { 0341 inputThickness = animated ? metrics.mask.thickness.zoomedForItems : metrics.mask.screenEdge + metrics.totals.thickness; 0342 } 0343 0344 var subtractedScreenEdge = root.hasFloatingGapInputEventsDisabled && !latteView.visibility.isHidden ? metrics.mask.screenEdge : 0; 0345 0346 var inputGeometry = Qt.rect(0, 0, root.width, root.height); 0347 0348 //!use view.localGeometry for length properties 0349 if (plasmoid.location === PlasmaCore.Types.TopEdge) { 0350 if (!animated) { 0351 inputGeometry.x = latteView.localGeometry.x; 0352 inputGeometry.width = latteView.localGeometry.width; 0353 } 0354 0355 inputGeometry.y = subtractedScreenEdge; 0356 inputGeometry.height = inputThickness; 0357 } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { 0358 if (!animated) { 0359 inputGeometry.x = latteView.localGeometry.x; 0360 inputGeometry.width = latteView.localGeometry.width; 0361 } 0362 0363 inputGeometry.y = root.height - inputThickness - subtractedScreenEdge; 0364 inputGeometry.height = inputThickness; 0365 } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { 0366 if (!animated) { 0367 inputGeometry.y = latteView.localGeometry.y; 0368 inputGeometry.height = latteView.localGeometry.height; 0369 } 0370 0371 inputGeometry.x = subtractedScreenEdge; 0372 inputGeometry.width = inputThickness; 0373 } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { 0374 if (!animated) { 0375 inputGeometry.y = latteView.localGeometry.y; 0376 inputGeometry.height = latteView.localGeometry.height; 0377 } 0378 0379 inputGeometry.x = root.width - inputThickness - subtractedScreenEdge; 0380 inputGeometry.width = inputThickness; 0381 } 0382 0383 //set the boundaries for latteView local geometry 0384 //qBound = qMax(min, qMin(value, max)). 0385 0386 inputGeometry.x = Math.max(0, Math.min(inputGeometry.x, latteView.width)); 0387 inputGeometry.y = Math.max(0, Math.min(inputGeometry.y, latteView.height)); 0388 inputGeometry.width = Math.min(inputGeometry.width, latteView.width); 0389 inputGeometry.height = Math.min(inputGeometry.height, latteView.height); 0390 0391 if (latteView.visibility.isSidebar && latteView.visibility.isHidden) { 0392 //! this way we make sure than no input is accepted anywhere 0393 inputGeometry = Qt.rect(-1, -1, 1, 1); 0394 } 0395 0396 latteView.effects.inputMask = inputGeometry; 0397 } 0398 } 0399 0400 Loader{ 0401 anchors.fill: parent 0402 active: debug.graphicsEnabled 0403 0404 sourceComponent: Item{ 0405 anchors.fill:parent 0406 0407 Rectangle{ 0408 id: windowBackground 0409 anchors.fill: parent 0410 border.color: "red" 0411 border.width: 1 0412 color: "transparent" 0413 } 0414 0415 Rectangle{ 0416 x: latteView ? latteView.effects.mask.x : -1 0417 y: latteView ? latteView.effects.mask.y : -1 0418 height: latteView ? latteView.effects.mask.height : 0 0419 width: latteView ? latteView.effects.mask.width : 0 0420 0421 border.color: "green" 0422 border.width: 1 0423 color: "transparent" 0424 } 0425 } 0426 } 0427 0428 /***Hiding/Showing Animations*****/ 0429 0430 //////////////// Animations - Slide In - Out 0431 SequentialAnimation{ 0432 id: slidingAnimationAutoHiddenOut 0433 0434 PropertyAnimation { 0435 target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner 0436 property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" 0437 to: { 0438 if (root.behaveAsPlasmaPanel) { 0439 return slidingOutToPos; 0440 } 0441 0442 if (LatteCore.WindowSystem.compositingActive) { 0443 return slidingOutToPos; 0444 } else { 0445 if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { 0446 return slidingOutToPos + 1; 0447 } else { 0448 return slidingOutToPos - 1; 0449 } 0450 } 0451 } 0452 duration: manager.animationSpeed 0453 easing.type: Easing.InQuad 0454 } 0455 0456 ScriptAction{ 0457 script: { 0458 latteView.visibility.isHidden = true; 0459 0460 if (root.behaveAsPlasmaPanel && latteView.positioner.slideOffset !== 0) { 0461 //! hide real panels when they slide-out 0462 latteView.visibility.hide(); 0463 } 0464 } 0465 } 0466 0467 onStarted: { 0468 if (debug.maskEnabled) { 0469 console.log("hiding animation started..."); 0470 } 0471 } 0472 0473 onStopped: { 0474 //! Trying to move the ending part of the signals at the end of editing animation 0475 if (!manager.inRelocationHiding) { 0476 manager.updateMaskArea(); 0477 } else { 0478 if (!root.editMode) { 0479 manager.sendSlidingOutAnimationEnded(); 0480 } 0481 } 0482 0483 latteView.visibility.slideOutFinished(); 0484 manager.updateInputGeometry(); 0485 0486 if (root.inStartup) { 0487 //! when view is first created slide-outs when that animation ends then 0488 //! it flags that startup has ended and first slide-in can be started 0489 //! this is important because if it is removed then some views 0490 //! wont slide-in after startup. 0491 root.inStartup = false; 0492 } 0493 } 0494 0495 function init() { 0496 if (manager.inRelocationAnimation || root.inStartup/*used from recreating views*/ || !latteView.visibility.blockHiding) { 0497 start(); 0498 } 0499 } 0500 } 0501 0502 SequentialAnimation{ 0503 id: slidingAnimationAutoHiddenIn 0504 0505 PauseAnimation{ 0506 duration: manager.inRelocationHiding && animations.active ? 500 : 0 0507 } 0508 0509 PropertyAnimation { 0510 target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner 0511 property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" 0512 to: 0 0513 duration: manager.animationSpeed 0514 easing.type: Easing.OutQuad 0515 } 0516 0517 ScriptAction{ 0518 script: { 0519 // deprecated 0520 // root.inStartup = false; 0521 } 0522 } 0523 0524 onStarted: { 0525 latteView.visibility.show(); 0526 manager.updateInputGeometry(); 0527 0528 if (debug.maskEnabled) { 0529 console.log("showing animation started..."); 0530 } 0531 } 0532 0533 onStopped: { 0534 inSlidingIn = false; 0535 0536 if (manager.inRelocationHiding) { 0537 manager.inRelocationHiding = false; 0538 autosize.updateIconSize(); 0539 } 0540 0541 manager.inRelocationHiding = false; 0542 autosize.updateIconSize(); 0543 0544 if (debug.maskEnabled) { 0545 console.log("showing animation ended..."); 0546 } 0547 0548 latteView.visibility.slideInFinished(); 0549 0550 //! this is needed in order to update dock absolute geometry correctly in the end AND 0551 //! when a floating dock is sliding-in through masking techniques 0552 updateMaskArea(); 0553 } 0554 0555 function init() { 0556 if (!root.viewIsAvailable) { 0557 return; 0558 } 0559 0560 inSlidingIn = true; 0561 0562 if (slidingAnimationAutoHiddenOut.running) { 0563 slidingAnimationAutoHiddenOut.stop(); 0564 } 0565 0566 latteView.visibility.isHidden = false; 0567 updateMaskArea(); 0568 0569 start(); 0570 } 0571 } 0572 0573 //! Slides Animations for FLOATING+BEHAVEASPLASMAPANEL when 0574 //! HIDETHICKSCREENCAP dynamically is enabled/disabled 0575 SequentialAnimation{ 0576 id: slidingInRealFloating 0577 0578 PropertyAnimation { 0579 target: latteView ? latteView.positioner : null 0580 property: "slideOffset" 0581 to: 0 0582 duration: manager.animationSpeed 0583 easing.type: Easing.OutQuad 0584 } 0585 0586 ScriptAction{ 0587 script: { 0588 latteView.positioner.inSlideAnimation = false; 0589 } 0590 } 0591 0592 onStopped: latteView.positioner.inSlideAnimation = false; 0593 0594 } 0595 0596 SequentialAnimation{ 0597 id: slidingOutRealFloating 0598 0599 ScriptAction{ 0600 script: { 0601 latteView.positioner.inSlideAnimation = true; 0602 } 0603 } 0604 0605 PropertyAnimation { 0606 target: latteView ? latteView.positioner : null 0607 property: "slideOffset" 0608 to: plasmoid.configuration.screenEdgeMargin 0609 duration: manager.animationSpeed 0610 easing.type: Easing.InQuad 0611 } 0612 } 0613 0614 Connections { 0615 target: root 0616 onHideThickScreenGapChanged: { 0617 if (!latteView || !root.viewIsAvailable) { 0618 return; 0619 } 0620 0621 if (root.behaveAsPlasmaPanel && !latteView.visibility.isHidden && !inSlidingIn && !inSlidingOut && !inStartup) { 0622 slideInOutRealFloating(); 0623 } 0624 } 0625 0626 onInStartupChanged: { 0627 //! used for positioning properly real floating panels when there is a maximized window 0628 if (root.hideThickScreenGap && !inStartup && latteView.positioner.slideOffset===0) { 0629 if (root.behaveAsPlasmaPanel && !latteView.visibility.isHidden) { 0630 slideInOutRealFloating(); 0631 } 0632 } 0633 } 0634 0635 function slideInOutRealFloating() { 0636 if (root.hideThickScreenGap) { 0637 slidingInRealFloating.stop(); 0638 slidingOutRealFloating.start(); 0639 } else { 0640 slidingOutRealFloating.stop(); 0641 slidingInRealFloating.start(); 0642 } 0643 } 0644 } 0645 0646 0647 }