]> Pileus Git - ~andy/gtk/blob - tests/testsocket.c
Deprecation cleanup
[~andy/gtk] / tests / testsocket.c
1 #include <gtk/gtk.h>
2
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6
7 int n_children = 0;
8
9 GSList *sockets = NULL;
10
11 GtkWidget *window;
12 GtkWidget *vbox;
13
14 typedef struct 
15 {
16   GtkWidget *box;
17   GtkWidget *frame;
18   GtkWidget *socket;
19 } Socket;
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 static void
48 socket_destroyed (GtkWidget *widget,
49                   Socket    *socket)
50 {
51   sockets = g_slist_remove (sockets, socket);
52   g_free (socket);
53 }
54
55 static void
56 plug_added (GtkWidget *widget,
57             Socket    *socket)
58 {
59   g_print ("Plug added to socket\n");
60   
61   gtk_widget_show (socket->socket);
62   gtk_widget_hide (socket->frame);
63 }
64
65 static gboolean
66 plug_removed (GtkWidget *widget,
67               Socket    *socket)
68 {
69   g_print ("Plug removed from socket\n");
70   
71   gtk_widget_hide (socket->socket);
72   gtk_widget_show (socket->frame);
73   
74   return TRUE;
75 }
76
77 static Socket *
78 create_socket (void)
79 {
80   GtkWidget *label;
81   
82   Socket *socket = g_new (Socket, 1);
83   
84   socket->box = gtk_vbox_new (FALSE, 0);
85
86   socket->socket = gtk_socket_new ();
87   
88   gtk_box_pack_start (GTK_BOX (socket->box), socket->socket, TRUE, TRUE, 0);
89   
90   socket->frame = gtk_frame_new (NULL);
91   gtk_frame_set_shadow_type (GTK_FRAME (socket->frame), GTK_SHADOW_IN);
92   gtk_box_pack_start (GTK_BOX (socket->box), socket->frame, TRUE, TRUE, 0);
93   gtk_widget_show (socket->frame);
94   
95   label = gtk_label_new (NULL);
96   gtk_label_set_markup (GTK_LABEL (label), "<span color=\"red\">Empty</span>");
97   gtk_container_add (GTK_CONTAINER (socket->frame), label);
98   gtk_widget_show (label);
99
100   sockets = g_slist_prepend (sockets, socket);
101
102
103   g_signal_connect (socket->socket, "destroy",
104                     G_CALLBACK (socket_destroyed), socket);
105   g_signal_connect (socket->socket, "plug_added",
106                     G_CALLBACK (plug_added), socket);
107   g_signal_connect (socket->socket, "plug_removed",
108                     G_CALLBACK (plug_removed), socket);
109
110   return socket;
111 }
112
113 void
114 steal (GtkWidget *window, GtkEntry *entry)
115 {
116   guint32 xid;
117   const gchar *text;
118   Socket *socket;
119
120   text = gtk_entry_get_text (entry);
121
122   xid = strtol (text, NULL, 0);
123   if (xid == 0)
124     {
125       g_warning ("Invalid window id '%s'\n", text);
126       return;
127     }
128
129   socket = create_socket ();
130   gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
131   gtk_widget_show (socket->box);
132
133   gtk_socket_steal (GTK_SOCKET (socket->socket), xid);
134 }
135
136 void
137 remove_child (GtkWidget *window)
138 {
139   if (sockets)
140     {
141       Socket *socket = sockets->data;
142       gtk_widget_destroy (socket->box);
143     }
144 }
145
146 static gboolean
147 child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data)
148 {
149   GIOStatus status;
150   GError *error = NULL;
151   char *line;
152   gsize term;
153   int xid;
154   
155   status = g_io_channel_read_line (channel, &line, NULL, &term, &error);
156   switch (status)
157     {
158     case G_IO_STATUS_NORMAL:
159       line[term] = '\0';
160       xid = strtol (line, NULL, 0);
161       if (xid == 0)
162         {
163           fprintf (stderr, "Invalid window id '%s'\n", line);
164         }
165       else
166         {
167           Socket *socket = create_socket ();
168           gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
169           gtk_widget_show (socket->box);
170           
171           gtk_socket_add_id (GTK_SOCKET (socket->socket), xid);
172         }
173       g_free (line);
174       return TRUE;
175     case G_IO_STATUS_AGAIN:
176       return TRUE;
177     case G_IO_STATUS_EOF:
178       n_children--;
179       g_io_channel_unref (channel);
180       return FALSE;
181     case G_IO_STATUS_ERROR:
182       fprintf (stderr, "Error reading fd from child: %s\n", error->message);
183       exit (1);
184       return FALSE;
185     default:
186       g_assert_not_reached ();
187       return FALSE;
188     }
189   
190 }
191
192 void
193 add_child (GtkWidget *window,
194            gboolean   active)
195 {
196   Socket *socket;
197   char *argv[3] = { "./testsocket_child", NULL, NULL };
198   char buffer[20];
199   int out_fd;
200   GIOChannel *channel;
201   GError *error = NULL;
202
203   if (active)
204     {
205       socket = create_socket ();
206       gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
207       gtk_widget_show (socket->box);
208       sprintf(buffer, "%#lx", (gulong) gtk_socket_get_id (GTK_SOCKET (socket->socket)));
209       argv[1] = buffer;
210     }
211   
212   if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, &out_fd, NULL, &error))
213     {
214       fprintf (stderr, "Can't exec testsocket_child: %s\n", error->message);
215       exit (1);
216     }
217
218   n_children++;
219   channel = g_io_channel_unix_new (out_fd);
220   g_io_channel_set_close_on_unref (channel, TRUE);
221   g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error);
222   if (error)
223     {
224       fprintf (stderr, "Error making channel non-blocking: %s\n", error->message);
225       exit (1);
226     }
227   
228   g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL);
229   g_io_channel_unref (channel);
230 }
231
232 void
233 add_active_child (GtkWidget *window)
234 {
235   add_child (window, TRUE);
236 }
237
238 void
239 add_passive_child (GtkWidget *window)
240 {
241   add_child (window, FALSE);
242 }
243
244 void
245 add_local_active_child (GtkWidget *window)
246 {
247   Socket *socket;
248
249   socket = create_socket ();
250   gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
251   gtk_widget_show (socket->box);
252
253   create_child_plug (gtk_socket_get_id (GTK_SOCKET (socket->socket)), TRUE);
254 }
255
256 void
257 add_local_passive_child (GtkWidget *window)
258 {
259   Socket *socket;
260   GdkNativeWindow xid;
261
262   socket = create_socket ();
263   gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
264   gtk_widget_show (socket->box);
265
266   xid = create_child_plug (0, TRUE);
267   gtk_socket_add_id (GTK_SOCKET (socket->socket), xid);
268 }
269
270 int
271 main (int argc, char *argv[])
272 {
273   GtkWidget *button;
274   GtkWidget *hbox;
275   GtkWidget *entry;
276   GtkAccelGroup *accel_group;
277   GtkItemFactory *item_factory;
278
279   gtk_init (&argc, &argv);
280
281   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
282   g_signal_connect (window, "destroy",
283                     G_CALLBACK (gtk_main_quit), NULL);
284   
285   gtk_window_set_title (GTK_WINDOW (window), "Socket Test");
286   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
287
288   vbox = gtk_vbox_new (FALSE, 0);
289   gtk_container_add (GTK_CONTAINER (window), vbox);
290
291   accel_group = gtk_accel_group_new ();
292   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
293   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
294
295   
296   gtk_item_factory_create_items (item_factory,
297                                  G_N_ELEMENTS (menu_items), menu_items,
298                                  NULL);
299       
300   gtk_box_pack_start (GTK_BOX (vbox),
301                       gtk_item_factory_get_widget (item_factory, "<main>"),
302                       FALSE, FALSE, 0);
303
304   button = gtk_button_new_with_label ("Add Active Child");
305   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
306
307   g_signal_connect_swapped (button, "clicked",
308                             G_CALLBACK (add_active_child), vbox);
309
310   button = gtk_button_new_with_label ("Add Passive Child");
311   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
312
313   g_signal_connect_swapped (button, "clicked",
314                             G_CALLBACK (add_passive_child), vbox);
315
316   button = gtk_button_new_with_label ("Add Local Active Child");
317   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
318
319   g_signal_connect_swapped (button, "clicked",
320                             G_CALLBACK (add_local_active_child), vbox);
321
322   button = gtk_button_new_with_label ("Add Local Passive Child");
323   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
324
325   g_signal_connect_swapped (button, "clicked",
326                             G_CALLBACK (add_local_passive_child), vbox);
327
328   button = gtk_button_new_with_label ("Remove Last Child");
329   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
330
331   g_signal_connect_swapped (button, "clicked",
332                             G_CALLBACK (remove_child), vbox);
333
334   hbox = gtk_hbox_new (FALSE, 0);
335   gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
336
337   entry = gtk_entry_new ();
338   gtk_box_pack_start (GTK_BOX(hbox), entry, FALSE, FALSE, 0);
339
340   button = gtk_button_new_with_label ("Steal");
341   gtk_box_pack_start (GTK_BOX(hbox), button, FALSE, FALSE, 0);
342
343   g_signal_connect (button, "clicked",
344                     G_CALLBACK (steal),
345                     entry);
346
347   gtk_widget_show_all (window);
348
349   gtk_main ();
350
351   if (n_children)
352     {
353       g_print ("Waiting for children to exit\n");
354
355       while (n_children)
356         g_main_context_iteration (NULL, TRUE);
357     }
358
359   return 0;
360 }