]> Dogcows Code - chaz/openbox/blobdiff - openbox/event.c
ignore mouse clicks on override-redirect windows that aren't owned by openbox
[chaz/openbox] / openbox / event.c
index 9c47c04a3a49e42290a94bfea25dd6ba4adb122c..cd5625990e9fa31ea1cac9f4863a6fb97bfe8f64 100644 (file)
@@ -91,6 +91,7 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e);
 static void event_handle_client(ObClient *c, XEvent *e);
 static void event_handle_user_input(ObClient *client, XEvent *e);
 static gboolean is_enter_focus_event_ignored(XEvent *e);
+static void event_ignore_enter_range(gulong start, gulong end);
 
 static void focus_delay_dest(gpointer data);
 static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
@@ -99,6 +100,8 @@ static void focus_delay_client_dest(ObClient *client, gpointer data);
 
 Time event_curtime = CurrentTime;
 Time event_last_user_time = CurrentTime;
+/*! The serial of the current X event */
+gulong event_curserial;
 
 static gboolean focus_left_screen = FALSE;
 /*! A list of ObSerialRanges which are to be ignored for mouse enter events */
@@ -243,10 +246,15 @@ static void event_set_curtime(XEvent *e)
         event_last_user_time = CurrentTime;
 
     event_curtime = t;
+    event_curserial = 0;
 }
 
 static void event_hack_mods(XEvent *e)
 {
+#ifdef XKB
+    XkbStateRec xkb_state;
+#endif
+
     switch (e->type) {
     case ButtonPress:
     case ButtonRelease:
@@ -256,10 +264,20 @@ static void event_hack_mods(XEvent *e)
         e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
         break;
     case KeyRelease:
-        e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
-        /* remove from the state the mask of the modifier key being released,
-           if it is a modifier key being released that is */
-        e->xkey.state &= ~modkeys_keycode_to_mask(e->xkey.keycode);
+#ifdef XKB
+        /* If XKB is present, then the modifiers are all strange from its
+           magic.  Our X core protocol stuff won't work, so we use this to
+           find what the modifier state is instead. */
+        if (XkbGetState(ob_display, XkbUseCoreKbd, &xkb_state) == Success)
+            e->xkey.state = xkb_state.compat_state;
+        else
+#endif
+        {
+            e->xkey.state = modkeys_only_modifier_masks(e->xkey.state);
+            /* remove from the state the mask of the modifier key being
+               released, if it is a modifier key being released that is */
+            e->xkey.state &= ~modkeys_keycode_to_mask(e->xkey.keycode);
+        }
         break;
     case MotionNotify:
         e->xmotion.state = modkeys_only_modifier_masks(e->xmotion.state);
@@ -465,6 +483,7 @@ static void event_process(const XEvent *ec, gpointer data)
     }
 
     event_set_curtime(e);
+    event_curserial = e->xany.serial;
     event_hack_mods(e);
     if (event_ignore(e, client)) {
         if (ed)
@@ -619,6 +638,11 @@ static void event_process(const XEvent *ec, gpointer data)
         event_handle_root(e);
     else if (e->type == MapRequest)
         client_manage(window);
+    else if (e->type == MappingNotify) {
+        /* keyboard layout changes, reconfigure openbox. need to restart the
+           modkeys system, but also to reload the key bindings. */
+        ob_reconfigure();
+    }
     else if (e->type == ClientMessage) {
         /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for
            windows that are not managed yet. */
@@ -670,12 +694,50 @@ static void event_process(const XEvent *ec, gpointer data)
     }
 #endif
 
-    if (e->type == ButtonPress || e->type == ButtonRelease ||
-        e->type == MotionNotify || e->type == KeyPress ||
-        e->type == KeyRelease)
-    {
-        event_handle_user_input(client, e);
+    if (e->type == ButtonPress || e->type == ButtonRelease) {
+        /* If the button press was on some non-root window, or was physically
+           on the root window, the process it */
+        if (window != RootWindow(ob_display, ob_screen) ||
+            e->xbutton.subwindow == None)
+        {
+            event_handle_user_input(client, e);
+        }
+        /* Otherwise only process it if it was physically on an openbox
+           internal window */
+        else {
+            Window target, parent, root, *children;
+            unsigned int nchildren;
+            ObWindow *w;
+
+            /* Find the top level ancestor of the subwindow, besides the
+               root */
+            target = e->xbutton.subwindow;
+            ob_debug("subwindow 0x%x\n", target);
+            while (XQueryTree(ob_display, target, &root, &parent, &children,
+                              &nchildren) != 0)
+            {
+                XFree(children);
+                if (parent == root) {
+                    ob_debug("parent is root\n");
+                    break;
+                }
+                target = parent;
+            }
+            ob_debug("toplevel 0x%x\n", target);
+
+            w = g_hash_table_lookup(window_map, &target);
+            ob_debug("w 0x%x\n", w);
+                
+            if ((w = g_hash_table_lookup(window_map, &target)) &&
+                WINDOW_IS_INTERNAL(w))
+            {
+                event_handle_user_input(client, e);
+            }
+        }
     }
+    else if (e->type == KeyPress || e->type == KeyRelease ||
+             e->type == MotionNotify)
+        event_handle_user_input(client, e);
 
     /* if something happens and it's not from an XEvent, then we don't know
        the time */
@@ -718,6 +780,8 @@ static void event_handle_root(XEvent *e)
                 ob_reconfigure();
             else if (e->xclient.data.l[0] == 2)
                 ob_restart();
+            else if (e->xclient.data.l[0] == 3)
+                ob_exit(0);
         }
         break;
     case PropertyNotify:
@@ -989,18 +1053,23 @@ static void event_handle_client(ObClient *client, XEvent *e)
                 is_enter_focus_event_ignored(e))
             {
                 ob_debug_type(OB_DEBUG_FOCUS,
-                              "%sNotify mode %d detail %d on %lx IGNORED\n",
+                              "%sNotify mode %d detail %d serial %lu on %lx "
+                              "IGNORED\n",
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
-                              e->xcrossing.detail, client?client->window:0);
+                              e->xcrossing.detail,
+                              e->xcrossing.serial,
+                              client?client->window:0);
             }
             else {
                 ob_debug_type(OB_DEBUG_FOCUS,
-                              "%sNotify mode %d detail %d on %lx, "
+                              "%sNotify mode %d detail %d serial %lu on %lx, "
                               "focusing window\n",
                               (e->type == EnterNotify ? "Enter" : "Leave"),
                               e->xcrossing.mode,
-                              e->xcrossing.detail, (client?client->window:0));
+                              e->xcrossing.detail,
+                              e->xcrossing.serial,
+                              (client?client->window:0));
                 if (config_focus_follow)
                     event_enter_client(client);
             }
