4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@users.sourceforge.net>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* This code is used to communicate between two copies of the filer:
23 * If the filer is run and the same version of the filer is already
24 * running on the same machine then the new copy simply asks the old
25 * one deal with it and quits.
32 #include <X11/Xatom.h>
34 #include <gtk/gtkinvisible.h>
40 #include "gui_support.h"
44 static GdkAtom filer_atom
; /* _ROX_FILER_VERSION_HOST */
45 static GdkAtom ipc_atom
; /* _ROX_FILER_OPEN */
47 /* Static prototypes */
48 static GdkWindow
*get_existing_ipc_window();
49 static gboolean
get_ipc_property(GdkWindow
*window
, Window
*r_xid
);
50 static gboolean
ipc_prop_changed(GtkWidget
*window
,
51 GdkEventProperty
*event
,
54 /****************************************************************
55 * EXTERNAL INTERFACE *
56 ****************************************************************/
59 /* Try to get an already-running filer to handle things (only if
60 * new_copy is FALSE); TRUE if we succeed.
61 * Create and IPC widget so that future filers can contact us.
63 * See main() for a description of 'to_open'.
65 gboolean
remote_init(GString
*to_open
, gboolean new_copy
)
68 GdkWindowPrivate
*window
;
69 GdkWindow
*existing_ipc_window
;
70 GtkWidget
*ipc_window
;
72 unique_id
= g_strdup_printf("_ROX_FILER_%s_%s",
73 VERSION
, our_host_name());
74 filer_atom
= gdk_atom_intern(unique_id
, FALSE
);
77 ipc_atom
= gdk_atom_intern("_ROX_FILER_OPEN", FALSE
);
79 existing_ipc_window
= new_copy
? NULL
: get_existing_ipc_window();
80 if (existing_ipc_window
)
82 gdk_property_change(existing_ipc_window
, ipc_atom
, XA_STRING
, 8,
83 GDK_PROP_MODE_APPEND
, to_open
->str
, to_open
->len
);
87 /* Note: possible race-condition here if two filers both
88 * start at the same time and one isn't already running.
92 ipc_window
= gtk_invisible_new();
93 gtk_widget_realize(ipc_window
);
95 window
= (GdkWindowPrivate
*) ipc_window
->window
;
97 /* Make the IPC window contain a property pointing to
98 * itself - this can then be used to check that it really
101 gdk_property_change(ipc_window
->window
, filer_atom
,
102 XA_WINDOW
, 32, GDK_PROP_MODE_REPLACE
,
103 (guchar
*) &window
->xwindow
, 1);
105 /* Get notified when the IPC property is changed */
106 gtk_widget_add_events(ipc_window
, GDK_PROPERTY_CHANGE_MASK
);
107 gtk_signal_connect(GTK_OBJECT(ipc_window
), "property-notify-event",
108 GTK_SIGNAL_FUNC(ipc_prop_changed
), NULL
);
110 /* Make the root window contain a pointer to the IPC window */
111 gdk_property_change(GDK_ROOT_PARENT(), filer_atom
,
112 XA_WINDOW
, 32, GDK_PROP_MODE_REPLACE
,
113 (guchar
*) &window
->xwindow
, 1);
119 /****************************************************************
120 * INTERNAL FUNCTIONS *
121 ****************************************************************/
123 /* Get the remote IPC window of the already-running filer if there
126 static GdkWindow
*get_existing_ipc_window()
128 Window xid
, xid_confirm
;
131 if (!get_ipc_property(GDK_ROOT_PARENT(), &xid
))
134 window
= gdk_window_foreign_new(xid
);
138 if (!get_ipc_property(window
, &xid_confirm
) || xid_confirm
!= xid
)
144 /* Returns the 'rox_atom' property of 'window' */
145 static gboolean
get_ipc_property(GdkWindow
*window
, Window
*r_xid
)
149 gboolean retval
= FALSE
;
151 if (gdk_property_get(window
, filer_atom
, XA_WINDOW
, 0, 4,
152 FALSE
, NULL
, &format
, &length
, &data
) && data
)
154 if (format
== 32 && length
== 4)
157 *r_xid
= *((Window
*) data
);
166 static gboolean
ipc_prop_changed(GtkWidget
*window
,
167 GdkEventProperty
*event
,
170 if (event
->atom
== ipc_atom
)
172 gint grab_len
= 4096;
179 if (!(gdk_property_get(window
->window
, ipc_atom
,
180 XA_STRING
, 0, grab_len
,
182 &length
, &data
) && data
))
183 return TRUE
; /* Error? */
185 if (length
>= grab_len
)
187 /* Didn't get all of it - try again */
193 data
= g_realloc(data
, length
+ 1);