X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=openbox%2Fclient.c;h=016a660fd486b9875b27714813cbc6db6dd0e959;hb=82db73cc4344cf4e8a3757fb1ec50be77e3bc9d8;hp=3a46f823a6d7853421216547f8eff8294d6210e5;hpb=c38a756ae50616b1431e3137141189a5588654a0;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 3a46f823..016a660f 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -108,7 +108,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, @@ -248,6 +247,7 @@ void client_manage(Window window, ObPrompt *prompt) gboolean transient = FALSE; Rect place, *monitor; Time launch_time, map_time; + guint32 user_time; grab_server(TRUE); @@ -313,6 +313,12 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug("Window type: %d\n", self->type); ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0); + ob_debug("Window name: %s class: %s\n", self->name, self->class); + + /* 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 @@ -334,16 +340,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 (!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); @@ -360,6 +365,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)) @@ -494,6 +501,14 @@ void client_manage(Window window, ObPrompt *prompt) activate ? "yes" : "no"); if (activate) { gboolean raise = 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)); /* This is focus stealing prevention */ ob_debug_type(OB_DEBUG_FOCUS, @@ -524,13 +539,12 @@ void client_manage(Window window, ObPrompt *prompt) "Not focusing the window because its on another " "desktop\n"); } - /* If something is focused, and it's not our relative... */ - else if (focus_client && client_search_focus_tree_full(self) == NULL && - client_search_focus_group_full(self) == NULL) - { + /* If something is focused... */ + 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, @@ -539,10 +553,12 @@ 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\n"); + "working in another window that is not " + "its parent\n"); } - /* If it's a transient (and its parents aren't focused) */ - else if (client_has_parent(self)) { + /* If the new window is a transient (and its relatives aren't + focused) */ + else if (client_has_parent(self) && !relative_focused) { activate = FALSE; ob_debug_type(OB_DEBUG_FOCUS, "Not focusing the window because it is a " @@ -568,8 +584,11 @@ void client_manage(Window window, ObPrompt *prompt) "Not focusing the window because another window " "would get the focus anyway\n"); } + /* Don't move focus if the window is not visible on the current + desktop and none of its relatives are focused */ else if (!(self->desktop == screen_desktop || - self->desktop == DESKTOP_ALL)) + self->desktop == DESKTOP_ALL) && + !relative_focused) { activate = FALSE; raise = TRUE; @@ -645,7 +664,6 @@ void client_manage(Window window, ObPrompt *prompt) return; } - ObClient *client_fake_manage(Window window) { ObClient *self; @@ -1368,7 +1386,6 @@ static void client_update_transient_tree(ObClient *self, transient windows as their children. * * */ - /* No change has occured */ if (oldgroup == newgroup && oldgtran == newgtran && @@ -2181,7 +2198,6 @@ void client_update_icons(ObClient *self) (gint*)&w, (gint*)&h, &data); xerror_set_ignore(FALSE); - if (xicon) { if (w > 0 && h > 0) { /* is this icon in the cache yet? */ @@ -2673,7 +2689,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) { @@ -2874,8 +2889,10 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, /* gets the client's position */ frame_frame_gravity(self->frame, x, y); - /* work within the preferred sizes given by the window */ - if (!(*w == self->area.width && *h == self->area.height)) { + /* work within the preferred sizes given by the window, these may have + changed rather than it's requested width and height, so always run + through this code */ + { gint basew, baseh, minw, minh; gint incw, inch; gfloat minratio, maxratio; @@ -2981,7 +2998,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) { @@ -3254,7 +3270,7 @@ void client_maximize(ObClient *self, gboolean max, gint dir) gint x, y, w, h; g_assert(dir == 0 || dir == 1 || dir == 2); - if (!(self->functions & OB_CLIENT_FUNC_MAXIMIZE)) return; /* can't */ + if (!(self->functions & OB_CLIENT_FUNC_MAXIMIZE) && max) return;/* can't */ /* check if already done */ if (max) { @@ -3390,12 +3406,20 @@ void client_close(ObClient *self) #define OB_KILL_RESULT_NO 0 #define OB_KILL_RESULT_YES 1 -static void client_kill_requested(ObPrompt *p, gint result, gpointer data) +static gboolean client_kill_requested(ObPrompt *p, gint result, gpointer data) { ObClient *self = data; if (result == OB_KILL_RESULT_YES) client_kill(self); + return TRUE; /* call the cleanup func */ +} + +static void client_kill_cleanup(ObPrompt *p, gpointer data) +{ + ObClient *self = data; + + g_assert(p == self->kill_prompt); prompt_unref(self->kill_prompt); self->kill_prompt = NULL; @@ -3406,10 +3430,18 @@ static void client_prompt_kill(ObClient *self) /* check if we're already prompting */ if (!self->kill_prompt) { ObPromptAnswer answers[] = { - { _("Cancel"), OB_KILL_RESULT_NO }, - { _("Force Exit"), OB_KILL_RESULT_YES } + { 0, OB_KILL_RESULT_NO }, + { 0, OB_KILL_RESULT_YES } }; gchar *m; + const gchar *y, *title; + + title = self->original_title; + if (title[0] == '\0') { + /* empty string, so use its parent */ + ObClient *p = client_search_top_direct_parent(self); + if (p) title = p->original_title; + } if (client_on_localhost(self)) { const gchar *sig; @@ -3420,18 +3452,27 @@ static void client_prompt_kill(ObClient *self) sig = "kill"; m = g_strdup_printf - (_("The window \"%s\" does not seem to be responding. Do you want to force it to exit by sending the %s signal?"), self->original_title, sig); + (_("The window \"%s\" does not seem to be responding. Do you want to force it to exit by sending the %s signal?"), + title, sig); + y = _("End Process"); } - else + else { m = g_strdup_printf - (_("The window \"%s\" does not seem to be responding. Do you want to disconnect it from the X server?"), self->original_title); - + (_("The window \"%s\" does not seem to be responding. Do you want to disconnect it from the X server?"), + title); + y = _("Disconnect"); + } + /* set the dialog buttons' text */ + answers[0].text = _("Cancel"); /* "no" */ + answers[1].text = y; /* "yes" */ - self->kill_prompt = prompt_new(m, answers, + self->kill_prompt = prompt_new(m, NULL, answers, sizeof(answers)/sizeof(answers[0]), OB_KILL_RESULT_NO, /* default = no */ OB_KILL_RESULT_NO, /* cancel = no */ - client_kill_requested, self); + client_kill_requested, + client_kill_cleanup, + self); g_free(m); } @@ -3864,12 +3905,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, @@ -4014,6 +4058,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; @@ -4097,12 +4156,12 @@ static void detect_edge(Rect area, ObDirection dir, /* check if the head of this window is closer than the previously chosen edge (take into account that the previously chosen edge might have been a tail, not a head) */ - if (head + (*near_edge ? 0 : my_size) < *dest) + if (head + (*near_edge ? 0 : my_size) <= *dest) skip_head = TRUE; /* check if the tail of this window is closer than the previously chosen edge (take into account that the previously chosen edge might have been a head, not a tail) */ - if (tail - (!*near_edge ? 0 : my_size) < *dest) + if (tail - (!*near_edge ? 0 : my_size) <= *dest) skip_tail = TRUE; break; case OB_DIRECTION_SOUTH: @@ -4116,12 +4175,12 @@ static void detect_edge(Rect area, ObDirection dir, /* check if the head of this window is closer than the previously chosen edge (take into account that the previously chosen edge might have been a tail, not a head) */ - if (head - (*near_edge ? 0 : my_size) > *dest) + if (head - (*near_edge ? 0 : my_size) >= *dest) skip_head = TRUE; /* check if the tail of this window is closer than the previously chosen edge (take into account that the previously chosen edge might have been a head, not a tail) */ - if (tail + (!*near_edge ? 0 : my_size) > *dest) + if (tail + (!*near_edge ? 0 : my_size) >= *dest) skip_tail = TRUE; break; default: @@ -4129,7 +4188,7 @@ static void detect_edge(Rect area, ObDirection dir, } ob_debug("my head %d size %d\n", my_head, my_size); - ob_debug("head %d tail %d deest %d\n", head, tail, *dest); + ob_debug("head %d tail %d dest %d\n", head, tail, *dest); if (!skip_head) { ob_debug("using near edge %d\n", head); *dest = head; @@ -4292,28 +4351,28 @@ void client_find_resize_directional(ObClient *self, ObDirection side, switch (side) { case OB_DIRECTION_EAST: head = RECT_RIGHT(self->frame->area) + - (self->size_inc.width - 1) * (grow ? 1 : -1); + (self->size_inc.width - 1) * (grow ? 1 : 0); e_start = RECT_TOP(self->frame->area); e_size = self->frame->area.height; dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST; break; case OB_DIRECTION_WEST: head = RECT_LEFT(self->frame->area) - - (self->size_inc.width - 1) * (grow ? 1 : -1); + (self->size_inc.width - 1) * (grow ? 1 : 0); e_start = RECT_TOP(self->frame->area); e_size = self->frame->area.height; dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST; break; case OB_DIRECTION_NORTH: head = RECT_TOP(self->frame->area) - - (self->size_inc.height - 1) * (grow ? 1 : -1); + (self->size_inc.height - 1) * (grow ? 1 : 0); e_start = RECT_LEFT(self->frame->area); e_size = self->frame->area.width; dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH; break; case OB_DIRECTION_SOUTH: head = RECT_BOTTOM(self->frame->area) + - (self->size_inc.height - 1) * (grow ? 1 : -1); + (self->size_inc.height - 1) * (grow ? 1 : 0); e_start = RECT_LEFT(self->frame->area); e_size = self->frame->area.width; dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH;