diff --git a/settings/quickshell.nix b/settings/quickshell.nix index 9353bd3..2cd4120 100644 --- a/settings/quickshell.nix +++ b/settings/quickshell.nix @@ -214,14 +214,16 @@ in visible = false; } - // Power actions go through Hyprland's exec dispatcher so they - // are NOT children of quickshell — a quickshell restart must - // never kill a running hyprlock. + // Lock/reboot/shutdown spawn via Quickshell.execDetached — fully + // detached, so a quickshell restart can never kill a running + // hyprlock. Logout (empty cmd) goes through Hyprland IPC; with a + // Lua config the dispatch body is evaluated as a Lua dispatcher + // expression, so it must use hl.dsp.* syntax, not hyprlang's. readonly property var powerActions: [ - { name: "Lock", glyph: "", dispatch: "exec " + Commands.hyprlock }, - { name: "Logout", glyph: "", dispatch: "exit" }, - { name: "Reboot", glyph: "", dispatch: "exec " + Commands.systemctl + " reboot" }, - { name: "Shutdown", glyph: "", dispatch: "exec " + Commands.systemctl + " poweroff" } + { name: "Lock", glyph: "", cmd: [Commands.hyprlock] }, + { name: "Logout", glyph: "", cmd: [] }, + { name: "Reboot", glyph: "", cmd: [Commands.systemctl, "reboot"] }, + { name: "Shutdown", glyph: "", cmd: [Commands.systemctl, "poweroff"] } ] function score(name, extra, q) { @@ -255,7 +257,8 @@ in function activate(item) { if (!item) return; if (mode === "power") { - Hyprland.dispatch(item.dispatch); + if (item.cmd.length === 0) Hyprland.dispatch("hl.dsp.exit()"); + else Quickshell.execDetached(item.cmd); } else { item.execute(); } @@ -469,8 +472,11 @@ in // Bar bottom border — left segment (up to gap) Rectangle { id: barBorderLeft - x: 0; y: 30 - width: bar.hasGap ? bar.gapLeft : bar.width + // Inset (inside the bar) so it lines up with the inset ear + // and dropdown borders; overlaps 8px into the gap to meet + // the ear curve's tapered start. + x: 0; y: 30 - Theme.borderWidth + width: bar.hasGap ? bar.gapLeft + 8 : bar.width height: Theme.borderWidth color: Theme.base03 } @@ -479,8 +485,8 @@ in Rectangle { id: barBorderRight visible: bar.hasGap && !bar.gapAlignRight - x: bar.gapRight - y: 30 + x: bar.gapRight - 8 + y: 30 - Theme.borderWidth width: bar.width - x height: Theme.borderWidth color: Theme.base03 @@ -1135,8 +1141,9 @@ in ctx.strokeStyle = Theme.base03; ctx.lineWidth = b; ctx.beginPath(); - // Start below the top ear, go down left side - ctx.moveTo(o, r); + // Start just under the bar — the ear band tapers + // through the first few px and this fills behind it + ctx.moveTo(o, b); ctx.lineTo(o, h - r); // Bottom-left curve — arc centered on the corner circle so // the stroke's outer edge matches the bg corner exactly @@ -1149,8 +1156,8 @@ in ctx.lineTo(w - r - o, h - o); // Bottom-right curve ctx.arc(w - r, h - r, r - o, Math.PI / 2, 0, true); - // Right side up (stop at ear height) - ctx.lineTo(w - o, r); + // Right side up to just under the bar + ctx.lineTo(w - o, b); } ctx.stroke(); } @@ -2435,12 +2442,12 @@ in ctx.strokeStyle = Theme.base03; ctx.lineWidth = b; ctx.beginPath(); - ctx.moveTo(o, r); + ctx.moveTo(o, b); ctx.lineTo(o, h - r); ctx.arc(r, h - r, r - o, Math.PI, Math.PI / 2, true); ctx.lineTo(w - r - o, h - o); ctx.arc(w - r, h - r, r - o, Math.PI / 2, 0, true); - ctx.lineTo(w - o, r); + ctx.lineTo(w - o, b); ctx.stroke(); } onWidthChanged: requestPaint()