Hyprland icon indicating copy to clipboard operation
Hyprland copied to clipboard

Dispatcher for alternating between most recent window in the focus history on the current workspace

Open adamnejm opened this issue 2 years ago • 4 comments

This issue technically breaks rule about extending Hyprland with scripts, you can close it without reading further (if you're a monster!).


I'm surprised Hyprland doesn't offer functionality to essentially Alt-Tab between windows as seen in KDE, Gnome, Awesome, etc.

At first it seems that a simple solution would be to alternate between cyclenext and cyclenext, prev, like so:


#!/usr/bin/env bash

TOGGLE=/tmp/hypr-alt-tab.toggle

if [ ! -e $TOGGLE ]; then
    touch $TOGGLE
    hyprctl dispatch cyclenext ""
else
    rm $TOGGLE
    hyprctl dispatch cyclenext prev
fi

But it has issues:

1. Changing workspaces has a chance to break the behavior

2. Changing window focus in any other way has a chance to break the behavior

4. Cosmic rays screwing with the if statement just like they with this list index ;o so you know it's a real issue!


To make an actual, working version would require a somewhat heavy script:

  1. Subscribe to socket, listen for activewindow>>>, call hyprctl activewindow to grab the address (not sure why it's not included in the socket message already)

  2. Segregate history based on workspaces, requires parsing hyprctl clients

  3. Upkeep saved adresses, another parsing of hyprctl clients on many socket updates (window moving, killing, etc.) to discard old addresses or move them around based on new workspace


Why? Because I suck at coding and I want you to do it for me. But seriously... this is a pretty basic feature that would greatly benefit Hyprland users if included :')

adamnejm avatar Dec 28 '22 00:12 adamnejm

Progress:

daemon

#!/usr/bin/env bash

previous_window=""
socat - UNIX-CONNECT:/tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | while read line; do
	if [[ ${line:0:12} == "activewindow" ]]; then
		
		current_window=$(hyprctl activewindow | rg 'Window ([A-Fa-f0-9]+)' -or '$1')
		
		if [[ $current_window != $previous_window ]]; then
			echo $previous_window > /tmp/hypr-alt-tab
			previous_window=$current_window
		fi
	fi
done

switcher

#!/usr/bin/env bash

target_window=$(cat /tmp/hypr-alt-tab)
hyprctl dispatch focuswindow address:0x$target_window

Issues:

  1. Doesn't switch to anything if window stored in history is invalid (would be useful if hyprctl dispatch focuswindow address:fuckingshit returned fail instead of ok), but fixing that would just require parsing hyprctl clients and checking if stored window address is in the list, otherwise do cyclenext.
  2. Works across workspaces, which is not actually intended.

After familiarizing myself more with hyprctl I think I over-complicated stuff in the original post, however I still expect it to become a built-in feature.

adamnejm avatar Dec 28 '22 21:12 adamnejm

I have no real input to give on the matter, but reading your script - hyprctl has -j option for json output, which is easier to parse with gojq, especially in case of something long like clients.

# windows I have open
❯ hyprctl clients -j | gojq -r '.[] | .address' 
0x662245b0
0x67f9ace0
0x67f79610

# check if window with this address exists, if it does, returns its parameters, empty otherwise
~ 
❯ target=awd                                  

~ 
❯ hyprctl clients -j | gojq -r ".[] | select(.address == \"$target\")"

~ 
❯ target=0x67f79610                                                   

~ 
❯ hyprctl clients -j | gojq -r ".[] | select(.address == \"$target\")"
{
  "address": "0x67f79610",
  "at": [
    0,
    0
  ],
  "class": "foot",
  "floating": false,
  "fullscreen": true,
  "fullscreenMode": 1,
  "grouped": [],
  "monitor": 0,
  "pid": 397793,
  "pinned": false,
  "size": [
    2560,
    1396
  ],
  "swallowing": null,
  "title": "~ - zsh",
  "workspace": {
    "id": 2,
    "name": "2"
  },
  "xwayland": false
}

So basically

if [[ "$(hyprctl clients -j | gojq -r ".[] | select(.address == \"$target\")")" != "" ]]; then
# switch
fi

etc

MahouShoujoMivutilde avatar Dec 28 '22 22:12 MahouShoujoMivutilde

would be useful if hyprctl dispatch focuswindow address:fuckingshit returned fail instead of ok

whoa, watch your language.

it is not a bad fucking idea, but for now all keybind handlers (dispatchers) are void functions so I'd have to make them into bools and think when a fail is reasonable.

vaxerski avatar Dec 28 '22 22:12 vaxerski

could probably done in layers :). I get a nice stoi now and again. Some blanket argument parsing, printing the intended usage of the furthest parable sub command (hyprctl = worst case) is a tactic.
But the case that triggered the suggestion requires more custom approach. "no window found with address terrible-invocation"

bklaase avatar Dec 29 '22 17:12 bklaase

Implemented in #1545

adamnejm avatar Apr 04 '23 22:04 adamnejm