]> Pileus Git - ~andy/gtk/blob - tests/testsocket.c
For XEMBED embedding add a _XEMBED_INFO property to the client with
[~andy/gtk] / tests / testsocket.c
1 #include <gtk/gtk.h>
2
3 #if defined (GDK_WINDOWING_X11)
4 #include "x11/gdkx.h"
5 #elif defined (GDK_WINDOWING_WIN32)
6 #include "win32/gdkwin32.h"
7 #define GDK_WINDOW_XWINDOW(w) (guint)GDK_WINDOW_HWND(w)
8 #endif
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <unistd.h>
14
15 int n_children = 0;
16
17 GtkWidget *window;
18 GtkWidget *vbox;
19 GtkWidget *lastsocket = NULL;
20
21 extern guint32 create_child_plug (guint32  xid,
22                                   gboolean local);
23
24 static void
25 quit_cb (gpointer        callback_data,
26          guint           callback_action,
27          GtkWidget      *widget)
28 {
29   GtkWidget *message_dialog = gtk_message_dialog_new (GTK_WINDOW (window), 0,
30                                                       GTK_MESSAGE_QUESTION,
31                                                       GTK_BUTTONS_YES_NO,
32                                                       "Really Quit?");
33   gtk_dialog_set_default_response (GTK_DIALOG (message_dialog), GTK_RESPONSE_NO);
34
35   if (gtk_dialog_run (GTK_DIALOG (message_dialog)) == GTK_RESPONSE_YES)
36     gtk_widget_destroy (window);
37
38   gtk_widget_destroy (message_dialog);
39 }
40
41 static GtkItemFactoryEntry menu_items[] =
42 {
43   { "/_File",            NULL,         0,                     0, "<Branch>" },
44   { "/File/_Quit",       "<control>Q", quit_cb,               0 },
45 };
46
47 void
48 steal (GtkWidget *window, GtkEntry *entry)
49 {
50   guint32 xid;
51   const gchar *text;
52   GtkWidget *socket;
53
54   text = gtk_entry_get_text (entry);
55
56   xid = strtol (text, NULL, 0);
57   if (xid == 0)
58     {
59       g_warning ("Invalid window id '%s'\n", text);
60       return;
61     }
62
63   socket = gtk_socket_new ();
64   gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
65   gtk_widget_show (socket);
66
67   gtk_socket_steal (GTK_SOCKET (socket), xid);
68 }
69
70 void
71 remove_child (GtkWidget *window)
72 {
73   if (lastsocket)
74     gtk_widget_destroy (lastsocket);
75   lastsocket = NULL;
76 }
77
78 static gboolean
79 child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data)
80 {
81   GIOStatus status;
82   GError *error = NULL;
83   char *line;
84   gsize term;
85   int xid;
86   
87   status = g_io_channel_read_line (channel, &line, NULL, &term, &error);
88   switch (status)
89     {
90     case G_IO_STATUS_NORMAL:
91       line[term] = '\0';
92       xid = strtol (line, NULL, 0);
93       if (xid == 0)
94         {
95           fprintf (stderr, "Invalid window id '%s'\n", line);
96         }
97       else
98         {
99           GtkWidget *socket = gtk_socket_new ();
100           gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
101           gtk_widget_show (socket);
102           
103           gtk_socket_steal (GTK_SOCKET (socket), xid);
104         }
105       g_free (line);
106       return TRUE;
107     case G_IO_STATUS_AGAIN:
108       return TRUE;
109     case G_IO_STATUS_EOF:
110       n_children--;
111       g_io_channel_close (channel);
112       return FALSE;
113     case G_IO_STATUS_ERROR:
114       fprintf (stderr, "Error reading fd from child: %s\n", error->message);
115       exit (1);
116       return FALSE;
117     default:
118       g_assert_not_reached ();
119       return FALSE;
120     }
121   
122 }
123
124 void
125 add_child (GtkWidget *window,
126            gboolean   active)
127 {
128   GtkWidget *socket;
129   char *argv[3] = { "./testsocket_child", NULL, NULL };
130   char buffer[20];
131   int out_fd;
132   GIOChannel *channel;
133   GError *error = NULL;
134
135   socket = gtk_socket_new ();
136   gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
137   gtk_widget_show (socket);
138
139   lastsocket = socket;
140
141   if (active)
142     {
143       sprintf(buffer, "%#lx", GDK_WINDOW_XWINDOW (socket->window));
144       argv[1] = buffer;
145     }
146   
147 #if 1
148   if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, &out_fd, NULL, &error))
149     {
150       fprintf (stderr, "Can't exec testsocket_child: %s\n", error->message);
151       exit (1);
152     }
153
154   n_children++;
155   channel = g_io_channel_unix_new (out_fd);
156   g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error);
157   if (error)
158     {
159       fprintf (stderr, "Error making channel non-blocking: %s\n", error->message);
160       exit (1);
161     }
162   
163   g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL);
164   
165 #else
166   fprintf(stderr,"%s\n", buffer);
167 #endif
168 }
169
170 void
171 add_active_child (GtkWidget *window)
172 {
173   add_child (window, TRUE);
174 }
175
176 void
177 add_passive_child (GtkWidget *window)
178 {
179   add_child (window, FALSE);
180 }
181
182 void
183 add_local_child (GtkWidget *window)
184 {
185   GtkWidget *socket;
186
187   socket = gtk_socket_new ();
188   gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
189   gtk_widget_show (socket);
190
191   lastsocket = socket;
192
193   create_child_plug (GDK_WINDOW_XWINDOW (socket->window), TRUE);
194 }
195
196 int
197 main (int argc, char *argv[])
198 {
199   GtkWidget *button;
200   GtkWidget *hbox;
201   GtkWidget *entry;
202   GtkAccelGroup *accel_group;
203   GtkItemFactory *item_factory;
204
205   gtk_init (&argc, &argv);
206
207   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
208   gtk_signal_connect (GTK_OBJECT (window), "destroy",
209                       (GtkSignalFunc) gtk_main_quit, NULL);
210   
211   gtk_window_set_title (GTK_WINDOW (window), "Socket Test");
212   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
213
214   vbox = gtk_vbox_new (FALSE, 0);
215   gtk_container_add (GTK_CONTAINER (window), vbox);
216
217   accel_group = gtk_accel_group_new ();
218   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
219   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
220
221   
222   gtk_item_factory_create_items (item_factory,
223                                  G_N_ELEMENTS (menu_items), menu_items,
224                                  NULL);
225       
226   gtk_box_pack_start (GTK_BOX (vbox),
227                       gtk_item_factory_get_widget (item_factory, "<main>"),
228                       FALSE, FALSE, 0);
229
230   button = gtk_button_new_with_label ("Add Active Child");
231   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
232
233   gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
234                              GTK_SIGNAL_FUNC(add_active_child),
235                              GTK_OBJECT(vbox));
236
237   button = gtk_button_new_with_label ("Add Passive Child");
238   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
239
240   gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
241                              GTK_SIGNAL_FUNC(add_passive_child),
242                              GTK_OBJECT(vbox));
243
244   button = gtk_button_new_with_label ("Add Local Child");
245   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
246
247   gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
248                              GTK_SIGNAL_FUNC(add_local_child),
249                              GTK_OBJECT(vbox));
250
251   button = gtk_button_new_with_label ("Remove Last Child");
252   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
253
254   gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
255                              GTK_SIGNAL_FUNC(remove_child),
256                              GTK_OBJECT(vbox));
257
258   hbox = gtk_hbox_new (FALSE, 0);
259   gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
260
261   entry = gtk_entry_new ();
262   gtk_box_pack_start (GTK_BOX(hbox), entry, FALSE, FALSE, 0);
263
264   button = gtk_button_new_with_label ("Steal");
265   gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
266
267   gtk_signal_connect (GTK_OBJECT(button), "clicked",
268                       GTK_SIGNAL_FUNC(steal),
269                       entry);
270
271   gtk_widget_show_all (window);
272
273   gtk_main ();
274
275   if (n_children)
276     {
277       g_print ("Waiting for children to exit\n");
278
279       while (n_children)
280         g_main_iteration (TRUE);
281     }
282
283   return 0;
284 }