baskerville / bspwm

A tiling window manager based on binary space partitioning
BSD 2-Clause "Simplified" License
7.61k stars 420 forks source link

Query to find active window on unfocused desktop not working #1474

Open tom8347 opened 7 months ago

tom8347 commented 7 months ago

I have 1 monitor with 9 desktops. I'm trying to write a script which will give me informatio about windows on the various desktops. I want to get the id/name of the window on each desktop that has focus on that desktop. Looking at the man page I thought it should be something like bspc query -N -n .window.active -d 4, for desktop 4 for example, and similar for all the desktops. This doesn't return anything.

I should note that bspc query -N -n .window -d 4 and bspc query -N -n .window.!active -d 4 both return the expected list of window IDs.

bspc query -N -n .window -d 4 returns 0x0680000E 0x04A00003 0x04800003 (as expected, all the windows I can see on desktop 4)

bspc query -N -n .window.!active -d 4 returns 0x0680000E 0x04800003 (as expected all the windows on desktop 4 apart from the one which has focus

emanuele6 commented 7 months ago

Hm, yes, I recall .active not working correctly for nodes, and having to work around it in one of my script a while ago, but I don't think I have ever actually investigated the issue.

As a workaround, if you need to get this information, you can use query -T (or wm -d) and extract it from the JSON output:

# "bspc query -N -n .window.active"
bspc wm -d |
jq '
  .monitors[].dekstops[] |
  # active nodes
  first(
    .focusedNodeId as $activeid |
    .root |
    .. |
    select(.id? == $activeid)
  ) |
  # that are windows
  select(.client)
  .id
'

# "bspc query -N -n '.window.!active' -d 4"
bspc query -T -d 4 |
jq '
  .focusedNodeId as $activeid |
  .root |
  .. |
  # windows
  select(.client?)
  .id |
  # that are not the active node
  select(. != $activeid)
'

# "bspc query -N -n '.window.active' -d 4"
bspc query -T -d 4 |
jq '
  # the active node
  first(
    .focusedNodeId as $activeid |
    .root |
    .. |
    select(.id? == $activeid)
  ) |
  # only if it is a window
  select(.client)
  .id
'
tom8347 commented 7 months ago

Thanks for the information

tom8347 commented 7 months ago

This works but seems to be slowing my script down quite a bit. I'm not sure what exactly is slowing it down (whether it's the bspc call or the jq call). Is there any way of speeding it up?

ortango commented 7 months ago

does changing the second active conditional in query.c:node_matches() to

if (sel->active != OPTION_NONE &&
    loc->desktop == mon->desk) {
        return false;
}

give you expected output? removing that second conditional entirely would get focused included with active, which allows for .active.!focused which I like more.


update: this is wrong, and should be ignored. It does seem to give sane output on a single monitor setup, but totally incorrect on a multimonitor setup.

tom8347 commented 7 months ago

Not sure what you mean by the second conditional in query.c:node_matches()? How should I modify

# "bspc query -N -n '.window.active' -d 4"
bspc query -T -d 4 |
jq '
  # the active node
  first(
    .focusedNodeId as $activeid |
    .root |
    .. |
    select(.id? == $activeid)
  ) |
  # only if it is a window
  select(.client)
  .id
'

to test what you mean?

ortango commented 7 months ago

@tom8347 in bspwm's source:

https://github.com/baskerville/bspwm/blob/af3bd8b4351f4478fe0fe3cfd6c09e44cb108b4b/src/query.c#L1104-L1109

tom8347 commented 7 months ago

Oh I see. I'm not sure. If I'm feeling adventurous I'll try to have a look later. I don't usually poke around in source code!