Merge branch 'backport' into work
authorDana Jansens <danakj@orodu.net>
Sun, 2 Mar 2008 22:23:23 +0000 (17:23 -0500)
committerDana Jansens <danakj@orodu.net>
Sun, 2 Mar 2008 22:23:23 +0000 (17:23 -0500)
Conflicts:

openbox/actions/execute.c
openbox/event.c
openbox/openbox.c
openbox/openbox.h

12 files changed:
openbox/actions/execute.c
openbox/actions/exit.c
openbox/actions/session.c
openbox/client.c
openbox/debug.c
openbox/event.c
openbox/misc.h
openbox/openbox.c
openbox/openbox.h
openbox/prompt.c
openbox/prompt.h
openbox/screen.c

index 81aa6d2..05ab2ef 100644 (file)
@@ -96,11 +96,15 @@ static Options* dup_options(Options *in)
 
 static gboolean run_func(ObActionsData *data, gpointer options);
 
-static void prompt_cb(ObPrompt *p, gint result, gpointer options)
+static gboolean prompt_cb(ObPrompt *p, gint result, gpointer options)
 {
     if (result)
         run_func(NULL, options);
+    return TRUE; /* call the cleanup func */
+}
 
+static void prompt_cleanup(ObPrompt *p, gpointer options)
+{
     prompt_unref(p);
     free_func(options);
 }
@@ -124,7 +128,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         };
 
         ocp = dup_options(options);
-        p = prompt_new(o->prompt, answers, 2, 0, 0, prompt_cb, ocp);
+        p = prompt_new(o->prompt, _("Execute"), answers, 2, 0, 0,
+                       prompt_cb, prompt_cleanup, ocp);
         prompt_show(p, NULL, FALSE);
 
         return FALSE;
@@ -204,7 +209,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
     e = NULL;
     if (!g_shell_parse_argv(cmd, NULL, &argv, &e)) {
-        g_message(_("Failed to execute \"%s\": %s"), o->cmd, e->message);
+        g_message(e->message, o->cmd);
         g_error_free(e);
     }
     else {
@@ -226,8 +231,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
                            G_SPAWN_DO_NOT_REAP_CHILD,
                            NULL, NULL, NULL, &e);
         if (!ok) {
-            g_message(_("Failed to execute \"%s\": %s"),
-                      o->cmd, e->message);
+            g_message(e->message, o->cmd);
             g_error_free(e);
         }
 
index 25fc08b..4f8cce6 100644 (file)
@@ -29,10 +29,15 @@ static gpointer setup_func(xmlNodePtr node)
     return o;
 }
 
-static void prompt_cb(ObPrompt *p, gint result, gpointer data)
+static gboolean prompt_cb(ObPrompt *p, gint result, gpointer data)
 {
     if (result)
         ob_exit(0);
+    return TRUE; /* call the cleanup func */
+}
+
+static void prompt_cleanup(ObPrompt *p, gpointer data)
+{
     prompt_unref(p);
 }
 
@@ -49,7 +54,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         };
 
         p = prompt_new(_("Are you sure you want to exit Openbox?"),
-                       answers, 2, 0, 0, prompt_cb, NULL);
+                       _("Exit Openbox"),
+                       answers, 2, 0, 0, prompt_cb, prompt_cleanup, NULL);
         prompt_show(p, NULL, FALSE);
     }
     else
index b6eebcb..27df917 100644 (file)
@@ -31,17 +31,22 @@ static gpointer setup_func(xmlNodePtr node)
     return o;
 }
 
-static void prompt_cb(ObPrompt *p, gint result, gpointer data)
+static gboolean prompt_cb(ObPrompt *p, gint result, gpointer data)
 {
     Options *o = data;
     if (result) {
-#ifndef USE_SM
+#ifdef USE_SM
         session_request_logout(o->silent);
 #else
         g_message(_("The SessionLogout actions is not available since Openbox was built without session management support"));
 #endif
     }
-    g_free(o);
+    return TRUE; /* call cleanup func */
+}
+
+static void prompt_cleanup(ObPrompt *p, gpointer data)
+{
+    g_free(data);
     prompt_unref(p);
 }
 
@@ -60,7 +65,8 @@ static gboolean logout_func(ObActionsData *data, gpointer options)
 
         o2 = g_memdup(o, sizeof(Options));
         p = prompt_new(_("Are you sure you want to log out?"),
-                       answers, 2, 0, 0, prompt_cb, o2);
+                       _("Log out"),
+                       answers, 2, 0, 0, prompt_cb, prompt_cleanup, o2);
         prompt_show(p, NULL, FALSE);
     }
     else
