X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=483050fa9b49498a4ee57f0e44ddcb084f095e61;hb=3a607fad9df628ab16e0f7436dfbfc9b22634003;hp=22a074fd462cfe420cc6864b114a5868f3134f3b;hpb=9caa096ad95772741514b1a5cccf288f249e9b1e;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 22a074fd..483050fa 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -15,6 +15,7 @@ #include "framerender.h" #include "focus.h" #include "moveresize.h" +#include "group.h" #include "stacking.h" #include "extensions.h" #include "event.h" @@ -35,12 +36,18 @@ #include #endif +typedef struct +{ + gboolean ignored; +} ObEventData; + static void event_process(const XEvent *e, gpointer data); static void event_handle_root(XEvent *e); static void event_handle_menu(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_group(ObGroup *g, XEvent *e); static gboolean focus_delay_func(gpointer data); static void focus_delay_client_dest(gpointer data); @@ -138,6 +145,10 @@ void event_shutdown(gboolean reconfig) { if (reconfig) return; +#ifdef USE_SM + IceRemoveConnectionWatch(ice_watch, NULL); +#endif + client_remove_destructor(focus_delay_client_dest); XFreeModifiermap(modmap); } @@ -283,8 +294,8 @@ static gboolean event_ignore(XEvent *e, ObClient *client) if (INVALID_FOCUSIN(e) || client == NULL) { #ifdef DEBUG_FOCUS - ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n", - e->xfocus.window, e->xfocus.mode, e->xfocus.detail); + ob_debug("FocusIn on %lx mode %d detail %d IGNORED\n", + e->xfocus.window, e->xfocus.mode, e->xfocus.detail); #endif /* says a client was not found for the event (or a valid FocusIn event was not found. @@ -366,14 +377,18 @@ static gboolean event_ignore(XEvent *e, ObClient *client) } } - /* once all the FocusOut's have been dealt with, if there - is a FocusIn still left and it is valid, then use it */ - event_process(&fe, NULL); - /* secret magic way of event_process telling us that no - client was found for the FocusIn event. ^_^ */ - if (fe.xfocus.window != None) { - fallback = FALSE; - break; + { + ObEventData d; + + /* once all the FocusOut's have been dealt with, if + there is a FocusIn still left and it is valid, then + use it */ + event_process(&fe, &d); + if (!d.ignored) { + ob_debug("FocusIn was OK, so don't fallback\n"); + fallback = FALSE; + break; + } } } } @@ -390,11 +405,14 @@ static gboolean event_ignore(XEvent *e, ObClient *client) case LeaveNotify: /* NotifyUngrab occurs when a mouse button is released and the event is caused, like when lowering a window */ - /* NotifyVirtual occurs when ungrabbing the pointer */ + /* NotifyVirtual and NotifyAncestor occurs when ungrabbing the + pointer (Ancestor happens when the pointer is on a window border) */ if (e->xcrossing.mode == NotifyGrab || e->xcrossing.detail == NotifyInferior || (e->xcrossing.mode == NotifyUngrab && - e->xcrossing.detail == NotifyVirtual)) { + (e->xcrossing.detail == NotifyAncestor || + e->xcrossing.detail == NotifyNonlinearVirtual || + e->xcrossing.detail == NotifyVirtual))) { #ifdef DEBUG_FOCUS ob_debug("%sNotify mode %d detail %d on %lx IGNORED\n", (e->type == EnterNotify ? "Enter" : "Leave"), @@ -417,43 +435,53 @@ static gboolean event_ignore(XEvent *e, ObClient *client) static void event_process(const XEvent *ec, gpointer data) { Window window; + ObGroup *group = NULL; ObClient *client = NULL; ObDock *dock = NULL; ObDockApp *dockapp = NULL; ObWindow *obwin = NULL; XEvent ee, *e; + ObEventData *ed = data; /* make a copy we can mangle */ ee = *ec; e = ⅇ window = event_get_window(e); - if ((obwin = g_hash_table_lookup(window_map, &window))) { - switch (obwin->type) { - case Window_Dock: - dock = WINDOW_AS_DOCK(obwin); - break; - case Window_DockApp: - dockapp = WINDOW_AS_DOCKAPP(obwin); - break; - case Window_Client: - client = WINDOW_AS_CLIENT(obwin); - break; - case Window_Menu: - case Window_Internal: - /* not to be used for events */ - g_assert_not_reached(); - break; + if (!(e->type == PropertyNotify && + (group = g_hash_table_lookup(group_map, &window)))) + if ((obwin = g_hash_table_lookup(window_map, &window))) { + switch (obwin->type) { + case Window_Dock: + dock = WINDOW_AS_DOCK(obwin); + break; + case Window_DockApp: + dockapp = WINDOW_AS_DOCKAPP(obwin); + break; + case Window_Client: + client = WINDOW_AS_CLIENT(obwin); + break; + case Window_Menu: + case Window_Internal: + /* not to be used for events */ + g_assert_not_reached(); + break; + } } - } event_set_lasttime(e); event_hack_mods(e); - if (event_ignore(e, client)) + if (event_ignore(e, client)) { + if (ed) + ed->ignored = TRUE; return; + } else if (ed) + ed->ignored = FALSE; /* deal with it in the kernel */ - if (client) + if (group) + event_handle_group(group, e); + else if (client) event_handle_client(client, e); else if (dockapp) event_handle_dockapp(dockapp, e); @@ -565,6 +593,16 @@ static void event_handle_root(XEvent *e) } } +static void event_handle_group(ObGroup *group, XEvent *e) +{ + GSList *it; + + g_assert(e->type == PropertyNotify); + + for (it = group->members; it; it = g_slist_next(it)) + event_handle_client(it->data, e); +} + static void event_handle_client(ObClient *client, XEvent *e) { XEvent ce; @@ -694,15 +732,7 @@ static void event_handle_client(ObClient *client, XEvent *e) break; case OB_FRAME_CONTEXT_FRAME: if (client_normal(client)) { - if (ob_state() == OB_STATE_STARTING) { - /* move it to the top of the focus order */ - guint desktop = client->desktop; - if (desktop == DESKTOP_ALL) desktop = screen_desktop; - focus_order[desktop] = g_list_remove(focus_order[desktop], - client); - focus_order[desktop] = g_list_prepend(focus_order[desktop], - client); - } else if (config_focus_follow) { + if (config_focus_follow) { #ifdef DEBUG_FOCUS ob_debug("EnterNotify on %lx, focusing window\n", client->window); @@ -1063,6 +1093,9 @@ static void event_handle_client(ObClient *client, XEvent *e) msgtype == prop_atoms.kwm_win_icon) { client_update_icons(client); } + else if (msgtype == prop_atoms.sm_client_id) { + client_update_sm_client_id(client); + } default: ; #ifdef SHAPE @@ -1148,6 +1181,16 @@ static void event_handle_menu(XEvent *ev) ev->xmotion.y_root))) menu_frame_select(f, e); } + { + ObMenuFrame *a; + + a = find_active_menu(); + if (a && a != f && + a->selected->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU) + { + menu_frame_select(a, NULL); + } + } break; case KeyPress: if (ev->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))