Index: xfce-utils/xfrun/org.xfce.RunDialog.service.in =================================================================== --- xfce-utils/xfrun/org.xfce.RunDialog.service.in (revision 0) +++ xfce-utils/xfrun/org.xfce.RunDialog.service.in (revision 0) @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.xfce.RunDialog +Exec=@bindir@/xfrun4 --daemon Index: xfce-utils/xfrun/xfrun.c =================================================================== --- xfce-utils/xfrun/xfrun.c (revision 20510) +++ xfce-utils/xfrun/xfrun.c (working copy) @@ -2,6 +2,8 @@ * xfrun - a simple quick run dialog with saved history and completion * * Copyright (c) 2006 Brian J. Tarricone + * Jani Monoses + * Jannis Pohlmann * * 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 @@ -32,6 +34,20 @@ #include #endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_DBUS +#include +#include +#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_ERROR_GENERAL "org.xfce.RunDialog.ErrorGeneral" +#endif + #include #include @@ -59,7 +75,200 @@ XFRUN_N_COLS, }; +static XfrunDialog *xfrun_dialog; +static void +xfrun_shutdown (void) +{ + if (G_LIKELY (xfrun_dialog != NULL)) + g_free (xfrun_dialog); +} + +static void +xfrun_dialog_show (GtkWidget *dialog) +{ + gtk_widget_show(dialog); + gtk_widget_set_size_request(dialog, -1, -1); +} + +#ifdef HAVE_DBUS +/* + * Call the org.xfce.RunDialog.OpenDialog(dir, display) method on whichever + * object owns that name on the session D-BUS + */ +static gboolean +xfrun_remote_dialog (int argc, + char **argv) +{ + DBusConnection *connection; + DBusMessage *method; + DBusMessage *result; + DBusError derror; + + GdkScreen *screen; + + gchar *directory; + gchar *display; + + gdk_init (&argc, &argv); + + dbus_error_init (&derror); + + /* Try establishing a connection to the session bus */ + connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); + + if (connection == NULL) + return FALSE; + + /* Create org.xfce.RunDialog.OpenDialog method message */ + 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); + + /* Dete the active display */ + screen = gdk_screen_get_default (); + display = gdk_screen_make_display_name (screen); + + /* Dete working directory */ + directory = g_get_current_dir (); + + /* Append method arguments */ + dbus_message_append_args (method, DBUS_TYPE_STRING, &directory, + DBUS_TYPE_STRING, &display, + DBUS_TYPE_INVALID); + + /* Send D-BUS message */ + result = dbus_connection_send_with_reply_and_block (connection, method, 2000, &derror); + + /* Free data */ + dbus_message_unref (method); + g_free (display); + g_free (directory); + + if (result == NULL) + return FALSE; + + dbus_message_unref (result); + + return TRUE; +} + +static DBusHandlerResult +xfrun_handle_dbus_message (DBusConnection *connection, + DBusMessage *message, + GtkWidget *dialog) +{ + 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 an error message */ + reply = dbus_message_new_error (message, RUNDIALOG_DBUS_ERROR_GENERAL, derror.message); + + /* Free error data */ + dbus_error_free (&derror); + } + else + { + /* Get default screen of display */ + screen = gdk_display_get_default_screen (gdk_display_open (display)); + + /* Set screen for xfrun dialog */ + gtk_window_set_screen (GTK_WINDOW (dialog), screen); + + /* Show xfrun dialog */ + xfrun_dialog_show (dialog); + + /* Reply a success message */ + reply = dbus_message_new_method_return (message); + } + + /* Send reply */ + dbus_connection_send (connection, reply, NULL); + + /* Destroy reply message object */ + 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")); + xfrun_shutdown (); + gtk_main_quit (); + } + else + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static gboolean +xfrun_register_dbus_service (GtkWidget *dialog) +{ + static const struct DBusObjectPathVTable vtable = { NULL, (DBusObjectPathMessageFunction)xfrun_handle_dbus_message, NULL, NULL, NULL, NULL }; + + DBusConnection *connection; + DBusError derror; + + dbus_error_init (&derror); + + /* Try connecting to the session bus */ + connection = dbus_bus_get (DBUS_BUS_SESSION, &derror); + + if (G_UNLIKELY (connection == NULL)) + { + dbus_error_free (&derror); + return FALSE; + } + + /* Register D-BUS connection with GLib main loop */ + dbus_connection_setup_with_g_main (connection, NULL); + + /* Try to request ownership of our D-BUS service */ + 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, dialog)) + return FALSE; + + return TRUE; +} +#endif + +static gboolean daemon_mode = FALSE; + +static void +xfrun_quit(GtkWidget *dialog) +{ + if (daemon_mode) { + gtk_widget_hide (dialog); + } else { + xfrun_shutdown (); + gtk_main_quit(); + } +} + /* this stuff is here so i don't have to link to libxfcegui4 */ static void @@ -244,10 +453,14 @@ gsize length = 0; histfile = xfce_resource_lookup(XFCE_RESOURCE_CACHE, "xfce4/xfrun4/history"); + if(histfile && g_file_get_contents(histfile, &contents, &length, NULL)) { lines = g_strsplit(contents, "\n", -1); g_free(contents); } + + if (G_LIKELY (histfile != NULL)) + g_free (histfile); return lines; } @@ -255,10 +468,10 @@ static gboolean xfrun_key_press(GtkWidget *widget, GdkEventKey *evt, - gpointer user_data) + GtkWidget *window) { if(evt->keyval == GDK_Escape) { - gtk_main_quit(); + xfrun_quit(window); return TRUE; } @@ -490,7 +703,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_quit(xfrun_dialog->window); } else { gchar *primary = g_strdup_printf(_("The command \"%s\" failed to run:"), command); @@ -557,36 +770,33 @@ return GTK_TREE_MODEL(ls); } -int -main(int argc, - char **argv) +GtkWidget* +xfrun_setup(int argc, + char **argv) { - XfrunDialog xfrun_dialog; + xfrun_dialog = g_malloc (sizeof (XfrunDialog)); + gchar title[8192], *first_item; GtkWidget *win, *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]; + 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); + 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_quit), xfrun_dialog->window); g_signal_connect(G_OBJECT(win), "key-press-event", - G_CALLBACK(xfrun_key_press), NULL); + G_CALLBACK(xfrun_key_press), xfrun_dialog->window); vbox = gtk_vbox_new(FALSE, BORDER/2); gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER); @@ -598,21 +808,21 @@ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); completion = gtk_entry_completion_new(); - xfrun_dialog.completion_model = completion_model = xfrun_create_completion_model(&xfrun_dialog); + xfrun_dialog->completion_model = completion_model = xfrun_create_completion_model(xfrun_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), &xfrun_dialog); + G_CALLBACK(xfrun_match_selected), xfrun_dialog); - xfrun_dialog.entry = entry = gtk_entry_new(); + xfrun_dialog->entry = entry = gtk_entry_new(); gtk_entry_set_completion(GTK_ENTRY(entry), completion); gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(entry), "focus-out-event", - G_CALLBACK(xfrun_entry_focus_out), &xfrun_dialog); + G_CALLBACK(xfrun_entry_focus_out), xfrun_dialog); if(gtk_tree_model_get_iter_first(completion_model, &itr)) { gtk_tree_model_get(completion_model, &itr, @@ -624,18 +834,18 @@ } } - xfrun_dialog.arrow_btn = btn = gtk_button_new(); + xfrun_dialog->arrow_btn = btn = gtk_button_new(); gtk_container_set_border_width(GTK_CONTAINER(btn), 0); gtk_widget_show(btn); gtk_box_pack_start(GTK_BOX(hbox), btn, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(btn), "clicked", - G_CALLBACK(xfrun_menu_button_clicked), &xfrun_dialog); + G_CALLBACK(xfrun_menu_button_clicked), xfrun_dialog); arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE); gtk_widget_show(arrow); gtk_container_add(GTK_CONTAINER(btn), arrow); - xfrun_dialog.terminal_chk = chk = gtk_check_button_new_with_mnemonic(_("Run in _terminal")); + xfrun_dialog->terminal_chk = chk = gtk_check_button_new_with_mnemonic(_("Run in _terminal")); gtk_widget_show(chk); gtk_box_pack_start(GTK_BOX(vbox), chk, FALSE, FALSE, 0); @@ -649,7 +859,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_quit), xfrun_dialog->window); btn = xfrun_create_mixed_button(GTK_STOCK_EXECUTE, _("_Run")); gtk_widget_show(btn); @@ -657,13 +867,49 @@ GTK_WIDGET_SET_FLAGS(btn, GTK_CAN_DEFAULT); gtk_widget_grab_default(btn); g_signal_connect(G_OBJECT(btn), "clicked", - G_CALLBACK(xfrun_run_clicked), &xfrun_dialog); + 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); - gtk_main(); - - return 0; + return xfrun_dialog->window; } + +int main(int argc, + char **argv) +{ + GtkWidget *dialog; + + xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8"); + +#ifdef HAVE_DBUS + if (argc == 1) + { + if (xfrun_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); + + dialog = xfrun_setup (argc, argv); + +#ifdef HAVE_DBUS + if (daemon_mode) + { + if (xfrun_register_dbus_service (dialog) == FALSE) + return EXIT_FAILURE; + } +#endif + + if (!daemon_mode) + xfrun_dialog_show (dialog); + + gtk_main (); + + return EXIT_SUCCESS; +} Index: xfce-utils/xfrun/Makefile.am =================================================================== --- xfce-utils/xfrun/Makefile.am (revision 20510) +++ xfce-utils/xfrun/Makefile.am (working copy) @@ -1,12 +1,28 @@ bin_PROGRAMS = xfrun4 -xfrun4_SOURCES = xfrun.c +xfrun4_SOURCES = \ + xfrun.c xfrun4_CFLAGS = \ @LIBXFCE4UTIL_CFLAGS@ \ @GTK_CFLAGS@ \ + @DBUS_CFLAGS@ \ + -DDBUS_API_SUBJECT_TO_CHANGE \ -DLOCALEDIR=\"$(localedir)\" xfrun4_LDADD = \ @LIBXFCE4UTIL_LIBS@ \ - @GTK_LIBS@ + @GTK_LIBS@ \ + @DBUS_LIBS@ + +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" < $< > $@ +DISTCLEANFILES = \ + $(service_DATA) +EXTRA_DIST = \ + $(service_in_files) +endif Index: xfce-utils/configure.ac =================================================================== --- xfce-utils/configure.ac (revision 20505) +++ xfce-utils/configure.ac (working copy) @@ -95,6 +95,10 @@ XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.3.0]) XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.3.0]) +dnl Check for optional packages +XDT_CHECK_OPTIONAL_PACKAGE([DBUS], [dbus-glib-1], + [0.33], [dbus], [D-BUS support]) + dnl configure the mcs plugin XDT_XFCE_MCS_PLUGIN([XFCE_MCS_MANAGER], [4.3.0])