fixed tray + media popouts
This commit is contained in:
@@ -52,6 +52,7 @@ BarPill {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: false
|
visible: false
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
layer.smooth: true
|
||||||
preferredRendererType: Shape.CurveRenderer
|
preferredRendererType: Shape.CurveRenderer
|
||||||
ShapePath {
|
ShapePath {
|
||||||
fillColor: "white"
|
fillColor: "white"
|
||||||
@@ -71,6 +72,7 @@ BarPill {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
visible: status === Image.Ready
|
visible: status === Image.Ready
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
layer.smooth: true
|
||||||
layer.effect: MaskedArt { maskItem: artMask }
|
layer.effect: MaskedArt { maskItem: artMask }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,14 @@ MultiEffect {
|
|||||||
|
|
||||||
maskEnabled: maskItem !== null
|
maskEnabled: maskItem !== null
|
||||||
maskSource: maskItem
|
maskSource: maskItem
|
||||||
// Hard edge — the chopped corners should read as cuts, not fades.
|
|
||||||
|
// The chopped corners should read as cuts, not fades — but a spread of 0
|
||||||
|
// is a hard `alpha < 0.5 ? 0 : 1` step, which throws away the one thing
|
||||||
|
// that makes the cut look drawn rather than pixelated: the mask Shape's own
|
||||||
|
// coverage antialiasing. Every partially covered pixel along a diagonal got
|
||||||
|
// rounded to all-or-nothing and the art came out with a visible staircase
|
||||||
|
// down both leaning edges. A narrow spread lets that single-pixel ramp
|
||||||
|
// through and nothing wider — still a cut, just not a jagged one.
|
||||||
maskThresholdMin: 0.5
|
maskThresholdMin: 0.5
|
||||||
maskSpreadAtMin: 0.0
|
maskSpreadAtMin: 0.3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
import "root:/config"
|
import "root:/config"
|
||||||
|
|
||||||
// Hover-driven panel that hangs off a bar item. Opens on a short dwell, stays
|
// Hover-driven panel that hangs off a bar item. Opens on a short dwell, stays
|
||||||
@@ -70,6 +71,31 @@ PopupWindow {
|
|||||||
onTriggered: root.open()
|
onTriggered: root.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A pinned popout ignores hover by design, which left it with exactly one
|
||||||
|
// way out: another click on the same bar item that opened it. Moving the
|
||||||
|
// pointer away did nothing, so a panel opened by a click — the notification
|
||||||
|
// history, most often — simply stayed on screen. Click anywhere else and
|
||||||
|
// the compositor drops the grab, which unpins it and hands it back to the
|
||||||
|
// hover rules.
|
||||||
|
//
|
||||||
|
// The grab can only take hold once the surface is mapped; asked for in the
|
||||||
|
// same tick as `shown`, Hyprland clears it immediately.
|
||||||
|
Timer {
|
||||||
|
id: grabDelay
|
||||||
|
interval: 60
|
||||||
|
running: root.pinned && root.shown
|
||||||
|
}
|
||||||
|
|
||||||
|
HyprlandFocusGrab {
|
||||||
|
active: root.pinned && root.shown && !grabDelay.running
|
||||||
|
windows: [root]
|
||||||
|
|
||||||
|
// A click on the trigger itself also clears the grab, but that click is
|
||||||
|
// the pill's own toggle — unpinning here as well would cancel it out and
|
||||||
|
// the panel would never close from its own button.
|
||||||
|
onCleared: if (!root.triggerHovered) root.pinned = false
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: hideTimer
|
id: hideTimer
|
||||||
interval: root.hideDelay
|
interval: root.hideDelay
|
||||||
@@ -109,8 +135,14 @@ PopupWindow {
|
|||||||
// The handler has to live on the content item, not the window: a
|
// The handler has to live on the content item, not the window: a
|
||||||
// HoverHandler parented to the PopupWindow itself latches on and the
|
// HoverHandler parented to the PopupWindow itself latches on and the
|
||||||
// panel never learns the pointer left.
|
// panel never learns the pointer left.
|
||||||
|
//
|
||||||
|
// Disabled while the popout is down, which clears `hovered`. An unmapped
|
||||||
|
// surface gets no leave event, so a handler that was hovered when the
|
||||||
|
// window went away stayed hovered — `wantsOpen` never went false again
|
||||||
|
// and the panel came back up and refused to close.
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
id: panelHover
|
id: panelHover
|
||||||
|
enabled: root.shown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ Popout {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: false
|
visible: false
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
// Without this the mask texture is point-sampled, so the
|
||||||
|
// antialiased pixels along the cuts get snapped back to hard
|
||||||
|
// steps before MultiEffect ever sees them — see MaskedArt.
|
||||||
|
layer.smooth: true
|
||||||
preferredRendererType: Shape.CurveRenderer
|
preferredRendererType: Shape.CurveRenderer
|
||||||
ShapePath {
|
ShapePath {
|
||||||
fillColor: "white"
|
fillColor: "white"
|
||||||
@@ -65,6 +69,7 @@ Popout {
|
|||||||
cache: true
|
cache: true
|
||||||
visible: status === Image.Ready
|
visible: status === Image.Ready
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
|
layer.smooth: true
|
||||||
layer.effect: MaskedArt { maskItem: artMask }
|
layer.effect: MaskedArt { maskItem: artMask }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -226,6 +226,24 @@ Column {
|
|||||||
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutExpo }
|
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutExpo }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The guide rule down the side of an expanded submenu.
|
||||||
|
//
|
||||||
|
// Same trap the separators hit, from the other direction: the
|
||||||
|
// house lean is a fraction of *height*, and this rule is as tall
|
||||||
|
// as the submenu. A Wi-Fi list of thirty networks made it 600px
|
||||||
|
// tall, which sheared a 1px hairline into a 150px crimson wedge
|
||||||
|
// lying across every entry in the list. The rise is pinned in
|
||||||
|
// pixels, and it is declared before the entries so it can never
|
||||||
|
// paint over them again.
|
||||||
|
Skew {
|
||||||
|
x: Theme.padS
|
||||||
|
width: 1
|
||||||
|
height: parent.height
|
||||||
|
lean: height > 0 ? 5 / height : 0
|
||||||
|
visible: row.expanded
|
||||||
|
color: Theme.alpha(Theme.accent, 0.8)
|
||||||
|
}
|
||||||
|
|
||||||
// Loaded by URL rather than as an inline component: QML rejects
|
// Loaded by URL rather than as an inline component: QML rejects
|
||||||
// a type that instantiates itself, even lazily, and a menu tree
|
// a type that instantiates itself, even lazily, and a menu tree
|
||||||
// is the one place recursion is the natural shape.
|
// is the one place recursion is the natural shape.
|
||||||
@@ -249,13 +267,6 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Skew {
|
|
||||||
x: Theme.padS
|
|
||||||
width: 1
|
|
||||||
height: parent.height
|
|
||||||
visible: row.expanded
|
|
||||||
color: Theme.alpha(Theme.accent, 0.8)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user