]> Dogcows Code - chaz/openbox/blobdiff - openbox/event.c
kill enter events without using pointer grabs
[chaz/openbox] / openbox / event.c
index 2ba9c4c7251ccb9f3e9e73cf67eb2fe04157d4a6..7b8793fa8bc0e28aaa0a59e3d3c7bf943a7dc643 100644 (file)
@@ -28,6 +28,7 @@
 #include "config.h"
 #include "screen.h"
 #include "frame.h"
+#include "grab.h"
 #include "menu.h"
 #include "menuframe.h"
 #include "keyboard.h"
@@ -98,13 +99,6 @@ Time event_curtime = CurrentTime;
 static guint ignore_enter_focus = 0;
 static gboolean menu_can_hide;
 static gboolean focus_left_screen = FALSE;
-/*! 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;
 
 #ifdef USE_SM
 static void ice_handler(gint fd, gpointer conn)
@@ -138,7 +132,7 @@ void event_startup(gboolean reconfig)
     IceAddConnectionWatch(ice_watch, NULL);
 #endif
 
-    client_add_destructor(focus_delay_client_dest, NULL);
+    client_add_destroy_notify(focus_delay_client_dest, NULL);
 }
 
 void event_shutdown(gboolean reconfig)
@@ -149,7 +143,7 @@ void event_shutdown(gboolean reconfig)
     IceRemoveConnectionWatch(ice_watch, NULL);
 #endif
 
-    client_remove_destructor(focus_delay_client_dest);
+    client_remove_destroy_notify(focus_delay_client_dest);
 }
 
 static Window event_get_window(XEvent *e)
@@ -300,24 +294,36 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only)
 
         /* These are the ones we want.. */
 
-        if (win == RootWindow(ob_display, ob_screen) && !in_client_only) {
+        if (win == RootWindow(ob_display, ob_screen)) {
+            /* If looking for a focus in on a client, then always return
+               FALSE for focus in's to the root window */
+            if (in_client_only)
+                return FALSE;
             /* This means focus reverted off of a client */
-            if (detail == NotifyPointerRoot || detail == NotifyDetailNone ||
-                detail == NotifyInferior)
+            else if (detail == NotifyPointerRoot ||
+                     detail == NotifyDetailNone ||
+                     detail == NotifyInferior)
                 return TRUE;
             else
                 return FALSE;
         }
 
+        /* It was on a client, was it a valid one?
+           It's possible to get a FocusIn event for a client that was managed
+           but has disappeared.
+        */
+        if (in_client_only) {
+            ObWindow *w = g_hash_table_lookup(window_map, &e->xfocus.window);
+            if (!w || !WINDOW_IS_CLIENT(w))
+                return FALSE;
+        }
+
         /* This means focus moved from the root window to a client */
         if (detail == NotifyVirtual)
             return TRUE;
         /* This means focus moved from one client to another */
         if (detail == NotifyNonlinearVirtual)
             return TRUE;
-        /* This means focus moved to the frame window */
-        if (detail == NotifyInferior && !in_client_only)
-            return TRUE;
 
         /* Otherwise.. */
         return FALSE;
@@ -342,21 +348,18 @@ static gboolean wanted_focusevent(XEvent *e, gboolean in_client_only)
         /* This means focus moved from one client to another */
         if (detail == NotifyNonlinearVirtual)
             return TRUE;
-        /* This means focus had moved to our frame window and now moved off */
-        if (detail == NotifyNonlinear)
-            return TRUE;
 
         /* Otherwise.. */
         return FALSE;
     }
 }
 
-static Bool look_for_focusin(Display *d, XEvent *e, XPointer arg)
+static Bool event_look_for_focusin(Display *d, XEvent *e, XPointer arg)
 {
     return e->type == FocusIn && wanted_focusevent(e, FALSE);
 }
 
-static Bool look_for_focusin_client(Display *d, XEvent *e, XPointer arg)
+Bool event_look_for_focusin_client(Display *d, XEvent *e, XPointer arg)
 {
     return e->type == FocusIn && wanted_focusevent(e, TRUE);
 }
