effects/private: Merge two state machines into one with substates
Having one state machine instead of two somehow simplifies the code and makes it less fragile. The new property `substate`, which replaces `thumbSource.state` still supports imperative assignments that are so important for Drag&Drop, and still triggers state updates. However, now a substate may not become an active state: that behavior didn't make sense in previous iterations, and has led to a glitch where a window won't resize during return-to-initial animation. The glitch happened because two state transitions were starting almost-simultaneously (and by Murphy's law in the worst possible order, of course), and both animations were playing, but one animation was supposed to to a property that is managed by the other. But since QtQuick animations cache their from/to values before they start, the dependent transition essentially didn't animate at all.
This commit is contained in:
parent
74af27dc55
commit
9897afa55f
1 changed files with 80 additions and 69 deletions
|
@ -56,12 +56,15 @@ Item {
|
||||||
readonly property alias downGestureProgress: touchDragHandler.downGestureProgress
|
readonly property alias downGestureProgress: touchDragHandler.downGestureProgress
|
||||||
signal downGestureTriggered()
|
signal downGestureTriggered()
|
||||||
|
|
||||||
|
// "normal" | "pressed" | "drag" | "reparenting"
|
||||||
|
property string substate: "normal"
|
||||||
|
|
||||||
state: {
|
state: {
|
||||||
if (effect.gestureInProgress) {
|
if (effect.gestureInProgress) {
|
||||||
return "partial";
|
return "partial";
|
||||||
}
|
}
|
||||||
if (windowHeap.effectiveOrganized) {
|
if (windowHeap.effectiveOrganized) {
|
||||||
return activeHidden ? "active-hidden" : "active";
|
return activeHidden ? "active-hidden" : `active-${substate}`;
|
||||||
}
|
}
|
||||||
return initialHidden ? "initial-hidden" : "initial";
|
return initialHidden ? "initial-hidden" : "initial";
|
||||||
}
|
}
|
||||||
|
@ -101,13 +104,12 @@ Item {
|
||||||
onXChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
onXChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
||||||
onYChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
onYChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
||||||
|
|
||||||
state: "normal"
|
|
||||||
function saveDND() {
|
function saveDND() {
|
||||||
const oldGlobalRect = mapToItem(null, 0, 0, width, height);
|
const oldGlobalRect = mapToItem(null, 0, 0, width, height);
|
||||||
thumb.windowHeap.saveDND(thumb.client.internalId, oldGlobalRect);
|
thumb.windowHeap.saveDND(thumb.client.internalId, oldGlobalRect);
|
||||||
}
|
}
|
||||||
function restoreDND(oldGlobalRect: rect) {
|
function restoreDND(oldGlobalRect: rect) {
|
||||||
state = "reparenting";
|
thumb.substate = "reparenting";
|
||||||
|
|
||||||
const newGlobalRect = mapFromItem(null, oldGlobalRect);
|
const newGlobalRect = mapFromItem(null, oldGlobalRect);
|
||||||
|
|
||||||
|
@ -116,56 +118,7 @@ Item {
|
||||||
width = newGlobalRect.width;
|
width = newGlobalRect.width;
|
||||||
height = newGlobalRect.height;
|
height = newGlobalRect.height;
|
||||||
|
|
||||||
state = "normal";
|
thumb.substate = "normal";
|
||||||
}
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "normal"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumbSource
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: thumb.width
|
|
||||||
height: thumb.height
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "pressed"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumbSource
|
|
||||||
width: thumb.width
|
|
||||||
height: thumb.height
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "drag"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumbSource
|
|
||||||
x: -thumb.activeDragHandler.centroid.pressPosition.x * thumb.targetScale +
|
|
||||||
thumb.activeDragHandler.centroid.position.x
|
|
||||||
y: -thumb.activeDragHandler.centroid.pressPosition.y * thumb.targetScale +
|
|
||||||
thumb.activeDragHandler.centroid.position.y
|
|
||||||
width: thumb.width * thumb.targetScale
|
|
||||||
height: thumb.height * thumb.targetScale
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "reparenting"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumbSource
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
transitions: Transition {
|
|
||||||
id: returning
|
|
||||||
from: "drag,reparenting"
|
|
||||||
to: "normal"
|
|
||||||
enabled: thumb.windowHeap.animationEnabled
|
|
||||||
NumberAnimation {
|
|
||||||
duration: thumb.windowHeap.animationDuration
|
|
||||||
properties: "x, y, width, height"
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlasmaCore.FrameSvgItem {
|
PlasmaCore.FrameSvgItem {
|
||||||
|
@ -244,6 +197,13 @@ Item {
|
||||||
width: thumb.client.width
|
width: thumb.client.width
|
||||||
height: thumb.client.height
|
height: thumb.client.height
|
||||||
}
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumbSource
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: thumb.client.width
|
||||||
|
height: thumb.client.height
|
||||||
|
}
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: icon
|
target: icon
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
@ -291,6 +251,11 @@ Item {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
|
name: "active-hidden"
|
||||||
|
extend: "initial-hidden"
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
// this state is never directly used without a substate
|
||||||
name: "active"
|
name: "active"
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
target: thumb
|
target: thumb
|
||||||
|
@ -309,20 +274,66 @@ Item {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
name: "active-hidden"
|
name: "active-normal"
|
||||||
extend: "initial-hidden"
|
extend: "active"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumbSource
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: cell.width
|
||||||
|
height: cell.height
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "active-pressed"
|
||||||
|
extend: "active"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumbSource
|
||||||
|
width: cell.width
|
||||||
|
height: cell.height
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "active-drag"
|
||||||
|
extend: "active"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumbSource
|
||||||
|
x: -thumb.activeDragHandler.centroid.pressPosition.x * thumb.targetScale +
|
||||||
|
thumb.activeDragHandler.centroid.position.x
|
||||||
|
y: -thumb.activeDragHandler.centroid.pressPosition.y * thumb.targetScale +
|
||||||
|
thumb.activeDragHandler.centroid.position.y
|
||||||
|
width: cell.width * thumb.targetScale
|
||||||
|
height: cell.height * thumb.targetScale
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "active-reparenting"
|
||||||
|
extend: "active"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
transitions: Transition {
|
transitions: [
|
||||||
to: "initial, initial-hidden, active, active-hidden"
|
Transition {
|
||||||
enabled: thumb.windowHeap.animationEnabled
|
id: returning
|
||||||
NumberAnimation {
|
from: "active-drag, active-reparenting"
|
||||||
duration: thumb.windowHeap.animationDuration
|
to: "active-normal"
|
||||||
properties: "x, y, width, height, opacity"
|
enabled: thumb.windowHeap.animationEnabled
|
||||||
easing.type: Easing.OutCubic
|
NumberAnimation {
|
||||||
|
duration: thumb.windowHeap.animationDuration
|
||||||
|
properties: "x, y, width, height"
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
to: "initial, initial-hidden, active-normal, active-hidden"
|
||||||
|
enabled: thumb.windowHeap.animationEnabled
|
||||||
|
NumberAnimation {
|
||||||
|
duration: thumb.windowHeap.animationDuration
|
||||||
|
properties: "x, y, width, height, opacity"
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
id: hoverHandler
|
id: hoverHandler
|
||||||
|
@ -341,12 +352,12 @@ Item {
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
var saved = Qt.point(thumbSource.x, thumbSource.y);
|
var saved = Qt.point(thumbSource.x, thumbSource.y);
|
||||||
thumbSource.Drag.active = true;
|
thumbSource.Drag.active = true;
|
||||||
thumbSource.state = "pressed";
|
thumb.substate = "pressed";
|
||||||
thumbSource.x = saved.x;
|
thumbSource.x = saved.x;
|
||||||
thumbSource.y = saved.y;
|
thumbSource.y = saved.y;
|
||||||
} else if (!thumb.activeDragHandler.active) {
|
} else if (!thumb.activeDragHandler.active) {
|
||||||
thumbSource.Drag.active = false;
|
thumbSource.Drag.active = false;
|
||||||
thumbSource.state = "normal";
|
thumb.substate = "normal";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,13 +376,13 @@ Item {
|
||||||
grabPermissions: PointerHandler.CanTakeOverFromAnything
|
grabPermissions: PointerHandler.CanTakeOverFromAnything
|
||||||
// This does not work when moving pointer fast and pressing along the way
|
// This does not work when moving pointer fast and pressing along the way
|
||||||
// See also QTBUG-105903, QTBUG-105904
|
// See also QTBUG-105903, QTBUG-105904
|
||||||
// enabled: thumbSource.state !== "normal"
|
// enabled: thumb.state !== "active-normal"
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
thumb.windowHeap.dragActive = active;
|
thumb.windowHeap.dragActive = active;
|
||||||
if (active) {
|
if (active) {
|
||||||
thumb.activeDragHandler = this;
|
thumb.activeDragHandler = this;
|
||||||
thumbSource.state = "drag";
|
thumb.substate = "drag";
|
||||||
} else {
|
} else {
|
||||||
thumbSource.saveDND();
|
thumbSource.saveDND();
|
||||||
|
|
||||||
|
@ -381,7 +392,7 @@ Item {
|
||||||
// another virtual desktop (not another screen).
|
// another virtual desktop (not another screen).
|
||||||
if (typeof thumbSource !== "undefined") {
|
if (typeof thumbSource !== "undefined") {
|
||||||
// Except the case when it was dropped on the same desktop which it's already on, so let's return to normal state anyway.
|
// Except the case when it was dropped on the same desktop which it's already on, so let's return to normal state anyway.
|
||||||
thumbSource.state = "normal";
|
thumb.substate = "normal";
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +401,7 @@ Item {
|
||||||
effect.checkItemDroppedOutOfScreen(globalPos, thumbSource);
|
effect.checkItemDroppedOutOfScreen(globalPos, thumbSource);
|
||||||
|
|
||||||
// else, return to normal without reparenting
|
// else, return to normal without reparenting
|
||||||
thumbSource.state = "normal";
|
thumb.substate = "normal";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue