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 }