]> Dogcows Code - chaz/openbox/blobdiff - openbox/focus.c
Don't kill keygrabs when focus moves.
[chaz/openbox] / openbox / focus.c
index f34021a47b5f4528b497d05e8e849a1924386913..8c3bd70a82e69bc89a6ef769736525abf10c3dc5 100644 (file)
@@ -57,6 +57,14 @@ void focus_shutdown(gboolean reconfig)
 
 static void push_to_top(ObClient *client)
 {
 
 static void push_to_top(ObClient *client)
 {
+    ObClient *p;
+
+    /* if it is modal for a single window, then put that window at the top
+       of the focus order first, so it will be right after ours. the same is
+       done with stacking */
+    if (client->modal && (p = client_direct_parent(client)))
+        push_to_top(p);
+
     focus_order = g_list_remove(focus_order, client);
     focus_order = g_list_prepend(focus_order, client);
 }
     focus_order = g_list_remove(focus_order, client);
     focus_order = g_list_prepend(focus_order, client);
 }
@@ -75,10 +83,6 @@ void focus_set_client(ObClient *client)
     screen_install_colormap(focus_client, FALSE);
     screen_install_colormap(client, TRUE);
 
     screen_install_colormap(focus_client, FALSE);
     screen_install_colormap(client, TRUE);
 
-    /* in the middle of cycling..? kill it. */
-    focus_cycle_stop(focus_client);
-    focus_cycle_stop(client);
-
     focus_client = client;
 
     if (client != NULL) {
     focus_client = client;
 
     if (client != NULL) {
@@ -122,12 +126,12 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
            1. it is on the current desktop. this ignores omnipresent
            windows, which are problematic in their own rite, unless they are
            specifically allowed
            1. it is on the current desktop. this ignores omnipresent
            windows, which are problematic in their own rite, unless they are
            specifically allowed
-           2. it is a normal type window, don't fall back onto a dock or
-           a splashscreen or a desktop window (save the desktop as a
-           backup fallback though)
+           2. it is a valid auto-focus target
+           3. it is not shaded
         */
         if ((allow_omnipresent || c->desktop == screen_desktop) &&
         */
         if ((allow_omnipresent || c->desktop == screen_desktop) &&
-            focus_valid_target(c, FALSE, FALSE, FALSE, FALSE) &&
+            focus_valid_target(c, TRUE, FALSE, FALSE, FALSE, FALSE) &&
+            !c->shaded &&
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
@@ -146,7 +150,7 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
            a splashscreen or a desktop window (save the desktop as a
            backup fallback though)
         */
            a splashscreen or a desktop window (save the desktop as a
            backup fallback though)
         */
-        if (focus_valid_target(c, FALSE, FALSE, FALSE, TRUE) &&
+        if (focus_valid_target(c, TRUE, FALSE, FALSE, FALSE, TRUE) &&
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
             (allow_refocus || client_focus_target(c) != old) &&
             client_focus(c))
         {
@@ -159,7 +163,7 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
 }
 
 ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer,
 }
 
 ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer,
-                         gboolean allow_omnipresent)
+                         gboolean allow_omnipresent, gboolean focus_lost)
 {
     ObClient *new;
     ObClient *old = focus_client;
 {
     ObClient *new;
     ObClient *old = focus_client;
@@ -167,7 +171,8 @@ ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer,
     /* 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. */
     /* 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 (focus_lost)
+        focus_nothing();
 
     new = focus_fallback_target(allow_refocus, allow_pointer,
                                 allow_omnipresent, old);
 
     new = focus_fallback_target(allow_refocus, allow_pointer,
                                 allow_omnipresent, old);
@@ -177,7 +182,7 @@ ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer,
     return new;
 }
 
     return new;
 }
 
-void focus_nothing()
+void focus_nothing(void)
 {
     /* Install our own colormap */
     if (focus_client != NULL) {
 {
     /* Install our own colormap */
     if (focus_client != NULL) {
@@ -188,15 +193,6 @@ void focus_nothing()
     /* nothing is focused, update the colormap and _the root property_ */
     focus_set_client(NULL);
 
     /* nothing is focused, update the colormap and _the root property_ */
     focus_set_client(NULL);
 
-    /* if there is a grab going on, then we need to cancel it. if we move
-       focus during the grab, applications will get NotifyWhileGrabbed events
-       and ignore them !
-
-       actions should not rely on being able to move focus during an
-       interactive grab.
-    */
-    event_cancel_all_key_grabs();
-
     /* when nothing will be focused, send focus to the backup target */
     XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot,
                    event_curtime);
     /* when nothing will be focused, send focus to the backup target */
     XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot,
                    event_curtime);
@@ -274,7 +270,7 @@ ObClient *focus_order_find_first(guint desktop)
 static gboolean focus_target_has_siblings(ObClient *ft,
                                           gboolean iconic_windows,
                                           gboolean all_desktops)
 static gboolean focus_target_has_siblings(ObClient *ft,
                                           gboolean iconic_windows,
                                           gboolean all_desktops)
-                                                         
+
 {
     GSList *it;
 
 {
     GSList *it;
 
@@ -284,7 +280,8 @@ static gboolean focus_target_has_siblings(ObClient *ft,
         ObClient *c = it->data;
         /* check that it's not a helper window to avoid infinite recursion */
         if (c != ft && c->type == OB_CLIENT_TYPE_NORMAL &&
         ObClient *c = it->data;
         /* check that it's not a helper window to avoid infinite recursion */
         if (c != ft && c->type == OB_CLIENT_TYPE_NORMAL &&
-            focus_valid_target(c, iconic_windows, all_desktops, FALSE, FALSE))
+            focus_valid_target(c, TRUE, iconic_windows, all_desktops,
+                               FALSE, FALSE))
         {
             return TRUE;
         }
         {
             return TRUE;
         }
@@ -293,6 +290,7 @@ static gboolean focus_target_has_siblings(ObClient *ft,
 }
 
 gboolean focus_valid_target(ObClient *ft,
 }
 
 gboolean focus_valid_target(ObClient *ft,
+                            gboolean helper_windows,
                             gboolean iconic_windows,
                             gboolean all_desktops,
                             gboolean dock_windows,
                             gboolean iconic_windows,
                             gboolean all_desktops,
                             gboolean dock_windows,
@@ -318,7 +316,7 @@ gboolean focus_valid_target(ObClient *ft,
         ok = ok && ((dock_windows && ft->type == OB_CLIENT_TYPE_DOCK) ||
                     (desktop_windows && ft->type == OB_CLIENT_TYPE_DESKTOP));
     /* modal windows are important and can always get focus if they are
         ok = ok && ((dock_windows && ft->type == OB_CLIENT_TYPE_DOCK) ||
                     (desktop_windows && ft->type == OB_CLIENT_TYPE_DESKTOP));
     /* modal windows are important and can always get focus if they are
-       visible and stuff, so don't change 'ok' based on their type */ 
+       visible and stuff, so don't change 'ok' based on their type */
     else if (!ft->modal)
         /* normal non-helper windows are valid targets */
         ok = ok &&
     else if (!ft->modal)
         /* normal non-helper windows are valid targets */
         ok = ok &&
@@ -326,19 +324,17 @@ gboolean focus_valid_target(ObClient *ft,
              ||
              /* helper windows are valid targets if... */
              (client_helper(ft) &&
              ||
              /* helper windows are valid targets if... */
              (client_helper(ft) &&
-              /* ...a window in its group already has focus ... */
-              ((focus_client && ft->group == focus_client->group) ||
-               /* ... or if there are no other windows in its group 
-                  that can be cycled to instead */
+              /* ...a window in its group already has focus and we want to
+                 include helper windows ... */
+              ((focus_client && ft->group == focus_client->group &&
+                helper_windows) ||
+               /* ... or if there are no other windows in its group
+                  that can be focused instead */
                !focus_target_has_siblings(ft, iconic_windows, all_desktops))));
 
                !focus_target_has_siblings(ft, iconic_windows, all_desktops))));
 
-    /* it's not set to skip the taskbar (unless it is a type that would be
-       expected to set this hint, or modal) */
-    ok = ok && ((ft->type == OB_CLIENT_TYPE_DOCK ||
-                 ft->type == OB_CLIENT_TYPE_DESKTOP ||
-                 ft->type == OB_CLIENT_TYPE_TOOLBAR ||
-                 ft->type == OB_CLIENT_TYPE_MENU ||
-                 ft->type == OB_CLIENT_TYPE_UTILITY) ||
+    /* it's not set to skip the taskbar (but this only applies to normal typed
+       windows, and is overridden if the window is modal) */
+    ok = ok && (ft->type != OB_CLIENT_TYPE_NORMAL ||
                 ft->modal ||
                 !ft->skip_taskbar);
 
                 ft->modal ||
                 !ft->skip_taskbar);
 
@@ -348,6 +344,7 @@ gboolean focus_valid_target(ObClient *ft,
     {
         ObClient *cft = client_focus_target(ft);
         ok = ok && (ft == cft || !focus_valid_target(cft,
     {
         ObClient *cft = client_focus_target(ft);
         ok = ok && (ft == cft || !focus_valid_target(cft,
+                                                     TRUE,
                                                      iconic_windows,
                                                      all_desktops,
                                                      dock_windows,
                                                      iconic_windows,
                                                      all_desktops,
                                                      dock_windows,
@@ -356,4 +353,3 @@ gboolean focus_valid_target(ObClient *ft,
 
     return ok;
 }
 
     return ok;
 }
-
This page took 0.024289 seconds and 4 git commands to generate.