diff --git a/bin/omarchy b/bin/omarchy index d4fd2570..c23a6457 100755 --- a/bin/omarchy +++ b/bin/omarchy @@ -29,6 +29,7 @@ declare -A GROUP_DESCRIPTIONS GROUP_DESCRIPTIONS[ac]="AC power detection" GROUP_DESCRIPTIONS[battery]="Battery status helpers" GROUP_DESCRIPTIONS[branch]="Omarchy git branch management" +GROUP_DESCRIPTIONS[branding]="About and screensaver branding" GROUP_DESCRIPTIONS[brightness]="Display and keyboard brightness" GROUP_DESCRIPTIONS[capture]="Screenshots and screen recording" GROUP_DESCRIPTIONS[channel]="Omarchy release channel management" @@ -54,6 +55,7 @@ GROUP_DESCRIPTIONS[plymouth]="Plymouth boot theme management" GROUP_DESCRIPTIONS[powerprofiles]="Power profile management" GROUP_DESCRIPTIONS[refresh]="Reset config to defaults" GROUP_DESCRIPTIONS[reinstall]="Reinstall and reset workflows" +GROUP_DESCRIPTIONS[reminder]="Desktop notification reminders" GROUP_DESCRIPTIONS[remove]="Removal workflows" GROUP_DESCRIPTIONS[restart]="Restart Omarchy components" GROUP_DESCRIPTIONS[setup]="Interactive setup wizards" diff --git a/bin/omarchy-branding-about b/bin/omarchy-branding-about new file mode 100755 index 00000000..aca234de --- /dev/null +++ b/bin/omarchy-branding-about @@ -0,0 +1,28 @@ +#!/bin/bash + +# omarchy:summary=Edit, set, or reset About branding +# omarchy:group=branding +# omarchy:name=about +# omarchy:args= +# omarchy:examples=omarchy branding about image | omarchy branding about text | omarchy branding about reset + +set -euo pipefail + +case "${1:-}" in +image) + image=$(omarchy-menu-file "Logo image" "$HOME" "svg png") + if [[ -n $image ]] && omarchy-transcode-ascii "$image" ~/.config/omarchy/branding/about.txt --width 54 --height 26 --mode block; then + omarchy-launch-about >/dev/null 2>&1 + fi + ;; +text) + omarchy-launch-editor ~/.config/omarchy/branding/about.txt >/dev/null 2>&1 && omarchy-launch-about >/dev/null 2>&1 + ;; +reset) + cp "$OMARCHY_PATH/icon.txt" ~/.config/omarchy/branding/about.txt && omarchy-launch-about >/dev/null 2>&1 + ;; +*) + echo "Usage: omarchy-branding-about " >&2 + exit 1 + ;; +esac diff --git a/bin/omarchy-branding-screensaver b/bin/omarchy-branding-screensaver new file mode 100755 index 00000000..57012af8 --- /dev/null +++ b/bin/omarchy-branding-screensaver @@ -0,0 +1,28 @@ +#!/bin/bash + +# omarchy:summary=Edit, set, or reset screensaver branding +# omarchy:group=branding +# omarchy:name=screensaver +# omarchy:args= +# omarchy:examples=omarchy branding screensaver image | omarchy branding screensaver text | omarchy branding screensaver reset + +set -euo pipefail + +case "${1:-}" in +image) + image=$(omarchy-menu-file "Logo image" "$HOME" "svg png") + if [[ -n $image ]] && omarchy-transcode-ascii "$image" ~/.config/omarchy/branding/screensaver.txt; then + omarchy-launch-screensaver force >/dev/null 2>&1 + fi + ;; +text) + omarchy-launch-editor ~/.config/omarchy/branding/screensaver.txt >/dev/null 2>&1 && omarchy-launch-screensaver force >/dev/null 2>&1 + ;; +reset) + cp "$OMARCHY_PATH/logo.txt" ~/.config/omarchy/branding/screensaver.txt && omarchy-launch-screensaver force >/dev/null 2>&1 + ;; +*) + echo "Usage: omarchy-branding-screensaver " >&2 + exit 1 + ;; +esac diff --git a/bin/omarchy-first-run b/bin/omarchy-first-run index 6ad54141..023d1a65 100755 --- a/bin/omarchy-first-run +++ b/bin/omarchy-first-run @@ -16,6 +16,7 @@ if [[ -f $FIRST_RUN_MODE ]]; then bash "$OMARCHY_PATH/install/first-run/firewall.sh" bash "$OMARCHY_PATH/install/first-run/dns-resolver.sh" bash "$OMARCHY_PATH/install/first-run/gnome-theme.sh" + bash "$OMARCHY_PATH/install/first-run/swayosd.sh" bash "$OMARCHY_PATH/install/first-run/gtk-primary-paste.sh" bash "$OMARCHY_PATH/install/first-run/elephant.sh" omarchy-hook-install post-update "$OMARCHY_PATH/install/first-run/install-voxtype.hook" diff --git a/bin/omarchy-haptic-touchpad b/bin/omarchy-haptic-touchpad deleted file mode 100755 index a98bd90a..00000000 --- a/bin/omarchy-haptic-touchpad +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python3 - -# omarchy:summary=Run the Synaptics touchpad haptic feedback daemon - -"""Haptic feedback daemon for Synaptics touchpads with Manual Trigger. - -Monitors touchpad button press events and sends haptic pulses via HID -feature reports. Required because the kernel's HID haptic subsystem only -supports Auto Trigger with waveform enumeration, not the simpler Manual -Trigger protocol used by these Synaptics touchpads. -""" - -import fcntl, glob, os, struct, sys - -VENDOR = "06CB" -REPORT_ID = 0x37 -INTENSITY = 40 # 0-100 - -# input_event: struct timeval (16 bytes on 64-bit) + type(H) + code(H) + value(i) -EVENT_FORMAT = "llHHi" -EVENT_SIZE = struct.calcsize(EVENT_FORMAT) -EV_KEY = 0x01 -BTN_LEFT = 272 -BTN_RIGHT = 273 -BTN_MIDDLE = 274 - -# ioctl: HIDIOCSFEATURE(len) = _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) -def HIDIOCSFEATURE(length): - return 0xC0000000 | (length << 16) | (ord("H") << 8) | 0x06 - - -def find_hidraw(): - for path in sorted(glob.glob("/sys/class/hidraw/hidraw*")): - uevent = os.path.join(path, "device", "uevent") - try: - with open(uevent) as f: - content = f.read().upper() - if f"0000{VENDOR}" in content: - return os.path.join("/dev", os.path.basename(path)) - except OSError: - continue - return None - - -def find_touchpad_event(): - for path in sorted(glob.glob("/sys/class/input/event*/device/name")): - try: - with open(path) as f: - name = f.read().strip().upper() - if VENDOR in name and "TOUCHPAD" in name: - event = path.split("/")[-3] - return os.path.join("/dev/input", event) - except OSError: - continue - return None - - -def main(): - hidraw = find_hidraw() - if not hidraw: - print("No Synaptics haptic touchpad hidraw device found", file=sys.stderr) - sys.exit(1) - - event = find_touchpad_event() - if not event: - print("No Synaptics haptic touchpad input device found", file=sys.stderr) - sys.exit(1) - - print(f"Haptic touchpad: hidraw={hidraw} input={event} intensity={INTENSITY}", flush=True) - - haptic_report = struct.pack("BB", REPORT_ID, INTENSITY) - ioctl_req = HIDIOCSFEATURE(len(haptic_report)) - - hidraw_fd = os.open(hidraw, os.O_RDWR) - event_fd = os.open(event, os.O_RDONLY) - - try: - while True: - data = os.read(event_fd, EVENT_SIZE) - if len(data) < EVENT_SIZE: - continue - _, _, ev_type, code, value = struct.unpack(EVENT_FORMAT, data) - if ev_type == EV_KEY and code in (BTN_LEFT, BTN_RIGHT, BTN_MIDDLE) and value == 1: - try: - fcntl.ioctl(hidraw_fd, ioctl_req, haptic_report) - except OSError: - pass - except KeyboardInterrupt: - pass - finally: - os.close(event_fd) - os.close(hidraw_fd) - - -if __name__ == "__main__": - main() diff --git a/bin/omarchy-hw-dell-xps-haptic-touchpad b/bin/omarchy-hw-dell-xps-haptic-touchpad new file mode 100755 index 00000000..cc0e5a62 --- /dev/null +++ b/bin/omarchy-hw-dell-xps-haptic-touchpad @@ -0,0 +1,5 @@ +#!/bin/bash + +# omarchy:summary=Match Dell XPS systems with the Synaptics haptic touchpad. + +omarchy-hw-match "XPS" && [[ -e /sys/bus/i2c/devices/i2c-VEN_06CB:00 ]] diff --git a/bin/omarchy-hyprland-monitor-scaling-cycle b/bin/omarchy-hyprland-monitor-scaling-cycle index 984057b6..8628c17c 100755 --- a/bin/omarchy-hyprland-monitor-scaling-cycle +++ b/bin/omarchy-hyprland-monitor-scaling-cycle @@ -1,6 +1,6 @@ #!/bin/bash -# omarchy:summary=Cycle focused Hyprland monitor scaling through 1x, 1.25x, 1.6x, 2x, and 3x +# omarchy:summary=Cycle focused Hyprland monitor scaling through 1x, 1.25x, 1.6x, 2x, 3x, and 4x MONITOR_INFO=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true)') ACTIVE_MONITOR=$(echo "$MONITOR_INFO" | jq -r '.name') @@ -9,8 +9,8 @@ WIDTH=$(echo "$MONITOR_INFO" | jq -r '.width') HEIGHT=$(echo "$MONITOR_INFO" | jq -r '.height') REFRESH_RATE=$(echo "$MONITOR_INFO" | jq -r '.refreshRate') -# Cycle through scales: 1 → 1.25 → 1.6 → 2 → 3 → 1 (or reverse with --reverse) -SCALES=(1 1.25 1.6 2 3) +# Cycle through scales: 1 → 1.25 → 1.6 → 2 → 3 → 4 → 1 (or reverse with --reverse) +SCALES=(1 1.25 1.6 2 3 4) # Find the index of the scale closest to the current one (Hyprland may # snap fractional scales to nearby values, so we can't match exactly) diff --git a/bin/omarchy-menu b/bin/omarchy-menu index ec9a5aae..9f098c92 100755 --- a/bin/omarchy-menu +++ b/bin/omarchy-menu @@ -93,9 +93,10 @@ show_learn_menu() { } show_trigger_menu() { - case $(menu "Trigger" " Capture\n󰧸 Transcode\n Share\n󰔎 Toggle\n Hardware") in + case $(menu "Trigger" "󰔛 Reminder\n Capture\n󰧸 Transcode\n Share\n󰔎 Toggle\n Hardware") in + *Reminder*) show_reminder_menu ;; *Capture*) show_capture_menu ;; - *Transcode*) show_transcode_menu ;; + *Transcode*) omarchy-transcode || back_to show_trigger_menu ;; *Share*) show_share_menu ;; *Toggle*) show_toggle_menu ;; *Hardware*) show_hardware_menu ;; @@ -103,6 +104,41 @@ show_trigger_menu() { esac } +show_reminder_menu() { + case $(menu "Reminder" "󰔛 Set one\n󰔛 Show all\n󰔛 Clear all") in + *Set*) show_custom_reminder_input ;; + *"Show all"*) omarchy-reminder show ;; + *"Clear all"*) omarchy-reminder clear ;; + *) back_to show_trigger_menu ;; + esac +} + +show_custom_reminder_input() { + local minutes + minutes=$(omarchy-menu-input "Remind in minutes") + + if [[ $minutes =~ ^[0-9]+$ ]] && ((minutes > 0)); then + show_reminder_message_input "$minutes" + elif [[ -n $minutes ]]; then + omarchy-notification-send "󰔛" "Invalid reminder" "Enter the number of minutes" -u critical + show_custom_reminder_input + else + back_to show_reminder_menu + fi +} + +show_reminder_message_input() { + local minutes="$1" + local message + message=$(omarchy-menu-input "Reminder message") + + if [[ -n $message ]]; then + omarchy-reminder "$minutes" "$message" + else + omarchy-reminder "$minutes" + fi +} + show_capture_menu() { case $(menu "Capture" " Screenshot\n Screenrecord\n󰴑 Text Extraction\n󰃉 Color") in *Screenshot*) omarchy-capture-screenshot ;; @@ -167,14 +203,6 @@ show_share_menu() { esac } -show_transcode_menu() { - case $(menu "Transcode" " Picture\n Video") in - *Picture*) present_terminal "omarchy-transcode --path '$HOME/Pictures'" ;; - *Video*) present_terminal "omarchy-transcode --path '$HOME/Videos'" ;; - *) back_to show_trigger_menu ;; - esac -} - show_toggle_menu() { local options="󱄄 Screensaver\n󰔎 Nightlight\n󱫖 Idle Lock\n󰂛 Notifications\n󰍜 Top Bar\n󱂬 Workspace Layout\n Window Gaps\n 1-Window Ratio\n󰍹 Monitor Scaling\n Direct Boot\n󰟵 Passwordless Sudo" @@ -205,13 +233,18 @@ show_hardware_menu() { options="$options\n󰟸 Touchpad" fi + if omarchy-hw-dell-xps-haptic-touchpad && omarchy-cmd-present dell-xps-touchpad-haptics; then + options="$options\n󰌌 Touchpad Haptics" + fi + if omarchy-hw-touchscreen; then options="$options\n󰆽 Touchscreen" fi case $(menu "Toggle" "$options") in *Laptop*) omarchy-hyprland-monitor-internal toggle ;; - *Mirror*) omarchy-hyprland-monitor-internal-mirror toggle;; + *Mirror*) omarchy-hyprland-monitor-internal-mirror toggle ;; + *Haptics*) show_hardware_touchpad_haptics_menu ;; *Touchpad*) omarchy-toggle-touchpad ;; *Touchscreen*) omarchy-toggle-touchscreen ;; *"Hybrid GPU"*) present_terminal omarchy-toggle-hybrid-gpu ;; @@ -219,6 +252,17 @@ show_hardware_menu() { esac } +show_hardware_touchpad_haptics_menu() { + local current=$(dell-xps-touchpad-haptics get) + local selected=$(menu "Touchpad Haptics" "low\nmid\nhigh" "" "$current") + + if [[ -n $selected ]]; then + dell-xps-touchpad-haptics set "$selected" + else + back_to show_hardware_menu + fi +} + show_style_menu() { case $(menu "Style" "󰸌 Theme\n󰟵 Unlock\n Font\n Background\n Hyprland\n󱄄 Screensaver\n About") in *Theme*) show_theme_menu ;; @@ -227,33 +271,27 @@ show_style_menu() { *Background*) show_background_menu ;; *Hyprland*) open_in_editor ~/.config/hypr/looknfeel.conf ;; *Screensaver*) show_screensaver_menu ;; - *About*) open_in_editor ~/.config/omarchy/branding/about.txt ;; + *About*) show_about_menu ;; *) show_main_menu ;; esac } -show_screensaver_menu() { - case $(menu "Screensaver" " Edit Text\n Set From Image\n󱄄 Preview\n Restore Default") in - *Text*) open_in_editor ~/.config/omarchy/branding/screensaver.txt ;; - *Image*) set_screensaver_from_image ;; - *Preview*) omarchy-launch-screensaver force ;; - *Default*) terminal bash -lc 'omarchy-screensaver-logo default; echo; read -n 1 -s -r -p "Press any key to close..."' ;; +show_about_menu() { + case $(menu "About" " Edit Text\n Set From Image\n Restore Default") in + *Text*) omarchy-branding-about text ;; + *Image*) omarchy-branding-about image ;; + *Default*) omarchy-branding-about reset ;; *) show_style_menu ;; esac } -set_screensaver_from_image() { - terminal bash -lc ' - image=$(fd --type file --ignore-case --extension svg --extension png . "$HOME" 2>/dev/null | fzf --prompt "Logo image> ") - if [[ -n $image ]]; then - if omarchy-screensaver-logo "$image"; then - echo - echo "Preview with: omarchy-launch-screensaver force" - fi - echo - read -n 1 -s -r -p "Press any key to close..." - fi - ' +show_screensaver_menu() { + case $(menu "Screensaver" " Edit Text\n Set From Image\n Restore Default") in + *Text*) omarchy-branding-screensaver text ;; + *Image*) omarchy-branding-screensaver image ;; + *Default*) omarchy-branding-screensaver reset ;; + *) show_style_menu ;; + esac } show_theme_menu() { @@ -308,8 +346,8 @@ show_setup_power_menu() { show_setup_security_menu() { case $(menu "Setup" "󰈷 Fingerprint\n Fido2") in - *Fingerprint*) present_terminal omarchy-setup-fingerprint ;; - *Fido2*) present_terminal omarchy-setup-fido2 ;; + *Fingerprint*) present_terminal omarchy-setup-security-fingerprint ;; + *Fido2*) present_terminal omarchy-setup-security-fido2 ;; *) show_setup_menu ;; esac } @@ -540,7 +578,7 @@ show_install_ai_menu() { } show_install_gaming_menu() { - case $(menu "Install" " Steam\n RetroArch\n󰍳 Minecraft\n󰢹 NVIDIA GeForce NOW\n Xbox Cloud Gaming\n󰖺 Xbox Controller (󰂯)\n󰍹 Moonlight (GameStream)\n Lutris (Battle.net)\n󱓟 Heroic (Epic Games)") in + case $(menu "Install" " Steam\n RetroArch\n󰍳 Minecraft\n󰢹 NVIDIA GeForce NOW\n Xbox Cloud Gaming\n󰂯 Xbox Controller\n󰍹 Moonlight (GameStream)\n Lutris (Battle.net)\n󱓟 Heroic (Epic Games)") in *Steam*) present_terminal omarchy-install-gaming-steam ;; *RetroArch*) present_terminal omarchy-install-gaming-retroarch ;; *Minecraft*) install_and_launch "Minecraft" "minecraft-launcher" "minecraft-launcher" ;; @@ -622,23 +660,30 @@ show_install_elixir_menu() { } show_remove_menu() { - case $(menu "Remove" "󰣇 Package\n Browser\n Web App\n TUI\n󰵮 Development\n Gaming\n󰏓 Preinstalls\n Dictation\n󰸌 Theme\n󰍲 Windows\n󰈷 Fingerprint\n Fido2") in + case $(menu "Remove" "󰣇 Package\n Web App\n TUI\n󰵮 Development\n󰸌 Theme\n Browser\n Dictation\n Gaming\n󰍲 Windows\n󰏓 Preinstalls\n Security") in *Package*) terminal omarchy-pkg-remove ;; - *Browser*) show_remove_browser_menu ;; *Web*) present_terminal omarchy-webapp-remove ;; *TUI*) present_terminal omarchy-tui-remove ;; *Development*) show_remove_development_menu ;; - *Gaming*) show_remove_gaming_menu ;; - *Preinstalls*) present_terminal omarchy-remove-preinstalls ;; - *Dictation*) present_terminal omarchy-voxtype-remove ;; *Theme*) present_terminal omarchy-theme-remove ;; + *Browser*) show_remove_browser_menu ;; + *Dictation*) present_terminal omarchy-voxtype-remove ;; + *Gaming*) show_remove_gaming_menu ;; *Windows*) present_terminal "omarchy-windows-vm remove" ;; - *Fingerprint*) present_terminal "omarchy-setup-fingerprint --remove" ;; - *Fido2*) present_terminal "omarchy-setup-fido2 --remove" ;; + *Preinstalls*) present_terminal omarchy-remove-preinstalls ;; + *Security*) show_remove_security_menu ;; *) show_main_menu ;; esac } +show_remove_security_menu() { + case $(menu "Remove" "󰈷 Fingerprint\n Fido2") in + *Fingerprint*) present_terminal omarchy-remove-security-fingerprint ;; + *Fido2*) present_terminal omarchy-remove-security-fido2 ;; + *) show_remove_menu ;; + esac +} + show_remove_browser_menu() { case $(menu "Remove" " Chrome\n Edge\n Brave\n Brave Origin\n Firefox\n Zen") in *Chrome*) present_terminal "omarchy-remove-browser chrome" ;; @@ -815,7 +860,8 @@ go_to_menu() { *toggle*) show_toggle_menu ;; *hardware*) show_hardware_menu ;; *share*) show_share_menu ;; - *transcode*) show_transcode_menu ;; + *reminder-set*) show_custom_reminder_input ;; + *reminder*) show_reminder_menu ;; *background*) show_background_menu ;; *capture*) show_capture_menu ;; *style*) show_style_menu ;; diff --git a/bin/omarchy-menu-file b/bin/omarchy-menu-file new file mode 100755 index 00000000..8cdf4bb0 --- /dev/null +++ b/bin/omarchy-menu-file @@ -0,0 +1,48 @@ +#!/bin/bash + +# omarchy:summary=Pick a file with Walker +# omarchy:group=menu +# omarchy:name=file +# omarchy:args=label paths formats [walker args...] +# omarchy:examples=omarchy menu file "Select image" "$HOME/Pictures" "jpg png webp"|omarchy-menu-file "Select media" "$HOME/Pictures:$HOME/Videos" "jpg png mp4 mov" --width 800 + +set -euo pipefail + +if (( $# < 3 )); then + echo "Usage: omarchy-menu-file