]> Dogcows Code - chaz/openbox/commitdiff
break focus. or maybe make it better.
authorDana Jansens <danakj@orodu.net>
Mon, 15 Sep 2003 10:54:07 +0000 (10:54 +0000)
committerDana Jansens <danakj@orodu.net>
Mon, 15 Sep 2003 10:54:07 +0000 (10:54 +0000)
these changes make it work when you alt-tab off a fullscreen window, that it doesnt iconify, and that it is immediately restacked instead of waiting for a FocusIn event to arrive. The code now assumes that if the window says it can focus, that if we focus it, it is focused.
add the XDone handler to ObMainLoop, which is fired upon the occurance of there being no more X events to read.

openbox/client.c
openbox/event.c
openbox/focus.c
openbox/mainloop.c
openbox/mainloop.h
openbox/stacking.c
openbox/startupnotify.c

index 59af202a6d426a9b28d14eb41da3c36026161ad7..83291132a14535917763ad0c622b6f743e566fcb 100644 (file)
@@ -1647,7 +1647,9 @@ static ObStackingLayer calc_layer(ObClient *self)
 {
     ObStackingLayer l;
 
-    if (self->fullscreen) l = OB_STACKING_LAYER_FULLSCREEN;
+    if (self->fullscreen &&
+        (client_focused(self) || client_search_focus_tree(self)))
+        l = OB_STACKING_LAYER_FULLSCREEN;
     else if (self->type == OB_CLIENT_TYPE_DESKTOP)
         l = OB_STACKING_LAYER_DESKTOP;
     else if (self->type == OB_CLIENT_TYPE_DOCK) {
@@ -1669,7 +1671,9 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
 
     old = self->layer;
     own = calc_layer(self);
-    self->layer = l > own ? l : own;
+    self->layer = MAX(l, own);
+
+    g_message("calc for 0x%x %d %d", self->window, old, self->layer);
 
     for (it = self->transients; it; it = it->next)
         client_calc_layer_recursive(it->data, orig,
@@ -1677,7 +1681,6 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
 
     if (!raised && l != old)
        if (orig->frame) { /* only restack if the original window is managed */
-            /* XXX add_non_intrusive ever? */
             stacking_remove(CLIENT_AS_WINDOW(self));
             stacking_add(CLIENT_AS_WINDOW(self));
         }
@@ -2526,14 +2529,15 @@ gboolean client_focus(ObClient *self)
     /* choose the correct target */
     self = client_focus_target(self);
 
-    if (!client_can_focus(self)) {
-        if (!self->frame->visible) {
-            /* update the focus lists */
-            focus_order_to_top(self);
-        }
+    if (!self->frame->visible) {
+        /* update the focus lists */
+        focus_order_to_top(self);
         return FALSE;
     }
 
+    if (!client_can_focus(self))
+        return FALSE;
+
     if (self->can_focus) {
         /* RevertToPointerRoot causes much more headache than RevertToNone, so
            I choose to use it always, hopefully to find errors quicker, if any
@@ -2561,6 +2565,8 @@ gboolean client_focus(ObClient *self)
        XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce);
     }
 
+    focus_set_client(self);
+
 #ifdef DEBUG_FOCUS
     ob_debug("%sively focusing %lx at %d\n",
              (self->can_focus ? "act" : "pass"),
index 483050fa9b49498a4ee57f0e44ddcb084f095e61..68d511352201e9afe33b584ed4168be7bd558666 100644 (file)
@@ -42,6 +42,7 @@ typedef struct
 } ObEventData;
 
 static void event_process(const XEvent *e, gpointer data);
+static void event_done(gpointer data);
 static void event_handle_root(XEvent *e);
 static void event_handle_menu(XEvent *e);
 static void event_handle_dock(ObDock *s, XEvent *e);
@@ -132,7 +133,7 @@ void event_startup(gboolean reconfig)
        }
     }
 
-    ob_main_loop_x_add(ob_main_loop, event_process, NULL, NULL);
+    ob_main_loop_x_add(ob_main_loop, event_process, event_done, NULL, NULL);
 
 #ifdef USE_SM
     IceAddConnectionWatch(ice_watch, NULL);
@@ -283,24 +284,32 @@ static void event_hack_mods(XEvent *e)
 
 static gboolean event_ignore(XEvent *e, ObClient *client)
 {
+    gboolean ignore = FALSE;
+    XEvent ce;
+
     switch(e->type) {
     case FocusIn:
+        while (XCheckTypedWindowEvent(ob_display, e->xfocus.window,
+                                      FocusIn, &ce))
+        {
+            if (!INVALID_FOCUSIN(&ce)) {
+                XPutBackEvent(ob_display, &ce);
+                ignore = TRUE;
+                break;
+            }
+        }            
+
         /* NotifyAncestor is not ignored in FocusIn like it is in FocusOut
            because of RevertToPointerRoot. If the focus ends up reverting to
            pointer root on a workspace change, then the FocusIn event that we
            want will be of type NotifyAncestor. This situation does not occur
            for FocusOut, so it is safely ignored there.
         */
-       if (INVALID_FOCUSIN(e) ||
-            client == NULL) {
+       if (ignore || INVALID_FOCUSIN(e) || client == NULL) {
 #ifdef DEBUG_FOCUS
             ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n",
                      e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
 #endif
-            /* says a client was not found for the event (or a valid FocusIn
-               event was not found.
-            */
-            e->xfocus.window = None;
             return TRUE;
         }
 
@@ -310,10 +319,20 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
 #endif
         break;
     case FocusOut:
-       if (INVALID_FOCUSOUT(e)) {
+        while (XCheckTypedWindowEvent(ob_display, e->xfocus.window,
+                                      FocusOut, &ce))
+        {
+            if (!INVALID_FOCUSOUT(&ce)) {
+                XPutBackEvent(ob_display, &ce);
+                ignore = TRUE;
+                break;
+            }
+        }            
+
+       if (ignore || INVALID_FOCUSOUT(e)) {
 #ifdef DEBUG_FOCUS
-        ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n",
-                 e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
+            ob_debug("FocusOut on %lx mode %d detail %d IGNORED\n",
+                     e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
 #endif
             return TRUE;
         }
@@ -322,84 +341,6 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
         ob_debug("FocusOut on %lx mode %d detail %d\n",
                  e->xfocus.window, e->xfocus.mode, e->xfocus.detail);
 #endif
-
-        {
-            XEvent fe;
-            gboolean fallback = TRUE;
-
-            while (TRUE) {
-                if (!XCheckTypedWindowEvent(ob_display, e->xfocus.window,
-                                            FocusOut, &fe))
-                    if (!XCheckTypedEvent(ob_display, FocusIn, &fe))
-                        break;
-                if (fe.type == FocusOut) {
-#ifdef DEBUG_FOCUS
-                    ob_debug("found pending FocusOut\n");
-#endif
-                    if (!INVALID_FOCUSOUT(&fe)) {
-                        /* if there is a VALID FocusOut still coming, don't
-                           fallback focus yet, we'll deal with it then */
-                        XPutBackEvent(ob_display, &fe);
-                        fallback = FALSE;
-                        break;
-                    }
-                } else {
-#ifdef DEBUG_FOCUS
-                    ob_debug("found pending FocusIn\n");
-#endif
-                    /* is the focused window getting a FocusOut/In back to
-                       itself?
-                    */
-                    if (fe.xfocus.window == e->xfocus.window &&
-                        !event_ignore(&fe, client)) {
-                        /*
-                          if focus_client is not set, then we can't do
-                          this. we need the FocusIn. This happens in the
-                          case when the set_focus_client(NULL) in the
-                          focus_fallback function fires and then
-                          focus_fallback picks the currently focused
-                          window (such as on a SendToDesktop-esque action.
-                        */
-                        if (focus_client) {
-#ifdef DEBUG_FOCUS
-                            ob_debug("focused window got an Out/In back to "
-                                     "itself IGNORED both\n");
-#endif
-                            return TRUE;
-                        } else {
-                            event_process(&fe, NULL);
-#ifdef DEBUG_FOCUS
-                            ob_debug("focused window got an Out/In back to "
-                                     "itself but focus_client was null "
-                                     "IGNORED just the Out\n");
-#endif
-                            return TRUE;
-                        }
-                    }
-
-                    {
-                        ObEventData d;
-
-                        /* once all the FocusOut's have been dealt with, if
-                           there is a FocusIn still left and it is valid, then
-                           use it */
-                        event_process(&fe, &d);
-                        if (!d.ignored) {
-                            ob_debug("FocusIn was OK, so don't fallback\n");
-                            fallback = FALSE;
-                            break;
-                        }
-                    }
-                }
-            }
-            if (fallback) {
-#ifdef DEBUG_FOCUS
-                ob_debug("no valid FocusIn and no FocusOut events found, "
-                         "falling back\n");
-#endif
-                focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
-            }
-        }
        break;
     case EnterNotify:
     case LeaveNotify:
@@ -413,7 +354,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
              (e->xcrossing.detail == NotifyAncestor ||
               e->xcrossing.detail == NotifyNonlinearVirtual ||
               e->xcrossing.detail == NotifyVirtual))) {
-#ifdef DEBUG_FOCUS
+#ifdef aDEBUG_FOCUS
             ob_debug("%sNotify mode %d detail %d on %lx IGNORED\n",
                      (e->type == EnterNotify ? "Enter" : "Leave"),
                      e->xcrossing.mode,
@@ -421,7 +362,7 @@ static gboolean event_ignore(XEvent *e, ObClient *client)
 #endif
             return TRUE;
         }
-#ifdef DEBUG_FOCUS
+#ifdef aDEBUG_FOCUS
         ob_debug("%sNotify mode %d detail %d on %lx\n",
                  (e->type == EnterNotify ? "Enter" : "Leave"),
                  e->xcrossing.mode,
@@ -545,6 +486,12 @@ static void event_process(const XEvent *ec, gpointer data)
     }
 }
 
+static void event_done(gpointer data)
+{
+    if (!focus_client)
+        focus_fallback(OB_FOCUS_FALLBACK_NOFOCUS);
+}
+
 static void event_handle_root(XEvent *e)
 {
     Atom msgtype;
@@ -650,27 +597,22 @@ static void event_handle_client(ObClient *client, XEvent *e)
         break;
     case FocusIn:
 #ifdef DEBUG_FOCUS
-        ob_debug("FocusIn on client for %lx\n", client->window);
+        ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"),
+                 client->window);
 #endif
-        if (client != focus_client) {
+        if (client != focus_client)
             focus_set_client(client);
-            frame_adjust_focus(client->frame, TRUE);
-        }
+        frame_adjust_focus(client->frame, e->type == FocusIn);
         break;
     case FocusOut:
 #ifdef DEBUG_FOCUS
-        ob_debug("FocusOut on client for %lx\n", client->window);
+        ob_debug("Focus%s on client for %lx\n", (e->type==FocusIn?"In":"Out"),
+                 client->window);
 #endif
-        /* are we a fullscreen window or a transient of one? (checks layer)
-           if we are then we need to be iconified since we are losing focus
-         */
-        if (client->layer == OB_STACKING_LAYER_FULLSCREEN && !client->iconic &&
-            !client_search_focus_tree_full(client))
-            /* iconify fullscreen windows when they and their transients
-               aren't focused */
-            client_iconify(client, TRUE, TRUE);
-        frame_adjust_focus(client->frame, FALSE);
-       break;
+        if (client == focus_client)
+            focus_client = NULL;
+        frame_adjust_focus(client->frame, e->type == FocusIn);
+        break;
     case LeaveNotify:
         con = frame_context(client, e->xcrossing.window);
         switch (con) {
@@ -733,7 +675,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
         case OB_FRAME_CONTEXT_FRAME:
             if (client_normal(client)) {
                 if (config_focus_follow) {
-#ifdef DEBUG_FOCUS
+#ifdef aDEBUG_FOCUS
                     ob_debug("EnterNotify on %lx, focusing window\n",
                              client->window);
 #endif
index a79049106a85ceb0efc1d6282cab7bdc2f1d4811..2582736bb59ac24ae485622dbc4ef05422410d64 100644 (file)
@@ -73,7 +73,7 @@ void focus_set_client(ObClient *client)
     screen_install_colormap(focus_client, FALSE);
     screen_install_colormap(client, TRUE);
 
-    if (client == NULL) {
+    if (!client) {
        /* when nothing will be focused, send focus to the backup target */
        XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot,
                        event_lasttime);
@@ -87,16 +87,22 @@ void focus_set_client(ObClient *client)
     old = focus_client;
     focus_client = client;
 
-    /* move to the top of the list */
-    if (client != NULL)
-        push_to_top(client);
+    if (old) {
+        /* focus state can affect the stacking layer */
+        client_calc_layer(old);
+    }
+    if (client) {
+        /* focus state can affect the stacking layer */
+        client_calc_layer(client);
 
-    /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
-    if (ob_state() != OB_STATE_EXITING) {
-        active = client ? client->window : None;
-        PROP_SET32(RootWindow(ob_display, ob_screen),
-                   net_active_window, window, active);
+        /* move to the top of the list */
+        push_to_top(client);
     }
+
+    /* set the NET_ACTIVE_WINDOW hint */
+    active = client ? client->window : None;
+    PROP_SET32(RootWindow(ob_display, ob_screen),
+               net_active_window, window, active);
 }
 
 static gboolean focus_under_pointer()
index 9ee2075784fa5c8420cad8224141fdc067419574..a50a48fb97cf755913831078c3fbf4cfdc196270 100644 (file)
@@ -1,4 +1,5 @@
 #include "mainloop.h"
+#include "focus.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -99,6 +100,7 @@ struct _ObMainLoopXHandlerType
     ObMainLoop *loop;
     gpointer data;
     ObMainLoopXHandler func;
+    ObMainLoopXDoneHandler done_func;
     GDestroyNotify destroy;
 };
 
@@ -263,6 +265,12 @@ void ob_main_loop_run(ObMainLoop *loop)
                     h->func(&e, h->data);
                 }
             } while (XPending(loop->display));
+
+            for (it = loop->x_handlers; it; it = g_slist_next(it)) {
+                ObMainLoopXHandlerType *h = it->data;
+                if (h->done_func)
+                    h->done_func(h->data);
+            }
         } else {
             /* this only runs if there were no x events received */
 
@@ -297,6 +305,7 @@ void ob_main_loop_exit(ObMainLoop *loop)
 
 void ob_main_loop_x_add(ObMainLoop *loop,
                         ObMainLoopXHandler handler,
+                        ObMainLoopXDoneHandler done_handler,
                         gpointer data,
                         GDestroyNotify notify)
 {
@@ -305,6 +314,7 @@ void ob_main_loop_x_add(ObMainLoop *loop,
     h = g_new(ObMainLoopXHandlerType, 1);
     h->loop = loop;
     h->func = handler;
+    h->done_func = done_handler;
     h->data = data;
     h->destroy = notify;
     loop->x_handlers = g_slist_prepend(loop->x_handlers, h);
index 8e0e5ed685dc418a47b9d30a4f70ec26485cb3f9..f33773169423c4e7204f9e5e1b51204e30272ff0 100644 (file)
@@ -10,9 +10,11 @@ ObMainLoop *ob_main_loop_new(Display *display);
 void        ob_main_loop_destroy(ObMainLoop *loop);
 
 typedef void (*ObMainLoopXHandler) (const XEvent *e, gpointer data);
+typedef void (*ObMainLoopXDoneHandler) (gpointer data);
 
 void ob_main_loop_x_add(ObMainLoop *loop,
                         ObMainLoopXHandler handler,
+                        ObMainLoopXDoneHandler done_handler,
                         gpointer data,
                         GDestroyNotify notify);
 void ob_main_loop_x_remove(ObMainLoop *loop,
index cebbfc9fd72d0f3efa091b535afd20611e0ed674..4d04bb24bcce44f7193d912df676c028e6cdd9c6 100644 (file)
@@ -249,6 +249,7 @@ void stacking_raise(ObWindow *window)
         ObClient *c;
         ObClient *selected;
         selected = WINDOW_AS_CLIENT(window);
+        g_message("raising 0x%x", selected->window);
         /*c = client_search_top_transient(selected);*/ c = selected;
         wins = pick_windows(c, selected, TRUE);
         /*wins = g_list_concat(wins, pick_group_windows(c, selected, TRUE));*/
index ebe6e6b3fdb8481f68057768b083a6291c33c355..d7591f7b9e7ab0aa890656733009eaf55a4277e8 100644 (file)
@@ -41,7 +41,7 @@ void sn_startup(gboolean reconfig)
     sn_context = sn_monitor_context_new(sn_display, ob_screen,
                                         sn_event_func, NULL, NULL);
 
-    ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL);
+    ob_main_loop_x_add(ob_main_loop, sn_handler, NULL, NULL, NULL);
 }
 
 void sn_shutdown(gboolean reconfig)
This page took 0.042479 seconds and 4 git commands to generate.