Move WindowHeap delegate to own file
This makes easier for individual effects to personalize it without adding ad-hoc api in the main WindowHeap class. WindowHeap and WindowHEapDelegate are still quite coupled and thing can probably still be improved, but the code should be more readable already
This commit is contained in:
parent
6d9d4c190a
commit
fd25e96969
6 changed files with 414 additions and 375 deletions
|
@ -105,9 +105,6 @@ DropArea {
|
||||||
animationEnabled: container.animationEnabled
|
animationEnabled: container.animationEnabled
|
||||||
organized: container.organized
|
organized: container.organized
|
||||||
layout: effect.layout
|
layout: effect.layout
|
||||||
supportsCloseWindows: false
|
|
||||||
supportsDragUpGesture: false
|
|
||||||
showCaptions: false
|
|
||||||
model: KWinComponents.ClientFilterModel {
|
model: KWinComponents.ClientFilterModel {
|
||||||
activity: KWinComponents.Workspace.currentActivity
|
activity: KWinComponents.Workspace.currentActivity
|
||||||
desktop: desktopView.desktop
|
desktop: desktopView.desktop
|
||||||
|
@ -117,6 +114,11 @@ DropArea {
|
||||||
~KWinComponents.ClientFilterModel.Desktop &
|
~KWinComponents.ClientFilterModel.Desktop &
|
||||||
~KWinComponents.ClientFilterModel.Notification;
|
~KWinComponents.ClientFilterModel.Notification;
|
||||||
}
|
}
|
||||||
|
delegate: WindowHeapDelegate {
|
||||||
|
windowHeap: heap
|
||||||
|
closeButtonVisible: false
|
||||||
|
windowTitleVisible: false
|
||||||
|
}
|
||||||
onActivated: effect.deactivate(effect.animationDuration);
|
onActivated: effect.deactivate(effect.animationDuration);
|
||||||
onWindowClicked: {
|
onWindowClicked: {
|
||||||
if (eventPoint.event.button !== Qt.MiddleButton) {
|
if (eventPoint.event.button !== Qt.MiddleButton) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.kde.kwin.private.effects 1.0
|
||||||
import org.kde.milou 0.3 as Milou
|
import org.kde.milou 0.3 as Milou
|
||||||
import org.kde.plasma.components 3.0 as PC3
|
import org.kde.plasma.components 3.0 as PC3
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
|
import org.kde.kirigami 2.12 as Kirigami
|
||||||
|
|
||||||
FocusScope {
|
FocusScope {
|
||||||
id: container
|
id: container
|
||||||
|
@ -183,13 +184,11 @@ FocusScope {
|
||||||
id: heap
|
id: heap
|
||||||
visible: !(container.organized && searchField.text)
|
visible: !(container.organized && searchField.text)
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
layout: effect.layout
|
layoutMode: effect.layout
|
||||||
padding: PlasmaCore.Units.largeSpacing
|
padding: PlasmaCore.Units.largeSpacing
|
||||||
animationDuration: effect.animationDuration
|
animationDuration: effect.animationDuration
|
||||||
animationEnabled: container.animationEnabled
|
animationEnabled: container.animationEnabled
|
||||||
organized: container.organized
|
organized: container.organized
|
||||||
supportsCloseWindows: true
|
|
||||||
supportsDragUpGesture: true
|
|
||||||
onWindowClicked: {
|
onWindowClicked: {
|
||||||
if (eventPoint.event.button !== Qt.MiddleButton) {
|
if (eventPoint.event.button !== Qt.MiddleButton) {
|
||||||
return;
|
return;
|
||||||
|
@ -207,6 +206,22 @@ FocusScope {
|
||||||
~KWinComponents.ClientFilterModel.Notification;
|
~KWinComponents.ClientFilterModel.Notification;
|
||||||
}
|
}
|
||||||
onActivated: effect.deactivate();
|
onActivated: effect.deactivate();
|
||||||
|
delegate: WindowHeapDelegate {
|
||||||
|
windowHeap: heap
|
||||||
|
|
||||||
|
targetScale: {
|
||||||
|
var localPressPosition = dragHandler.centroid.scenePressPosition.y - heap.expoLayout.Kirigami.ScenePosition.y;
|
||||||
|
if (localPressPosition == 0) {
|
||||||
|
return 0.1
|
||||||
|
} else {
|
||||||
|
var localPosition = dragHandler.centroid.scenePosition.y - heap.expoLayout.Kirigami.ScenePosition.y;
|
||||||
|
return Math.max(0.1, Math.min(localPosition / localPressPosition, 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opacity: 1 - downGestureProgress
|
||||||
|
onDownGestureTriggered: client.closeWindow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Milou.ResultsView {
|
Milou.ResultsView {
|
||||||
|
@ -246,7 +261,7 @@ FocusScope {
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
enabled: !container.effect.gestureInProgress
|
enabled: !container.effect.gestureInProgress
|
||||||
NumberAnimation { duration: animationDuration; easing.type: Easing.OutCubic }
|
NumberAnimation { duration: effect.animationDuration; easing.type: Easing.OutCubic }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,10 @@ FocusScope {
|
||||||
Down
|
Down
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool supportsCloseWindows: false
|
|
||||||
property bool supportsDragUpGesture: false
|
|
||||||
property bool showCaptions: true
|
|
||||||
property alias model: windowsRepeater.model
|
property alias model: windowsRepeater.model
|
||||||
|
property alias delegate: windowsRepeater.delegate
|
||||||
property alias layout: expoLayout.mode
|
property alias layout: expoLayout.mode
|
||||||
|
property alias expoLayout: expoLayout
|
||||||
property int selectedIndex: -1
|
property int selectedIndex: -1
|
||||||
property int animationDuration: PlasmaCore.Units.longDuration
|
property int animationDuration: PlasmaCore.Units.longDuration
|
||||||
property bool animationEnabled: false
|
property bool animationEnabled: false
|
||||||
|
@ -110,369 +109,7 @@ FocusScope {
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: windowsRepeater
|
id: windowsRepeater
|
||||||
|
delegate: WindowHeapDelegate {}
|
||||||
Item {
|
|
||||||
id: thumb
|
|
||||||
|
|
||||||
required property QtObject client
|
|
||||||
required property int index
|
|
||||||
|
|
||||||
readonly property bool selected: heap.selectedIndex == index
|
|
||||||
readonly property bool hidden: {
|
|
||||||
if (heap.showOnly === "activeClass") {
|
|
||||||
return heap.activeClass !== String(thumb.client.resourceName); // thumb.client.resourceName is not an actual String as comes from a QByteArray so === would fail
|
|
||||||
} else {
|
|
||||||
return heap.showOnly.length && heap.showOnly.indexOf(client.internalId) == -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (thumb.client.active) {
|
|
||||||
heap.activeClass = thumb.client.resourceName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Connections {
|
|
||||||
target: thumb.client
|
|
||||||
function onActiveChanged() {
|
|
||||||
if (thumb.client.active) {
|
|
||||||
heap.activeClass = thumb.client.resourceName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state: {
|
|
||||||
if (effect.gestureInProgress) {
|
|
||||||
return "partial";
|
|
||||||
}
|
|
||||||
if (heap.effectiveOrganized) {
|
|
||||||
return hidden ? "active-hidden" : "active";
|
|
||||||
}
|
|
||||||
return client.minimized ? "initial-minimized" : "initial";
|
|
||||||
}
|
|
||||||
|
|
||||||
visible: opacity > 0
|
|
||||||
z: thumb.activeDragHandler.active ? 100 : client.stackingOrder
|
|
||||||
|
|
||||||
component TweenBehavior : Behavior {
|
|
||||||
enabled: thumb.state !== "partial" && heap.animationEnabled && !thumb.activeDragHandler.active
|
|
||||||
NumberAnimation {
|
|
||||||
duration: heap.animationDuration
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TweenBehavior on x {}
|
|
||||||
TweenBehavior on y {}
|
|
||||||
TweenBehavior on width {}
|
|
||||||
TweenBehavior on height {}
|
|
||||||
|
|
||||||
KWinComponents.WindowThumbnailItem {
|
|
||||||
id: thumbSource
|
|
||||||
wId: thumb.client.internalId
|
|
||||||
state: thumb.activeDragHandler.active ? "drag" : "normal"
|
|
||||||
readonly property QtObject screen: targetScreen
|
|
||||||
readonly property QtObject client: thumb.client
|
|
||||||
|
|
||||||
Drag.active: thumb.activeDragHandler.active
|
|
||||||
Drag.source: thumb.client
|
|
||||||
Drag.hotSpot: Qt.point(
|
|
||||||
thumb.activeDragHandler.centroid.pressPosition.x * thumb.activeDragHandler.targetScale,
|
|
||||||
thumb.activeDragHandler.centroid.pressPosition.y * thumb.activeDragHandler.targetScale)
|
|
||||||
|
|
||||||
onXChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
|
||||||
onYChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
|
||||||
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "normal"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumbSource
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: thumb.width
|
|
||||||
height: thumb.height
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "drag"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumbSource
|
|
||||||
x: -thumb.activeDragHandler.centroid.pressPosition.x * thumb.activeDragHandler.targetScale +
|
|
||||||
thumb.activeDragHandler.centroid.position.x
|
|
||||||
y: -thumb.activeDragHandler.centroid.pressPosition.y * thumb.activeDragHandler.targetScale +
|
|
||||||
thumb.activeDragHandler.centroid.position.y
|
|
||||||
width: cell.width * thumb.activeDragHandler.targetScale
|
|
||||||
height: cell.height * thumb.activeDragHandler.targetScale
|
|
||||||
opacity: thumb.activeDragHandler.targetOpacity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
transitions: Transition {
|
|
||||||
to: "normal"
|
|
||||||
enabled: heap.animationEnabled
|
|
||||||
NumberAnimation {
|
|
||||||
duration: heap.animationDuration
|
|
||||||
properties: "x, y, width, height, opacity"
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.NoButton
|
|
||||||
cursorShape: thumb.activeDragHandler.active ? Qt.ClosedHandCursor : Qt.ArrowCursor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PC3.Label {
|
|
||||||
anchors.fill: thumbSource
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
text: i18nd("kwin_effects", "Drag Down To Close")
|
|
||||||
opacity: 1 - thumbSource.opacity
|
|
||||||
visible: !thumb.hidden
|
|
||||||
}
|
|
||||||
|
|
||||||
PlasmaCore.IconItem {
|
|
||||||
id: icon
|
|
||||||
usesPlasmaTheme: false
|
|
||||||
width: PlasmaCore.Units.iconSizes.large
|
|
||||||
height: width
|
|
||||||
source: thumb.client.icon
|
|
||||||
anchors.horizontalCenter: thumbSource.horizontalCenter
|
|
||||||
anchors.bottom: thumbSource.bottom
|
|
||||||
anchors.bottomMargin: -height / 4
|
|
||||||
visible: !thumb.hidden && !activeDragHandler.active
|
|
||||||
|
|
||||||
|
|
||||||
PC3.Label {
|
|
||||||
id: caption
|
|
||||||
visible: heap.showCaptions
|
|
||||||
width: Math.min(implicitWidth, thumbSource.width)
|
|
||||||
anchors.top: parent.bottom
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
text: thumb.client.caption
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpoCell {
|
|
||||||
id: cell
|
|
||||||
layout: expoLayout
|
|
||||||
enabled: !thumb.hidden
|
|
||||||
naturalX: thumb.client.x - targetScreen.geometry.x - expoLayout.Kirigami.ScenePosition.x
|
|
||||||
naturalY: thumb.client.y - targetScreen.geometry.y - expoLayout.Kirigami.ScenePosition.y
|
|
||||||
naturalWidth: thumb.client.width
|
|
||||||
naturalHeight: thumb.client.height
|
|
||||||
persistentKey: thumb.client.internalId
|
|
||||||
bottomMargin: icon.height / 4 + caption.height
|
|
||||||
}
|
|
||||||
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "initial"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumb
|
|
||||||
x: thumb.client.x - targetScreen.geometry.x - (heap.absolutePositioning ? expoLayout.Kirigami.ScenePosition.x : 0)
|
|
||||||
y: thumb.client.y - targetScreen.geometry.y - (heap.absolutePositioning ? expoLayout.Kirigami.ScenePosition.y : 0)
|
|
||||||
width: thumb.client.width
|
|
||||||
height: thumb.client.height
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: icon
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: closeButton
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "partial"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumb
|
|
||||||
x: (thumb.client.x - targetScreen.geometry.x - (heap.absolutePositioning ? expoLayout.Kirigami.ScenePosition.x : 0)) * (1 - effect.partialActivationFactor) + cell.x * effect.partialActivationFactor
|
|
||||||
y: (thumb.client.y - targetScreen.geometry.y - (heap.absolutePositioning ? expoLayout.Kirigami.ScenePosition.y : 0)) * (1 - effect.partialActivationFactor) + cell.y * effect.partialActivationFactor
|
|
||||||
width: thumb.client.width * (1 - effect.partialActivationFactor) + cell.width * effect.partialActivationFactor
|
|
||||||
height: thumb.client.height * (1 - effect.partialActivationFactor) + cell.height * effect.partialActivationFactor
|
|
||||||
opacity: thumb.client.minimized ? effect.partialActivationFactor : 1
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: icon
|
|
||||||
opacity: effect.partialActivationFactor
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: closeButton
|
|
||||||
opacity: effect.partialActivationFactor
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "initial-minimized"
|
|
||||||
extend: "initial"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumb
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: icon
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: closeButton
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "active"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumb
|
|
||||||
x: cell.x
|
|
||||||
y: cell.y
|
|
||||||
width: cell.width
|
|
||||||
height: cell.height
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: icon
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
PropertyChanges {
|
|
||||||
target: closeButton
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "active-hidden"
|
|
||||||
extend: "active"
|
|
||||||
PropertyChanges {
|
|
||||||
target: thumb
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
transitions: Transition {
|
|
||||||
to: "initial, active, active-hidden"
|
|
||||||
enabled: heap.animationEnabled
|
|
||||||
NumberAnimation {
|
|
||||||
duration: heap.animationDuration
|
|
||||||
properties: "x, y, width, height, opacity"
|
|
||||||
easing.type: Easing.InOutCubic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PlasmaCore.FrameSvgItem {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: -PlasmaCore.Units.smallSpacing
|
|
||||||
imagePath: "widgets/viewitem"
|
|
||||||
prefix: "hover"
|
|
||||||
z: -1
|
|
||||||
visible: !thumb.activeDragHandler.active && (hoverHandler.hovered || selected)
|
|
||||||
}
|
|
||||||
|
|
||||||
HoverHandler {
|
|
||||||
id: hoverHandler
|
|
||||||
onHoveredChanged: if (hovered != selected) {
|
|
||||||
heap.resetSelected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TapHandler {
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onTapped: {
|
|
||||||
KWinComponents.Workspace.activeClient = thumb.client;
|
|
||||||
heap.activated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TapHandler {
|
|
||||||
acceptedPointerTypes: PointerDevice.GenericPointer | PointerDevice.Pen
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
|
|
||||||
onTapped: {
|
|
||||||
heap.windowClicked(thumb.client, eventPoint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component DragManager : DragHandler {
|
|
||||||
id: dragHandler
|
|
||||||
target: null
|
|
||||||
grabPermissions: PointerHandler.CanTakeOverFromAnything
|
|
||||||
|
|
||||||
readonly property double targetScale: {
|
|
||||||
if (!heap.supportsDragUpGesture) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
const localPressPosition = centroid.scenePressPosition.y - expoLayout.Kirigami.ScenePosition.y;
|
|
||||||
if (localPressPosition == 0) {
|
|
||||||
return 0.1
|
|
||||||
} else {
|
|
||||||
const localPosition = centroid.scenePosition.y - expoLayout.Kirigami.ScenePosition.y;
|
|
||||||
return Math.max(0.1, Math.min(localPosition / localPressPosition, 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onActiveChanged: {
|
|
||||||
heap.dragActive = active;
|
|
||||||
if (active) {
|
|
||||||
thumb.activeDragHandler = dragHandler;
|
|
||||||
} else {
|
|
||||||
thumbSource.Drag.drop();
|
|
||||||
let globalPos = targetScreen.mapToGlobal(centroid.scenePosition);
|
|
||||||
effect.checkItemDroppedOutOfScreen(globalPos, thumbSource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
property DragManager activeDragHandler: dragHandler
|
|
||||||
DragManager {
|
|
||||||
id: dragHandler
|
|
||||||
readonly property double targetOpacity: 1
|
|
||||||
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
|
|
||||||
}
|
|
||||||
DragManager {
|
|
||||||
id: touchDragHandler
|
|
||||||
acceptedDevices: PointerDevice.TouchScreen
|
|
||||||
readonly property double targetOpacity: {
|
|
||||||
if (!heap.supportsCloseWindows) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
const startDistance = heap.Kirigami.ScenePosition.y + heap.height - centroid.scenePressPosition.y;
|
|
||||||
const localPosition = heap.Kirigami.ScenePosition.y + heap.height - centroid.scenePosition.y;
|
|
||||||
return Math.min(localPosition / startDistance, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
onActiveChanged: {
|
|
||||||
if (!active) {
|
|
||||||
if (heap.supportsCloseWindows && targetOpacity < 0.4) {
|
|
||||||
thumb.client.closeWindow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PC3.Button {
|
|
||||||
id: closeButton
|
|
||||||
visible: heap.supportsCloseWindows && (hoverHandler.hovered || Kirigami.Settings.tabletMode || Kirigami.Settings.hasTransientTouchInput) && thumb.client.closeable && !dragHandler.active
|
|
||||||
anchors {
|
|
||||||
right: thumbSource.right
|
|
||||||
rightMargin: PlasmaCore.Units.smallSpacing
|
|
||||||
top: thumbSource.top
|
|
||||||
topMargin: PlasmaCore.Units.smallSpacing
|
|
||||||
}
|
|
||||||
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
|
|
||||||
icon.name: "window-close"
|
|
||||||
implicitWidth: PlasmaCore.Units.iconSizes.medium
|
|
||||||
implicitHeight: implicitWidth
|
|
||||||
onClicked: thumb.client.closeWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onDestruction: {
|
|
||||||
if (selected) {
|
|
||||||
heap.resetSelected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
380
src/effects/private/qml/WindowHeapDelegate.qml
Normal file
380
src/effects/private/qml/WindowHeapDelegate.qml
Normal file
|
@ -0,0 +1,380 @@
|
||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Window 2.12
|
||||||
|
import org.kde.kirigami 2.12 as Kirigami
|
||||||
|
import org.kde.kwin 3.0 as KWinComponents
|
||||||
|
import org.kde.kwin.private.effects 1.0
|
||||||
|
import org.kde.plasma.components 3.0 as PC3
|
||||||
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
|
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: thumb
|
||||||
|
|
||||||
|
required property QtObject client
|
||||||
|
required property int index
|
||||||
|
required property Item windowHeap
|
||||||
|
|
||||||
|
readonly property alias dragHandler: thumb.activeDragHandler
|
||||||
|
readonly property bool selected: thumb.windowHeap.selectedIndex == index
|
||||||
|
//TODO: move?
|
||||||
|
readonly property bool hidden: {
|
||||||
|
if (thumb.windowHeap.showOnly === "activeClass") {
|
||||||
|
return thumb.windowHeap.activeClass !== String(thumb.client.resourceName); // thumb.client.resourceName is not an actual String as comes from a QByteArray so === would fail
|
||||||
|
} else {
|
||||||
|
return thumb.windowHeap.showOnly.length && thumb.windowHeap.showOnly.indexOf(client.internalId) == -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show a close button on this thumbnail
|
||||||
|
property bool closeButtonVisible: true
|
||||||
|
// Show a text label under this thumbnail
|
||||||
|
property bool windowTitleVisible: true
|
||||||
|
|
||||||
|
//scale up and down the whole thumbnail without affecting layouting
|
||||||
|
property real targetScale: 1.0
|
||||||
|
|
||||||
|
// Swipe down gesture by touch, in some effects will close the window
|
||||||
|
readonly property alias downGestureProgress: touchDragHandler.downGestureProgress
|
||||||
|
signal downGestureTriggered()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (thumb.client.active) {
|
||||||
|
thumb.windowHeap.activeClass = thumb.client.resourceName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Connections {
|
||||||
|
target: thumb.client
|
||||||
|
function onActiveChanged() {
|
||||||
|
if (thumb.client.active) {
|
||||||
|
thumb.windowHeap.activeClass = thumb.client.resourceName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state: {
|
||||||
|
if (effect.gestureInProgress) {
|
||||||
|
return "partial";
|
||||||
|
}
|
||||||
|
if (thumb.windowHeap.effectiveOrganized) {
|
||||||
|
return hidden ? "active-hidden" : "active";
|
||||||
|
}
|
||||||
|
return client.minimized ? "initial-minimized" : "initial";
|
||||||
|
}
|
||||||
|
|
||||||
|
visible: opacity > 0
|
||||||
|
z: thumb.activeDragHandler.active ? 100 : client.stackingOrder
|
||||||
|
|
||||||
|
component TweenBehavior : Behavior {
|
||||||
|
enabled: thumb.state !== "partial" && thumb.windowHeap.animationEnabled && !thumb.activeDragHandler.active
|
||||||
|
NumberAnimation {
|
||||||
|
duration: thumb.windowHeap.animationDuration
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TweenBehavior on x {}
|
||||||
|
TweenBehavior on y {}
|
||||||
|
TweenBehavior on width {}
|
||||||
|
TweenBehavior on height {}
|
||||||
|
|
||||||
|
KWinComponents.WindowThumbnailItem {
|
||||||
|
id: thumbSource
|
||||||
|
wId: thumb.client.internalId
|
||||||
|
state: thumb.activeDragHandler.active ? "drag" : "normal"
|
||||||
|
readonly property QtObject screen: targetScreen
|
||||||
|
readonly property QtObject client: thumb.client
|
||||||
|
|
||||||
|
Drag.active: thumb.activeDragHandler.active
|
||||||
|
Drag.source: thumb.client
|
||||||
|
Drag.hotSpot: Qt.point(
|
||||||
|
thumb.activeDragHandler.centroid.pressPosition.x * thumb.targetScale,
|
||||||
|
thumb.activeDragHandler.centroid.pressPosition.y * thumb.targetScale)
|
||||||
|
|
||||||
|
onXChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
||||||
|
onYChanged: effect.checkItemDraggedOutOfScreen(thumbSource)
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "normal"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumbSource
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: thumb.width * thumb.targetScale
|
||||||
|
height: thumb.height * thumb.targetScale
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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: cell.width * thumb.targetScale
|
||||||
|
height: cell.height * thumb.targetScale
|
||||||
|
opacity: thumb.activeDragHandler.targetOpacity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
transitions: Transition {
|
||||||
|
to: "normal"
|
||||||
|
enabled: thumb.windowHeap.animationEnabled
|
||||||
|
NumberAnimation {
|
||||||
|
duration: thumb.windowHeap.animationDuration
|
||||||
|
properties: "x, y, width, height, opacity"
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
cursorShape: thumb.activeDragHandler.active ? Qt.ClosedHandCursor : Qt.ArrowCursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PC3.Label {
|
||||||
|
anchors.fill: thumbSource
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
text: i18nd("kwin_effects", "Drag Down To Close")
|
||||||
|
opacity: 1 - thumbSource.opacity
|
||||||
|
visible: !thumb.hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
PlasmaCore.IconItem {
|
||||||
|
id: icon
|
||||||
|
width: PlasmaCore.Units.iconSizes.large
|
||||||
|
height: width
|
||||||
|
source: thumb.client.icon
|
||||||
|
anchors.horizontalCenter: thumbSource.horizontalCenter
|
||||||
|
anchors.bottom: thumbSource.bottom
|
||||||
|
anchors.bottomMargin: -height / 4
|
||||||
|
visible: !thumb.hidden && !activeDragHandler.active
|
||||||
|
|
||||||
|
|
||||||
|
PC3.Label {
|
||||||
|
id: caption
|
||||||
|
visible: thumb.windowTitleVisible
|
||||||
|
width: Math.min(implicitWidth, thumbSource.width)
|
||||||
|
anchors.top: parent.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: thumb.client.caption
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpoCell {
|
||||||
|
id: cell
|
||||||
|
layout: windowHeap.expoLayout
|
||||||
|
enabled: !thumb.hidden
|
||||||
|
naturalX: thumb.client.x - targetScreen.geometry.x - windowHeap.expoLayout.Kirigami.ScenePosition.x
|
||||||
|
naturalY: thumb.client.y - targetScreen.geometry.y - windowHeap.expoLayout.Kirigami.ScenePosition.y
|
||||||
|
naturalWidth: thumb.client.width
|
||||||
|
naturalHeight: thumb.client.height
|
||||||
|
persistentKey: thumb.client.internalId
|
||||||
|
bottomMargin: icon.height / 4 + caption.height
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "initial"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumb
|
||||||
|
x: thumb.client.x - targetScreen.geometry.x - (thumb.windowHeap.absolutePositioning ? windowHeap.expoLayout.Kirigami.ScenePosition.x : 0)
|
||||||
|
y: thumb.client.y - targetScreen.geometry.y - (thumb.windowHeap.absolutePositioning ? windowHeap.expoLayout.Kirigami.ScenePosition.y : 0)
|
||||||
|
width: thumb.client.width
|
||||||
|
height: thumb.client.height
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: icon
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: closeButton
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "partial"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumb
|
||||||
|
x: (thumb.client.x - targetScreen.geometry.x - (thumb.windowHeap.absolutePositioning ? windowHeap.expoLayout.Kirigami.ScenePosition.x : 0)) * (1 - effect.partialActivationFactor) + cell.x * effect.partialActivationFactor
|
||||||
|
y: (thumb.client.y - targetScreen.geometry.y - (thumb.windowHeap.absolutePositioning ? windowHeap.expoLayout.Kirigami.ScenePosition.y : 0)) * (1 - effect.partialActivationFactor) + cell.y * effect.partialActivationFactor
|
||||||
|
width: thumb.client.width * (1 - effect.partialActivationFactor) + cell.width * effect.partialActivationFactor
|
||||||
|
height: thumb.client.height * (1 - effect.partialActivationFactor) + cell.height * effect.partialActivationFactor
|
||||||
|
opacity: thumb.client.minimized ? effect.partialActivationFactor : 1
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: icon
|
||||||
|
opacity: effect.partialActivationFactor
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: closeButton
|
||||||
|
opacity: effect.partialActivationFactor
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "initial-minimized"
|
||||||
|
extend: "initial"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumb
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: icon
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: closeButton
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "active"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumb
|
||||||
|
x: cell.x
|
||||||
|
y: cell.y
|
||||||
|
width: cell.width
|
||||||
|
height: cell.height
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: icon
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: closeButton
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "active-hidden"
|
||||||
|
extend: "active"
|
||||||
|
PropertyChanges {
|
||||||
|
target: thumb
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
transitions: Transition {
|
||||||
|
to: "initial, active, active-hidden"
|
||||||
|
enabled: thumb.windowHeap.animationEnabled
|
||||||
|
NumberAnimation {
|
||||||
|
duration: thumb.windowHeap.animationDuration
|
||||||
|
properties: "x, y, width, height, opacity"
|
||||||
|
easing.type: Easing.InOutCubic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PlasmaCore.FrameSvgItem {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: -PlasmaCore.Units.smallSpacing
|
||||||
|
imagePath: "widgets/viewitem"
|
||||||
|
prefix: "hover"
|
||||||
|
z: -1
|
||||||
|
visible: !thumb.activeDragHandler.active && (hoverHandler.hovered || selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
HoverHandler {
|
||||||
|
id: hoverHandler
|
||||||
|
onHoveredChanged: if (hovered != selected) {
|
||||||
|
thumb.windowHeap.resetSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onTapped: {
|
||||||
|
KWinComponents.Workspace.activeClient = thumb.client;
|
||||||
|
thumb.windowHeap.activated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedPointerTypes: PointerDevice.GenericPointer | PointerDevice.Pen
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
|
||||||
|
onTapped: {
|
||||||
|
thumb.windowHeap.windowClicked(thumb.client, eventPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component DragManager : DragHandler {
|
||||||
|
id: dragHandler
|
||||||
|
target: null
|
||||||
|
grabPermissions: PointerHandler.CanTakeOverFromAnything
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
thumb.windowHeap.dragActive = active;
|
||||||
|
if (active) {
|
||||||
|
thumb.activeDragHandler = dragHandler;
|
||||||
|
} else {
|
||||||
|
thumbSource.Drag.drop();
|
||||||
|
var globalPos = targetScreen.mapToGlobal(centroid.scenePosition);
|
||||||
|
effect.checkItemDroppedOutOfScreen(globalPos, thumbSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
property DragManager activeDragHandler: dragHandler
|
||||||
|
DragManager {
|
||||||
|
id: dragHandler
|
||||||
|
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
|
||||||
|
}
|
||||||
|
DragManager {
|
||||||
|
id: touchDragHandler
|
||||||
|
acceptedDevices: PointerDevice.TouchScreen
|
||||||
|
readonly property double downGestureProgress: {
|
||||||
|
if (!active) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const startDistance = thumb.windowHeap.Kirigami.ScenePosition.y + thumb.windowHeap.height - centroid.scenePressPosition.y;
|
||||||
|
const localPosition = thumb.windowHeap.Kirigami.ScenePosition.y + thumb.windowHeap.height - centroid.scenePosition.y;
|
||||||
|
return Math.min(startDistance / localPosition, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
onActiveChanged: {
|
||||||
|
if (!active) {
|
||||||
|
if (downGestureProgress > 0.6) {
|
||||||
|
thumb.downGestureTriggered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PC3.Button {
|
||||||
|
id: closeButton
|
||||||
|
visible: thumb.closeButtonVisible && (hoverHandler.hovered || Kirigami.Settings.tabletMode || Kirigami.Settings.hasTransientTouchInput) && thumb.client.closeable && !dragHandler.active
|
||||||
|
anchors {
|
||||||
|
right: thumbSource.right
|
||||||
|
rightMargin: PlasmaCore.Units.smallSpacing
|
||||||
|
top: thumbSource.top
|
||||||
|
topMargin: PlasmaCore.Units.smallSpacing
|
||||||
|
}
|
||||||
|
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
|
||||||
|
icon.name: "window-close"
|
||||||
|
implicitWidth: PlasmaCore.Units.iconSizes.medium
|
||||||
|
implicitHeight: implicitWidth
|
||||||
|
onClicked: thumb.client.closeWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
if (selected) {
|
||||||
|
thumb.windowHeap.resetSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,3 +8,4 @@ plugin effectsplugin
|
||||||
classname EffectKitExtensionPlugin
|
classname EffectKitExtensionPlugin
|
||||||
|
|
||||||
WindowHeap 1.0 WindowHeap.qml
|
WindowHeap 1.0 WindowHeap.qml
|
||||||
|
WindowHeapDelegate 1.0 WindowHeapDelegate.qml
|
||||||
|
|
|
@ -119,8 +119,7 @@ Item {
|
||||||
animationEnabled: container.animationEnabled
|
animationEnabled: container.animationEnabled
|
||||||
organized: container.organized
|
organized: container.organized
|
||||||
showOnly: container.effect.mode === WindowView.ModeWindowClass ? "activeClass" : selectedIds
|
showOnly: container.effect.mode === WindowView.ModeWindowClass ? "activeClass" : selectedIds
|
||||||
layout: effect.layout
|
layoutMode: effect.layout
|
||||||
supportsCloseWindows: true
|
|
||||||
onWindowClicked: {
|
onWindowClicked: {
|
||||||
if (eventPoint.event.button !== Qt.MiddleButton) {
|
if (eventPoint.event.button !== Qt.MiddleButton) {
|
||||||
return;
|
return;
|
||||||
|
@ -138,6 +137,11 @@ Item {
|
||||||
~KWinComponents.ClientFilterModel.Desktop &
|
~KWinComponents.ClientFilterModel.Desktop &
|
||||||
~KWinComponents.ClientFilterModel.Notification;
|
~KWinComponents.ClientFilterModel.Notification;
|
||||||
}
|
}
|
||||||
|
delegate: WindowHeapDelegate {
|
||||||
|
windowHeap: heap
|
||||||
|
opacity: 1 - downGestureProgress
|
||||||
|
onDownGestureTriggered: client.closeWindow()
|
||||||
|
}
|
||||||
onActivated: effect.deactivate(animationDuration);
|
onActivated: effect.deactivate(animationDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue