Author: kelnos
Date: 2006-07-16 10:06:10 +0000 (Sun, 16 Jul 2006)
New Revision: 22460

Added:
   xfce-utils/trunk/xfrun/org.xfce.RunDialog.service.in
   xfce-utils/trunk/xfrun/xfrun-dbus.c
Modified:
   xfce-utils/trunk/configure.in.in
   xfce-utils/trunk/po/POTFILES.in
   xfce-utils/trunk/xfrun/Makefile.am
   xfce-utils/trunk/xfrun/xfrun-dialog.c
   xfce-utils/trunk/xfrun/xfrun-dialog.h
Log:
dbus daemon support for xfrun, a few memleak fixes, etc.


Modified: xfce-utils/trunk/configure.in.in
===================================================================
--- xfce-utils/trunk/configure.in.in    2006-07-16 08:17:54 UTC (rev 22459)
+++ xfce-utils/trunk/configure.in.in    2006-07-16 10:06:10 UTC (rev 22460)
@@ -37,8 +37,8 @@
 
 dnl Check for standard header files
 AC_HEADER_STDC
-AC_CHECK_HEADERS([unistd.h string.h])
-AC_CHECK_FUNCS([setsid])
+AC_CHECK_HEADERS([errno.h unistd.h string.h])
+AC_CHECK_FUNCS([daemon setsid])
 
 dnl Check for X11 installed
 XDT_CHECK_LIBX11_REQUIRE

Modified: xfce-utils/trunk/po/POTFILES.in
===================================================================
--- xfce-utils/trunk/po/POTFILES.in     2006-07-16 08:17:54 UTC (rev 22459)
+++ xfce-utils/trunk/po/POTFILES.in     2006-07-16 10:06:10 UTC (rev 22460)
@@ -2,3 +2,5 @@
 
 xfce4-about/info.c
 xfrun/xfrun.c
+xfrun/xfrun-dbus.c
+xfrun/xfrun-dialog.c

Modified: xfce-utils/trunk/xfrun/Makefile.am
===================================================================
--- xfce-utils/trunk/xfrun/Makefile.am  2006-07-16 08:17:54 UTC (rev 22459)
+++ xfce-utils/trunk/xfrun/Makefile.am  2006-07-16 10:06:10 UTC (rev 22460)
@@ -4,20 +4,21 @@
        xfrun-dialog.c \
        xfrun-dialog.h
 
-#if HAVE_DBUS
+if HAVE_DBUS
 
-#xfrun4_SOURCES += \
-#      xfrun-dbus.c
+xfrun4_SOURCES += \
+       xfrun-dbus.c
 
-#else
+else
 
 xfrun4_SOURCES += \
        xfrun.c
 
-#endif
+endif
 
 xfrun4_CFLAGS = \
        -DLOCALEDIR=\"$(localedir)\" \
+       -DDBUS_API_SUBJECT_TO_CHANGE \
        @LIBXFCE4UTIL_CFLAGS@ \
        @LIBXFCEGUI4_CFLAGS@ \
        @GTK_CFLAGS@ \
@@ -29,7 +30,23 @@
        @GTK_LIBS@ \
        @DBUS_LIBS@
 
+
+if HAVE_DBUS
+
+service_in_files = org.xfce.RunDialog.service.in
+
+servicedir = $(datadir)/dbus-1/services
+service_DATA = $(service_in_files:.service.in=.service)
+
+%.service: %.service.in
+       sed -e "s,[EMAIL PROTECTED]@,$(bindir),g" < $< > $@
+
+DISTCLEANFILES = \
+       $(service_DATA)
+
+endif
+
 EXTRA_DIST = \
        xfrun.c \
-
-#      xfrun-dbus.c
+       xfrun-dbus.c \
+       $(service_in_files)

Added: xfce-utils/trunk/xfrun/org.xfce.RunDialog.service.in
===================================================================
--- xfce-utils/trunk/xfrun/org.xfce.RunDialog.service.in                        
        (rev 0)
+++ xfce-utils/trunk/xfrun/org.xfce.RunDialog.service.in        2006-07-16 
10:06:10 UTC (rev 22460)
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.xfce.RunDialog
[EMAIL PROTECTED]@/xfrun4 --daemon

