diff --git a/openbox/action.c b/openbox/action.c index 4bb292ef..39da39a5 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -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"), diff --git a/openbox/client.c b/openbox/client.c index ffbcd5ca..bf772336 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -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; diff --git a/openbox/event.c b/openbox/event.c index cb739339..e7ef27fb 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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); diff --git a/openbox/event.h b/openbox/event.h index 542115fb..29f621d5 100644 --- a/openbox/event.h +++ b/openbox/event.h @@ -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(); diff --git a/openbox/keyboard.c b/openbox/keyboard.c index 2c60ac3d..218e251a 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -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); diff --git a/tests/focusout.c b/tests/focusout.c index 1f31a8aa..1cc7259d 100644 --- a/tests/focusout.c +++ b/tests/focusout.c @@ -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;