@@ -385,6 +388,9 @@ static void print_focusevent(XEvent *e)
     case NotifyDetailNone:  detailstr="NotifyDetailNone";  break;
     }
 
+    if (mode == NotifyGrab || mode == NotifyUngrab)
+        return;
+
     g_assert(modestr);
     g_assert(detailstr);
     ob_debug_type(OB_DEBUG_FOCUS, "Focus%s 0x%x mode=%s detail=%s\n",
@@ -471,9 +477,8 @@ static void event_process(const XEvent *ec, gpointer data)
             e->xfocus.detail == NotifyInferior)
         {
             XEvent ce;
-            ob_debug_type(OB_DEBUG_FOCUS,
-                          "Focus went to pointer root/none or to our frame "
-                          "window\n");
+
+            ob_debug_type(OB_DEBUG_FOCUS, "Focus went to pointer root/none\n");
 
             /* If another FocusIn is in the queue then don't fallback yet. This
                fixes the fun case of:
@@ -488,40 +493,45 @@ static void event_process(const XEvent *ec, gpointer data)
                But if the other focus in is something like PointerRoot then we
                still want to fall back.
             */
-            if (XCheckIfEvent(ob_display, &ce, look_for_focusin_client, NULL)){
+            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 {
-                /* Focus has been reverted to the root window, nothing, or to
-                   our frame window.
+                /* Focus has been reverted to the root window or nothing.
 
                    FocusOut events come after UnmapNotify, so we don't need to
                    worry about focusing an invalid window
                 */
 
-                /* In this case we know focus is in our screen */
-                if (e->xfocus.detail == NotifyInferior)
-                    focus_left_screen = FALSE;
-
                 if (!focus_left_screen)
-                    focus_tried = focus_fallback(TRUE);
+                    focus_fallback(TRUE);
             }
-        } else if (client && client != focus_client) {
+        }
+        else if (!client)
+        {
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Focus went to a window that is already gone\n");
+
+            /* If you send focus to a window and then it disappears, you can
+               get the FocusIn for it, after it is unmanaged.
+               Just wait for the next FocusOut/FocusIn pair. */
+        }
+        else if (client != focus_client) {
             focus_left_screen = FALSE;
             frame_adjust_focus(client->frame, TRUE);
             focus_set_client(client);
             client_calc_layer(client);
             client_bring_helper_windows(client);
-
-            focus_tried = NULL; /* focus isn't "trying" to go anywhere now */
         }
     } else if (e->type == FocusOut) {
         gboolean nomove = FALSE;
         XEvent ce;
 
         /* Look for the followup FocusIn */
-        if (!XCheckIfEvent(ob_display, &ce, look_for_focusin, NULL)) {
+        if (!XCheckIfEvent(ob_display, &ce, event_look_for_focusin, NULL)) {
             /* There is no FocusIn, this means focus went to a window that
                is not being managed, or a window on another screen. */
             Window win, root;
@@ -556,12 +566,14 @@ static void event_process(const XEvent *ec, gpointer data)
                 ob_debug_type(OB_DEBUG_FOCUS,
                               "Focus went to an unmanaged window 0x%x !\n",
                               ce.xfocus.window);
-                focus_tried = focus_fallback(TRUE);
+                focus_fallback(TRUE);
             }
         }
 
         if (client && !nomove) {
             frame_adjust_focus(client->frame, FALSE);
+            if (client == focus_client)
+                focus_set_client(NULL);
             /* focus_set_client has already been called for sure */
             client_calc_layer(client);
         }
@@ -670,7 +682,7 @@ static void event_handle_root(XEvent *e)
                 screen_set_num_desktops(d);
         } else if (msgtype == prop_atoms.net_showing_desktop) {
             screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
-        } else if (msgtype == prop_atoms.openbox_control) {
+        } else if (msgtype == prop_atoms.ob_control) {
             if (e->xclient.data.l[0] == 1)
                 ob_reconfigure();
             else if (e->xclient.data.l[0] == 2)
@@ -1070,7 +1082,10 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
         if (config) {
             client_find_onscreen(client, &x, &y, w, h, FALSE);
-            client_configure_full(client, x, y, w, h, FALSE, TRUE);
+            client_configure(client, x, y, w, h, FALSE, TRUE);
+
+            /* ignore enter events caused by these like ob actions do */
+            event_ignore_queued_enters();
         }
         break;
     }
