X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=ddf78e4fb48e261edd29cea9b0d3a0759d03ff65;hb=ea28a9e7ab6c81547b2730268097c4ad7d814a80;hp=5d85eaeb3dfdecbf771533c9dbb3a4f199c4f323;hpb=fb7a71da202632c7301ada67c8b4420bfb8d8fbe;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 5d85eaeb..ddf78e4f 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -31,6 +31,7 @@ #include "frame.h" #include "grab.h" #include "menu.h" +#include "prompt.h" #include "menuframe.h" #include "keyboard.h" #include "modkeys.h" @@ -43,6 +44,7 @@ #include "stacking.h" #include "extensions.h" #include "translate.h" +#include "ping.h" #include #include @@ -87,11 +89,12 @@ static void event_process(const XEvent *e, gpointer data); static void event_handle_root(XEvent *e); static gboolean event_handle_menu_keyboard(XEvent *e); static gboolean event_handle_menu(XEvent *e); +static void event_handle_prompt(ObPrompt *p, XEvent *e); static void event_handle_dock(ObDock *s, XEvent *e); 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 gboolean is_enter_focus_event_ignored(gulong serial); static void event_ignore_enter_range(gulong start, gulong end); static void focus_delay_dest(gpointer data); @@ -102,8 +105,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 gulong event_curserial; static gboolean focus_left_screen = FALSE; /*! A list of ObSerialRanges which are to be ignored for mouse enter events */ static GSList *ignore_serials = NULL; @@ -269,7 +272,8 @@ static void event_hack_mods(XEvent *e) 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; + e->xkey.state = + modkeys_only_modifier_masks(xkb_state.compat_state); else #endif { @@ -457,6 +461,7 @@ static void event_process(const XEvent *ec, gpointer data) ObWindow *obwin = NULL; XEvent ee, *e; ObEventData *ed = data; + ObPrompt *prompt = NULL; /* make a copy we can mangle */ ee = *ec; @@ -473,6 +478,8 @@ static void event_process(const XEvent *ec, gpointer data) break; case Window_Client: client = WINDOW_AS_CLIENT(obwin); + /* events on clients can be events on prompt windows too */ + prompt = client->prompt; break; case Window_Menu: /* not to be used for events */ @@ -481,6 +488,9 @@ static void event_process(const XEvent *ec, gpointer data) case Window_Internal: /* we don't do anything with events directly on these windows */ break; + case Window_Prompt: + prompt = WINDOW_AS_PROMPT(obwin); + break; } } @@ -517,7 +527,6 @@ static void event_process(const XEvent *ec, gpointer data) window with RevertToParent focus */ frame_adjust_focus(client->frame, FALSE); /* focus_set_client(NULL) has already been called */ - client_calc_layer(client); } else if (e->xfocus.detail == NotifyPointerRoot || e->xfocus.detail == NotifyDetailNone || @@ -627,7 +636,6 @@ static void event_process(const XEvent *ec, gpointer data) frame_adjust_focus(client->frame, FALSE); /* focus_set_client(NULL) has already been called in this section or by focus_fallback */ - client_calc_layer(client); } } else if (client) @@ -639,7 +647,7 @@ static void event_process(const XEvent *ec, gpointer data) else if (window == RootWindow(ob_display, ob_screen)) event_handle_root(e); else if (e->type == MapRequest) - client_manage(window); + client_manage(window, NULL); else if (e->type == MappingNotify) { /* keyboard layout changes for modifier mapping changes. reload the modifier map, and rebind all the key bindings as appropriate */ @@ -699,9 +707,11 @@ static void event_process(const XEvent *ec, gpointer data) } #endif - if (e->type == ButtonPress || e->type == ButtonRelease) { + if (prompt) + event_handle_prompt(prompt, e); + else 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 */ + on the root window, then process it */ if (window != RootWindow(ob_display, ob_screen) || e->xbutton.subwindow == None) { @@ -768,7 +778,7 @@ static void event_handle_root(XEvent *e) else if (e->xclient.data.l[0] == 3) ob_exit(0); } else if (msgtype == prop_atoms.wm_protocols) { - if (e->xclient.data.l[0] == prop_atoms.net_wm_ping) + if ((Atom)e->xclient.data.l[0] == prop_atoms.net_wm_ping) ping_got_pong(e->xclient.data.l[1]); } break; @@ -795,6 +805,12 @@ void event_enter_client(ObClient *client) { g_assert(config_focus_follow); + if (is_enter_focus_event_ignored(event_curserial)) { + ob_debug_type(OB_DEBUG_FOCUS, "Ignoring enter event with serial %lu\n" + "on client 0x%x", event_curserial, client->window); + return; + } + if (client_enter_focusable(client) && client_can_focus(client)) { if (config_focus_delay) { ObFocusDelayData *data; @@ -1039,8 +1055,7 @@ static void event_handle_client(ObClient *client, XEvent *e) if (e->xcrossing.mode == NotifyGrab || e->xcrossing.mode == NotifyUngrab || /*ignore enters when we're already in the window */ - e->xcrossing.detail == NotifyInferior || - is_enter_focus_event_ignored(e)) + e->xcrossing.detail == NotifyInferior) { ob_debug_type(OB_DEBUG_FOCUS, "%sNotify mode %d detail %d serial %lu on %lx " @@ -1350,7 +1365,7 @@ static void event_handle_client(ObClient *client, XEvent *e) ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_ACTIVE_WINDOW message for window %s is " "missing source indication\n"); - client_activate(client, FALSE, TRUE, TRUE, + client_activate(client, TRUE, TRUE, TRUE, (e->xclient.data.l[0] == 0 || e->xclient.data.l[0] == 2)); } else if (msgtype == prop_atoms.net_wm_moveresize) { @@ -1662,6 +1677,20 @@ static ObMenuFrame* find_active_or_last_menu(void) return ret; } +static void event_handle_prompt(ObPrompt *p, XEvent *e) +{ + switch (e->type) { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + prompt_mouse_event(p, e); + break; + case KeyPress: + prompt_key_event(p, e); + break; + } +} + static gboolean event_handle_menu_keyboard(XEvent *ev) { guint keycode, state; @@ -1917,7 +1946,7 @@ static void focus_delay_client_dest(ObClient *client, gpointer data) client, FALSE); } -void event_halt_focus_delay() +void event_halt_focus_delay(void) { /* ignore all enter events up till the event which caused this to occur */ if (event_curserial) event_ignore_enter_range(1, event_curserial); @@ -1926,8 +1955,7 @@ void event_halt_focus_delay() gulong event_start_ignore_all_enters(void) { - XSync(ob_display, FALSE); - return LastKnownRequestProcessed(ob_display); + return NextRequest(ob_display); } static void event_ignore_enter_range(gulong start, gulong end) @@ -1946,35 +1974,35 @@ static void event_ignore_enter_range(gulong start, gulong end) r->start, r->end); /* increment the serial so we don't ignore events we weren't meant to */ - XSync(ob_display, FALSE); + PROP_ERASE(screen_support_win, motif_wm_hints); } void event_end_ignore_all_enters(gulong start) { - XSync(ob_display, FALSE); - event_ignore_enter_range(start, LastKnownRequestProcessed(ob_display)); + /* Use (NextRequest-1) so that we ignore up to the current serial only. + Inside event_ignore_enter_range, we increment the serial by one, but if + we ignore that serial too, then any enter events generated by mouse + movement will be ignored until we create some further network traffic. + Instead ignore up to NextRequest-1, then when we increment the serial, + we will be *past* the range of ignored serials */ + event_ignore_enter_range(start, NextRequest(ob_display)-1); } -static gboolean is_enter_focus_event_ignored(XEvent *e) +static gboolean is_enter_focus_event_ignored(gulong serial) { GSList *it, *next; - g_assert(e->type == EnterNotify && - !(e->xcrossing.mode == NotifyGrab || - e->xcrossing.mode == NotifyUngrab || - e->xcrossing.detail == NotifyInferior)); - for (it = ignore_serials; it; it = next) { ObSerialRange *r = it->data; next = g_slist_next(it); - if ((glong)(e->xany.serial - r->end) > 0) { + if ((glong)(serial - r->end) > 0) { /* past the end */ ignore_serials = g_slist_delete_link(ignore_serials, it); g_free(r); } - else if ((glong)(e->xany.serial - r->start) >= 0) + else if ((glong)(serial - r->start) >= 0) return TRUE; } return FALSE;