X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=62489c1d86af20b5e07fd4e30e46d2d49905aeae;hb=cd3aa44b6a78e84e75420d6cca2c32f117a096a4;hp=7add1222d93484aaf683689e5888ddc0fd885881;hpb=c7af49b5c564d6287a0293ae26fc713fb55b4dc8;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 7add1222..62489c1d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -105,6 +105,7 @@ static GSList *client_search_all_top_parents_internal(ObClient *self, ObStackingLayer layer); 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) @@ -302,7 +303,8 @@ void client_manage(Window window, ObPrompt *prompt) client_setup_decor_and_functions(self, FALSE); /* specify that if we exit, the window should not be destroyed and - should be reparented back to root automatically */ + should be reparented back to root automatically, unless we are managing + an internal ObPrompt window */ if (!self->prompt) XChangeSaveSet(ob_display, window, SetModeInsert); @@ -617,15 +619,6 @@ void client_manage(Window window, ObPrompt *prompt) /* update the list hints */ client_set_list(); - /* watch for when the application stops responding. only do this for - normal windows, i.e. windows which have titlebars and close buttons - and things like that. - we don't need to stop pinging on unmanage, because it will be handled - automatically by the destroy callback! - */ - if (self->ping && client_normal(self)) - ping_start(self, client_ping_event); - /* free the ObAppSettings shallow copy */ g_free(settings); @@ -704,7 +697,8 @@ void client_unmanage(ObClient *self) mouse_grab_for_client(self, FALSE); - /* remove the window from our save set */ + /* remove the window from our save set, unless we are managing an internal + ObPrompt window */ if (!self->prompt) XChangeSaveSet(ob_display, self->window, SetModeDelete); @@ -715,6 +709,10 @@ void client_unmanage(ObClient *self) focus_client = NULL; } + /* if we're prompting to kill the client, close that */ + prompt_unref(self->kill_prompt); + self->kill_prompt = NULL; + client_list = g_list_remove(client_list, self); stacking_remove(self); g_hash_table_remove(window_map, &self->window); @@ -813,6 +811,7 @@ void client_unmanage(ObClient *self) g_free(self->wm_command); g_free(self->title); g_free(self->icon_title); + g_free(self->original_title); g_free(self->name); g_free(self->class); g_free(self->role); @@ -1967,6 +1966,7 @@ void client_update_title(ObClient *self) gchar *visible = NULL; g_free(self->title); + g_free(self->original_title); /* try netwm */ if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) { @@ -1983,6 +1983,7 @@ void client_update_title(ObClient *self) data = g_strdup("Unnamed Window"); } } + self->original_title = g_strdup(data); if (self->client_machine) { visible = g_strdup_printf("%s (%s)", data, self->client_machine); @@ -1992,7 +1993,7 @@ void client_update_title(ObClient *self) if (self->not_responding) { data = visible; - if (self->close_tried_term) + if (self->kill_level > 0) visible = g_strdup_printf("%s - [%s]", data, _("Killing...")); else visible = g_strdup_printf("%s - [%s]", data, _("Not Responding")); @@ -2024,7 +2025,7 @@ void client_update_title(ObClient *self) if (self->not_responding) { data = visible; - if (self->close_tried_term) + if (self->kill_level > 0) visible = g_strdup_printf("%s - [%s]", data, _("Killing...")); else visible = g_strdup_printf("%s - [%s]", data, _("Not Responding")); @@ -3334,13 +3335,23 @@ void client_shade(ObClient *self, gboolean shade) static void client_ping_event(ObClient *self, gboolean dead) { - self->not_responding = dead; - client_update_title(self); + if (self->not_responding != dead) { + self->not_responding = dead; + client_update_title(self); + + if (dead) + /* the client isn't responding, so ask to kill it */ + client_prompt_kill(self); + else { + /* it came back to life ! */ + + if (self->kill_prompt) { + prompt_unref(self->kill_prompt); + self->kill_prompt = NULL; + } - if (!dead) { - /* try kill it nicely the first time again, if it started responding - at some point */ - self->close_tried_term = FALSE; + self->kill_level = 0; + } } } @@ -3348,6 +3359,7 @@ void client_close(ObClient *self) { if (!(self->functions & OB_CLIENT_FUNC_CLOSE)) return; + /* if closing an internal obprompt, that is just cancelling it */ if (self->prompt) { prompt_cancel(self->prompt); return; @@ -3359,24 +3371,88 @@ void client_close(ObClient *self) /* don't use client_kill(), we should only kill based on PID in response to a lack of PING replies */ XKillClient(ob_display, self->window); - else if (self->not_responding) - client_kill(self); - else + else { /* request the client to close with WM_DELETE_WINDOW */ PROP_MSG_TO(self->window, self->window, wm_protocols, prop_atoms.wm_delete_window, event_curtime, 0, 0, 0, NoEventMask); + + /* we're trying to close the window, so see if it is responding. if it + is not, then we will let them kill the window */ + if (self->ping) + ping_start(self, client_ping_event); + + /* if we already know the window isn't responding (maybe they clicked + no in the kill dialog but it hasn't come back to life), then show + the kill dialog */ + if (self->not_responding) + client_prompt_kill(self); + } +} + +#define OB_KILL_RESULT_NO 0 +#define OB_KILL_RESULT_YES 1 + +static void client_kill_requested(ObPrompt *p, gint result, gpointer data) +{ + ObClient *self = data; + + if (result == OB_KILL_RESULT_YES) + client_kill(self); + + prompt_unref(self->kill_prompt); + self->kill_prompt = NULL; +} + +static void client_prompt_kill(ObClient *self) +{ + /* check if we're already prompting */ + if (!self->kill_prompt) { + ObPromptAnswer answers[] = { + { _("No"), OB_KILL_RESULT_NO }, + { _("Yes"), OB_KILL_RESULT_YES } + }; + gchar *m; + + if (client_on_localhost(self)) { + const gchar *sig; + + if (self->kill_level == 0) + sig = "terminate"; + else + 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); + } + 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); + + + self->kill_prompt = prompt_new(m, answers, + sizeof(answers)/sizeof(answers[0]), + OB_KILL_RESULT_NO, /* default = no */ + OB_KILL_RESULT_NO, /* cancel = no */ + client_kill_requested, self); + g_free(m); + } + + prompt_show(self->kill_prompt, self); } void client_kill(ObClient *self) { - if (!self->client_machine && self->pid) { + /* don't kill our own windows */ + if (self->prompt) return; + + if (client_on_localhost(self) && self->pid) { /* running on the local host */ - if (!self->close_tried_term) { - ob_debug("killing window 0x%x with pid %lu, with SIGTERM\n", + if (self->kill_level == 0) { + ob_debug("killing window 0x%x with pid %lu, with SIGTERM", self->window, self->pid); kill(self->pid, SIGTERM); - self->close_tried_term = TRUE; + ++self->kill_level; /* show that we're trying to kill it */ client_update_title(self); @@ -3387,8 +3463,10 @@ void client_kill(ObClient *self) kill(self->pid, SIGKILL); /* kill -9 */ } } - else + else { + /* running on a remote host */ XKillClient(ob_display, self->window); + } } void client_hilite(ObClient *self, gboolean hilite) @@ -4358,3 +4436,9 @@ gboolean client_has_group_siblings(ObClient *self) { return self->group && self->group->members->next; } + +/*! Returns TRUE if the client is running on the same machine as Openbox */ +gboolean client_on_localhost(ObClient *self) +{ + return self->client_machine == NULL; +}