X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=c8c6c93b513ca130dc127eb6bec0ed19cd65999a;hb=4eecbeb611680cf98df68905a0d22fcf68ca94a5;hp=500562b0423a329e894f8fc6a2f3724978a0557d;hpb=deca45dadad1e0e1d5183341a601267f2deb1aa5;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 500562b0..c8c6c93b 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); @@ -704,7 +706,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 +718,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 +820,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 +1975,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 +1992,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 +2002,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 +2034,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")); @@ -3338,9 +3348,14 @@ static void client_ping_event(ObClient *self, gboolean dead) client_update_title(self); if (!dead) { - /* try kill it nicely the first time again, if it started responding - at some point */ - self->close_tried_term = FALSE; + /* it came back to life ! */ + + if (self->kill_prompt) { + prompt_unref(self->kill_prompt); + self->kill_prompt = NULL; + } + + self->kill_level = 0; } } @@ -3349,7 +3364,7 @@ void client_close(ObClient *self) if (!(self->functions & OB_CLIENT_FUNC_CLOSE)) return; if (self->prompt) { - prompt_hide(self->prompt); + prompt_cancel(self->prompt); return; } @@ -3359,24 +3374,73 @@ 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); + + 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; + 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); + + 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) { + /* don't kill our own windows */ + if (self->prompt) return; + if (!self->client_machine && 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 +3451,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)