From 9e81d2f65c8c4ecdf94f81e7ca15b4bcc0995fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Venerandi?= Date: Wed, 15 Nov 2023 17:41:02 +0000 Subject: [PATCH] plugins/overview: Bind values to 1:1 animation while gesture is ongoing Otherwise the animation feels wrong while activating with a gesture. Now when a 1:1 gesture is ongoing, then the Overview effect will stop animating the overviewVal/gridVal values. I implemented this by porting to states, giving 1:1 gestures their own states, and only animating the change between states. BUG: 476536 --- src/libkwineffects/effecttogglablestate.cpp | 5 +- src/plugins/overview/overvieweffect.cpp | 5 - src/plugins/overview/qml/main.qml | 113 +++++++++++++++----- 3 files changed, 87 insertions(+), 36 deletions(-) diff --git a/src/libkwineffects/effecttogglablestate.cpp b/src/libkwineffects/effecttogglablestate.cpp index 20f90b3592..a6b31da24e 100644 --- a/src/libkwineffects/effecttogglablestate.cpp +++ b/src/libkwineffects/effecttogglablestate.cpp @@ -66,6 +66,7 @@ void EffectTogglableState::deactivate() void EffectTogglableState::stop() { setInProgress(false); + setPartialActivationFactor(0.0); setStatus(Status::Stopped); } @@ -97,15 +98,15 @@ void EffectTogglableState::partialActivate(qreal factor) } setStatus(Status::Activating); - setPartialActivationFactor(factor); setInProgress(true); + setPartialActivationFactor(factor); } void EffectTogglableState::partialDeactivate(qreal factor) { setStatus(Status::Deactivating); - setPartialActivationFactor(1.0 - factor); setInProgress(true); + setPartialActivationFactor(1.0 - factor); } void EffectTogglableState::toggle() diff --git a/src/plugins/overview/overvieweffect.cpp b/src/plugins/overview/overvieweffect.cpp index 2faab09e4a..507911380f 100644 --- a/src/plugins/overview/overvieweffect.cpp +++ b/src/plugins/overview/overvieweffect.cpp @@ -296,11 +296,6 @@ void OverviewEffect::activate() void OverviewEffect::deactivate() { const auto screens = effects->screens(); - for (const auto screen : screens) { - if (QuickSceneView *view = viewForScreen(screen)) { - QMetaObject::invokeMethod(view->rootItem(), "stop"); - } - } m_shutdownTimer->start(animationDuration()); m_overviewState->deactivate(); } diff --git a/src/plugins/overview/qml/main.qml b/src/plugins/overview/qml/main.qml index 88129fe924..accf7d144a 100644 --- a/src/plugins/overview/qml/main.qml +++ b/src/plugins/overview/qml/main.qml @@ -41,34 +41,89 @@ FocusScope { property real overviewVal: 0 property real gridVal: 0 - Behavior on overviewVal { + states: [ + State { + name: "initial" + PropertyChanges { + target: container + overviewVal: 0 + gridVal: 0 + } + }, + State { + name: "grid" + PropertyChanges { + target: container + overviewVal: 0 + gridVal: 1 + } + }, + State { + name: "overview" + PropertyChanges { + target: container + overviewVal: 1 + gridVal: 0 + } + }, + State { + name: "partialOverview" + PropertyChanges { + target: container + overviewVal: effect.overviewPartialActivationFactor + gridVal: 0 + } + }, + State { + name: "partialGrid" + PropertyChanges { + target: container + overviewVal: 0 + gridVal: effect.gridPartialActivationFactor + } + }, + State { + name: "transition" + PropertyChanges { + target: container + overviewVal: 1 - effect.transitionPartialActivationFactor + gridVal: effect.transitionPartialActivationFactor + } + } + ] + state: { + // If the effect hasn't started, we remain on the initial state + if (!organized) return "initial"; + + // If a gesture is ongoing, we use a partial state + if (effect.overviewGestureInProgress) return "partialOverview"; + if (effect.gridGestureInProgress) return "partialGrid"; + if (effect.transitionGestureInProgress) return "transition"; + + // If either the overview or grid gestures are completed, either + // by a touchpad/touchscreen gesture or through a shortcut, we use + // that state + if (effect.overviewPartialActivationFactor === 1) return "overview"; + if (effect.gridPartialActivationFactor === 1) return "grid"; + + // If neither is active, we are in the initial state. + if (effect.overviewPartialActivationFactor + effect.gridPartialActivationFactor === 0) return "initial"; + + // If we are inbetween a state but no gesture is going on, we snap to + // the closest state + if (overviewVal >= 0.5) return "overview"; + if (gridVal >= 0.5) return "grid"; + return "initial"; + } + transitions: Transition { + to: "initial, grid, overview" NumberAnimation { duration: Kirigami.Units.shortDuration + properties: "gridVal, overviewVal" + easing.type: Easing.OutCubic } } - Behavior on gridVal { - NumberAnimation { - duration: Kirigami.Units.shortDuration - } - } - - function start() { - animationEnabled = true; - organized = true; - - overviewVal = Qt.binding(() => effect.overviewGestureInProgress ? effect.overviewPartialActivationFactor : - effect.transitionGestureInProgress ? 1 - effect.transitionPartialActivationFactor : - effect.overviewPartialActivationFactor == 1 && effect.transitionPartialActivationFactor == 0) - gridVal = Qt.binding(() => effect.transitionGestureInProgress ? effect.transitionPartialActivationFactor : - effect.gridGestureInProgress ? effect.gridPartialActivationFactor : - effect.transitionPartialActivationFactor == 1 && effect.gridPartialActivationFactor == 1) - } - - function stop() { - organized = false; - } - function switchTo(desktop) { KWinComponents.Workspace.currentDesktop = desktop; effect.deactivate(); @@ -352,7 +407,7 @@ FocusScope { color: Kirigami.Theme.highlightColor visible: gridVal > 0 || nearCurrent anchors.fill: parent - property bool shouldBeVisibleInOverview: !(container.organized && effect.searchText.length > 0 && current) || (heap.count !== 0 && effect.filterWindows) + property bool shouldBeVisibleInOverview: !(effect.searchText.length > 0 && current) || (heap.count !== 0 && effect.filterWindows) opacity: 1 - overviewVal * (shouldBeVisibleInOverview ? 0 : 1) function selectLastItem(direction) { @@ -550,8 +605,8 @@ FocusScope { focus: current padding: Kirigami.Units.largeSpacing animationDuration: effect.animationDuration - animationEnabled: container.animationEnabled && (gridVal !== 0 || mainBackground.current) - organized: container.organized + animationEnabled: (gridVal !== 0 || mainBackground.current) && organized + organized: container.state !== "initial" dndManagerStore: desktopGrid.dndManagerStore Keys.priority: Keys.AfterItem Keys.forwardTo: [searchResults, searchField] @@ -649,12 +704,12 @@ FocusScope { Item { width: parent.width height: parent.height - topBar.height - visible: container.organized && effect.searchText.length > 0 && (allDesktopHeaps.currentHeap.count === 0 || !effect.filterWindows) + visible: effect.searchText.length > 0 && (allDesktopHeaps.currentHeap.count === 0 || !effect.filterWindows) opacity: overviewVal PlasmaExtras.PlaceholderMessage { id: placeholderMessage - visible: container.organized && effect.searchText.length > 0 && allDesktopHeaps.currentHeap.count === 0 && effect.filterWindows + visible: effect.searchText.length > 0 && allDesktopHeaps.currentHeap.count === 0 && effect.filterWindows anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter text: i18ndc("kwin", "@info:placeholder", "No matching windows") @@ -710,6 +765,6 @@ FocusScope { // don't want the desktop bar changing screenside whilst the user is // interacting with it, e.g. by adding desktops container.verticalDesktopBar = container.verticalDesktopBar - start(); + organized = true } }