X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=openbox%2Fclient.c;h=35afb318ca9ef40d1e2ea5a901fa5c92501f9e7f;hb=9c356d370ab3e5a6b28e38ce8289d80bf35c8828;hp=012454c724c141ad2c099403966e21a7879ab254;hpb=5d5714f01e1a7140847f6e7f2922d457f6bbe66a;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 012454c7..35afb318 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -114,18 +114,9 @@ static gboolean client_can_steal_focus(ObClient *self, void client_startup(gboolean reconfig) { - if ((client_default_icon = RrImageCacheFind(ob_rr_icons, - ob_rr_theme->def_win_icon, - ob_rr_theme->def_win_icon_w, - ob_rr_theme->def_win_icon_h))) - RrImageRef(client_default_icon); - else { - client_default_icon = RrImageNew(ob_rr_icons); - RrImageAddPicture(client_default_icon, - ob_rr_theme->def_win_icon, - ob_rr_theme->def_win_icon_w, - ob_rr_theme->def_win_icon_h); - } + client_default_icon = RrImageNewFromData( + ob_rr_icons, ob_rr_theme->def_win_icon, + ob_rr_theme->def_win_icon_w, ob_rr_theme->def_win_icon_h); if (reconfig) return; @@ -201,7 +192,8 @@ void client_manage(Window window, ObPrompt *prompt) { ObClient *self; XSetWindowAttributes attrib_set; - gboolean activate = FALSE; + gboolean try_activate = FALSE; + gboolean do_activate; ObAppSettings *settings; gboolean transient = FALSE; Rect place; @@ -293,7 +285,7 @@ void client_manage(Window window, ObPrompt *prompt) FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, settings->focus == 1)) { - activate = TRUE; + try_activate = TRUE; } /* remove the client's border */ @@ -307,6 +299,14 @@ void client_manage(Window window, ObPrompt *prompt) /* where the frame was placed is where the window was originally */ place = self->area; + ob_debug("Going to try activate new window? %s", + try_activate ? "yes" : "no"); + if (try_activate) + do_activate = client_can_steal_focus(self, settings->focus, + event_time(), launch_time); + else + do_activate = FALSE; + /* figure out placement for the window if the window is new */ if (ob_state() == OB_STATE_RUNNING) { ob_debug("Positioned: %s @ %d %d", @@ -325,7 +325,8 @@ void client_manage(Window window, ObPrompt *prompt) "program + user specified" : "BADNESS !?")))), place.width, place.height); - obplaced = place_client(self, &place.x, &place.y, settings); + obplaced = place_client(self, do_activate, &place.x, &place.y, + settings); /* watch for buggy apps that ask to be placed at (0,0) when there is a strut there */ @@ -433,13 +434,30 @@ void client_manage(Window window, ObPrompt *prompt) client_apply_startup_state(self, place.x, place.y, place.width, place.height); - ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s", - activate ? "yes" : "no"); - if (activate) { - activate = client_can_steal_focus(self, settings->focus, - event_time(), launch_time); + /* grab mouse bindings before showing the window */ + mouse_grab_for_client(self, TRUE); + + /* this has to happen before we try focus the window, but we want it to + happen after the client's stacking has been determined or it looks bad + */ + { + gulong ignore_start; + if (!config_focus_under_mouse) + ignore_start = event_start_ignore_all_enters(); + + client_show(self); + + if (!config_focus_under_mouse) + event_end_ignore_all_enters(ignore_start); + } - if (!activate) { + /* activate/hilight/raise the window */ + if (try_activate) { + if (do_activate) { + gboolean stacked = client_restore_session_stacking(self); + client_present(self, FALSE, !stacked, TRUE); + } + else { /* if the client isn't stealing focus, then hilite it so the user knows it is there, but don't do this if we're restoring from a session */ @@ -459,27 +477,6 @@ void client_manage(Window window, ObPrompt *prompt) stacking_raise(CLIENT_AS_WINDOW(self)); } - mouse_grab_for_client(self, TRUE); - - /* this has to happen before we try focus the window, but we want it to - happen after the client's stacking has been determined or it looks bad - */ - { - gulong ignore_start; - if (!config_focus_under_mouse) - ignore_start = event_start_ignore_all_enters(); - - client_show(self); - - if (!config_focus_under_mouse) - event_end_ignore_all_enters(ignore_start); - } - - if (activate) { - gboolean stacked = client_restore_session_stacking(self); - client_present(self, FALSE, !stacked, TRUE); - } - /* add to client list/map */ client_list = g_list_append(client_list, self); window_add(&self->window, CLIENT_AS_WINDOW(self)); @@ -702,62 +699,100 @@ static gboolean client_can_steal_focus(ObClient *self, { gboolean steal; gboolean relative_focused; - gboolean parent_focused; steal = TRUE; - 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)); /* This is focus stealing prevention */ - ob_debug_type(OB_DEBUG_FOCUS, - "Want to focus window 0x%x at time %u " - "launched at %u (last user interaction time %u)", - self->window, steal_time, launch_time, - event_last_user_time); + ob_debug("Want to focus window 0x%x at time %u " + "launched at %u (last user interaction time %u)", + self->window, steal_time, launch_time, + event_last_user_time); + + /* + if no launch time is provided for an application, make one up. + + if the window is related to other existing windows + and one of those windows was the last used + then we will give it a launch time equal to the last user time, + which will end up giving the window focus probably. + else + the window is related to other windows, but you are not working in + them? + seems suspicious, so we will give it a launch time of + NOW - STEAL_INTERVAL, + so it will be given focus only if we didn't use something else + during the steal interval. + else + the window is all on its own, so we can't judge it. give it a launch + time equal to the last user time, so it will probably take focus. + + this way running things from a terminal will give them focus, but popups + without a launch time shouldn't steal focus so easily. + */ - /* if it's on another desktop... */ + if (!launch_time) { + if (client_has_relative(self)) { + if (event_last_user_time && client_search_focus_group_full(self)) { + /* our relative is focused */ + launch_time = event_last_user_time; + ob_debug("Unknown launch time, using %u window in active " + "group", launch_time); + } + else { + /* has relatives which are not being used. suspicious */ + launch_time = event_time() - OB_EVENT_USER_TIME_DELAY; + ob_debug("Unknown launch time, using %u window in inactive " + "group", launch_time); + } + } + else { + /* the window is on its own, probably the user knows it is going + to appear */ + launch_time = event_last_user_time; + ob_debug("Unknown launch time, using %u for solo window", + launch_time); + } + } + + /* if it's on another desktop + then if allow_other_desktop is false, we don't want to let it steal + focus, unless it was launched after we changed desktops + */ if (!(self->desktop == screen_desktop || self->desktop == DESKTOP_ALL) && - /* and (we dont know when it launched, and we don't want to allow - focus stealing from other desktops */ - ((!launch_time && !allow_other_desktop) || - /* or the timestamp is from before you changed desktops) */ + (!allow_other_desktop || (screen_desktop_user_time && !event_time_after(launch_time, screen_desktop_user_time)))) { steal = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because its on another " - "desktop\n"); + ob_debug("Not focusing the window because its on another desktop\n"); } /* If something is focused... */ else if (focus_client) { /* If the user is working in another window right now, then don't steal focus */ - if (!parent_focused && - event_last_user_time && launch_time && - event_time_after(event_last_user_time, launch_time) && - event_last_user_time != launch_time && + if (!relative_focused && + event_last_user_time && + /* last user time must be strictly > launch_time to block focus */ + (event_time_after(event_last_user_time, launch_time) && + event_last_user_time != launch_time) && event_time_after(event_last_user_time, steal_time - OB_EVENT_USER_TIME_DELAY)) { steal = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because the user is " - "working in another window that is not " - "its parent"); + ob_debug("Not focusing the window because the user is " + "working in another window that is not its relative"); } /* If the new window is a transient (and its relatives aren't focused) */ else if (client_has_parent(self) && !relative_focused) { steal = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because it is a " - "transient, and its relatives aren't focused"); + ob_debug("Not focusing the window because it is a " + "transient, and its relatives aren't focused"); } /* Don't steal focus from globally active clients. I stole this idea from KWin. It seems nice. @@ -766,17 +801,15 @@ static gboolean client_can_steal_focus(ObClient *self, focus_client->focus_notify)) { steal = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because a globally " - "active client has focus"); + ob_debug("Not focusing the window because a globally " + "active client has focus"); } /* Don't move focus if it's not going to go to this window anyway */ else if (client_focus_target(self) != self) { steal = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because another window " - "would get the focus anyway"); + ob_debug("Not focusing the window because another window " + "would get the focus anyway"); } /* Don't move focus if the window is not visible on the current desktop and none of its relatives are focused */ @@ -785,17 +818,15 @@ static gboolean client_can_steal_focus(ObClient *self, !relative_focused) { steal = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because it is on " - "another desktop and no relatives are focused "); + ob_debug("Not focusing the window because it is on " + "another desktop and no relatives are focused "); } } if (!steal) - ob_debug_type(OB_DEBUG_FOCUS, - "Focus stealing prevention activated for %s at " - "time %u (last user interaction time %u)", - self->title, steal_time, event_last_user_time); + ob_debug("Focus stealing prevention activated for %s at " + "time %u (last user interaction time %u)", + self->title, steal_time, event_last_user_time); return steal; } @@ -2092,7 +2123,6 @@ void client_update_icons(ObClient *self) guint num; guint32 *data; guint w, h, i, j; - guint num_seen; /* number of icons present */ RrImage *img; img = NULL; @@ -2105,13 +2135,15 @@ void client_update_icons(ObClient *self) if (OBT_PROP_GETA32(self->window, NET_WM_ICON, CARDINAL, &data, &num)) { /* figure out how many valid icons are in here */ i = 0; - num_seen = 0; while (i + 2 < num) { /* +2 is to make sure there is a w and h */ w = data[i++]; h = data[i++]; /* watch for the data being too small for the specified size, or for zero sized icons. */ - if (i + w*h > num || w == 0 || h == 0) break; + if (i + w*h > num || w == 0 || h == 0) { + i += w*h; + continue; + } /* convert it to the right bit order for ObRender */ for (j = 0; j < w*h; ++j) @@ -2121,29 +2153,13 @@ void client_update_icons(ObClient *self) (((data[i+j] >> 8) & 0xff) << RrDefaultGreenOffset) + (((data[i+j] >> 0) & 0xff) << RrDefaultBlueOffset); - /* is it in the cache? */ - img = RrImageCacheFind(ob_rr_icons, &data[i], w, h); - if (img) RrImageRef(img); /* own it */ + /* add it to the image cache as an original */ + if (!img) + img = RrImageNewFromData(ob_rr_icons, &data[i], w, h); + else + RrImageAddFromData(img, &data[i], w, h); i += w*h; - ++num_seen; - - /* don't bother looping anymore if we already found it in the cache - since we'll just use that! */ - if (img) break; - } - - /* if it's not in the cache yet, then add it to the cache now. - we have already converted it to the correct bit order above */ - if (!img && num_seen > 0) { - img = RrImageNew(ob_rr_icons); - i = 0; - for (j = 0; j < num_seen; ++j) { - w = data[i++]; - h = data[i++]; - RrImageAddPicture(img, &data[i], w, h); - i += w*h; - } } g_free(data); @@ -2167,15 +2183,10 @@ void client_update_icons(ObClient *self) if (xicon) { if (w > 0 && h > 0) { - /* is this icon in the cache yet? */ - img = RrImageCacheFind(ob_rr_icons, data, w, h); - if (img) RrImageRef(img); /* own it */ - - /* if not, then add it */ - if (!img) { - img = RrImageNew(ob_rr_icons); - RrImageAddPicture(img, data, w, h); - } + if (!img) + img = RrImageNewFromData(ob_rr_icons, data, w, h); + else + RrImageAddFromData(img, data, w, h); } g_free(data); @@ -2472,6 +2483,11 @@ gboolean client_has_parent(ObClient *self) return self->parents != NULL; } +gboolean client_has_children(ObClient *self) +{ + return self->transients != NULL; +} + gboolean client_is_oldfullscreen(const ObClient *self, const Rect *area) { @@ -4496,6 +4512,13 @@ gboolean client_has_group_siblings(ObClient *self) return self->group && self->group->members->next; } +gboolean client_has_relative(ObClient *self) +{ + return client_has_parent(self) || + client_has_group_siblings(self) || + client_has_children(self); +} + /*! Returns TRUE if the client is running on the same machine as Openbox */ gboolean client_on_localhost(ObClient *self) {