baskerville / bspwm

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

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

Open tom8347 opened 12 months ago

tom8347 commented 12 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 12 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 12 months ago

Thanks for the information

tom8347 commented 12 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 11 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 11 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 11 months ago

@tom8347 in bspwm's source:

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

tom8347 commented 11 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!