X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=openbox%2Fevent.c;h=ea24971236da54a21eaa9e48ac86955399b4d01f;hb=e7a86f5fe47906ef845af83fc419dc540cf19daf;hp=03229117d145f0bc55c42e6f0959c4ceebdbc141;hpb=0ce14a727968736e57fb3fabba3794b46903875f;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 03229117..ea249712 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 @@ -74,6 +76,7 @@ typedef struct { ObClient *client; Time time; + gulong serial; } ObFocusDelayData; typedef struct @@ -86,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 gboolean 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); @@ -101,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; @@ -246,7 +250,6 @@ 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) @@ -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,12 +478,19 @@ 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: - case Window_Internal: /* not to be used for events */ g_assert_not_reached(); break; + case Window_Internal: + /* we don't do anything with events directly on these windows */ + break; + case Window_Prompt: + prompt = WINDOW_AS_PROMPT(obwin); + break; } } @@ -515,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 || @@ -625,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) @@ -637,11 +647,14 @@ 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, reconfigure openbox. need to restart the - modkeys system, but also to reload the key bindings. */ - ob_reconfigure(); + /* keyboard layout changes for modifier mapping changes. reload the + modifier map, and rebind all the key bindings as appropriate */ + ob_debug("Kepboard map changed. Reloading keyboard bindings.\n"); + modkeys_shutdown(TRUE); + modkeys_startup(TRUE); + keyboard_rebind(); } else if (e->type == ClientMessage) { /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for @@ -694,16 +707,36 @@ 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 (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, then 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 { + ObWindow *w; + + if ((w = g_hash_table_lookup(window_map, &e->xbutton.subwindow)) && + 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 */ event_curtime = CurrentTime; + event_curserial = 0; } static void event_handle_root(XEvent *e) @@ -744,6 +777,9 @@ static void event_handle_root(XEvent *e) ob_restart(); else if (e->xclient.data.l[0] == 3) ob_exit(0); + } else if (msgtype == prop_atoms.wm_protocols) { + if ((Atom)e->xclient.data.l[0] == prop_atoms.net_wm_ping) + ping_got_pong(e->xclient.data.l[1]); } break; case PropertyNotify: @@ -769,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; @@ -778,6 +820,7 @@ void event_enter_client(ObClient *client) data = g_new(ObFocusDelayData, 1); data->client = client; data->time = event_curtime; + data->serial = event_curserial; ob_main_loop_timeout_add(ob_main_loop, config_focus_delay * 1000, @@ -787,6 +830,7 @@ void event_enter_client(ObClient *client) ObFocusDelayData data; data.client = client; data.time = event_curtime; + data.serial = event_curserial; focus_delay_func(&data); } } @@ -1011,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 " @@ -1322,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) { @@ -1634,6 +1677,21 @@ static ObMenuFrame* find_active_or_last_menu(void) return ret; } +static gboolean event_handle_prompt(ObPrompt *p, XEvent *e) +{ + switch (e->type) { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + return prompt_mouse_event(p, e); + break; + case KeyPress: + return prompt_key_event(p, e); + break; + } + return FALSE; +} + static gboolean event_handle_menu_keyboard(XEvent *ev) { guint keycode, state; @@ -1651,6 +1709,8 @@ static gboolean event_handle_menu_keyboard(XEvent *ev) /* Allow control while going thru the menu */ else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { + frame->got_press = TRUE; + if (keycode == ob_keycode(OB_KEY_ESCAPE)) { menu_frame_hide_all(); ret = TRUE; @@ -1684,7 +1744,7 @@ static gboolean event_handle_menu_keyboard(XEvent *ev) Allow ControlMask only, and don't bother if the menu is empty */ else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 && - frame->entries) + frame->entries && frame->got_press) { if (keycode == ob_keycode(OB_KEY_RETURN)) { /* Enter runs the active item or goes into the submenu. @@ -1874,6 +1934,7 @@ static gboolean focus_delay_func(gpointer data) if (menu_frame_visible || moveresize_in_progress) return FALSE; event_curtime = d->time; + event_curserial = d->serial; if (client_focus(d->client) && config_focus_raise) stacking_raise(CLIENT_AS_WINDOW(d->client)); event_curtime = old; @@ -1886,7 +1947,7 @@ static void focus_delay_client_dest(ObClient *client, gpointer data) client, FALSE); } -void event_halt_focus_delay(gulong serial) +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); @@ -1895,9 +1956,7 @@ void event_halt_focus_delay(gulong serial) 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); + return NextRequest(ob_display); } static void event_ignore_enter_range(gulong start, gulong end) @@ -1916,34 +1975,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) { - 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; @@ -1969,6 +2029,8 @@ void event_cancel_all_key_grabs(void) } else ungrab_passive_key(); + + XSync(ob_display, FALSE); } gboolean event_time_after(Time t1, Time t2)