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

openbox/openbox.h

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

index eb1b461..cb3ab24 100644 (file)
@@ -98,11 +98,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);
 }
@@ -126,7 +130,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;
@@ -143,7 +148,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
     event_cancel_all_key_grabs();
 
     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 {
@@ -162,7 +167,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
                            G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                            NULL, NULL, NULL, &e))
         {
-            g_message(_("Failed to execute \"%s\": %s"), o->cmd, e->message);
+            g_message(e->message, o->cmd);
             g_error_free(e);
 
             if (o->sn)
index 747514f..875a181 100644 (file)
@@ -29,10 +29,15 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, 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 0117e07..9bc9ea8 100644 (file)
@@ -3,10 +3,6 @@
 #include "openbox/session.h"
 #include "gettext.h"
 
-#ifndef USE_SM
-void action_logout_startup(void) {}
-#else
-
 typedef struct {
     gboolean prompt;
     gboolean silent;
@@ -35,12 +31,22 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, 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)
+    if (result) {
+#ifdef USE_SM
         session_request_logout(o->silent);
-    g_free(o);
+#else
+        g_message(_("The SessionLogout actions is not available since Openbox was built without session management support"));
+#endif
+    }
+    return TRUE; /* call cleanup func */
+}
+
+static void prompt_cleanup(ObPrompt *p, gpointer data)
+{
+    g_free(data);
     prompt_unref(p);
 }
 
@@ -59,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
@@ -67,5 +74,3 @@ static gboolean logout_func(ObActionsData *data, gpointer options)
 
     return FALSE;
 }
-
-#endif
index 98d1035..82976f6 100644 (file)
@@ -3400,12 +3400,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;
@@ -3452,11 +3460,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 5c4700a..a7f65fc 100644 (file)
@@ -652,9 +652,11 @@ 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.\n");
+        ob_set_state(OB_STATE_RECONFIGURING);
         modkeys_shutdown(TRUE);
         modkeys_startup(TRUE);
         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 c73c926..c1ec407 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 adbf7c6..6cd9ba9 100644 (file)
@@ -121,7 +121,7 @@ gint main(gint argc, gchar **argv)
 {
     gchar *program_name;
 
-    state = OB_STATE_STARTING;
+    ob_set_state(OB_STATE_STARTING);
 
     /* initialize the locale */
     if (!setlocale(LC_ALL, ""))
@@ -229,6 +229,8 @@ gint main(gint argc, gchar **argv)
 
     if (screen_annex()) { /* it will be ours! */
         do {
+            ObPrompt *xmlprompt = NULL;
+
             modkeys_startup(reconfigure);
 
             /* get the keycodes for keys we use */
@@ -323,7 +325,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);
@@ -331,6 +332,7 @@ gint main(gint argc, gchar **argv)
             mouse_startup(reconfigure);
             menu_frame_startup(reconfigure);
             menu_startup(reconfigure);
+            prompt_startup(reconfigure);
 
             if (!reconfigure) {
                 guint32 xid;
@@ -367,15 +369,37 @@ 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);
+                }
+            }
+
             ob_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) {
                 dock_remove_all();
                 client_unmanage_all();
             }
 
+            prompt_shutdown(reconfigure);
             menu_shutdown(reconfigure);
             menu_frame_shutdown(reconfigure);
             mouse_shutdown(reconfigure);
@@ -383,7 +407,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);
@@ -709,3 +732,8 @@ ObState ob_state(void)
 {
     return state;
 }
+
+void ob_set_state(ObState s)
+{
+    state = s;
+}
index 48c7c82..2c0f38c 100644 (file)
@@ -52,6 +52,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 0278757..f531b70 100644 (file)
@@ -50,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)
 {
@@ -121,6 +122,17 @@ void prompt_startup(gboolean reconfig)
 
 void prompt_shutdown(gboolean reconfig)
 {
+    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);
     RrAppearanceFree(prompt_a_press);
@@ -128,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;
@@ -142,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;
@@ -158,6 +172,10 @@ ObPrompt* prompt_new(const gchar *msg,
     PROP_SET32(self->super.window, net_wm_window_type, atom,
                prop_atoms.net_wm_window_type_dialog);
 
+    /* set the window's title */
+    if (title)
+        PROP_SETS(self->super.window, net_wm_name, title);
+
     /* listen for key presses on the window */
     self->event_mask = KeyPressMask;
 
@@ -218,6 +236,9 @@ void prompt_unref(ObPrompt *self)
     if (self && --self->ref == 0) {
         gint i;
 
+        if (self->mapped)
+            prompt_hide(self);
+
         prompt_list = g_list_remove(prompt_list, self);
 
         for (i = 0; i < self->n_buttons; ++i) {
@@ -517,8 +538,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) ||
@@ -576,10 +596,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;
@@ -597,6 +615,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_run_callback(self, self->cancel_result);
+}
+
+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_unref(p);
+}
+
+ObPrompt* prompt_show_message(const gchar *msg, const gchar *title,
+                              const gchar *answer)
+{
+    ObPrompt *p;
+    ObPromptAnswer ans[] = {
+        { answer, 0 }
+    };
+
+    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 89d3d59..ef19990 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,4 +116,7 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e);
 gboolean prompt_mouse_event(ObPrompt *self, XEvent *e);
 void prompt_cancel(ObPrompt *self);
 
+ObPrompt* prompt_show_message(const gchar *msg, const gchar *title,
+                              const gchar *answer);
+
 #endif
index 2e48f85..15b3c8d 100644 (file)
@@ -492,7 +492,7 @@ void screen_resize(void)
     PROP_SETA32(RootWindow(ob_display, ob_screen),
                 net_desktop_geometry, cardinal, geometry, 2);
 
-    if (ob_state() == OB_STATE_STARTING)
+    if (ob_state() != OB_STATE_RUNNING)
         return;
 
     screen_update_areas();
index 85938de..bb6beff 100644 (file)
@@ -2,6 +2,7 @@
 openbox/actions.c
 openbox/actions/execute.c
 openbox/actions/exit.c
+openbox/actions/session.c
 openbox/client.c
 openbox/client_list_combined_menu.c
 openbox/client_list_menu.c