Index: xfrun/xfrun.c =================================================================== --- xfrun/xfrun.c (revision 20306) +++ xfrun/xfrun.c (working copy) @@ -32,11 +32,22 @@ #include #endif +#ifdef HAVE_STDLIB_H +#include +#endif + #include #include #include +#ifdef HAVE_DBUS +#include "xfrun.h" +#define DBUS_API_SUBJECT_TO_CHANGE +#include +#include +#endif + #define BORDER 8 #define MAX_ENTRIES 20 @@ -59,7 +70,172 @@ XFRUN_N_COLS, }; +GtkWidget *win; +static void +show_rundialog(void) { + gtk_widget_show(win); +} + +static gboolean daemon_mode = FALSE; + +static void +xfrun_main_quit(void) +{ + if (!daemon_mode) + gtk_main_quit(); + else + gtk_widget_hide(win); +} + +#ifdef HAVE_DBUS +/* + * Call the org.xfce.RunDialog.OpenDialogOnDisplay( dir, display ) + * method on whichever object owns that name on the session D-BUS + */ +static gboolean +remote_dialog(int argc, char **argv) +{ + DBusConnection *connection; + DBusMessage *method; + DBusMessage *result; + DBusError derror; + + GdkScreen *screen; + + gchar *dir; + gchar *display; + + gdk_init(&argc, &argv); + + dbus_error_init(&derror); + + connection = dbus_bus_get(DBUS_BUS_SESSION, &derror); + + if (connection == NULL) + 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); + + screen = gdk_screen_get_default(); + display = gdk_screen_make_display_name(screen); + + dir = g_get_current_dir(); + + dbus_message_append_args (method, DBUS_TYPE_STRING, &dir, + DBUS_TYPE_STRING, &display, + DBUS_TYPE_INVALID); + + result = dbus_connection_send_with_reply_and_block(connection, method, 2000, &derror); + dbus_message_unref(method); + + g_free(display); + g_free(dir); + + if (result == NULL) + return FALSE; + + dbus_message_unref(result); + return TRUE; +} + + +static DBusHandlerResult +handle_message (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + DBusMessage *reply; + DBusError derror; + uid_t user_id; + gchar *directory; + gchar *display; + GdkScreen *screen; + + if (dbus_message_is_method_call (message, + RUNDIALOG_DBUS_INTERFACE, + RUNDIALOG_DBUS_METHOD_OPEN)) + { + dbus_error_init (&derror); + + /* query the list of arguments to this call */ + if (!dbus_message_get_args (message, &derror, + DBUS_TYPE_STRING, &directory, + DBUS_TYPE_STRING, &display, + DBUS_TYPE_INVALID)) + { + reply = dbus_message_new_error (message, + RUNDIALOG_DBUS_ERROR_GENERAL, + derror.message); + dbus_error_free (&derror); + } + else + { + screen = gdk_display_get_default_screen(gdk_display_open(display)); + gtk_window_set_screen (GTK_WINDOW(win), screen); + show_rundialog (); + 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_signal (message, + DBUS_INTERFACE_LOCAL, + "Disconnected")) + { + g_printerr (_("D-BUS message bus disconnected, exiting...\n")); + gtk_main_quit (); + } + else + { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } +} + +static gboolean +xfrun_dbus_register_service(void) +{ + static const struct DBusObjectPathVTable vtable = { NULL, handle_message, NULL, NULL, NULL, NULL }; + + DBusConnection *connection; + DBusError derror; + + dbus_error_init (&derror); + + /* try to connect to the session bus */ + connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); + if (G_UNLIKELY (connection == NULL)) + { + dbus_error_free (&derror); + return FALSE; + } + + /* register DBus connection with GLib main loop */ + 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; + } + + /* register the application object */ + if (!dbus_connection_register_object_path (connection, RUNDIALOG_DBUS_PATH, &vtable, NULL)) + { + return FALSE; + } + + return TRUE; +} +#endif + /* this stuff is here so i don't have to link to libxfcegui4 */ static void @@ -258,7 +434,7 @@ gpointer user_data) { if(evt->keyval == GDK_Escape) { - gtk_main_quit(); + xfrun_main_quit(); return TRUE; } @@ -490,7 +666,7 @@ gscreen = gtk_widget_get_screen(widget); if(xfrun_exec_on_screen(gscreen, command, in_terminal, &error)) { xfrun_add_to_history(command, in_terminal); - gtk_main_quit(); + xfrun_main_quit(); } else { gchar *primary = g_strdup_printf(_("The command \"%s\" failed to run:"), command); @@ -557,34 +733,31 @@ return GTK_TREE_MODEL(ls); } -int -main(int argc, - char **argv) +static void +setup(int argc, char *argv[]) { XfrunDialog xfrun_dialog; + gchar title[8192], *first_item; - GtkWidget *win, *entry, *chk, *btn, *vbox, *bbox, *hbox, *arrow; + GtkWidget *entry, *chk, *btn, *vbox, *bbox, *hbox, *arrow; GtkEntryCompletion *completion; GtkTreeModel *completion_model; GtkTreeIter itr; - xfce_textdomain(GETTEXT_PACKAGE, LOCALEDIR, "UTF-8"); - - gtk_init(&argc, &argv); - if(argc >= 2) { g_snprintf(title, 8192, _("Open %s with what program?"), argv[1]); xfrun_dialog.run_argument = argv[1]; } else { g_strlcpy(title, _("Run program"), 8192); - xfrun_dialog.run_argument = NULL; + xfrun_dialog.run_argument = NULL; } + xfrun_dialog.window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win), title); gtk_widget_set_size_request(win, 400, -1); g_signal_connect(G_OBJECT(win), "delete-event", - G_CALLBACK(gtk_main_quit), NULL); + G_CALLBACK(xfrun_main_quit), NULL); g_signal_connect(G_OBJECT(win), "key-press-event", G_CALLBACK(xfrun_key_press), NULL); @@ -649,7 +822,7 @@ gtk_widget_show(btn); gtk_box_pack_end(GTK_BOX(bbox), btn, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(btn), "clicked", - G_CALLBACK(gtk_main_quit), NULL); + G_CALLBACK(xfrun_main_quit), NULL); btn = xfrun_create_mixed_button(GTK_STOCK_EXECUTE, _("_Run")); gtk_widget_show(btn); @@ -660,10 +833,43 @@ G_CALLBACK(xfrun_run_clicked), &xfrun_dialog); xfrun_gtk_window_center_on_monitor_with_pointer(GTK_WINDOW(win)); - gtk_widget_show(win); - gtk_widget_set_size_request(win, -1, -1); + +} + +int +main(int argc, + char **argv) +{ + xfce_textdomain(GETTEXT_PACKAGE, LOCALEDIR, "UTF-8"); + +#ifdef HAVE_DBUS + if(argc == 1) { + if(remote_dialog(argc, argv)) { + return EXIT_SUCCESS; + } + } else + if(argc >= 2 && !strcmp("--daemon", argv[1])) { + daemon_mode = TRUE; + argc = 1; + } +#endif + + gtk_init(&argc, &argv); + setup(argc, argv); + +#ifdef HAVE_DBUS + if (daemon_mode) { + if (xfrun_dbus_register_service() == FALSE) { + return EXIT_FAILURE; + } + } +#endif + + if (!daemon_mode) + show_rundialog(); + gtk_main(); - return 0; + return EXIT_SUCCESS; } Index: xfrun/Makefile.am =================================================================== --- xfrun/Makefile.am (revision 20306) +++ xfrun/Makefile.am (working copy) @@ -5,8 +5,10 @@ xfrun4_CFLAGS = \ @LIBXFCE4UTIL_CFLAGS@ \ @GTK_CFLAGS@ \ + @DBUS_CFLAGS@ \ -DLOCALEDIR=\"$(localedir)\" xfrun4_LDADD = \ @LIBXFCE4UTIL_LIBS@ \ - @GTK_LIBS@ + @GTK_LIBS@ \ + @DBUS_LIBS@ Index: configure.ac =================================================================== --- configure.ac (revision 20306) +++ configure.ac (working copy) @@ -98,6 +98,13 @@ dnl configure the mcs plugin XDT_XFCE_MCS_PLUGIN([XFCE_MCS_MANAGER], [4.3.0]) +dnl check for d-bus support. look for >=0.31 + +XDT_CHECK_OPTIONAL_PACKAGE([DBUS], [dbus-glib-1], [0.31], [dbus], + AC_HELP_STRING([--disable-dbus], + [Disable the use of dbus (default=enabled)])) +AM_CONDITIONAL([HAVE_DBUS], [test "x$DBUS_FOUND" = "xyes"]) + dnl Check for debugging support XDT_FEATURE_DEBUG Index: Makefile.am =================================================================== --- Makefile.am (revision 20306) +++ Makefile.am (working copy) @@ -4,6 +4,14 @@ SUBDIRS = doc icons xfrun scripts gdm xfce4-about po +if HAVE_DBUS +servicedir = $(datadir)/dbus-1/services +service_in_files = org.xfce.RunDialog.service.in +service_DATA = $(service_in_files:.service.in=.service) +%.service: %.service.in + sed -e "s,\@bindir\@,$(bindir),g" < $< > $@ +endif + distclean-local: rm -rf xfce-utils.spec *.cache *~