all repos — openbox @ d714bb5708bb8b99d71803404af7af01029c5553

openbox fork - make it a bit more like ryudo

prompt to kill windows when they are not responding
Dana Jansens danakj@orodu.net
commit

d714bb5708bb8b99d71803404af7af01029c5553

parent

c7af49b5c564d6287a0293ae26fc713fb55b4dc8

M openbox/client.copenbox/client.c

@@ -105,6 +105,7 @@ gboolean bylayer,

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 @@ mapping and doesn't go applying things right away */

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 @@ event_end_ignore_all_enters(ignore_start);

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);

@@ -714,6 +717,10 @@ if (client_focused(self)) {

/* don't leave an invalid focus_client */ 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);

@@ -1992,7 +1999,7 @@ visible = data;

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 +2031,7 @@ visible = data;

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 +3345,14 @@ self->not_responding = 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; } }

@@ -3359,24 +3371,64 @@ if (!self->delete_window)

/* 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) +{ + ObPromptAnswer answers[] = { + { _("No"), OB_KILL_RESULT_NO }, + { _("Yes"), OB_KILL_RESULT_YES } + }; + gchar *m; + + /* check if we're already prompting */ + if (self->kill_prompt) return; + + m = g_strdup_printf + (_("The window \"%s\" does not seem to be responding. Do you want to force it to exit?"), self->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); + prompt_show(self->kill_prompt, self); + + g_free(m); } void client_kill(ObClient *self) { 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 +3439,10 @@ self->window, self->pid);

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)
M openbox/client.hopenbox/client.h

@@ -236,8 +236,11 @@ gboolean ping;

/*! Indicates if the client is trying to close but has stopped responding to pings */ gboolean not_responding; + /*! A prompt shown when you are trying to close a client that is not + responding. It asks if you want to kill the client */ + struct _ObPrompt *kill_prompt; /*! We tried to close the window with a SIGTERM */ - gboolean close_tried_term; + gint kill_level; #ifdef SYNC /*! The client wants to sync during resizes */
M openbox/event.copenbox/event.c

@@ -89,7 +89,7 @@ static void event_process(const XEvent *e, gpointer data);

static void event_handle_root(XEvent *e); static gboolean event_handle_menu_keyboard(XEvent *e); static gboolean event_handle_menu(XEvent *e); -static void event_handle_prompt(ObPrompt *p, XEvent *e); +static gboolean event_handle_prompt(ObPrompt *p, XEvent *e); static void event_handle_dock(ObDock *s, XEvent *e); static void event_handle_dockapp(ObDockApp *app, XEvent *e); static void event_handle_client(ObClient *c, XEvent *e);

@@ -707,8 +707,8 @@ moveresize_event(e);

} #endif - if (prompt) - event_handle_prompt(prompt, e); + if (prompt && event_handle_prompt(prompt, e)) + ; else if (e->type == ButtonPress || e->type == ButtonRelease) { /* If the button press was on some non-root window, or was physically on the root window, then process it */

@@ -1677,18 +1677,19 @@ ret = menu_frame_visible->data;

return ret; } -static void event_handle_prompt(ObPrompt *p, XEvent *e) +static gboolean event_handle_prompt(ObPrompt *p, XEvent *e) { switch (e->type) { case ButtonPress: case ButtonRelease: case MotionNotify: - prompt_mouse_event(p, e); + return prompt_mouse_event(p, e); break; case KeyPress: - prompt_key_event(p, e); + return prompt_key_event(p, e); break; } + return FALSE; } static gboolean event_handle_menu_keyboard(XEvent *ev)
M openbox/misc.hopenbox/misc.h

@@ -52,6 +52,7 @@ OB_KEY_RIGHT,

OB_KEY_UP, OB_KEY_DOWN, OB_KEY_TAB, + OB_KEY_SPACE, OB_NUM_KEYS } ObKey;
M openbox/openbox.copenbox/openbox.c

@@ -232,6 +232,8 @@ keys[OB_KEY_LEFT] = modkeys_sym_to_code(XK_Left);