Added: xfce-utils/trunk/xfrun/xfrun-dbus.c
===================================================================
--- xfce-utils/trunk/xfrun/xfrun-dbus.c                         (rev 0)
+++ xfce-utils/trunk/xfrun/xfrun-dbus.c 2006-07-16 10:06:10 UTC (rev 22460)
@@ -0,0 +1,377 @@
+/*
+ * xfrun - a simple quick run dialog with saved history and completion
+ *                    Jannis Pohlmann <[EMAIL PROTECTED]>
+ *                    Jani Monoses <[EMAIL PROTECTED]>
+ *
+ * Copyright (c) 2006 Brian J. Tarricone <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "xfrun-dialog.h"
+
+/**
+ * method: org.xfce.RunDialog.OpenDialog
+ * param:  display_name (DBUS_TYPE_STRING)
+ * param:  working_directory (DBUS_TYPE_STRING)
+ * param:  run_argument (DBUS_TYPE_STRING)
+ * return: success, or org.xfce.RunDialog.ErrorGeneral
+ * description: shows the run dialog on the specified display.  will execute
+ *              the command in the specified working directory.  an optional
+ *              argument can be passed that will be passed to the program that
+ *              is executed.
+ **
+ * method: org.xfce.RunDialog.Quit
+ * description: instructs the xfrun daemon to quit.
+ */
+#define RUNDIALOG_DBUS_SERVICE        "org.xfce.RunDialog"
+#define RUNDIALOG_DBUS_INTERFACE      "org.xfce.RunDialog"
+#define RUNDIALOG_DBUS_PATH           "/org/xfce/RunDialog"
+#define RUNDIALOG_DBUS_METHOD_OPEN    "OpenDialog"
+#define RUNDIALOG_DBUS_METHOD_QUIT    "Quit"
+#define RUNDIALOG_DBUS_ERROR_GENERAL  "org.xfce.RunDialog.ErrorGeneral"
+
+
+static GtkWidget *static_dialog = NULL;
+static gboolean static_dialog_in_use = FALSE;
+
+static void
+xfrun_static_dialog_closed(XfrunDialog *dialog,
+                           gpointer user_data)
+{
+    static_dialog_in_use = FALSE;
+}
+
+/* gdk_display_close() is essentially broken on X11.  so every time we call
+ * gdk_display_open(), we can't close it, and thus leak memory.  instead, let's
+ * keep a cache of all open displays, and, in normal situations we'll only have
+ * one display open per screen.
+ */
+static GdkDisplay *
+xfrun_find_or_open_display(const gchar *display_name)
+{
+    static GHashTable *open_displays = NULL;
+    GdkDisplay *gdpy = NULL;
+    
+    if(G_UNLIKELY(!open_displays)) {
+        open_displays = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                              (GDestroyNotify)g_free, NULL);
+    }
+    
+    gdpy = g_hash_table_lookup(open_displays, display_name);
+    if(!gdpy) {
+        gdpy = gdk_display_open(display_name);
+        if(gdpy)
+            g_hash_table_insert(open_displays, g_strdup(display_name), gdpy);
+    }
+    
+    return gdpy;
+}
+
+
+/* server message handler */
+static DBusHandlerResult
+xfrun_handle_dbus_message(DBusConnection *connection,
+                          DBusMessage *message,
+                          void *user_data)
+{
+    if(dbus_message_is_method_call(message,
+                                   RUNDIALOG_DBUS_INTERFACE,
+                                   RUNDIALOG_DBUS_METHOD_OPEN))
+    {
+        DBusMessage *reply = NULL;
+        DBusError derror;
+        gchar *display_name = NULL, *cwd = NULL, *run_argument = NULL;
+        
+        dbus_error_init(&derror);
+        
+        if(!dbus_message_get_args(message, &derror, 
+                                  DBUS_TYPE_STRING, &display_name,
+                                  DBUS_TYPE_STRING, &cwd,
+                                  DBUS_TYPE_STRING, &run_argument,
+                                  DBUS_TYPE_INVALID))
+        {
+            reply = dbus_message_new_error(message, 
RUNDIALOG_DBUS_ERROR_GENERAL,
+                                           derror.message);
+            dbus_error_free(&derror);
+        } else {
+            GdkDisplay *gdpy;
+            GdkScreen *gscreen = NULL;
+            
+            gdpy = xfrun_find_or_open_display(display_name);
+            if(!gdpy) {
+                gchar *msgstr = g_strdup_printf(_("Unable to open display 
\"%s\"."),
+                                                display_name);
+                reply = dbus_message_new_error(message,
+                                               RUNDIALOG_DBUS_ERROR_GENERAL,
+                                               msgstr);
+                g_free(msgstr);
+            } else {
+                GtkWidget *dialog;
+                
+                gscreen = gdk_display_get_default_screen(gdpy);
+                
+                if(!strlen(run_argument))
+                    run_argument = NULL;
+                
+                if(static_dialog_in_use) {
+                    dialog = xfrun_dialog_new(run_argument);
+                    xfrun_dialog_set_destroy_on_close(XFRUN_DIALOG(dialog),
+                                                      TRUE);
+                    xfrun_dialog_set_working_directory(XFRUN_DIALOG(dialog),
+                                                       cwd);
+                } else {
+                    dialog = static_dialog;
+                    xfrun_dialog_set_run_argument(XFRUN_DIALOG(dialog),
+                                                  run_argument);
+                    xfrun_dialog_set_working_directory(XFRUN_DIALOG(dialog),
+                                                       cwd);
+                    if(GTK_WIDGET_REALIZED(dialog)) {
+                        gdk_x11_window_set_user_time(dialog->window,
+                                                     
gdk_x11_get_server_time(dialog->window));
+                    }
+                    static_dialog_in_use = TRUE;
+                }
+                
+                /* this handles setting the dialog to the right screen */
+                xfce_gtk_window_center_on_monitor(GTK_WINDOW(dialog),
+                                                  gscreen, 0);
+                gtk_widget_show(dialog);
+            
+                reply = dbus_message_new_method_return(message);
+                
+            }
+        }
+
+        dbus_connection_send(connection, reply, NULL);
+        dbus_message_unref(reply);
+        
+        return DBUS_HANDLER_RESULT_HANDLED;
+    } else if(dbus_message_is_method_call(message,
+                                          RUNDIALOG_DBUS_INTERFACE,
+                                          RUNDIALOG_DBUS_METHOD_QUIT))
+    {
+        DBusMessage *reply = dbus_message_new_method_return(message);
+        dbus_connection_send(connection, reply, NULL);
+        dbus_message_unref(reply);
+        
+        gtk_main_quit();
+    } else if(dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL,
+                                     "Disconnected"))
+    {
+        g_printerr(_("D-BUS message bus disconnected. Exiting ...\n"));
+        gtk_main_quit();
+        
+        return DBUS_HANDLER_RESULT_HANDLED;
+    }
+    
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/* server registration */
+static gboolean
+xfrun_register_dbus_service()
+{
+    static const struct DBusObjectPathVTable vtable = {
+        NULL, 
+        xfrun_handle_dbus_message,
+        NULL,
+    };
+    DBusConnection *connection;
+    DBusError derror;
+    
+    dbus_error_init(&derror);
+    connection = dbus_bus_get(DBUS_BUS_SESSION, &derror);
+    if(G_UNLIKELY(!connection)) {
+        dbus_error_free(&derror);
+        return FALSE;
+    }
+    
+    dbus_connection_setup_with_g_main(connection, NULL);
+    
+    if(dbus_bus_request_name(connection, RUNDIALOG_DBUS_SERVICE, 0, &derror) < 
0) {
+        dbus_error_free(&derror);
+        return FALSE;
+    }
+    
+    if(!dbus_connection_register_object_path(connection, RUNDIALOG_DBUS_PATH,
+                                             &vtable, NULL))
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/* client handler */
+static gboolean
+xfrun_show_dialog(const gchar *run_argument)
+{
+    DBusConnection *connection;
+    DBusMessage *method;
+    DBusMessage *result;
+    DBusError derror;
+    gchar *cwd, *display_name, *dummy_run_argument = NULL;
+    
+    dbus_error_init(&derror);
+    connection = dbus_bus_get(DBUS_BUS_SESSION, &derror);
+    if(!connection) {
+        dbus_error_free(&derror);
+        return FALSE;
+    }
+    
+    method = dbus_message_new_method_call(RUNDIALOG_DBUS_SERVICE,
+                                          RUNDIALOG_DBUS_PATH,
+                                          RUNDIALOG_DBUS_INTERFACE,
+                                          RUNDIALOG_DBUS_METHOD_OPEN);
+    dbus_message_set_auto_start(method, TRUE);
+    
+    display_name = gdk_screen_make_display_name(gdk_screen_get_default());
+    cwd = g_get_current_dir();
+    
+    if(!run_argument)
+        run_argument = dummy_run_argument = g_strdup("");
+    
+    dbus_message_append_args(method,
+                             DBUS_TYPE_STRING, &display_name,
+                             DBUS_TYPE_STRING, &cwd,
+                             DBUS_TYPE_STRING, &run_argument,
+                             DBUS_TYPE_INVALID);
+    
+    g_free(display_name);
+    g_free(cwd);
+    g_free(dummy_run_argument);
+    
+    result = dbus_connection_send_with_reply_and_block(connection, method,
+                                                       5000, &derror);
+    dbus_message_unref(method);
+    if(!result) {
+        dbus_error_free(&derror);
+        return FALSE;
+    }
+    
+    dbus_message_unref(result);
+    
+    return TRUE;
+}
+
+/* send quit message */
+static void
+xfrun_send_quit()
+{
+    DBusConnection *connection;
+    DBusMessage *method, *result;
+    
+    connection = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+    if(!connection)
+        return;
+    
+    method = dbus_message_new_method_call(RUNDIALOG_DBUS_SERVICE,
+                                          RUNDIALOG_DBUS_PATH,
+                                          RUNDIALOG_DBUS_INTERFACE,
+                                          RUNDIALOG_DBUS_METHOD_QUIT);
+    dbus_message_set_auto_start(method, FALSE);
+    
+    result = dbus_connection_send_with_reply_and_block(connection, method,
+                                                       5000, NULL);
+    dbus_message_unref(method);
+    if(result)
+        dbus_message_unref(result);
+}
+
+int
+main(int argc,
+     char **argv)
+{
+    if(argc > 1 && !strcmp(argv[1], "--quit"))
+        xfrun_send_quit();
+    else if(argc > 1 && !strcmp(argv[1], "--daemon")) {
+        if(argc == 2 || strcmp(argv[2], "--no-detach")) {  /* for debugging 
purposes... */
+#ifdef HAVE_DAEMON
+            if(daemon(1, 1)) {
+                xfce_message_dialog(NULL, _("System Error"),
+                                    GTK_STOCK_DIALOG_ERROR,
+                                    _("Unable to fork to background:"),
+                                    strerror(errno), GTK_STOCK_QUIT,
+                                    GTK_RESPONSE_ACCEPT, NULL);
+                return 1;
+            }
+#else
+            switch(fork()) {
+                case -1:
+                    /* failed */
+                    xfce_message_dialog(NULL, _("System Error"),
+                                        GTK_STOCK_DIALOG_ERROR,
+                                        _("Unable to fork to background:"),
+                                        strerror(errno), GTK_STOCK_QUIT,
+                                        GTK_RESPONSE_ACCEPT, NULL);
+                    return 1;
+                case 0:
+                    /* child (daemon) */
+# ifdef HAVE_SETSID
+                    setsid();
+# endif
+                    break;
+                default:
+                    /* parent */
+                    _exit(0);
+            }
+#endif
+        }
+        
+        gtk_init(&argc, &argv);
+        
+        static_dialog = xfrun_dialog_new(NULL);
+        xfrun_dialog_set_destroy_on_close(XFRUN_DIALOG(static_dialog), FALSE);
+        g_signal_connect(G_OBJECT(static_dialog), "closed",
+                         G_CALLBACK(xfrun_static_dialog_closed), NULL);
+        static_dialog_in_use = FALSE;
+        
+        xfrun_register_dbus_service();
+        
+        gtk_main();
+    } else {
+        gdk_init(&argc, &argv);
+        
+        xfrun_show_dialog(argc > 1 ? argv[1] : NULL);
+    }
+    
+    return 0;
+}

Modified: xfce-utils/trunk/xfrun/xfrun-dialog.c
===================================================================
--- xfce-utils/trunk/xfrun/xfrun-dialog.c       2006-07-16 08:17:54 UTC (rev 
22459)
+++ xfce-utils/trunk/xfrun/xfrun-dialog.c       2006-07-16 10:06:10 UTC (rev 
22460)
@@ -51,6 +51,7 @@
     
     gchar *run_argument;
     gboolean destroy_on_close;
+    gchar *working_directory;
     
     gchar *entry_val_tmp;
 };
