X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=5bf22fb7fa546d0f23ff63d0787af3c906c16dde;hb=fa0ae17adbc8f73b707c33836d37841e81b9303a;hp=e9443d4914e256ac5647e7ef2dafd261c7ca13b8;hpb=4b5373f609e6462995a38cc4f0f50b17cbc8f835;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index e9443d49..5bf22fb7 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -80,7 +80,6 @@ static void client_get_area(ObClient *self); static void client_get_desktop(ObClient *self); static void client_get_state(ObClient *self); static void client_get_shaped(ObClient *self); -static void client_get_mwm_hints(ObClient *self); static void client_get_colormap(ObClient *self); static void client_set_desktop_recursive(ObClient *self, guint target, @@ -108,7 +107,6 @@ static void client_call_notifies(ObClient *self, GSList *list); static void client_ping_event(ObClient *self, gboolean dead); static void client_prompt_kill(ObClient *self); - void client_startup(gboolean reconfig) { if ((client_default_icon = RrImageCacheFind(ob_rr_icons, @@ -203,6 +201,7 @@ void client_manage(Window window, ObPrompt *prompt) gboolean transient = FALSE; Rect place, *monitor; Time launch_time, map_time; + guint32 user_time; ob_debug("Managing window: 0x%lx", window); @@ -233,6 +232,12 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug("Window type: %d", self->type); ob_debug("Window group: 0x%x", self->group?self->group->leader:0); + ob_debug("Window name: %s class: %s role: %s", self->name, self->class, self->role); + + /* per-app settings override stuff from client_get_all, and return the + settings for other uses too. the returned settings is a shallow copy, + that needs to be freed with g_free(). */ + settings = client_get_settings_state(self); /* now we have all of the window's information so we can set this up. do this before creating the frame, so it can tell that we are still @@ -254,16 +259,15 @@ void client_manage(Window window, ObPrompt *prompt) time now */ grab_server(FALSE); - /* per-app settings override stuff from client_get_all, and return the - settings for other uses too. the returned settings is a shallow copy, - that needs to be freed with g_free(). */ - settings = client_get_settings_state(self); /* the session should get the last say though */ client_restore_session_state(self); /* tell startup notification that this app started */ launch_time = sn_app_started(self->startup_id, self->class, self->name); + if (!OBT_PROP_GET32(self->window, NET_WM_USER_TIME, CARDINAL, &user_time)) + user_time = map_time; + /* do this after we have a frame.. it uses the frame to help determine the WM_STATE to apply. */ client_change_state(self); @@ -280,6 +284,8 @@ void client_manage(Window window, ObPrompt *prompt) /* this means focus=true for window is same as config_focus_new=true */ ((config_focus_new || (settings && settings->focus == 1)) || client_search_focus_tree_full(self)) && + /* NET_WM_USER_TIME 0 when mapping means don't focus */ + (user_time != 0) && /* this checks for focus=false for the window */ (!settings || settings->focus != 0) && focus_valid_target(self, FALSE, FALSE, TRUE, FALSE, FALSE)) @@ -414,12 +420,14 @@ void client_manage(Window window, ObPrompt *prompt) activate ? "yes" : "no"); if (activate) { gboolean raise = FALSE; - gboolean relative_focused = FALSE; + gboolean relative_focused; + gboolean parent_focused; + parent_focused = (focus_client != NULL && + client_search_focus_parent(self)); relative_focused = (focus_client != NULL && - client_search_focus_tree_full(self) != NULL && - client_search_focus_group_full(self) != NULL); - + (client_search_focus_tree_full(self) != NULL || + client_search_focus_group_full(self) != NULL)); /* This is focus stealing prevention */ ob_debug_type(OB_DEBUG_FOCUS, @@ -427,6 +435,12 @@ void client_manage(Window window, ObPrompt *prompt) "launched at %u (last user interaction time %u)", self->window, map_time, launch_time, event_last_user_time); + ob_debug_type(OB_DEBUG_FOCUS, + "Current focus_client: %s", + (focus_client ? focus_client->title : "(none)")); + ob_debug_type(OB_DEBUG_FOCUS, + "parent focused: %d relative focused: %d", + parent_focused, relative_focused); if (menu_frame_visible || moveresize_in_progress) { activate = FALSE; @@ -454,7 +468,8 @@ void client_manage(Window window, ObPrompt *prompt) else if (focus_client) { /* If the user is working in another window right now, then don't steal focus */ - if (event_last_user_time && launch_time && + if (!parent_focused && + event_last_user_time && launch_time && event_time_after(event_last_user_time, launch_time) && event_last_user_time != launch_time && event_time_after(event_last_user_time, @@ -463,7 +478,8 @@ void client_manage(Window window, ObPrompt *prompt) activate = FALSE; ob_debug_type(OB_DEBUG_FOCUS, "Not focusing the window because the user is " - "working in another window"); + "working in another window that is not " + "its parent"); } /* If the new window is a transient (and its relatives aren't focused) */ @@ -573,7 +589,6 @@ void client_manage(Window window, ObPrompt *prompt) hooks_queue(OB_HOOK_WIN_NEW, self); } - ObClient *client_fake_manage(Window window) { ObClient *self; @@ -1300,7 +1315,6 @@ static void client_update_transient_tree(ObClient *self, transient windows as their children. * * */ - /* No change has occured */ if (oldgroup == newgroup && oldgtran == newgtran && @@ -1394,7 +1408,7 @@ static void client_update_transient_tree(ObClient *self, } } -static void client_get_mwm_hints(ObClient *self) +void client_get_mwm_hints(ObClient *self) { guint num; guint32 *hints; @@ -2116,7 +2130,6 @@ void client_update_icons(ObClient *self) (gint*)&w, (gint*)&h, &data); obt_display_ignore_errors(FALSE); - if (xicon) { if (w > 0 && h > 0) { /* is this icon in the cache yet? */ @@ -2365,7 +2378,7 @@ ObClient *client_search_focus_tree_full(ObClient *self) for (it = self->parents; it; it = g_slist_next(it)) { ObClient *c = it->data; - if ((c = client_search_focus_tree_full(it->data))) return c; + if ((c = client_search_focus_tree_full(c))) return c; } return NULL; @@ -2613,7 +2626,6 @@ gboolean client_enter_focusable(ObClient *self) self->type != OB_CLIENT_TYPE_DESKTOP); } - static void client_apply_startup_state(ObClient *self, gint x, gint y, gint w, gint h) { @@ -2923,7 +2935,6 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, g_assert(*h > 0); } - void client_configure(ObClient *self, gint x, gint y, gint w, gint h, gboolean user, gboolean final, gboolean force_reply) { @@ -3527,19 +3538,38 @@ ObClient *client_search_modal_child(ObClient *self) return NULL; } +static gboolean client_validate_unmap(ObClient *self, int n) +{ + XEvent e; + gboolean ret = TRUE; + + if (XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) { + if (n < self->ignore_unmaps) // ignore this one, but look for more + ret = client_validate_unmap(self, n+1); + else + ret = FALSE; // the window is going to become unmanaged + + /* put them back on the event stack so they end up in the same order */ + XPutBackEvent(obt_display, &e); + } + + return ret; +} + gboolean client_validate(ObClient *self) { XEvent e; XSync(obt_display, FALSE); /* get all events on the server */ - if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e) || - XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) - { + if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e)) { XPutBackEvent(obt_display, &e); return FALSE; } + if (!client_validate_unmap(self, 0)) + return FALSE; + return TRUE; } @@ -3609,6 +3639,8 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) value = self->demands_attention; else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED)) value = undecorated; + else + g_assert_not_reached(); action = value ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) : OBT_PROP_ATOM(NET_WM_STATE_ADD); } @@ -3805,12 +3837,15 @@ static void client_present(ObClient *self, gboolean here, gboolean raise, client_focus(self); } -/* this function exists to map to the client_activate message in the ewmh, - the user arg is unused because nobody uses it correctly anyway. */ +/* this function exists to map to the net_active_window message in the ewmh */ void client_activate(ObClient *self, gboolean here, gboolean raise, gboolean unshade, gboolean user) { - client_present(self, here, raise, unshade); + if (user || (self->desktop == DESKTOP_ALL || + self->desktop == screen_desktop)) + client_present(self, here, raise, unshade); + else + client_hilite(self, TRUE); } static void client_bring_windows_recursive(ObClient *self, @@ -3958,6 +3993,21 @@ ObClient *client_search_focus_parent(ObClient *self) return NULL; } +ObClient *client_search_focus_parent_full(ObClient *self) +{ + GSList *it; + ObClient *ret = NULL; + + for (it = self->parents; it; it = g_slist_next(it)) { + if (client_focused(it->data)) + ret = it->data; + else + ret = client_search_focus_parent_full(it->data); + if (ret) break; + } + return ret; +} + ObClient *client_search_parent(ObClient *self, ObClient *search) { GSList *it;