keys[OB_KEY_RIGHT] = modkeys_sym_to_code(XK_Right); keys[OB_KEY_UP] = modkeys_sym_to_code(XK_Up); keys[OB_KEY_DOWN] = modkeys_sym_to_code(XK_Down); + keys[OB_KEY_TAB] = modkeys_sym_to_code(XK_Tab); + keys[OB_KEY_SPACE] = modkeys_sym_to_code(XK_space); { ObParseInst *i;
M openbox/prompt.copenbox/prompt.c

@@ -348,8 +348,8 @@ hints.min_width = hints.max_width = self->width;

hints.min_height = hints.max_height = self->height; XSetWMNormalHints(ob_display, self->super.window, &hints); - XSetTransientForHint(ob_display, (parent ? parent->window : 0), - self->super.window); + XSetTransientForHint(ob_display, self->super.window, + (parent ? parent->window : 0)); /* set up the dialog and render it */ prompt_layout(self);

@@ -366,12 +366,12 @@ XUnmapWindow(ob_display, self->super.window);

self->mapped = FALSE; } -void prompt_key_event(ObPrompt *self, XEvent *e) +gboolean prompt_key_event(ObPrompt *self, XEvent *e) { gboolean shift; guint shift_mask; - if (e->type != KeyPress) return; + if (e->type != KeyPress) return FALSE; g_print("key 0x%x 0x%x\n", e->xkey.keycode, ob_keycode(OB_KEY_TAB));

@@ -380,23 +380,31 @@ shift = !!(e->xkey.state & shift_mask);

/* only accept shift */ if (e->xkey.state != 0 && e->xkey.state != shift_mask) - return; + return FALSE; if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) prompt_cancel(self); - else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) { + else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) || + e->xkey.keycode == ob_keycode(OB_KEY_SPACE)) + { if (self->func) self->func(self, self->focus->result, self->data); prompt_hide(self); } - else if (e->xkey.keycode == ob_keycode(OB_KEY_TAB)) { + else if (e->xkey.keycode == ob_keycode(OB_KEY_TAB) || + e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || + e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) + { gint i; + gboolean left; ObPromptElement *oldfocus; + left = e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || + (e->xkey.keycode == ob_keycode(OB_KEY_TAB) && shift); oldfocus = self->focus; for (i = 0; i < self->n_buttons; ++i) if (self->focus == &self->button[i]) break; - i += (shift ? -1 : 1); + i += (left ? -1 : 1); if (i < 0) i = self->n_buttons - 1; else if (i >= self->n_buttons) i = 0; self->focus = &self->button[i];

@@ -404,9 +412,10 @@

if (oldfocus != self->focus) render_button(self, oldfocus); render_button(self, self->focus); } + return TRUE; } -void prompt_mouse_event(ObPrompt *self, XEvent *e) +gboolean prompt_mouse_event(ObPrompt *self, XEvent *e) { gint i; ObPromptElement *but;

@@ -415,6 +424,7 @@ if (e->type != ButtonPress && e->type != ButtonRelease &&

e->type != MotionNotify) return; /* find the button */ + but = NULL; for (i = 0; i < self->n_buttons; ++i) if (self->button[i].window == (e->type == MotionNotify ? e->xmotion.window : e->xbutton.window))

@@ -422,7 +432,7 @@ {

but = &self->button[i]; break; } - g_assert(but != NULL); + if (!but) return FALSE; if (e->type == ButtonPress) { ObPromptElement *oldfocus;

@@ -452,6 +462,7 @@ but->pressed = press;

render_button(self, but); } } + return TRUE; } void prompt_cancel(ObPrompt *self)
M openbox/prompt.hopenbox/prompt.h

@@ -103,8 +103,8 @@ /*! Show the prompt. It will be centered within the given area rectangle */

void prompt_show(ObPrompt *self, struct _ObClient *parent); void prompt_hide(ObPrompt *self); -void prompt_key_event(ObPrompt *self, XEvent *e); -void prompt_mouse_event(ObPrompt *self, XEvent *e); +gboolean prompt_key_event(ObPrompt *self, XEvent *e); +gboolean prompt_mouse_event(ObPrompt *self, XEvent *e); void prompt_cancel(ObPrompt *self); #endif