change in how things are ungrabbed to avoid grabwhilenotify. don't ungrab every key...
authorDana Jansens <danakj@orodu.net>
Sat, 26 May 2007 22:13:34 +0000 (22:13 +0000)
committerDana Jansens <danakj@orodu.net>
Sat, 26 May 2007 22:13:34 +0000 (22:13 +0000)
this should be less intrusive and seems to work

openbox/action.c
openbox/client.c
openbox/event.c
openbox/event.h
openbox/keyboard.c
tests/focusout.c

index 4bb292e..39da39a 100644 (file)
@@ -1216,11 +1216,9 @@ void action_execute(union ActionData *data)
     if (data->execute.path) {
         cmd = g_filename_from_utf8(data->execute.path, -1, NULL, NULL, NULL);
         if (cmd) {
-            /* If there is an interactive action going on, then cancel it
-               to release the keyboard, so that the run application
-               can grab the keyboard if it wants to. */
-            if (keyboard_interactively_grabbed())
-                keyboard_interactive_cancel();
+            /* If there is a keyboard grab going on then we need to cancel
+               it so the application can grab things */
+            event_cancel_all_key_grabs();
 
             if (!g_shell_parse_argv (cmd, NULL, &argv, &e)) {
                 g_message(_("Failed to execute '%s': %s"),
index ffbcd5c..bf77233 100644 (file)
@@ -2540,8 +2540,7 @@ gboolean client_hide(ObClient *self)
                actions should not rely on being able to move focus during an
                interactive grab.
             */
-            if (keyboard_interactively_grabbed())
-                keyboard_interactive_cancel();
+            event_cancel_all_key_grabs();
         }
 
         frame_hide(self->frame);
@@ -3526,8 +3525,7 @@ gboolean client_focus(ObClient *self)
        actions should not rely on being able to move focus during an
        interactive grab.
     */
-    if (keyboard_interactively_grabbed())
-        keyboard_interactive_cancel();
+    event_cancel_all_key_grabs();
 
     xerror_set_ignore(TRUE);
     xerror_occured = FALSE;
index cb73933..e7ef27f 100644 (file)
@@ -1837,6 +1837,25 @@ static gboolean is_enter_focus_event_ignored(XEvent *e)
     return FALSE;
 }
 
+void event_cancel_all_key_grabs()
+{
+    if (keyboard_interactively_grabbed())
+        keyboard_interactive_cancel();
+    else if (menu_frame_visible)
+        menu_frame_hide_all();
+    else if (grab_on_keyboard())
+        ungrab_keyboard();
+    else
+        /* If we don't have the keyboard grabbed, then ungrab it with
+           XUngrabKeyboard, so that there is not a passive grab left
+           on from the KeyPress. If the grab is left on, and focus
+           moves during that time, it will be NotifyWhileGrabbed, and
+           applications like to ignore those! */
+        if (!keyboard_interactively_grabbed())
+            XUngrabKeyboard(ob_display, CurrentTime);
+
+}
+
 gboolean event_time_after(Time t1, Time t2)
 {
     g_assert(t1 != CurrentTime);
index 542115f..29f621d 100644 (file)
@@ -43,6 +43,9 @@ void event_enter_client(struct _ObClient *client);
   till now. */
 void event_ignore_all_queued_enters();
 
+/*! End *all* active and passive grabs on the keyboard */
+void event_cancel_all_key_grabs();
+
 /* Halts any focus delay in progress, use this when the user is selecting a
    window for focus */
 void event_halt_focus_delay();
index 2c60ac3..218e251 100644 (file)
@@ -311,14 +311,6 @@ void keyboard_event(ObClient *client, const XEvent *e)
             else {
                 keyboard_reset_chains(0);
 
-                /* If we don't have the keyboard grabbed, then ungrab it with
-                   XUngrabKeyboard, so that there is not a passive grab left
-                   on from the KeyPress. If the grab is left on, and focus
-                   moves during that time, it will be NotifyWhileGrabbed, and
-                   applications like to ignore those! */
-                if (!keyboard_interactively_grabbed())
-                    XUngrabKeyboard(ob_display, e->xkey.time);
-
                 action_run_key(p->actions, client, e->xkey.state,
                                e->xkey.x_root, e->xkey.y_root,
                                e->xkey.time);
index 1f31a8a..1cc7259 100644 (file)
@@ -47,7 +47,8 @@ int main () {
     XSetWindowBackground(display,win,WhitePixel(display,0)); 
     XSetWindowBackground(display,child,BlackPixel(display,0)); 
 
-    XSelectInput(display, win, FocusChangeMask);
+    XSelectInput(display, win,
+                 FocusChangeMask|EnterWindowMask|LeaveWindowMask);
     XMapWindow(display, win);
     XMapWindow(display, child);
 
@@ -157,8 +158,62 @@ int main () {
             printf("mode      : %s\n", mode);
             printf("detail    : %s\n", detail);
             printf("---\n");
-        }
+            break;
+        case EnterNotify:
+            switch (report.xcrossing.mode) {
+            case NotifyNormal: mode = "NotifyNormal"; break;
+            case NotifyGrab: mode = "NotifyGrab"; break;
+            case NotifyUngrab: mode = "NotifyUngrab"; break;
+            }
+
+            switch (report.xcrossing.detail) {
+            case NotifyAncestor: detail = "NotifyAncestor"; break;
+            case NotifyVirtual: detail = "NotifyVirtual"; break;
+            case NotifyInferior: detail = "NotifyInferior"; break;
+            case NotifyNonlinear: detail = "NotifyNonlinear"; break;
+            case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+            case NotifyPointer: detail = "NotifyPointer"; break;
+            case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+            case NotifyDetailNone: detail = "NotifyDetailNone"; break;
+            }
+            printf("enternotify\n");
+            printf("type      : %d\n", report.xcrossing.type);
+            printf("serial    : %d\n", report.xcrossing.serial);
+            printf("send_event: %d\n", report.xcrossing.send_event);
+            printf("display   : 0x%x\n", report.xcrossing.display);
+            printf("window    : 0x%x\n", report.xcrossing.window);
+            printf("mode      : %s\n", mode);
+            printf("detail    : %s\n", detail);
+            printf("---\n");
+            break;
+        case LeaveNotify:
+            switch (report.xcrossing.mode) {
+            case NotifyNormal: mode = "NotifyNormal"; break;
+            case NotifyGrab: mode = "NotifyGrab"; break;
+            case NotifyUngrab: mode = "NotifyUngrab"; break;
+            }
 
+            switch (report.xcrossing.detail) {
+            case NotifyAncestor: detail = "NotifyAncestor"; break;
+            case NotifyVirtual: detail = "NotifyVirtual"; break;
+            case NotifyInferior: detail = "NotifyInferior"; break;
+            case NotifyNonlinear: detail = "NotifyNonlinear"; break;
+            case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+            case NotifyPointer: detail = "NotifyPointer"; break;
+            case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+            case NotifyDetailNone: detail = "NotifyDetailNone"; break;
+            }
+            printf("leavenotify\n");
+            printf("type      : %d\n", report.xcrossing.type);
+            printf("serial    : %d\n", report.xcrossing.serial);
+            printf("send_event: %d\n", report.xcrossing.send_event);
+            printf("display   : 0x%x\n", report.xcrossing.display);
+            printf("window    : 0x%x\n", report.xcrossing.window);
+            printf("mode      : %s\n", mode);
+            printf("detail    : %s\n", detail);
+            printf("---\n");
+            break;
+        }
     }
 
     return 1;