index b57d616..e9443d4 100644 (file)
@@ -3339,12 +3339,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;
@@ -3391,11 +3399,13 @@ static void client_prompt_kill(ObClient *self)
         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);
     }
 
index 04a9582..6b92c9e 100644 (file)
@@ -135,7 +135,7 @@ static void prompt_handler(const gchar *log_domain, GLogLevelFlags log_level,
                            const gchar *message, gpointer data)
 {
     if (ob_state() == OB_STATE_RUNNING)
-        prompt_show_message(message, _("Close"));
+        prompt_show_message(message, _("Openbox"), _("Close"));
 }
 
 static inline void log_argv(ObDebugType type,
index 9705fb6..a0ce223 100644 (file)
@@ -657,8 +657,10 @@ static void event_process(const XEvent *ec, gpointer data)
         /* keyboard layout changes for modifier mapping changes. reload the
            modifier map, and rebind all the key bindings as appropriate */
         ob_debug("Kepboard map changed. Reloading keyboard bindings.");
+        ob_set_state(OB_STATE_RECONFIGURING);
         obt_keyboard_reload();
         keyboard_rebind();
+        ob_set_state(OB_STATE_RUNNING);
     }
     else if (e->type == ClientMessage) {
         /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for
index 13530ed..05b5ac8 100644 (file)
@@ -60,7 +60,8 @@ typedef enum
 {
     OB_STATE_STARTING,
     OB_STATE_RUNNING,
-    OB_STATE_EXITING
+    OB_STATE_EXITING,
+    OB_STATE_RECONFIGURING
 } ObState;
 
 typedef enum
index 01aa58a..3f28609 100644 (file)
@@ -118,7 +118,7 @@ gint main(gint argc, gchar **argv)
 {
     gchar *program_name;
 
-    state = OB_STATE_STARTING;
+    ob_set_state(OB_STATE_STARTING);
 
     ob_debug_startup();
 
@@ -212,6 +212,8 @@ gint main(gint argc, gchar **argv)
 
     if (screen_annex()) { /* it will be ours! */
         do {
+            ObPrompt *xmlprompt = NULL;
+
             if (reconfigure) obt_keyboard_reload();
 
             /* get the keycodes for keys we use */
@@ -308,7 +310,6 @@ gint main(gint argc, gchar **argv)
             grab_startup(reconfigure);
             group_startup(reconfigure);
             ping_startup(reconfigure);
-            prompt_startup(reconfigure);
             client_startup(reconfigure);
             dock_startup(reconfigure);
             moveresize_startup(reconfigure);
@@ -316,6 +317,7 @@ gint main(gint argc, gchar **argv)
             mouse_startup(reconfigure);
             menu_frame_startup(reconfigure);
             menu_startup(reconfigure);
+            prompt_startup(reconfigure);
 
             if (!reconfigure) {
                 guint32 xid;
@@ -351,13 +353,35 @@ gint main(gint argc, gchar **argv)
 
             reconfigure = FALSE;
 
-            state = OB_STATE_RUNNING;
+            ob_set_state(OB_STATE_RUNNING);
+
+            /* look for parsing errors */
+            {
+                xmlErrorPtr e = xmlGetLastError();
+                if (e) {
+                    gchar *m;
+
+                    m = g_strdup_printf(_("One or more XML syntax errors were found while parsing the Openbox configuration files.  See stdout for more information.  The last error seen was in file \"%s\" line %d, with message: %s"), e->file, e->line, e->message);
+                    xmlprompt =
+                        prompt_show_message(m, _("Openbox Syntax Error"), _("Close"));
+                    g_free(m);
+                    xmlResetError(e);
+                }
+            }
+
             obt_main_loop_run(ob_main_loop);
-            state = OB_STATE_EXITING;
+            ob_set_state(reconfigure ?
+                         OB_STATE_RECONFIGURING : OB_STATE_EXITING);
+
+            if (xmlprompt) {
+                prompt_unref(xmlprompt);
+                xmlprompt = NULL;
+            }
 
             if (!reconfigure)
                 window_unmanage_all();
 
+            prompt_shutdown(reconfigure);
             menu_shutdown(reconfigure);
             menu_frame_shutdown(reconfigure);
             mouse_shutdown(reconfigure);
@@ -365,7 +389,6 @@ gint main(gint argc, gchar **argv)
             moveresize_shutdown(reconfigure);
             dock_shutdown(reconfigure);
             client_shutdown(reconfigure);
-            prompt_shutdown(reconfigure);
             ping_shutdown(reconfigure);
             group_shutdown(reconfigure);
             grab_shutdown(reconfigure);
@@ -695,3 +718,8 @@ ObState ob_state(void)
 {
     return state;
 }
+
+void ob_set_state(ObState s)
+{
+    state = s;
+}
index ba22183..2a938c5 100644 (file)
@@ -49,6 +49,7 @@ extern gboolean ob_debug_xinerama;
 
 /* The state of execution of the window manager */
 ObState ob_state(void);
+void ob_set_state(ObState state);
 
 void ob_restart_other(const gchar *path);
 void ob_restart(void);
index d4dcbb7..31d805a 100644 (file)
@@ -28,7 +28,6 @@
 #include "gettext.h"
 
 static GList *prompt_list = NULL;
-static GList *prompt_msg_list = NULL;
 
 /* we construct these */
 static RrAppearance *prompt_a_bg;
@@ -51,6 +50,7 @@ static void prompt_layout(ObPrompt *self);
 static void render_all(ObPrompt *self);
 static void render_button(ObPrompt *self, ObPromptElement *e);
 static void prompt_resize(ObPrompt *self, gint w, gint h);
+static void prompt_run_callback(ObPrompt *self, gint result);
 
 void prompt_startup(gboolean reconfig)
 {
@@ -122,8 +122,16 @@ void prompt_startup(gboolean reconfig)
 
 void prompt_shutdown(gboolean reconfig)
 {
-    while (prompt_msg_list)
-        prompt_cancel(prompt_msg_list->data);
+    GList *it;
+
+    if (!reconfig) {
+        for (it = prompt_list; it; it = g_list_next(it)) {
+            ObPrompt *p = it->data;
+            if (p->cleanup) p->cleanup(p, p->data);
+        }
+
+        g_assert(prompt_list == NULL);
+    }
 
     RrAppearanceFree(prompt_a_button);
     RrAppearanceFree(prompt_a_focus);
@@ -132,10 +140,11 @@ void prompt_shutdown(gboolean reconfig)
     RrAppearanceFree(prompt_a_msg);
 }
 
-ObPrompt* prompt_new(const gchar *msg,
+ObPrompt* prompt_new(const gchar *msg, const gchar *title,
                      const ObPromptAnswer *answers, gint n_answers,
                      gint default_result, gint cancel_result,
-                     ObPromptCallback func, gpointer data)
+                     ObPromptCallback func, ObPromptCleanup cleanup,
+                     gpointer data)
 {
     ObPrompt *self;
     XSetWindowAttributes attrib;
@@ -146,6 +155,7 @@ ObPrompt* prompt_new(const gchar *msg,
     self = g_new0(ObPrompt, 1);
     self->ref = 1;
     self->func = func;
+    self->cleanup = cleanup;
     self->data = data;
     self->default_result = default_result;
     self->cancel_result = cancel_result;
@@ -161,6 +171,10 @@ ObPrompt* prompt_new(const gchar *msg,
     OBT_PROP_SET32(self->super.window, NET_WM_WINDOW_TYPE, ATOM,
                    OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG));
 
+    /* set the window's title */
+    if (title)
+        OBT_PROP_SETS(self->super.window, NET_WM_NAME, utf8, title);
+
     /* listen for key presses on the window */
     self->event_mask = KeyPressMask;
 
@@ -523,8 +537,7 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e)
     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);
+        prompt_run_callback(self, self->focus->result);
     }
     else if (e->xkey.keycode == ob_keycode(OB_KEY_TAB) ||
              e->xkey.keycode == ob_keycode(OB_KEY_LEFT) ||
@@ -582,10 +595,8 @@ gboolean prompt_mouse_event(ObPrompt *self, XEvent *e)
         render_button(self, but);
     }
     else if (e->type == ButtonRelease) {
-        if (but->pressed) {
-            if (self->func) self->func(self, but->result, self->data);
-            prompt_hide(self);
-        }
+        if (but->pressed)
+            prompt_run_callback(self, but->result);
     }
     else if (e->type == MotionNotify) {
         gboolean press;
@@ -603,24 +614,41 @@ gboolean prompt_mouse_event(ObPrompt *self, XEvent *e)
 
 void prompt_cancel(ObPrompt *self)
 {
-    if (self->func) self->func(self, self->cancel_result, self->data);
-    prompt_hide(self);
+    prompt_run_callback(self, self->cancel_result);
 }
 
-static void prompt_show_message_cb(ObPrompt *p, int res, gpointer data)
+static gboolean prompt_show_message_cb(ObPrompt *p, int res, gpointer data)
+{
+    return TRUE; /* call the cleanup func */
+}
+
+static void prompt_show_message_cleanup(ObPrompt *p, gpointer data)
 {
-    prompt_msg_list = g_list_remove(prompt_msg_list, p);
     prompt_unref(p);
 }
 
-void prompt_show_message(const gchar *msg, const gchar *answer)
+ObPrompt* prompt_show_message(const gchar *msg, const gchar *title,
+                              const gchar *answer)
 {
     ObPrompt *p;
     ObPromptAnswer ans[] = {
         { answer, 0 }
     };
 
-    p = prompt_new(msg, ans, 1, 0, 0, prompt_show_message_cb, NULL);
-    prompt_msg_list = g_list_prepend(prompt_msg_list, p);
+    p = prompt_new(msg, title, ans, 1, 0, 0,
+                   prompt_show_message_cb, prompt_show_message_cleanup, NULL);
     prompt_show(p, NULL, FALSE);
+    return p;
+}
+
+static void prompt_run_callback(ObPrompt *self, gint result)
+{
+    prompt_ref(self);
+    if (self->func) {
+        gboolean clean = self->func(self, self->focus->result, self->data);
+        if (clean && self->cleanup)
+            self->cleanup(self, self->data);
+    }
+    prompt_hide(self);
+    prompt_unref(self);
 }
index f51d66d..d07793a 100644 (file)
@@ -29,7 +29,8 @@ typedef struct _ObPrompt       ObPrompt;
 typedef struct _ObPromptElement ObPromptElement;
 typedef struct _ObPromptAnswer ObPromptAnswer;
 
-typedef void (*ObPromptCallback)(ObPrompt *p, gint result, gpointer data);
+typedef gboolean (*ObPromptCallback)(ObPrompt *p, gint result, gpointer data);
+typedef void (*ObPromptCleanup)(ObPrompt *p, gpointer data);
 
 struct _ObPromptElement {
     gchar *text;
@@ -69,6 +70,7 @@ struct _ObPrompt
     gint cancel_result;
 
     ObPromptCallback func;
+    ObPromptCleanup cleanup;
     gpointer data;
 };
 
@@ -90,12 +92,19 @@ void prompt_shutdown(gboolean reconfig);
          of having a button presssed
   @param func The callback function which is called when the dialog is closed
          or a button is pressed
+  @param cleanup The cleanup function which is called if the prompt system
+         is shutting down, and someone is still holding a reference to the
+         prompt.  This callback should cause the prompt's refcount to go to
+         zero so it can be freed, and free any other memory associated with
+         the prompt.  The cleanup function is also called if the prompt's
+         callback function returns TRUE.
   @param data User defined data which will be passed to the callback
 */
-ObPrompt* prompt_new(const gchar *msg,
+ObPrompt* prompt_new(const gchar *msg, const gchar *title,
                      const ObPromptAnswer *answers, gint n_answers,
                      gint default_result, gint cancel_result,
-                     ObPromptCallback func, gpointer data);
+                     ObPromptCallback func, ObPromptCleanup cleanup,
+                     gpointer data);
 void prompt_ref(ObPrompt *self);
 void prompt_unref(ObPrompt *self);
 
@@ -107,6 +116,7 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e);
 gboolean prompt_mouse_event(ObPrompt *self, XEvent *e);
 void prompt_cancel(ObPrompt *self);
 
-void prompt_show_message(const gchar *msg, const gchar *answer);
+ObPrompt* prompt_show_message(const gchar *msg, const gchar *title,
+                              const gchar *answer);
 
 #endif
index cd46c53..3b9f66f 100644 (file)
@@ -481,7 +481,7 @@ void screen_resize(void)
     OBT_PROP_SETA32(obt_root(ob_screen),
                     NET_DESKTOP_GEOMETRY, CARDINAL, geometry, 2);
 
-    if (ob_state() == OB_STATE_STARTING)
+    if (ob_state() != OB_STATE_RUNNING)
         return;
 
     screen_update_areas();