[Goodies-commits] r6924 - in gigolo/trunk: . src
Enrico Troeger
enrico at xfce.org
Mon Mar 16 22:25:59 CET 2009
Author: enrico
Date: 2009-03-16 21:25:59 +0000 (Mon, 16 Mar 2009)
New Revision: 6924
Added:
gigolo/trunk/src/singleinstance.c
gigolo/trunk/src/singleinstance.h
Modified:
gigolo/trunk/ChangeLog
gigolo/trunk/gigolo.1.in
gigolo/trunk/src/Makefile.am
gigolo/trunk/src/main.c
gigolo/trunk/wscript
Log:
Detect an already running instance and show its window instead of starting a new instance.
Add command line option "--new-instance" ("-i") to restore the old behaviour.
Modified: gigolo/trunk/ChangeLog
===================================================================
--- gigolo/trunk/ChangeLog 2009-03-16 21:25:27 UTC (rev 6923)
+++ gigolo/trunk/ChangeLog 2009-03-16 21:25:59 UTC (rev 6924)
@@ -1,3 +1,13 @@
+2009-03-17 Enrico Tröger <enrico(at)xfce(dot)org>
+
+ * gigolo.1.in, src/Makefile.am, src/main.c, src/singleinstance.c,
+ src/singleinstance.h, wscript:
+ Detect an already running instance and show its window instead of
+ starting a new instance.
+ Add command line option "--new-instance" ("-i") to restore the
+ old behaviour.
+
+
2009-03-05 Enrico Tröger <enrico(at)xfce(dot)org>
* src/backendgvfs.c, src/backendgvfs.h, src/bookmarkeditdialog.c,
Modified: gigolo/trunk/gigolo.1.in
===================================================================
--- gigolo/trunk/gigolo.1.in 2009-03-16 21:25:27 UTC (rev 6923)
+++ gigolo/trunk/gigolo.1.in 2009-03-16 21:25:59 UTC (rev 6924)
@@ -1,6 +1,6 @@
.TH "GIGOLO" "1" "" "gigolo @VERSION@" ""
.SH "NAME"
-Gigolo \(em a simple frontend to easily connect to remote filesystems with GIO/GVFS
+Gigolo \(em a simple frontend to easily connect to remote filesystems with GIO/GVfs
.SH "SYNOPSIS"
.PP
\fBgigolo\fR [\fBoption\fP]
@@ -13,6 +13,9 @@
Homepage: http://www.uvena.de/gigolo/
.SH "OPTIONS"
If called without any arguments, the Gigolo main window is shown.
+.IP "\fB-i\fP, \fB\-\-new-instance\fP " 10
+Don't find and show an already running instance of Gigolo, instead
+force opening a new instance.
.IP "\fB-l\fP, \fB\-\-list-schemes\fP " 10
Print a list of supported URI schemes and exit.
.IP "\fB-v\fP, \fB\-\-verbose\fP " 10
Modified: gigolo/trunk/src/Makefile.am
===================================================================
--- gigolo/trunk/src/Makefile.am 2009-03-16 21:25:27 UTC (rev 6923)
+++ gigolo/trunk/src/Makefile.am 2009-03-16 21:25:59 UTC (rev 6924)
@@ -15,6 +15,7 @@
bookmarkdialog.c bookmarkdialog.h \
bookmarkeditdialog.c bookmarkeditdialog.h \
browsenetworkdialog.c browsenetworkdialog.h \
+ singleinstance.c singleinstance.h \
preferencesdialog.c preferencesdialog.h
Modified: gigolo/trunk/src/main.c
===================================================================
--- gigolo/trunk/src/main.c 2009-03-16 21:25:27 UTC (rev 6923)
+++ gigolo/trunk/src/main.c 2009-03-16 21:25:59 UTC (rev 6924)
@@ -33,14 +33,17 @@
#include "bookmark.h"
#include "window.h"
#include "backendgvfs.h"
+#include "singleinstance.h"
static gboolean show_version = FALSE;
static gboolean verbose_mode = FALSE;
static gboolean list_schemes = FALSE;
+static gboolean new_instance = FALSE;
static GOptionEntry cli_options[] =
{
+ { "new-instance", 'i', 0, G_OPTION_ARG_NONE, &new_instance, N_("Ignore running instances, enforce opening a new instance"), NULL },
{ "list-schemes", 'l', 0, G_OPTION_ARG_NONE, &list_schemes, N_("Print a list of supported URI schemes"), NULL },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_mode, N_("Be verbose"), NULL },
{ "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Show version information"), NULL },
@@ -89,6 +92,7 @@
gint main(gint argc, gchar** argv)
{
GigoloSettings *settings;
+ GigoloSingleInstance *gis = NULL;
const gchar *vm_impl;
gchar *accel_filename;
GOptionContext *context;
@@ -124,6 +128,17 @@
return EXIT_SUCCESS;
}
+ if (! new_instance)
+ {
+ gis = gigolo_single_instance_new();
+ if (gigolo_single_instance_is_running(gis))
+ {
+ gigolo_single_instance_present(gis);
+ g_object_unref(gis);
+ exit(0);
+ }
+ }
+
verbose("Gigolo %s (GTK+ %u.%u.%u, GLib %u.%u.%u)",
VERSION,
gtk_major_version, gtk_minor_version, gtk_micro_version,
@@ -142,6 +157,9 @@
window = gigolo_window_new(settings);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
+ if (gis != NULL)
+ gigolo_single_instance_set_parent(gis, GTK_WINDOW(window));
+
if (gigolo_settings_get_boolean(settings, "start-in-systray"))
gdk_notify_startup_complete();
else
@@ -150,6 +168,8 @@
gtk_main();
g_object_unref(settings);
+ if (gis != NULL)
+ g_object_unref(gis);
gtk_accel_map_save(accel_filename);
g_free(accel_filename);
Added: gigolo/trunk/src/singleinstance.c
===================================================================
--- gigolo/trunk/src/singleinstance.c (rev 0)
+++ gigolo/trunk/src/singleinstance.c 2009-03-16 21:25:59 UTC (rev 6924)
@@ -0,0 +1,280 @@
+/*
+ * singleinstance.c
+ *
+ * Copyright 2009 Enrico Tröger <enrico(at)xfce(dot)org>
+ * Copyright 2006 Darren Salt
+ * Copyright 2002-2006 Olivier Fourdan
+ *
+ * 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 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+
+/*
+ * This is very simple detection of an already running by using XSelections.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+#include "singleinstance.h"
+#include "common.h"
+#include "compat.h"
+#include "main.h"
+
+
+#define GIGOLO_SI_NAME "GIGOLO_SEL"
+#define GIGOLO_SI_CMD "gigolo_show_window"
+
+
+enum
+{
+ PROP_0,
+
+ PROP_PARENT
+};
+
+
+struct _GigoloSingleInstance
+{
+ GObject parent;
+};
+
+struct _GigoloSingleInstanceClass
+{
+ GObjectClass parent_class;
+};
+
+typedef struct _GigoloSingleInstancePrivate GigoloSingleInstancePrivate;
+
+#define GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),\
+ GIGOLO_SINGLE_INSTANCE_TYPE, GigoloSingleInstancePrivate))
+
+
+struct _GigoloSingleInstancePrivate
+{
+ gboolean found_instance;
+ Window id;
+ GtkWidget *window;
+
+ GtkWindow *parent;
+};
+
+static void gigolo_single_instance_finalize (GObject *object);
+
+
+G_DEFINE_TYPE(GigoloSingleInstance, gigolo_single_instance, G_TYPE_OBJECT);
+
+
+void gigolo_single_instance_set_parent(GigoloSingleInstance *gis, GtkWindow *parent)
+{
+ GigoloSingleInstancePrivate *priv;
+
+ g_return_if_fail(gis != NULL);
+ g_return_if_fail(parent != NULL);
+
+ priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(gis);
+ priv->parent = parent;
+}
+
+
+static void gigolo_single_instance_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_PARENT:
+ gigolo_single_instance_set_parent(GIGOLO_SINGLE_INSTANCE(object), g_value_get_object(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void gigolo_single_instance_class_init(GigoloSingleInstanceClass *klass)
+{
+ GObjectClass *g_object_class;
+
+ g_object_class = G_OBJECT_CLASS(klass);
+ g_object_class->finalize = gigolo_single_instance_finalize;
+ g_object_class->set_property = gigolo_single_instance_set_property;
+
+ g_type_class_add_private(klass, sizeof(GigoloSingleInstancePrivate));
+
+ g_object_class_install_property(g_object_class,
+ PROP_PARENT,
+ g_param_spec_object(
+ "parent",
+ "Parent",
+ "The Gigolo main window which gets popped up by the remote instance.",
+ GTK_TYPE_WINDOW,
+ G_PARAM_WRITABLE));
+}
+
+
+static void gigolo_single_instance_finalize(GObject *object)
+{
+ GigoloSingleInstancePrivate *priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(object);
+
+ if (priv->window != NULL)
+ gtk_widget_destroy(priv->window);
+
+ G_OBJECT_CLASS(gigolo_single_instance_parent_class)->finalize(object);
+}
+
+
+static gboolean message_received(GtkWidget *w, GdkEventClient *ev, GigoloSingleInstance *gis)
+{
+ if (ev->data_format == 8 && gigolo_str_equal(ev->data.b, GIGOLO_SI_CMD))
+ {
+ GigoloSingleInstancePrivate *priv;
+
+ g_return_val_if_fail(gis != NULL, FALSE);
+
+ priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(gis);
+ gtk_window_present(priv->parent);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static void setup_selection(GigoloSingleInstance *gis)
+{
+ GdkScreen *gscreen;
+ gchar selection_name[32];
+ Atom selection_atom;
+ GtkWidget *win;
+ Window xwin;
+
+ win = gtk_invisible_new();
+ gtk_widget_realize(win);
+ xwin = GDK_WINDOW_XID(gigolo_widget_get_window(GTK_WIDGET(win)));
+
+ gscreen = gtk_widget_get_screen(win);
+ g_snprintf(selection_name, sizeof(selection_name),
+ GIGOLO_SI_NAME"%d", gdk_screen_get_number(gscreen));
+ selection_atom = XInternAtom(GDK_DISPLAY(), selection_name, False);
+
+ if (XGetSelectionOwner(GDK_DISPLAY(), selection_atom))
+ {
+ gtk_widget_destroy(win);
+ return;
+ }
+
+ XSelectInput(GDK_DISPLAY(), xwin, PropertyChangeMask);
+ XSetSelectionOwner(GDK_DISPLAY(), selection_atom, xwin, GDK_CURRENT_TIME);
+
+ g_signal_connect(G_OBJECT(win), "client-event", G_CALLBACK(message_received), gis);
+}
+
+
+static void gigolo_single_instance_init(GigoloSingleInstance *self)
+{
+ GigoloSingleInstancePrivate *priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(self);
+
+ priv->found_instance = FALSE;
+ priv->window = NULL;
+}
+
+
+gboolean gigolo_single_instance_is_running(GigoloSingleInstance *gis)
+{
+ GigoloSingleInstancePrivate *priv;
+
+ g_return_val_if_fail(gis != NULL, FALSE);
+
+ priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(gis);
+
+ return priv->found_instance;
+}
+
+
+static gboolean find_running_instance(GigoloSingleInstance *gis)
+{
+ GdkScreen *gscreen;
+ gchar selection_name[32];
+ Atom selection_atom;
+ GigoloSingleInstancePrivate *priv;
+
+ g_return_val_if_fail(gis != NULL, FALSE);
+
+ priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(gis);
+ priv->window = gtk_invisible_new();
+ gtk_widget_realize(priv->window);
+
+ gscreen = gtk_widget_get_screen(priv->window);
+ g_snprintf(selection_name, sizeof(selection_name),
+ GIGOLO_SI_NAME"%d", gdk_screen_get_number(gscreen));
+ selection_atom = XInternAtom(GDK_DISPLAY(), selection_name, False);
+
+ priv->id = XGetSelectionOwner(GDK_DISPLAY(), selection_atom);
+
+ gdk_flush();
+
+ return (priv->id != None);
+}
+
+
+void gigolo_single_instance_present(GigoloSingleInstance *gis)
+{
+ GigoloSingleInstancePrivate *priv;
+
+ g_return_if_fail(gis != NULL);
+
+ priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(gis);
+ if (priv->id != None && priv->found_instance)
+ {
+ GdkEventClient gev;
+
+ gev.type = GDK_CLIENT_EVENT;
+ gev.window = gigolo_widget_get_window(priv->window);
+ gev.send_event = TRUE;
+ gev.message_type = gdk_atom_intern("STRING", FALSE);
+ gev.data_format = 8;
+ g_strlcpy(gev.data.b, GIGOLO_SI_CMD, sizeof(gev.data.b));
+
+ gdk_event_send_client_message((GdkEvent*) &gev, (GdkNativeWindow) priv->id);
+ }
+}
+
+
+/* When creating a new object of this class we search an already running instance of Gigolo
+ * and in case we found one, we set the 'found_instance' member to TRUE.
+ * Otherwise, we register ourselves as new single running instance. */
+GigoloSingleInstance *gigolo_single_instance_new(void)
+{
+ GigoloSingleInstance *gis = g_object_new(GIGOLO_SINGLE_INSTANCE_TYPE, NULL);
+ GigoloSingleInstancePrivate *priv = GIGOLO_SINGLE_INSTANCE_GET_PRIVATE(gis);
+
+ if (find_running_instance(gis))
+ {
+ priv->found_instance = TRUE;
+ }
+ else
+ {
+ setup_selection(gis);
+ }
+
+ return gis;
+}
+
Added: gigolo/trunk/src/singleinstance.h
===================================================================
--- gigolo/trunk/src/singleinstance.h (rev 0)
+++ gigolo/trunk/src/singleinstance.h 2009-03-16 21:25:59 UTC (rev 6924)
@@ -0,0 +1,52 @@
+/*
+ * singleinstance.h
+ *
+ * Copyright 2009 Enrico Tröger <enrico(at)xfce(dot)org>
+ *
+ * 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 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+
+#ifndef __SINGLEINSTANCE_H__
+#define __SINGLEINSTANCE_H__
+
+G_BEGIN_DECLS
+
+#define GIGOLO_SINGLE_INSTANCE_TYPE (gigolo_single_instance_get_type())
+#define GIGOLO_SINGLE_INSTANCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
+ GIGOLO_SINGLE_INSTANCE_TYPE, GigoloSingleInstance))
+#define GIGOLO_SINGLE_INSTANCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
+ GIGOLO_SINGLE_INSTANCE_TYPE, GigoloSingleInstanceClass))
+#define IS_GIGOLO_SINGLE_INSTANCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
+ GIGOLO_SINGLE_INSTANCE_TYPE))
+#define IS_GIGOLO_SINGLE_INSTANCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
+ GIGOLO_SINGLE_INSTANCE_TYPE))
+
+typedef struct _GigoloSingleInstance GigoloSingleInstance;
+typedef struct _GigoloSingleInstanceClass GigoloSingleInstanceClass;
+
+GType gigolo_single_instance_get_type (void);
+GigoloSingleInstance* gigolo_single_instance_new (void);
+
+gboolean gigolo_single_instance_is_running (GigoloSingleInstance *gis);
+void gigolo_single_instance_present (GigoloSingleInstance *gis);
+
+void gigolo_single_instance_set_parent (GigoloSingleInstance *gis,
+ GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* __SINGLEINSTANCE_H__ */
Modified: gigolo/trunk/wscript
===================================================================
--- gigolo/trunk/wscript 2009-03-16 21:25:27 UTC (rev 6923)
+++ gigolo/trunk/wscript 2009-03-16 21:25:59 UTC (rev 6924)
@@ -36,7 +36,8 @@
sources = [ 'src/main.c', 'src/compat.c', 'src/window.c', 'src/bookmark.c', 'src/settings.c',
'src/menubuttonaction.c', 'src/mountoperation.c', 'src/bookmarkdialog.c',
'src/bookmarkeditdialog.c', 'src/preferencesdialog.c', 'src/backendgvfs.c',
- 'src/common.c', 'src/mountdialog.c', 'src/browsenetworkdialog.c' ]
+ 'src/common.c', 'src/mountdialog.c', 'src/browsenetworkdialog.c',
+ 'src/singleinstance.c' ]
More information about the Goodies-commits
mailing list