X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=openbox%2Fevent.c;h=cd5625990e9fa31ea1cac9f4863a6fb97bfe8f64;hb=2b80e4e8ef56bb4fba614139601e750344418e5b;hp=9c47c04a3a49e42290a94bfea25dd6ba4adb122c;hpb=0cfd92ab9e56d8f790c92b83436e981fa46efe20;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 9c47c04a..cd562599 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -91,6 +91,7 @@ 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 void event_ignore_enter_range(gulong start, gulong end); static void focus_delay_dest(gpointer data); static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2); @@ -99,6 +100,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 gboolean focus_left_screen = FALSE; /*! A list of ObSerialRanges which are to be ignored for mouse enter events */ @@ -243,10 +246,15 @@ 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) { +#ifdef XKB + XkbStateRec xkb_state; +#endif + switch (e->type) { case ButtonPress: case ButtonRelease: @@ -256,10 +264,20 @@ static void event_hack_mods(XEvent *e) e->xkey.state = modkeys_only_modifier_masks(e->xkey.state); break; case KeyRelease: - e->xkey.state = modkeys_only_modifier_masks(e->xkey.state); - /* remove from the state the mask of the modifier key being released, - if it is a modifier key being released that is */ - e->xkey.state &= ~modkeys_keycode_to_mask(e->xkey.keycode); +#ifdef XKB + /* If XKB is present, then the modifiers are all strange from its + 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; + else +#endif + { + e->xkey.state = modkeys_only_modifier_masks(e->xkey.state); + /* remove from the state the mask of the modifier key being + released, if it is a modifier key being released that is */ + e->xkey.state &= ~modkeys_keycode_to_mask(e->xkey.keycode); + } break; case MotionNotify: e->xmotion.state = modkeys_only_modifier_masks(e->xmotion.state); @@ -465,6 +483,7 @@ static void event_process(const XEvent *ec, gpointer data) } event_set_curtime(e); + event_curserial = e->xany.serial; event_hack_mods(e); if (event_ignore(e, client)) { if (ed) @@ -619,6 +638,11 @@ static void event_process(const XEvent *ec, gpointer data) event_handle_root(e); else if (e->type == MapRequest) client_manage(window); + 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(); + } else if (e->type == ClientMessage) { /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for windows that are not managed yet. */ @@ -670,12 +694,50 @@ 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 (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 */ + 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 { + Window target, parent, root, *children; + unsigned int nchildren; + ObWindow *w; + + /* Find the top level ancestor of the subwindow, besides the + root */ + target = e->xbutton.subwindow; + ob_debug("subwindow 0x%x\n", target); + while (XQueryTree(ob_display, target, &root, &parent, &children, + &nchildren) != 0) + { + XFree(children); + if (parent == root) { + ob_debug("parent is root\n"); + break; + } + target = parent; + } + ob_debug("toplevel 0x%x\n", target); + + w = g_hash_table_lookup(window_map, &target); + ob_debug("w 0x%x\n", w); + + if ((w = g_hash_table_lookup(window_map, &target)) && + 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 */ @@ -718,6 +780,8 @@ static void event_handle_root(XEvent *e) ob_reconfigure(); else if (e->xclient.data.l[0] == 2) ob_restart(); + else if (e->xclient.data.l[0] == 3) + ob_exit(0); } break; case PropertyNotify: @@ -989,18 +1053,23 @@ static void event_handle_client(ObClient *client, XEvent *e) is_enter_focus_event_ignored(e)) { ob_debug_type(OB_DEBUG_FOCUS, - "%sNotify mode %d detail %d on %lx IGNORED\n", + "%sNotify mode %d detail %d serial %lu on %lx " + "IGNORED\n", (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, - e->xcrossing.detail, client?client->window:0); + e->xcrossing.detail, + e->xcrossing.serial, + client?client->window:0); } else { ob_debug_type(OB_DEBUG_FOCUS, - "%sNotify mode %d detail %d on %lx, " + "%sNotify mode %d detail %d serial %lu on %lx, " "focusing window\n", (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, - e->xcrossing.detail, (client?client->window:0)); + e->xcrossing.detail, + e->xcrossing.serial, + (client?client->window:0)); if (config_focus_follow) event_enter_client(client); } @@ -1579,7 +1648,7 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e) } } -static ObMenuFrame* find_active_menu() +static ObMenuFrame* find_active_menu(void) { GList *it; ObMenuFrame *ret = NULL; @@ -1593,7 +1662,7 @@ static ObMenuFrame* find_active_menu() return ret; } -static ObMenuFrame* find_active_or_last_menu() +static ObMenuFrame* find_active_or_last_menu(void) { ObMenuFrame *ret = NULL; @@ -1843,10 +1912,8 @@ static gboolean focus_delay_func(gpointer data) if (menu_frame_visible || moveresize_in_progress) return FALSE; event_curtime = d->time; - if (focus_client != d->client) { - if (client_focus(d->client) && config_focus_raise) - stacking_raise(CLIENT_AS_WINDOW(d->client)); - } + if (client_focus(d->client) && config_focus_raise) + stacking_raise(CLIENT_AS_WINDOW(d->client)); event_curtime = old; return FALSE; /* no repeat */ } @@ -1857,33 +1924,44 @@ static void focus_delay_client_dest(ObClient *client, gpointer data) client, FALSE); } -void event_halt_focus_delay() +void event_halt_focus_delay(gulong serial) { + /* ignore all enter events up till the event which caused this to occur */ + if (event_curserial) event_ignore_enter_range(1, event_curserial); ob_main_loop_timeout_remove(ob_main_loop, focus_delay_func); } -gulong event_start_ignore_all_enters() +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); } -void event_end_ignore_all_enters(gulong start) +static void event_ignore_enter_range(gulong start, gulong end) { ObSerialRange *r; g_assert(start != 0); - XSync(ob_display, FALSE); + g_assert(end != 0); r = g_new(ObSerialRange, 1); r->start = start; - r->end = LastKnownRequestProcessed(ob_display); + r->end = end; ignore_serials = g_slist_prepend(ignore_serials, r); + ob_debug_type(OB_DEBUG_FOCUS, "ignoring enters from %lu until %lu\n", + r->start, r->end); + /* increment the serial so we don't ignore events we weren't meant to */ XSync(ob_display, FALSE); } +void event_end_ignore_all_enters(gulong start) +{ + event_ignore_enter_range(start, LastKnownRequestProcessed(ob_display)); +} + static gboolean is_enter_focus_event_ignored(XEvent *e) { GSList *it, *next; @@ -1909,7 +1987,7 @@ static gboolean is_enter_focus_event_ignored(XEvent *e) return FALSE; } -void event_cancel_all_key_grabs() +void event_cancel_all_key_grabs(void) { if (actions_interactive_act_running()) { actions_interactive_cancel_act(); @@ -1956,7 +2034,7 @@ gboolean event_time_after(Time t1, Time t2) return t1 >= t2 && t1 < (t2 + TIME_HALF); } -Time event_get_server_time() +Time event_get_server_time(void) { /* Generate a timestamp */ XEvent event;