From e8ff5b35521bd3d7dbfdf5919ed368b303d512cd Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Thu, 12 Nov 2026 10:55:28 -0500 Subject: [PATCH] feat(scripts): add workspace master layout toggle helper --- dot_local/bin/executable_omarchy-pip | 70 ------------------ dot_local/bin/executable_omarchy-summon | 55 -------------- .../bin/executable_omarchy-toggle-master | 72 +++++++++++++++++++ 3 files changed, 72 insertions(+), 125 deletions(-) delete mode 100755 dot_local/bin/executable_omarchy-pip delete mode 100755 dot_local/bin/executable_omarchy-summon create mode 100755 dot_local/bin/executable_omarchy-toggle-master diff --git a/dot_local/bin/executable_omarchy-pip b/dot_local/bin/executable_omarchy-pip deleted file mode 100755 index 00b7ca1..0000000 --- a/dot_local/bin/executable_omarchy-pip +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash - -# omarchy:summary=Toggle a window between picture-in-picture (floating, pinned, bottom-left corner of the focused monitor) and tiled. -# omarchy:args=[toggle|on] [address:0x...] - -set -uo pipefail - -# Usage: omarchy-pip [toggle|on] [address:0x...] -# -# "on" always fits the window: float, pin, resize to FRACTION of the focused -# monitor on both axes and park it in the bottom-left corner, inset by GAP. -# "toggle" (the default) does that unless the window is already floating and -# pinned, in which case it unpins and tiles it again. The window defaults to -# the active one. omarchy-summon calls "on" after carrying its window to the -# focused monitor; the YouTube window rule in hypr/hyprland.lua mirrors the -# same fraction and inset for the first open, so keep the three in sync. -MODE=${1:-toggle} -WINDOW=${2:-} -case $MODE in -toggle | on) ;; -*) - echo "usage: ${0##*/} [toggle|on] [address:0x...]" >&2 - exit 2 - ;; -esac - -FRACTION=0.3 -# Matches general:gaps_out so the window lines up with tiled neighbours and -# its border stays on screen. -GAP=10 - -# Lua dispatcher first, classic name as the pre-lua fallback (same shape as -# the other omarchy-* scripts here). -hypr_dispatch() { - local lua="$1" - shift - hyprctl dispatch "$lua" >/dev/null 2>&1 || hyprctl dispatch "$@" >/dev/null -} - -if [[ -z $WINDOW ]]; then - ACTIVE=$(hyprctl activewindow -j 2>/dev/null) - [[ -n $ACTIVE && $ACTIVE != "{}" ]] || exit 0 - WINDOW="address:$(jq -r '.address' <<<"$ACTIVE")" -else - ACTIVE=$(hyprctl clients -j | jq -c --arg a "${WINDOW#address:}" 'first(.[] | select(.address == $a)) // empty') - [[ -n $ACTIVE ]] || exit 1 -fi - -# The wiki documents action = "set", but on Hyprland 0.56 "set" toggles; -# "on" / "off" are what the dispatcher actually honours. -if [[ $MODE == toggle ]] && [[ $(jq -r '.floating and .pinned' <<<"$ACTIVE") == true ]]; then - hypr_dispatch "hl.dsp.window.pin({ action = \"off\", window = \"$WINDOW\" })" pin "$WINDOW" - hypr_dispatch "hl.dsp.window.float({ action = \"off\", window = \"$WINDOW\" })" settiled "$WINDOW" - exit 0 -fi - -# Focused monitor: origin and logical size. -read -r MON_X MON_Y MON_W MON_H < <(hyprctl monitors -j | - jq -r '.[] | select(.focused) | "\(.x) \(.y) \(((.width / .scale) | floor)) \(((.height / .scale) | floor))"') -[[ -n ${MON_H:-} ]] || exit 1 - -WIDTH=$(awk "BEGIN { printf \"%d\", $MON_W * $FRACTION }") -HEIGHT=$(awk "BEGIN { printf \"%d\", $MON_H * $FRACTION }") -X=$((MON_X + GAP)) -Y=$((MON_Y + MON_H - HEIGHT - GAP)) - -hypr_dispatch "hl.dsp.window.float({ action = \"on\", window = \"$WINDOW\" })" setfloating "$WINDOW" -hypr_dispatch "hl.dsp.window.pin({ action = \"on\", window = \"$WINDOW\" })" pin "$WINDOW" -hypr_dispatch "hl.dsp.window.resize({ x = $WIDTH, y = $HEIGHT, window = \"$WINDOW\" })" resizewindowpixel "exact $WIDTH $HEIGHT,$WINDOW" -hypr_dispatch "hl.dsp.window.move({ x = $X, y = $Y, window = \"$WINDOW\" })" movewindowpixel "exact $X $Y,$WINDOW" diff --git a/dot_local/bin/executable_omarchy-summon b/dot_local/bin/executable_omarchy-summon deleted file mode 100755 index 7a17bb4..0000000 --- a/dot_local/bin/executable_omarchy-summon +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -# omarchy:summary=Launch a floating pinned app (youtube) or bring its window to the focused monitor's bottom-left corner. - -set -uo pipefail - -# Usage: omarchy-summon [youtube] -# -# Each profile is one app kept as a picture-in-picture window: the window -# rule in hypr/hyprland.lua floats, pins, sizes and parks it when it first -# opens, so a plain launch is enough when no window exists. When one does, -# this script carries it to the focused monitor and hands it to omarchy-pip -# to fit it there again: the two panels differ in logical size, and Hyprland -# keeps a floating window's pixel size and offset across a monitor move. -# -# PATTERN is an ERE over the window class. A web app's picture-in-picture -# overlay shares the class, so windows titled Picture-in-Picture are skipped -# (Omarchy's own pip rule owns those). -case ${1:-youtube} in -youtube) - # Chromium derives the class from the app URL, and the same web app has - # shown up under more than one host spelling (youtube.com vs - # www.youtube.com) once a video is playing, so match the family. - PATTERN='^brave-(www\.)?youtube\.com__.*$' - LAUNCH="gtk-launch YouTube" - ;; -*) - echo "usage: ${0##*/} [youtube]" >&2 - exit 2 - ;; -esac - -# Lua dispatcher first, classic name as the pre-lua fallback (same shape as -# the other omarchy-* scripts here). -hypr_dispatch() { - local lua="$1" - shift - hyprctl dispatch "$lua" >/dev/null 2>&1 || hyprctl dispatch "$@" >/dev/null -} - -ADDRESS=$(hyprctl clients -j | jq -r --arg re "$PATTERN" ' - first(.[] | select((.class | test($re)) and ((.title | test("Picture.?in.?[Pp]icture")) | not))) - | .address // empty') - -if [[ -z $ADDRESS ]]; then - exec setsid uwsm-app -- $LAUNCH >/dev/null 2>&1 -fi - -WINDOW="address:$ADDRESS" -MON_NAME=$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name') -[[ -n $MON_NAME ]] || exit 1 - -hypr_dispatch "hl.dsp.window.move({ monitor = \"$MON_NAME\", window = \"$WINDOW\" })" movewindow "mon:$MON_NAME,$WINDOW" -omarchy-pip on "$WINDOW" -hypr_dispatch "hl.dsp.focus({ window = \"$WINDOW\" })" focuswindow "$WINDOW" diff --git a/dot_local/bin/executable_omarchy-toggle-master b/dot_local/bin/executable_omarchy-toggle-master new file mode 100755 index 0000000..eecf5d8 --- /dev/null +++ b/dot_local/bin/executable_omarchy-toggle-master @@ -0,0 +1,72 @@ +#!/bin/bash + +# omarchy:summary=Toggle the active workspace between the master layout and the layout it had before + +set -uo pipefail + +# Usage: omarchy-toggle-master +# +# Goes through Omarchy's o.workspace_mode and its saved-mode files, like +# omarchy-hyprland-workspace-layout-toggle (SUPER + W), so the layout survives +# a reload or login and the two keys agree on what the workspace is: SUPER + W +# on a master workspace cycles on to dwindle. The layout master replaced is +# kept under STATE_DIR and restored by the next press; without one, the +# workspace goes back to the default layout. Named workspaces are skipped for +# the same reason Omarchy skips them: their negative id is read as a relative +# selector. + +STATE="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy" +MODES_DIR="$STATE/workspace-layouts" +STATE_DIR="$STATE/master-toggle" + +# Same replace-in-place notification as Omarchy's layout toggle, sharing its +# id file, so switching with either key leaves one current notification. +notify_layout() { + local state="$STATE/workspace-layout-notification" + local last id + [[ -r $state ]] && read -r last <"$state" + if id=$(omarchy-notification-send -p -r "${last:-0}" -g $'\U000f10ac' "$1") && [[ $id =~ ^[0-9]+$ ]]; then + mkdir -p "$(dirname "$state")" && printf '%s\n' "$id" >"$state" + fi +} + +WORKSPACE=$(hyprctl activeworkspace -j | jq -r '.id') +[[ $WORKSPACE =~ ^[0-9]+$ ]] || exit 1 +MODE_FILE="$MODES_DIR/$WORKSPACE.lua" +PREVIOUS_FILE="$STATE_DIR/$WORKSPACE" + +CURRENT=$(omarchy-hyprland-workspace-layout-current) +DEFAULT=$(omarchy-hyprland-workspace-layout-default) + +if [[ $CURRENT == master ]]; then + NEW=$(cat "$PREVIOUS_FILE" 2>/dev/null) + [[ $NEW =~ ^(dwindle|scrolling|floating)$ ]] || NEW=$DEFAULT +else + NEW=master +fi + +APPLY="o.workspace_mode({ workspace = \"$WORKSPACE\", mode = \"$NEW\" })" +if ! hyprctl eval "$APPLY" >/dev/null 2>&1; then + notify_layout "$(omarchy-i18n layout.needsReload)" + exit 1 +fi + +if [[ $NEW == master ]]; then + mkdir -p "$STATE_DIR" && printf '%s\n' "$CURRENT" >"$PREVIOUS_FILE" + # A layout change fires no event, so Ghostty is made the master here + # (hypr/master.lua). + hyprctl eval 'require("hypr.master").enforce()' >/dev/null +else + rm -f "$PREVIOUS_FILE" +fi + +# Back on the default, the workspace follows it again (as Omarchy does). +if [[ $NEW == "$DEFAULT" ]]; then + rm -f "$MODE_FILE" +else + mkdir -p "$MODES_DIR" && printf '%s\n' "$APPLY" >"$MODE_FILE" +fi + +notify_layout "Workspace layout: $NEW" +omarchy-shell -q omarchy.workspaces refresh +omarchy-shell -q omarchy.dock refresh