From 36bbff0b88cefe9838fa10adeb04fe22b717b86a Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 26 May 2007 22:29:33 +0000 Subject: [PATCH] merge r6904-6915 from trunk --- doc/rc-mouse-focus.xml | 6 +-- openbox/action.c | 29 ++++++------- openbox/client.c | 8 ++-- openbox/event.c | 19 ++++++++ openbox/event.h | 3 ++ openbox/focus.c | 24 ++++++++++- openbox/focus_cycle.c | 98 +++++++++++++++++++++++------------------- openbox/focus_cycle.h | 2 +- openbox/keyboard.c | 8 ---- tests/focusout.c | 59 ++++++++++++++++++++++++- 10 files changed, 174 insertions(+), 82 deletions(-) diff --git a/doc/rc-mouse-focus.xml b/doc/rc-mouse-focus.xml index e5f327e1..af62b260 100644 --- a/doc/rc-mouse-focus.xml +++ b/doc/rc-mouse-focus.xml @@ -238,7 +238,7 @@ - + @@ -279,8 +279,6 @@ - - @@ -346,8 +344,6 @@ - - diff --git a/openbox/action.c b/openbox/action.c index faf065a1..39da39a5 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -47,17 +47,18 @@ static void client_action_end(union ActionData *data) { if (config_focus_follow) if (data->any.context != OB_FRAME_CONTEXT_CLIENT) { - if (!data->any.button && data->any.c) + if (!data->any.button && data->any.c) { event_ignore_all_queued_enters(); - else { - /* we USED to create a fake enter event here, so that when you - used a Press context, and the button was still down, - you could still get enter events that weren't - NotifyWhileGrabbed. - - only problem with this is that then the resulting focus - change events can ALSO be NotifyWhileGrabbed. And that is - bad. So, don't create fake enter events anymore. */ + } else { + ObClient *c; + + /* usually this is sorta redundant, but with a press action + that moves windows our from under the cursor, the enter + event will come as a GrabNotify which is ignored, so this + makes a fake enter event + */ + if ((c = client_under_pointer())) + event_enter_client(c); } } } @@ -1215,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..9c679fee 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); @@ -2932,7 +2931,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, event.xconfigure.y = self->root_pos.y; event.xconfigure.width = w; event.xconfigure.height = h; - event.xconfigure.border_width = 0; + event.xconfigure.border_width = self->border_width; event.xconfigure.above = self->frame->plate; event.xconfigure.override_redirect = FALSE; XSendEvent(event.xconfigure.display, event.xconfigure.window, @@ -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/focus.c b/openbox/focus.c index fad53e92..6713d98d 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -75,7 +75,8 @@ void focus_set_client(ObClient *client) screen_install_colormap(client, TRUE); /* in the middle of cycling..? kill it. */ - focus_cycle_stop(); + focus_cycle_stop(focus_client); + focus_cycle_stop(client); focus_client = client; @@ -193,9 +194,30 @@ void focus_nothing() event_curtime); } +void focus_order_add_new(ObClient *c) +{ + if (c->iconic) + focus_order_to_top(c); + else { + g_assert(!g_list_find(focus_order, c)); + /* if there are any iconic windows, put this above them in the order, + but if there are not, then put it under the currently focused one */ + if (focus_order && ((ObClient*)focus_order->data)->iconic) + focus_order = g_list_insert(focus_order, c, 0); + else + focus_order = g_list_insert(focus_order, c, 1); + } + + /* in the middle of cycling..? kill it. */ + focus_cycle_stop(c); +} + void focus_order_remove(ObClient *c) { focus_order = g_list_remove(focus_order, c); + + /* in the middle of cycling..? kill it. */ + focus_cycle_stop(c); } void focus_order_to_top(ObClient *c) diff --git a/openbox/focus_cycle.c b/openbox/focus_cycle.c index 4c0630b3..46f5f058 100644 --- a/openbox/focus_cycle.c +++ b/openbox/focus_cycle.c @@ -31,9 +31,12 @@ #include #include -ObClient *focus_cycle_target = NULL; +ObClient *focus_cycle_target = NULL; +static gboolean focus_cycle_iconic_windows; +static gboolean focus_cycle_all_desktops; +static gboolean focus_cycle_dock_windows; +static gboolean focus_cycle_desktop_windows; -static void focus_cycle_destroy_notify (ObClient *client, gpointer data); static gboolean focus_target_has_siblings (ObClient *ft, gboolean iconic_windows, gboolean all_desktops); @@ -49,30 +52,27 @@ static ObClient *focus_find_directional (ObClient *c, void focus_cycle_startup(gboolean reconfig) { if (reconfig) return; - - client_add_destroy_notify(focus_cycle_destroy_notify, NULL); } void focus_cycle_shutdown(gboolean reconfig) { if (reconfig) return; - - client_remove_destroy_notify(focus_cycle_destroy_notify); -} - -void focus_cycle_stop() -{ - if (focus_cycle_target) - focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); } -static void focus_cycle_destroy_notify(ObClient *client, gpointer data) +void focus_cycle_stop(ObClient *ifclient) { - /* end cycling if the target disappears. CurrentTime is fine, time won't - be used - */ - if (focus_cycle_target == client) + /* stop focus cycling if the given client is a valid focus target, + and so the cycling is being disrupted */ + if (focus_cycle_target && ifclient && + focus_cycle_target_valid(ifclient, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows)) + { focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); + focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); + } } /*! Returns if a focus target has valid group siblings that can be cycled @@ -185,7 +185,15 @@ void focus_cycle(gboolean forward, gboolean all_desktops, goto done_cycle; list = client_list; } - if (!focus_cycle_target) focus_cycle_target = focus_client; + + + if (focus_cycle_target == NULL) { + focus_cycle_iconic_windows = TRUE; + focus_cycle_all_desktops = all_desktops; + focus_cycle_dock_windows = dock_windows; + focus_cycle_desktop_windows = desktop_windows; + focus_cycle_target = focus_client; + } start = it = g_list_find(list, focus_cycle_target); if (!start) /* switched desktops or something? */ @@ -201,9 +209,11 @@ void focus_cycle(gboolean forward, gboolean all_desktops, if (it == NULL) it = g_list_last(list); } ft = it->data; - if (focus_cycle_target_valid(ft, TRUE, - all_desktops, dock_windows, - desktop_windows)) + if (focus_cycle_target_valid(ft, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows)) { if (interactive) { if (ft != focus_cycle_target) { /* prevents flicker */ @@ -212,9 +222,11 @@ void focus_cycle(gboolean forward, gboolean all_desktops, } if (dialog) /* same arguments as focus_target_valid */ - focus_cycle_popup_show(ft, TRUE, - all_desktops, dock_windows, - desktop_windows); + focus_cycle_popup_show(ft, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows); return; } else if (ft != focus_cycle_target) { focus_cycle_target = ft; @@ -355,8 +367,15 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows, if (!focus_order) goto done_cycle; + if (focus_cycle_target == NULL) { + focus_cycle_iconic_windows = FALSE; + focus_cycle_all_desktops = FALSE; + focus_cycle_dock_windows = dock_windows; + focus_cycle_desktop_windows = desktop_windows; + focus_cycle_target = focus_client; + } + if (!first) first = focus_client; - if (!focus_cycle_target) focus_cycle_target = focus_client; if (focus_cycle_target) ft = focus_find_directional(focus_cycle_target, dir, dock_windows, @@ -365,8 +384,11 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows, GList *it; for (it = focus_order; it; it = g_list_next(it)) - if (focus_cycle_target_valid(it->data, FALSE, FALSE, dock_windows, - desktop_windows)) + if (focus_cycle_target_valid(it->data, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows)) ft = it->data; } @@ -379,8 +401,10 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows, if (focus_cycle_target && dialog) { /* same arguments as focus_target_valid */ focus_cycle_popup_single_show(focus_cycle_target, - FALSE, FALSE, dock_windows, - desktop_windows); + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows); return; } @@ -396,19 +420,3 @@ done_cycle: return; } - -void focus_order_add_new(ObClient *c) -{ - if (c->iconic) - focus_order_to_top(c); - else { - g_assert(!g_list_find(focus_order, c)); - /* if there are any iconic windows, put this above them in the order, - but if there are not, then put it under the currently focused one */ - if (focus_order && ((ObClient*)focus_order->data)->iconic) - focus_order = g_list_insert(focus_order, c, 0); - else - focus_order = g_list_insert(focus_order, c, 1); - } -} - diff --git a/openbox/focus_cycle.h b/openbox/focus_cycle.h index 38c0e837..afdbdc79 100644 --- a/openbox/focus_cycle.h +++ b/openbox/focus_cycle.h @@ -42,7 +42,7 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows, gboolean desktop_windows, gboolean interactive, gboolean dialog, gboolean done, gboolean cancel); -void focus_cycle_stop(); +void focus_cycle_stop(struct _ObClient *ifclient); gboolean focus_cycle_target_valid(struct _ObClient *ft, gboolean iconic_windows, 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; -- 2.34.1