@@ -1579,7 +1648,7 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e)
     }
 }
 
-static ObMenuFrame* find_active_menu()
+static ObMenuFrame* find_active_menu(void)
 {
     GList *it;
     ObMenuFrame *ret = NULL;
@@ -1593,7 +1662,7 @@ static ObMenuFrame* find_active_menu()
     return ret;
 }
 
-static ObMenuFrame* find_active_or_last_menu()
+static ObMenuFrame* find_active_or_last_menu(void)
 {
     ObMenuFrame *ret = NULL;
 
@@ -1843,10 +1912,8 @@ static gboolean focus_delay_func(gpointer data)
     if (menu_frame_visible || moveresize_in_progress) return FALSE;
 
     event_curtime = d->time;
-    if (focus_client != d->client) {
-        if (client_focus(d->client) && config_focus_raise)
-            stacking_raise(CLIENT_AS_WINDOW(d->client));
-    }
+    if (client_focus(d->client) && config_focus_raise)
+        stacking_raise(CLIENT_AS_WINDOW(d->client));
     event_curtime = old;
     return FALSE; /* no repeat */
 }
@@ -1857,33 +1924,44 @@ static void focus_delay_client_dest(ObClient *client, gpointer data)
                                      client, FALSE);
 }
 
-void event_halt_focus_delay()
+void event_halt_focus_delay(gulong serial)
 {
+    /* ignore all enter events up till the event which caused this to occur */
+    if (event_curserial) event_ignore_enter_range(1, event_curserial);
     ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func);
 }
 
-gulong event_start_ignore_all_enters()
+gulong event_start_ignore_all_enters(void)
 {
+    /* increment the serial so we don't ignore events we weren't meant to */
     XSync(ob_display, FALSE);
     return LastKnownRequestProcessed(ob_display);
 }
 
-void event_end_ignore_all_enters(gulong start)
+static void event_ignore_enter_range(gulong start, gulong end)
 {
     ObSerialRange *r;
 
     g_assert(start != 0);
-    XSync(ob_display, FALSE);
+    g_assert(end != 0);
 
     r = g_new(ObSerialRange, 1);
     r->start = start;
-    r->end = LastKnownRequestProcessed(ob_display);
+    r->end = end;
     ignore_serials = g_slist_prepend(ignore_serials, r);
 
+    ob_debug_type(OB_DEBUG_FOCUS, "ignoring enters from %lu until %lu\n",
+                  r->start, r->end);
+
     /* increment the serial so we don't ignore events we weren't meant to */
     XSync(ob_display, FALSE);
 }
 
+void event_end_ignore_all_enters(gulong start)
+{
+    event_ignore_enter_range(start, LastKnownRequestProcessed(ob_display));
+}
+
 static gboolean is_enter_focus_event_ignored(XEvent *e)
 {
     GSList *it, *next;
@@ -1909,7 +1987,7 @@ static gboolean is_enter_focus_event_ignored(XEvent *e)
     return FALSE;
 }
 
-void event_cancel_all_key_grabs()
+void event_cancel_all_key_grabs(void)
 {
     if (actions_interactive_act_running()) {
         actions_interactive_cancel_act();
@@ -1956,7 +2034,7 @@ gboolean event_time_after(Time t1, Time t2)
         return t1 >= t2 && t1 < (t2 + TIME_HALF);
 }
 
-Time event_get_server_time()
+Time event_get_server_time(void)
 {
     /* Generate a timestamp */
     XEvent event;
This page took 0.031613 seconds and 4 git commands to generate.