diff --git a/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewContent.qml b/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewContent.qml index cbb61b2fe..31d0a0945 100644 --- a/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewContent.qml @@ -16,29 +16,43 @@ Rectangle { id: root color: ColorUtils.transparentize(Looks.colors.bg1Base, 0.5) + property bool draggingWindow: false property real openProgress: 0 + property Item hoveredWorkspace: null + signal closed Component.onCompleted: { openAnim.start(); } + function close() { + closeAnim.start(); + } PropertyAnimation { id: openAnim target: root property: "openProgress" to: 1 - duration: 200 + duration: 250 easing.type: Easing.BezierSpline easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn } - PropertyAnimation { + SequentialAnimation { id: closeAnim - target: root - property: "openProgress" - to: 0 - duration: 200 - easing.type: Easing.BezierSpline - easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn + + PropertyAnimation { + target: root + property: "openProgress" + to: 0 + duration: 200 + easing.type: Easing.BezierSpline + easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn + } + ScriptAction { + script: { + root.closed(); + } + } } // Windows @@ -81,8 +95,18 @@ Rectangle { return resultLayout; } + MouseArea { + z: 0 + anchors.fill: parent + onClicked: { + GlobalStates.overviewOpen = false; + } + } + // Windows WListView { + id: windowListView + z: root.openProgress == 1 ? 2 : 1 anchors { left: parent.left right: parent.right @@ -96,9 +120,8 @@ Rectangle { rightMargin: root.padding height: Math.min(contentHeight + topMargin + bottomMargin, root.height - (wsBorder.height + 16)) - interactive: height < contentHeight - - clip: true + interactive: (height < contentHeight) && !root.draggingWindow + clip: root.openProgress > 0.99 && !root.draggingWindow model: ScriptModel { values: root.arrangedToplevels @@ -107,7 +130,7 @@ Rectangle { id: clientRow required property var modelData spacing: root.spacing - anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenter: parent?.horizontalCenter ?? undefined Repeater { model: ScriptModel { @@ -117,24 +140,61 @@ Rectangle { id: clientGridArea required property int index required property var modelData - implicitWidth: windowItem.implicitWidth - implicitHeight: windowItem.implicitHeight + implicitWidth: windowItem.openedSize.width + implicitHeight: windowItem.openedSize.height + windowItem.titleBarImplicitHeight TaskViewWindow { id: windowItem - z: 9999 - drag { - target: this + z: Drag.active ? 2 : 1 + opacity: openAnim.running ? root.openProgress : 1 + + property int mappedX: { + // print("AAAWAWAAWAWWA: ", -(clientRow.x + clientGridArea.x + root.padding)); + var rootPosToThis = -(clientRow.x + clientGridArea.x + root.padding); + return rootPosToThis + hyprlandClient.at[0]; + } + property int mappedY: { + // print("AAAWAWAAWAWWA YYYY YUIUSDFOIU: ", clientRow.y + windowListView.y + root.padding + windowItem.titleBarImplicitHeight) + var rootPosToThis = -(clientRow.y + windowListView.y + root.padding + windowItem.titleBarImplicitHeight); + return rootPosToThis + hyprlandClient.at[1]; + } + property int openedX: 0 + property int openedY: 0 + // property int openedX: Drag.active ? (dragHandler.xAxis.activeValue) : 0 + // property int openedY: Drag.active ? (dragHandler.yAxis.activeValue) : 0 + scaleSize: (root.openProgress > 0 && !closeAnim.running) + x: mappedX + (openedX - mappedX) * root.openProgress + y: mappedY + (openedY - mappedY) * root.openProgress + + droppable: root.hoveredWorkspace !== null + Drag.active: dragHandler.active + Drag.hotSpot.x: mouseX + Drag.hotSpot.y: mouseY + + DragHandler { + id: dragHandler + target: null + xAxis.onActiveValueChanged: { + windowItem.openedX = dragHandler.xAxis.activeValue; + } + yAxis.onActiveValueChanged: { + windowItem.openedY = dragHandler.yAxis.activeValue; + } onActiveChanged: { - if (drag.active) { - parent = root; + if (active) { + root.draggingWindow = true; } else { - parent = clientGridArea; - x = 0; - y = 0; + root.draggingWindow = false; + if (root.hoveredWorkspace !== null && root.hoveredWorkspace.workspace !== windowItem.hyprlandClient.workspace.id) { + Hyprland.dispatch(`movetoworkspacesilent ${root.hoveredWorkspace.workspace}, address:${windowItem.hyprlandClient.address}`); + } else { + windowItem.openedX = 0; + windowItem.openedY = 0; + } } } } + Layout.alignment: Qt.AlignTop maxHeight: root.maxWindowHeight maxWidth: root.maxWindowWidth @@ -148,6 +208,7 @@ Rectangle { // Workspaces Rectangle { id: wsBorder + z: root.openProgress == 1 ? 1 : 2 property real sourceEdgeMargin: -(height + 8) + root.openProgress * (height + 16) anchors { left: parent.left @@ -210,9 +271,29 @@ Rectangle { } } delegate: TaskViewWorkspace { + id: workspaceItem required property int index workspace: index + 1 newWorkspace: index == workspaceIndexModel.count - 1 + + droppable: root.hoveredWorkspace === workspaceItem + DropArea { + anchors.fill: parent + onEntered: drag => { + root.hoveredWorkspace = workspaceItem; + } + onExited: { + if (root.hoveredWorkspace === workspaceItem) { + root.hoveredWorkspace = null; + } + } + } + + onClicked: { + GlobalStates.overviewOpen = false; + root.closed(); // Close immediately to avoid weird animations + Hyprland.dispatch(`workspace ${workspaceItem.workspace}`); + } } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWindow.qml b/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWindow.qml index d8bf4b45b..0cab91fe5 100644 --- a/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWindow.qml +++ b/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWindow.qml @@ -25,47 +25,60 @@ WMouseAreaButton { property string iconName: AppSearch.guessIcon(hyprlandClient?.class) - color: containsMouse ? Looks.colors.bg1Base : Looks.colors.bgPanelFooterBase - borderColor: Looks.colors.bg2Border + color: drag.active ? ColorUtils.transparentize(Looks.colors.bg1Base) : (containsMouse ? Looks.colors.bg1Base : Looks.colors.bgPanelFooterBase) + borderColor: ColorUtils.transparentize(Looks.colors.bg2Border, drag.active ? 1 : 0) radius: Looks.radius.xLarge - property size size: WindowLayout.scaleWindow(hyprlandClient, maxWidth, maxHeight) + property real titleBarImplicitHeight: titleBar.implicitHeight + property bool scaleSize: true + property size openedSize: WindowLayout.scaleWindow(hyprlandClient, maxWidth, maxHeight); + property size fullSize: Qt.size(hyprlandClient?.size[0] ?? maxWidth, hyprlandClient?.size[1] ?? maxHeight) + property size size: scaleSize ? openedSize : fullSize implicitWidth: Math.max(Math.round(contentItem.implicitWidth), 138) implicitHeight: Math.round(contentItem.implicitHeight) layer.enabled: true layer.effect: OpacityMask { - maskSource: Rectangle { + maskSource: Item { width: root.background.width height: root.background.height - radius: root.background.radius + Rectangle { + radius: root.background.radius + anchors { + fill: parent + topMargin: root.drag.active ? root.titleBarImplicitHeight : 0 + } + } } } - scale: (root.pressedButtons & Qt.LeftButton) ? 0.95 : 1 + property bool droppable: false + scale: (root.pressedButtons & Qt.LeftButton || root.Drag.active) ? (droppable ? 0.4 : 0.95) : 1 Behavior on scale { NumberAnimation { id: scaleAnim - duration: 300 + duration: 200 easing.type: Easing.OutExpo } } function closeWindow() { - Hyprland.dispatch(`closewindow address:${root.hyprlandClient?.address}`) + Hyprland.dispatch(`closewindow address:${root.hyprlandClient?.address}`); } acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton - onClicked: (event) => { + onClicked: event => { if (event.button === Qt.LeftButton) { - GlobalStates.overviewOpen = false - Hyprland.dispatch(`focuswindow address:${root.hyprlandClient?.address}`) + GlobalStates.overviewOpen = false; + Hyprland.dispatch(`focuswindow address:${root.hyprlandClient?.address}`); GlobalStates.overviewOpen = false; } else if (event.button === Qt.MiddleButton) { root.closeWindow(); event.accepted = true; } else if (event.button === Qt.RightButton) { - if (!windowMenu.visible) windowMenu.popup(); - else windowMenu.close(); + if (!windowMenu.visible) + windowMenu.popup(); + else + windowMenu.close(); } } @@ -77,6 +90,8 @@ WMouseAreaButton { spacing: 0 RowLayout { + id: titleBar + opacity: root.drag.active ? 0 : 1 spacing: 8 WAppIcon { Layout.leftMargin: 10 @@ -104,6 +119,14 @@ WMouseAreaButton { Layout.alignment: Qt.AlignHCenter implicitWidth: Math.round(root.size.width) implicitHeight: Math.round(root.size.height) + constraintSize: Qt.size(Math.round(root.size.width), Math.round(root.size.height)) + + Behavior on implicitWidth { + animation: Looks.transition.enter.createObject(this) + } + Behavior on implicitHeight { + animation: Looks.transition.enter.createObject(this) + } captureSource: root.toplevel ?? null live: true @@ -120,7 +143,7 @@ WMouseAreaButton { icon.name: isPinned ? "checkmark" : "empty" text: Translation.tr("Show this window on all desktops") onTriggered: { - Hyprland.dispatch(`pin address:${root.hyprlandClient?.address}`) + Hyprland.dispatch(`pin address:${root.hyprlandClient?.address}`); } } Action { diff --git a/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWorkspace.qml b/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWorkspace.qml index 56451a4e7..8fe3f35bd 100644 --- a/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWorkspace.qml +++ b/dots/.config/quickshell/ii/modules/waffle/taskView/TaskViewWorkspace.qml @@ -16,6 +16,7 @@ WMouseAreaButton { required property int workspace property bool newWorkspace: false + property bool droppable: false readonly property bool isActiveWorkspace: HyprlandData.activeWorkspace?.id === root.workspace readonly property real screenWidth: QsWindow.window?.width ?? 0 @@ -28,12 +29,7 @@ WMouseAreaButton { height: ListView.view?.height ?? 100 implicitWidth: 244 // for now - onClicked: { - GlobalStates.overviewOpen = false; - Hyprland.dispatch(`workspace ${root.workspace}`); - } - - colBackground: ColorUtils.transparentize(Looks.colors.bg2, isActiveWorkspace ? 0 : 1) + colBackground: ColorUtils.transparentize(Looks.colors.bg2, (isActiveWorkspace || droppable) ? 0 : 1) Behavior on color { animation: Looks.transition.color.createObject(this) } @@ -119,6 +115,14 @@ WMouseAreaButton { icon: "add" } } + + Rectangle { + z: 2 + visible: root.droppable && !root.newWorkspace + anchors.fill: parent + color: Looks.colors.accent + opacity: 0.2 + } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/taskView/WaffleTaskView.qml b/dots/.config/quickshell/ii/modules/waffle/taskView/WaffleTaskView.qml index 75e71ccb1..fc145f221 100644 --- a/dots/.config/quickshell/ii/modules/waffle/taskView/WaffleTaskView.qml +++ b/dots/.config/quickshell/ii/modules/waffle/taskView/WaffleTaskView.qml @@ -23,7 +23,14 @@ Scope { Loader { id: panelLoader required property var modelData - active: GlobalStates.overviewOpen + active: false + Connections { + target: GlobalStates + function onOverviewOpenChanged() { + if (GlobalStates.overviewOpen) + panelLoader.active = true; + } + } sourceComponent: PanelWindow { id: root property string searchingText: "" @@ -44,7 +51,16 @@ Scope { } TaskViewContent { + id: taskViewContent anchors.fill: parent + + Connections { + target: GlobalStates + function onOverviewOpenChanged() { + if (!GlobalStates.overviewOpen) taskViewContent.close(); + } + } + onClosed: panelLoader.active = false; } } } diff --git a/dots/.config/quickshell/ii/services/HyprlandData.qml b/dots/.config/quickshell/ii/services/HyprlandData.qml index 7bb437c84..5ec7bd68d 100644 --- a/dots/.config/quickshell/ii/services/HyprlandData.qml +++ b/dots/.config/quickshell/ii/services/HyprlandData.qml @@ -88,6 +88,7 @@ Singleton { function onRawEvent(event) { // console.log("Hyprland raw event:", event.name); + if (["openlayer", "closelayer", "screencast"].includes(event.name)) return; updateAll() } }