diff options
| author | Dana Jansens <danakj@orodu.net> | 2007-05-13 07:09:34 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2007-05-13 07:09:34 +0000 |
| commit | 1e957a168808f0357509300e879c0a7e97b49a24 (patch) | |
| tree | 96f90517ae2d2a2196bd0dc6d54d89b203538fd8 /openbox/focus.c | |
| parent | f694c650c83a7c29324debf3ac35d5e0c3abd84e (diff) | |
some changes to focus handling.
most interesting is the change in focus_fallback, which means that it won't
call xsetinput focus in some cases, potentially reducing flicker and stuff.
also potentially producing bugs? heh.
the screen.c focus fallback code doesn't seem to need special cases anymore,
which is really good, if that is really the case.
move the focus_tried stuff out of event.c into focus.c, where it seems to
belong.
Diffstat (limited to 'openbox/focus.c')
| -rw-r--r-- | openbox/focus.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/openbox/focus.c b/openbox/focus.c index 4aeeab5b..92cd7662 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -43,6 +43,14 @@ ObClient *focus_client = NULL; GList *focus_order = NULL; ObClient *focus_cycle_target = NULL; +/*! This variable is used for focus fallback. If we fallback to a window, we + set this to the window. And when focus goes somewhere after that, it will + be set to NULL. If between falling back to that window and something + getting focused, the window gets unmanaged, then if there are no incoming + FocusIn events, we fallback again because focus has just gotten itself lost. + */ +static ObClient *focus_tried = NULL; + struct { InternalWindow top; InternalWindow left; @@ -60,6 +68,7 @@ static gboolean valid_focus_target(ObClient *ft, gboolean dock_windows, gboolean desktop_windows); static void focus_cycle_destructor(ObClient *client, gpointer data); +static void focus_tried_destructor(ObClient *client, gpointer data); static Window createWindow(Window parent, gulong mask, XSetWindowAttributes *attrib) @@ -78,6 +87,7 @@ void focus_startup(gboolean reconfig) XSetWindowAttributes attr; client_add_destructor(focus_cycle_destructor, NULL); + client_add_destructor(focus_tried_destructor, NULL); /* start with nothing focused */ focus_nothing(); @@ -131,6 +141,7 @@ void focus_shutdown(gboolean reconfig) if (!reconfig) { client_remove_destructor(focus_cycle_destructor); + client_remove_destructor(focus_tried_destructor); /* reset focus to root */ XSetInputFocus(ob_display, PointerRoot, RevertToNone, CurrentTime); @@ -184,9 +195,12 @@ void focus_set_client(ObClient *client) PROP_SET32(RootWindow(ob_display, ob_screen), net_active_window, window, active); } + + + focus_tried = NULL; /* focus isn't "trying" to go anywhere now */ } -ObClient* focus_fallback_target(gboolean allow_refocus, ObClient *old) +static ObClient* focus_fallback_target(gboolean allow_refocus, ObClient *old) { GList *it; ObClient *target = NULL; @@ -259,19 +273,27 @@ ObClient* focus_fallback_target(gboolean allow_refocus, ObClient *old) ObClient* focus_fallback(gboolean allow_refocus) { ObClient *new; - ObClient *old = focus_client; + ObClient *old; - /* unfocus any focused clients.. they can be focused by Pointer events - and such, and then when I try focus them, I won't get a FocusIn event - at all for them. - */ - focus_nothing(); + old = focus_client; + new = focus_fallback_target(allow_refocus, focus_client); - if ((new = focus_fallback_target(allow_refocus, old))) { - client_focus(new); - return new; - } else - return NULL; + /* send focus somewhere if it is moving or if it was NULL before, + in which case it may not even be on the screen */ + if (!old || new != old) { + /* unfocus any focused clients.. they can be focused by Pointer events + and such, and then when we try focus them, we won't get a FocusIn + event at all for them. */ + focus_nothing(); + + if (new) { + client_focus(new); + /* remember that we tried to send focus here */ + focus_tried = new; + } + } + + return new; } void focus_nothing() @@ -283,6 +305,7 @@ void focus_nothing() } focus_client = NULL; + focus_tried = NULL; /* focus isn't "trying" to go anywhere now */ /* when nothing will be focused, send focus to the backup target */ XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot, @@ -918,3 +941,25 @@ ObClient *focus_order_find_first(guint desktop) } return NULL; } + +static void focus_tried_destructor(ObClient *client, gpointer data) +{ + XEvent ce; + + if (client == focus_tried) { + /* we were trying to focus this window but it's gone */ + + focus_tried = NULL; + + ob_debug_type(OB_DEBUG_FOCUS, "Tried to focus window 0x%x and it " + "is being unmanaged:\n"); + if (XCheckIfEvent(ob_display, &ce, event_look_for_focusin_client,NULL)) + { + XPutBackEvent(ob_display, &ce); + ob_debug_type(OB_DEBUG_FOCUS, " but another FocusIn is coming\n"); + } else { + ob_debug_type(OB_DEBUG_FOCUS, " so falling back focus again.\n"); + focus_fallback(TRUE); + } + } +} |
