Bug 4449 - Change window focus when pressing Alt-Tab
Status: ASSIGNED
Alias: None
Product: Openbox
Classification: Unclassified
Component: general
Version: unspecified
Hardware: PC Linux
: P3 enhancement
Assignee: Dana Jansens
QA Contact:
URL:
Depends on:
Blocks:
 
Reported: 2010-01-01 15:22 EST by Vladimir A. Pavlov
Modified: 2012-10-06 21:08:44 EDT
0 users

See Also:


Attachments
The patch implementing the feature for cyclewindows.c (2.99 KB, patch)
2010-12-20 14:21 EST, Vladimir A. Pavlov
Newer patch version (4.92 KB, patch)
2012-05-21 13:01 EDT, Vladimir A. Pavlov

Description Vladimir A. Pavlov 2010-01-01 15:22:59 EST
Hi!

I came to openbox from dwm and I like openbox it very much. The only thing I miss for is the following.

Currently I have the following settings for Alt-Tab (which I mapped to Win-Tab):
    <keybind key="W-Tab">
      <action name="NextWindow">
        <dialog>no</dialog>
        <raise>yes</raise>
        <bar>no</bar>
      </action>
    </keybind>

If I have several windows on the same desktop then when I press Alt-Tab the focus remains on the window where it was before I started pressing. But another window is raised, so I can press Alt-Tab for several times and "visually" find the window I wish to choose. That's great. When the window is found I release Alt and Tab keys and the selected window gets focus.

