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 }