@@ -59,6 +60,7 @@
 {
     PROP0,
     PROP_RUN_ARGUMENT,
+    PROP_WORKING_DIRECTORY,
 };
 
 enum
@@ -110,6 +112,7 @@
                                      GtkTreeModel *model,
                                      GtkTreeIter *iter,
                                      gpointer user_data);
+static void xfrun_setup_entry_completion(XfrunDialog *dialog);
 static GtkTreeModel *xfrun_create_completion_model(XfrunDialog *dialog);
 
 guint __signals[N_SIGS] = { 0, };
@@ -145,14 +148,19 @@
                                                         "1st argument to pass 
to the program run",
                                                         NULL,
                                                         G_PARAM_READWRITE));
+    
+    g_object_class_install_property(gobject_class, PROP_WORKING_DIRECTORY,
+                                    g_param_spec_string("working-directory",
+                                                        "Working directory",
+                                                        "Directory to chdir() 
to before running the command",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
 }
 
 static void
 xfrun_dialog_init(XfrunDialog *dialog)
 {
     GtkWidget *entry, *chk, *btn, *vbox, *bbox, *hbox, *arrow;
-    GtkEntryCompletion *completion;
-    GtkTreeModel *completion_model;
     GtkTreeIter itr;
     gchar *first_item = NULL;
     
@@ -170,18 +178,10 @@
     gtk_widget_show(hbox);
     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
     
-    completion = gtk_entry_completion_new();
-    dialog->priv->completion_model = completion_model = 
xfrun_create_completion_model(dialog);
-    gtk_entry_completion_set_model(completion, completion_model);
-    gtk_entry_completion_set_text_column(completion, XFRUN_COL_COMMAND);
-    gtk_entry_completion_set_popup_completion(completion, TRUE);
-    gtk_entry_completion_set_inline_completion(completion, TRUE);
-    g_signal_connect(G_OBJECT(completion), "match-selected",
-                     G_CALLBACK(xfrun_match_selected), dialog);
     
     dialog->priv->entry = entry = gtk_entry_new();
-    gtk_entry_set_completion(GTK_ENTRY(entry), completion);
     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
+    xfrun_setup_entry_completion(dialog);
     gtk_widget_show(entry);
     gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
     g_signal_connect(G_OBJECT(entry), "focus-out-event",
@@ -189,8 +189,8 @@
     g_signal_connect(G_OBJECT(entry), "key-press-event",
                      G_CALLBACK(xfrun_entry_key_press), dialog);
     
-    if(gtk_tree_model_get_iter_first(completion_model, &itr)) {
-        gtk_tree_model_get(completion_model, &itr,
+    if(gtk_tree_model_get_iter_first(dialog->priv->completion_model, &itr)) {
+        gtk_tree_model_get(dialog->priv->completion_model, &itr,
                            XFRUN_COL_COMMAND, &first_item,
                            -1);
         if(first_item) {
@@ -248,6 +248,11 @@
             xfrun_dialog_set_run_argument(dialog, g_value_get_string(value));
             break;
         
+        case PROP_WORKING_DIRECTORY:
+            xfrun_dialog_set_working_directory(dialog,
+                                               g_value_get_string(value));
+            break;
+        
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -267,6 +272,11 @@
             g_value_set_string(value, xfrun_dialog_get_run_argument(dialog));
             break;
         
+        case PROP_WORKING_DIRECTORY:
+            g_value_set_string(value,
+                               xfrun_dialog_get_working_directory(dialog));
+            break;
+        
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
             break;
@@ -279,8 +289,12 @@
     XfrunDialog *dialog = XFRUN_DIALOG(object);
     
     g_free(dialog->priv->run_argument);
+    g_free(dialog->priv->working_directory);
     g_free(dialog->priv->entry_val_tmp);
     
+    if(dialog->priv->completion_model)
+        g_object_unref(G_OBJECT(dialog->priv->completion_model));
+    
     g_free(dialog->priv);
 }
 
@@ -302,16 +316,39 @@
 {
     XfrunDialog *dialog = XFRUN_DIALOG(widget);
     
+    g_signal_emit(G_OBJECT(widget), __signals[SIG_CLOSED], 0);
+    
     if(dialog->priv->destroy_on_close)
         gtk_widget_destroy(widget);
     else
         gtk_widget_hide(widget);
     
-    g_signal_emit(G_OBJECT(widget), __signals[SIG_CLOSED], 0);
-    
     return TRUE;
 }
 
+static void
+xfrun_setup_entry_completion(XfrunDialog *dialog)
+{
+    GtkEntryCompletion *completion = gtk_entry_completion_new();
+    GtkTreeModel *completion_model;
+    
+    /* clear out the old completion and resources, if any */
+    gtk_entry_set_completion(GTK_ENTRY(dialog->priv->entry), NULL);
+    if(dialog->priv->completion_model)
+        g_object_unref(dialog->priv->completion_model);
+    
+    dialog->priv->completion_model = completion_model = 
xfrun_create_completion_model(dialog);
+    gtk_entry_completion_set_model(completion, completion_model);
+    gtk_entry_completion_set_text_column(completion, XFRUN_COL_COMMAND);
+    gtk_entry_completion_set_popup_completion(completion, TRUE);
+    gtk_entry_completion_set_inline_completion(completion, TRUE);
+    g_signal_connect(G_OBJECT(completion), "match-selected",
+                     G_CALLBACK(xfrun_match_selected), dialog);
+    
+    gtk_entry_set_completion(GTK_ENTRY(dialog->priv->entry), completion);
+    g_object_unref(G_OBJECT(completion));
+}
+
 static gchar **
 xfrun_get_histfile_content()
 {
@@ -324,6 +361,8 @@
         g_free(contents);
     }
     
+    g_free(histfile);
+    
     return lines;
 }
 
@@ -511,9 +550,13 @@
     
     if(!lines) {
         fp = fopen(histfile, "w");
-        fprintf(fp, "%d:%s\n", in_terminal ? 1 : 0, command);
-        fclose(fp);
+        if(fp) {
+            fprintf(fp, "%d:%s\n", in_terminal ? 1 : 0, command);
+            fclose(fp);
+        }
     } else {
+        gchar *new_line;
+        
         for(i = 0; lines[i]; ++i) {
             if(strlen(lines[i]) < 3 || lines[i][1] != ':')
                 continue;
@@ -522,14 +565,17 @@
                 new_lines = g_list_append(new_lines, lines[i]);
         }
         
-        new_lines = g_list_prepend(new_lines, g_strdup_printf("%d:%s",
-                                                              in_terminal ? 1 
: 0,
-                                                              command));
+        new_line = g_strdup_printf("%d:%s", in_terminal ? 1 : 0, command);
+        new_lines = g_list_prepend(new_lines, new_line);
         
         fp = fopen(histfile, "w");
-        for(l = new_lines, i = 0; l && i < MAX_ENTRIES; l = l->next, ++i)
-            fprintf(fp, "%s\n", (char *)l->data);
-        fclose(fp);
+        if(fp) {
+            for(l = new_lines, i = 0; l && i < MAX_ENTRIES; l = l->next, ++i)
+                fprintf(fp, "%s\n", (char *)l->data);
+            fclose(fp);
+        }
+        
+        g_free(new_line);
     }
     
     histfile1 = g_strdup(histfile);
@@ -545,36 +591,54 @@
 }
 
 static void
+xfrun_spawn_child_setup(gpointer data)
+{
+#if !defined(G_OS_WIN32) && defined(HAVE_SETSID)
+    setsid();
+#endif
+}
+
+static void
 xfrun_run_clicked(GtkWidget *widget,
                   gpointer user_data)
 {
     XfrunDialog *dialog = XFRUN_DIALOG(user_data);
-    gchar *entry_str, *display_name, *command;
+    gchar *entry_str, **argv;
     gboolean in_terminal;
     GdkScreen *gscreen;
     GError *error = NULL;
+    gint i = 0;
     
     entry_str = gtk_editable_get_chars(GTK_EDITABLE(dialog->priv->entry), 0, 
-1);
     in_terminal = 
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->priv->terminal_chk));
     
     gscreen = gtk_widget_get_screen(widget);
-    display_name = gdk_screen_make_display_name(gscreen);
     
-    if(dialog->priv->run_argument) {
-        command = g_strdup_printf("env DISPLAY=\"%s\" \"%s\" \"%s\"",
-                                  display_name, entry_str,
-                                  dialog->priv->run_argument);
-    } else {
-        command = g_strdup_printf("env DISPLAY=\"%s\" \"%s\"", display_name,
-                                  entry_str);
+    argv = g_new0(gchar *, 5);
+    
+    if(in_terminal) {
+        argv[i++] = "xfterm4";
+        argv[i++] = "-e";
     }
+    argv[i++] = entry_str;
+    if(dialog->priv->run_argument)
+        argv[i++] = dialog->priv->run_argument;
+    argv[i++] = NULL;
     
-    if(xfce_exec(command, in_terminal, FALSE, &error)) {
+    if(xfce_gdk_spawn_on_screen(gscreen, dialog->priv->working_directory,
+                                argv, NULL, G_SPAWN_SEARCH_PATH,
+                                xfrun_spawn_child_setup, NULL, NULL, &error))
+    {
         xfrun_add_to_history(entry_str, in_terminal);
+        if(!dialog->priv->destroy_on_close) {
+            /* assume we're going to use this again */
+            xfrun_setup_entry_completion(dialog);
+            gtk_widget_grab_focus(dialog->priv->entry);
+        }
         xfrun_dialog_delete_event(GTK_WIDGET(dialog), NULL);
     } else {
         gchar *primary = g_strdup_printf(_("The command \"%s\" failed to 
run:"),
-                                         command);
+                                         entry_str);
         xfce_message_dialog(GTK_WINDOW(dialog), _("Run Error"),
                             GTK_STOCK_DIALOG_ERROR, primary, error->message,
                             GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
@@ -583,7 +647,7 @@
     }
     
     g_free(entry_str);
-    g_free(command);
+    g_free(argv);
 }
 
 static gboolean
@@ -688,3 +752,20 @@
     g_return_val_if_fail(XFRUN_IS_DIALOG(dialog), FALSE);
     return dialog->priv->destroy_on_close;
 }
+
+void
+xfrun_dialog_set_working_directory(XfrunDialog *dialog,
+                                   const gchar *working_directory)
+{
+    g_return_if_fail(XFRUN_IS_DIALOG(dialog));
+    
+    g_free(dialog->priv->working_directory);
+    dialog->priv->working_directory = g_strdup(working_directory);
+}
+
+G_CONST_RETURN gchar *
+xfrun_dialog_get_working_directory(XfrunDialog *dialog)
+{
+    g_return_val_if_fail(XFRUN_IS_DIALOG(dialog), NULL);
+    return dialog->priv->working_directory;
+}

Modified: xfce-utils/trunk/xfrun/xfrun-dialog.h
===================================================================
--- xfce-utils/trunk/xfrun/xfrun-dialog.h       2006-07-16 08:17:54 UTC (rev 
22459)
+++ xfce-utils/trunk/xfrun/xfrun-dialog.h       2006-07-16 10:06:10 UTC (rev 
22460)
@@ -49,6 +49,8 @@
     void (*closed)(XfrunDialog *dialog);
 };
 
+GType xfrun_dialog_get_type                        () G_GNUC_CONST;
+
 GtkWidget *xfrun_dialog_new                        (const gchar *run_argument);
 
 void xfrun_dialog_set_run_argument                 (XfrunDialog *dialog,
@@ -59,6 +61,11 @@
                                                     gboolean destroy_on_close);
 gboolean xfrun_dialog_get_destroy_on_close         (XfrunDialog *dialog);
 
+void xfrun_dialog_set_working_directory            (XfrunDialog *dialog,
+                                                    const gchar 
*working_directory);
+G_CONST_RETURN gchar *xfrun_dialog_get_working_directory
+                                                   (XfrunDialog *dialog);
+
 G_END_DECLS
 
 #endif  /* __XFRUN_DIALOG_H__ */

_______________________________________________
Xfce4-commits mailing list
[email protected]
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to