aboutsummaryrefslogtreecommitdiffstats
path: root/window-switcher/WindowCard.qml
diff options
context:
space:
mode:
Diffstat (limited to 'window-switcher/WindowCard.qml')
-rw-r--r--window-switcher/WindowCard.qml135
1 files changed, 67 insertions, 68 deletions
diff --git a/window-switcher/WindowCard.qml b/window-switcher/WindowCard.qml
index b671f0f..177aac9 100644
--- a/window-switcher/WindowCard.qml
+++ b/window-switcher/WindowCard.qml
@@ -14,12 +14,13 @@ import Quickshell.Wayland
import Quickshell.Widgets
import QtQuick
-Column {
+// One window in the expose: a live preview sized from outside to its rect in
+// the scatter. App icon and workspace marker are always shown; title and
+// close only on hover, so the scatter stays clean.
+Item {
id: card
required property var toplevel
- property bool selected: false
- property int cardWidth: 380
signal activated()
signal closeRequested()
@@ -37,34 +38,29 @@ Column {
return name !== "" ? Quickshell.iconPath(name, true) : "";
}
- width: cardWidth
- spacing: 8
+ HoverHandler { id: cardHover }
- // A fixed 16:10 box with the preview fitted inside it. The previews are
- // not one shape: DP-1 windows are near 21:9 and DP-3 is rotated, so its
- // windows are portrait. Sizing each card to its own preview would give
- // ragged rows and break the alignment of the text lines below.
Rectangle {
id: box
- width: card.cardWidth
- height: Math.round(card.cardWidth * 10 / 16)
+ anchors.fill: parent
radius: 10
color: Theme.surface
- border.color: card.selected ? Theme.accent : Theme.surfaceAlt
- border.width: card.selected ? 3 : 1
+ border.color: cardHover.hovered ? Theme.accent : Theme.surfaceAlt
+ border.width: cardHover.hovered ? 3 : 1
+ // The rect already has the window's shape, so the preview fills it.
+ // The fit is kept for the moment before a capture lands: an
+ // uncaptured view reports sourceSize (-1, -1) rather than (0, 0), so
+ // this tests for a positive height, falling back to the box's ratio.
ScreencopyView {
id: preview
anchors.centerIn: parent
captureSource: card.wl
live: true
- // An uncaptured view reports sourceSize (-1, -1) rather than
- // (0, 0), so this tests for a positive height rather than a
- // non-zero one, and falls back to the box's own ratio.
readonly property real ar: sourceSize.height > 0
? sourceSize.width / sourceSize.height
- : 16 / 10
+ : parent.width / Math.max(1, parent.height)
width: Math.min(parent.width - 8, (parent.height - 8) * ar)
height: Math.min(parent.height - 8, (parent.width - 8) / ar)
}
@@ -74,24 +70,53 @@ Column {
onClicked: card.activated()
}
- // Both corner overlays sit on an arbitrary window preview, so each
- // carries its own scrim: a themed icon can otherwise land on a
- // same-coloured region and vanish, a light icon on a white page being
- // the obvious case.
- Rectangle {
+ // Every overlay sits on an arbitrary window preview, so each carries
+ // its own scrim: a themed icon can otherwise land on a same-coloured
+ // region and vanish, a light icon on a white page being the obvious
+ // case.
+ Row {
anchors { left: parent.left; top: parent.top; margins: 8 }
- width: 34; height: 34; radius: 8
- color: Qt.rgba(Theme.base.r, Theme.base.g, Theme.base.b, 0.75)
+ spacing: 6
- IconImage {
- anchors.centerIn: parent
- width: 24; height: 24
- source: Quickshell.iconPath(card.wl ? card.wl.appId : "", true)
+ Rectangle {
+ width: 34; height: 34; radius: 8
+ color: Qt.rgba(Theme.base.r, Theme.base.g, Theme.base.b, 0.75)
+
+ IconImage {
+ anchors.centerIn: parent
+ width: 24; height: 24
+ source: Quickshell.iconPath(card.wl ? card.wl.appId : "", true)
+ }
+ }
+
+ // The desktop marker, drawn with the workspace icon rather than
+ // the number. A workspace with no icon keeps the name, so the
+ // marker never goes blank.
+ Rectangle {
+ width: Math.max(34, wsName.implicitWidth + 12); height: 34; radius: 8
+ color: Qt.rgba(Theme.base.r, Theme.base.g, Theme.base.b, 0.75)
+
+ IconImage {
+ anchors.centerIn: parent
+ width: 22; height: 22
+ source: card.workspaceIconPath
+ }
+
+ Text {
+ id: wsName
+ anchors.centerIn: parent
+ visible: card.workspaceIconPath === ""
+ text: card.toplevel.workspace ? card.toplevel.workspace.name : "?"
+ color: Theme.accent
+ font.family: Theme.fontFamily
+ font.pixelSize: 13
+ }
}
}
Rectangle {
id: closeButton
+ visible: cardHover.hovered
anchors { right: parent.right; top: parent.top; margins: 8 }
width: 34; height: 34; radius: 17
color: closeArea.pressed
@@ -114,48 +139,22 @@ Column {
onClicked: card.closeRequested()
}
}
- }
-
- Text {
- width: parent.width
- horizontalAlignment: Text.AlignHCenter
- elide: Text.ElideRight
- text: card.wl ? card.wl.appId : ""
- color: Theme.text
- font.family: Theme.fontFamily
- font.pixelSize: 16
- font.bold: true
- }
- Text {
- width: parent.width
- elide: Text.ElideRight
- text: card.toplevel.title
- color: Theme.subtext
- font.family: Theme.fontFamily
- font.pixelSize: 13
- }
-
- // The desktop marker, drawn with waybar's workspace icon rather than the
- // number. A workspace with no icon keeps the number, so the line never
- // goes blank.
- Item {
- width: card.width
- height: 24
-
- IconImage {
- anchors.centerIn: parent
- width: 22; height: 22
- source: card.workspaceIconPath
- }
+ Rectangle {
+ visible: cardHover.hovered
+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom; margins: 8 }
+ height: 30; radius: 8
+ color: Qt.rgba(Theme.base.r, Theme.base.g, Theme.base.b, 0.75)
- Text {
- anchors.centerIn: parent
- visible: card.workspaceIconPath === ""
- text: "[" + (card.toplevel.workspace ? card.toplevel.workspace.name : "?") + "]"
- color: Theme.accent
- font.family: Theme.fontFamily
- font.pixelSize: 13
+ Text {
+ anchors { fill: parent; leftMargin: 10; rightMargin: 10 }
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ text: card.toplevel.title
+ color: Theme.text
+ font.family: Theme.fontFamily
+ font.pixelSize: 13
+ }
}
}
}