But I use tint2 panel to view the list of opened windows. Before I release the keys tint2 thinks that the old window is active. Moreover, focused xterms are displayed slightly different than unfocused ones (the cursor in a focused xterm is a filled rectangle while in an unfocused term it's not filled). So I should have <bar>yes</bar> do see which xterm is active and which one is not.

Is it possible to make fluxbox move the focus temporarily to the currently-raised window (if the config contains <raise>yes</raise>) when doing Alt-Tab? I mean, not just raising the currently selected window but also focus it so that the panel will highlight the currently selected window?
Comment 1 Dana Jansens 2010-01-04 21:48:08 EST
Need a temp-focus option, similar to the temp-raise one.
Comment 2 Dana Jansens 2010-01-04 21:49:23 EST
(In reply to comment #0)
> Is it possible to make fluxbox move the focus temporarily to the
> currently-raised window (if the config contains <raise>yes</raise>) when doing

Fluxbox? Wrong bugzilla :P
Comment 3 Vladimir A. Pavlov 2010-01-05 17:22:21 EST
(In reply to comment #2)
> (In reply to comment #0)
> > Is it possible to make fluxbox move the focus temporarily to the
> > currently-raised window (if the config contains <raise>yes</raise>) when doing
> 
> Fluxbox? Wrong bugzilla :P

Sorry sorry sorry. Freud seems to be in my head.

I actually meant openbox of course :)
Comment 4 Vladimir A. Pavlov 2010-12-20 14:21:03 EST
Created attachment 2542 [details]
The patch implementing the feature for cyclewindows.c

I had a few free days at last to implement the feature by myself.

I added an option "focus" (similar to "raise") in "NextWindow" action controlling whether the active window gets the focus while switching between windows using Alt-Tab.

Unlike stacking_temp_raise(), we cannot just reorder focus_order contents since such reorderings influence the way other parts of openbox works. For example, "NextWindow" algorithm uses this list via focus_cycle() and my early implementations led me to strange bugs so I decided just not to modify the list.

The solution is to implement focus_temp_set_client() (analog of stacking_temp_raise()) which moves "visual" focus to the current active window and focus_restore() (analog of stacking_restore()) returning the focus back to the original focus_client, focus_client and focus_order are unused. Besides, when switching between windows we disable focus_set_client() execution.

So, the questions:
1. Does the patch look correct or did I miss anything in openbox sources?
2. Can this be commited to mainline?
3. Is the similar option required for directionalwindows.c?
Comment 5 Vladimir A. Pavlov 2010-12-26 15:09:42 EST
Any comments on the patch?
Comment 6 Dana Jansens 2011-10-18 11:08:10 EDT
I think this needs to be done without calling client_focus().  I don't want to actually move focus until it's done.

Setting _net_active_window will get it showing in other apps.
It needs to have the frames repaint so need a way to say to the frame "display this focus state".

Frame currently has a bool focused but we don't want to change its actual state.

In my first though it would take something like this added to Frame..
bool override_fake_focused - TRUE when we display focus from fake_focused instead of focused.
bool fake_focused - TRUE if the window should fake being focused, FALSE for unfocused.
Comment 7 Vladimir A. Pavlov 2012-05-21 12:59:53 EDT
The modified version of the patch. Changes:
1. A very annoying hard-to-reproduce issue with focusing incorrect windows fixed;
2. The patch is updated to openbox 3.5.0;
3. An unnecessary focus_restore() call removed.
Comment 8 Vladimir A. Pavlov 2012-05-21 13:01:58 EDT
Created attachment 3148 [details]
Newer patch version
Comment 9 Vladimir A. Pavlov 2012-05-21 13:14:25 EDT
> I think this needs to be done without calling client_focus().  I don't want to
> actually move focus until it's done.

You are right. Just calling client_focus() was a stupid idea and caused strange and very annoying effects mentioned in the previous message. I discovered that it was due to sending notification when "temporarily" setting the input focus. Calling client_focus() without a notify event seems to fix the issue for me.

> Setting _net_active_window will get it showing in other apps.
> It needs to have the frames repaint so need a way to say to the frame "display
this focus state".

Sorry, I don't fully understand what you mean. May be it's because my X11 programming knowledge are not too deep.

If you mean we don't have to call XSetInputFocus() then you're wrong. I tried that and just setting _net_active_window doesn't make openbox to work as expected (though I looked at tint2 sources and it seems it just checks NET_ACTIVE_WINDOW). I guess it's just insufficient to just set the NET_* and we also have to somehow notify the X that we have set it, and I guess XSetInputFocus does that for us.

> Frame currently has a bool focused but we don't want to change its actual state.
Will this affect only openbox or will it affect external programs such as panels (like tint2 or bmpanel), docks, etc... as well?
Comment 10 Dana Jansens 2012-10-06 21:08:44 EDT
(In reply to comment #9)
> > I think this needs to be done without calling client_focus().  I don't want to
> > actually move focus until it's done.
> 
> You are right. Just calling client_focus() was a stupid idea and caused strange
> and very annoying effects mentioned in the previous message. I discovered that
> it was due to sending notification when "temporarily" setting the input focus.
> Calling client_focus() without a notify event seems to fix the issue for me.
> 
> > Setting _net_active_window will get it showing in other apps.
> > It needs to have the frames repaint so need a way to say to the frame "display
> this focus state".
> 
> Sorry, I don't fully understand what you mean. May be it's because my X11
> programming knowledge are not too deep.
> 
> If you mean we don't have to call XSetInputFocus() then you're wrong. I tried
> that and just setting _net_active_window doesn't make openbox to work as
> expected (though I looked at tint2 sources and it seems it just checks
> NET_ACTIVE_WINDOW). I guess it's just insufficient to just set the NET_* and we
> also have to somehow notify the X that we have set it, and I guess
> XSetInputFocus does that for us.

It really should be enough to set the NET_ACTIVE_WINDOW property to change what panels are showing as focused.

Doing XSetInputFocus is going cause race conditions with apps setting focus. We can't tell when we receive the focus change if it came from us or from another app. So then, how do we know to change the focus order or not?

We should just make the window's frame look focused by setting internal variables on it, and set NET_ACTIVE_WINDOW for panels to match it.

> > Frame currently has a bool focused but we don't want to change its actual state.
> Will this affect only openbox or will it affect external programs such as
> panels (like tint2 or bmpanel), docks, etc... as well?