@@ -1084,40 +1099,10 @@ static void event_handle_client(ObClient *client, XEvent *e)
                  client->window, e->xunmap.event, e->xunmap.from_configure,
                  client->ignore_unmaps);
         client_unmanage(client);
-
-        /* we were trying to focus this window but it's gone */
-        if (client == focus_tried) {
-            ob_debug_type(OB_DEBUG_FOCUS, "Tried to focus window 0x%x and it "
-                          "is being unmanaged:\n");
-            if (XCheckIfEvent(ob_display, &ce, 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_tried = focus_fallback(TRUE);
-            }
-        }
         break;
     case DestroyNotify:
         ob_debug("DestroyNotify for window 0x%x\n", client->window);
         client_unmanage(client);
-
-        /* we were trying to focus this window but it's gone */
-        if (client == focus_tried) {
-            ob_debug_type(OB_DEBUG_FOCUS, "Tried to focus window 0x%x and it "
-                          "is being unmanaged:\n");
-            if (XCheckIfEvent(ob_display, &ce, 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_tried = focus_fallback(TRUE);
-            }
-        }
         break;
     case ReparentNotify:
         /* this is when the client is first taken captive in the frame */
@@ -1136,21 +1121,6 @@ static void event_handle_client(ObClient *client, XEvent *e)
      
         ob_debug("ReparentNotify for window 0x%x\n", client->window);
         client_unmanage(client);
-
-        /* we were trying to focus this window but it's gone */
-        if (client == focus_tried) {
-            ob_debug_type(OB_DEBUG_FOCUS, "Tried to focus window 0x%x and it "
-                          "is being unmanaged:\n");
-            if (XCheckIfEvent(ob_display, &ce, 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_tried = focus_fallback(TRUE);
-            }
-        }
         break;
     case MapRequest:
         ob_debug("MapRequest for 0x%lx\n", client->window);
@@ -1209,6 +1179,9 @@ static void event_handle_client(ObClient *client, XEvent *e)
                      client->window);
             client_set_state(client, e->xclient.data.l[0],
                              e->xclient.data.l[1], e->xclient.data.l[2]);
+
+            /* ignore enter events caused by these like ob actions do */
+            event_ignore_queued_enters();
         } else if (msgtype == prop_atoms.net_close_window) {
             ob_debug("net_close_window for 0x%lx\n", client->window);
             client_close(client);
@@ -1292,7 +1265,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
                      e->xclient.data.l[0] & 1 << 9, y);
             client_convert_gravity(client, grav, &x, &y, w, h);
             client_find_onscreen(client, &x, &y, w, h, FALSE);
+
             client_configure(client, x, y, w, h, FALSE, TRUE);
+
+            /* ignore enter events caused by these like ob actions do */
+            event_ignore_queued_enters();
         } else if (msgtype == prop_atoms.net_restack_window) {
             if (e->xclient.data.l[0] != 2) {
                 ob_debug_type(OB_DEBUG_APP_BUGS,
@@ -1326,11 +1303,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
                                              e->xclient.data.l[2], FALSE);
                     /* send a synthetic ConfigureNotify, cuz this is supposed
                        to be like a ConfigureRequest. */
-                    client_configure_full(client, client->area.x,
-                                          client->area.y,
-                                          client->area.width,
-                                          client->area.height,
-                                          FALSE, TRUE);
+                    client_reconfigure(client);
                 } else
                     ob_debug_type(OB_DEBUG_APP_BUGS,
                                   "_NET_RESTACK_WINDOW sent for window %s "
@@ -1645,6 +1618,7 @@ static gboolean event_handle_menu(XEvent *ev)
         {
             menu_frame_select(e->frame, NULL, FALSE);
         }
+        break;
     case MotionNotify:   
         if ((e = menu_entry_frame_under(ev->xmotion.x_root,   
                                         ev->xmotion.y_root)))
This page took 0.027521 seconds and 4 git commands to generate.