]> Pileus Git - ~andy/gtk/blob - tests/testsocket.c
gtkiconview: Use symbolic names for button numbers
[~andy/gtk] / tests / testsocket.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*- */
2 /* testsocket.c
3  * Copyright (C) 2001 Red Hat, Inc
4  * Author: Owen Taylor
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23 #include <gtk/gtk.h>
24 #include <gtk/gtkx.h>
25
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29
30 int n_children = 0;
31
32 GSList *sockets = NULL;
33
34 GtkWidget *window;
35 GtkWidget *box;
36
37 typedef struct 
38 {
39   GtkWidget *box;
40   GtkWidget *frame;
41   GtkWidget *socket;
42 } Socket;
43
44 extern guint32 create_child_plug (guint32  xid,
45                                   gboolean local);
46
47 static void
48 quit_cb (gpointer        callback_data,
49          guint           callback_action,
50          GtkWidget      *widget)
51 {
52   GtkWidget *message_dialog = gtk_message_dialog_new (GTK_WINDOW (window), 0,
53                                                       GTK_MESSAGE_QUESTION,
54                                                       GTK_BUTTONS_YES_NO,
55                                                       "Really Quit?");
56   gtk_dialog_set_default_response (GTK_DIALOG (message_dialog), GTK_RESPONSE_NO);
57
58   if (gtk_dialog_run (GTK_DIALOG (message_dialog)) == GTK_RESPONSE_YES)
59     gtk_widget_destroy (window);
60
61   gtk_widget_destroy (message_dialog);
62 }
63
64 static void
65 socket_destroyed (GtkWidget *widget,
66                   Socket    *socket)
67 {
68   sockets = g_slist_remove (sockets, socket);
69   g_free (socket);
70 }
71
72 static void
73 plug_added (GtkWidget *widget,
74             Socket    *socket)
75 {
76   g_print ("Plug added to socket\n");
77   
78   gtk_widget_show (socket->socket);
79   gtk_widget_hide (socket->frame);
80 }
81
82 static gboolean
83 plug_removed (GtkWidget *widget,
84               Socket    *socket)
85 {
86   g_print ("Plug removed from socket\n");
87   
88   gtk_widget_hide (socket->socket);
89   gtk_widget_show (socket->frame);
90   
91   return TRUE;
92 }
93
94 static Socket *
95 create_socket (void)
96 {
97   GtkWidget *label;
98   
99   Socket *socket = g_new (Socket, 1);
100   
101   socket->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
102
103   socket->socket = gtk_socket_new ();
104   
105   gtk_box_pack_start (GTK_BOX (socket->box), socket->socket, TRUE, TRUE, 0);
106   
107   socket->frame = gtk_frame_new (NULL);
108   gtk_frame_set_shadow_type (GTK_FRAME (socket->frame), GTK_SHADOW_IN);
109   gtk_box_pack_start (GTK_BOX (socket->box), socket->frame, TRUE, TRUE, 0);
110   gtk_widget_show (socket->frame);
111   
112   label = gtk_label_new (NULL);
113   gtk_label_set_markup (GTK_LABEL (label), "<span color=\"red\">Empty</span>");
114   gtk_container_add (GTK_CONTAINER (socket->frame), label);
115   gtk_widget_show (label);
116
117   sockets = g_slist_prepend (sockets, socket);
118
119
120   g_signal_connect (socket->socket, "destroy",
121                     G_CALLBACK (socket_destroyed), socket);
122   g_signal_connect (socket->socket, "plug_added",
123                     G_CALLBACK (plug_added), socket);
124   g_signal_connect (socket->socket, "plug_removed",
125                     G_CALLBACK (plug_removed), socket);
126
127   return socket;
128 }
129
130 void
131 remove_child (GtkWidget *window)
132 {
133   if (sockets)
134     {
135       Socket *socket = sockets->data;
136       gtk_widget_destroy (socket->box);
137     }
138 }
139
140 static gboolean
141 child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data)
142 {
143   GIOStatus status;
144   GError *error = NULL;
145   char *line;
146   gsize term;
147   int xid;
148   
149   status = g_io_channel_read_line (channel, &line, NULL, &term, &error);
150   switch (status)
151     {
152     case G_IO_STATUS_NORMAL:
153       line[term] = '\0';
154       xid = strtol (line, NULL, 0);
155       if (xid == 0)
156         {
157           fprintf (stderr, "Invalid window id '%s'\n", line);
158         }
159       else
160         {
161           Socket *socket = create_socket ();
162           gtk_box_pack_start (GTK_BOX (box), socket->box, TRUE, TRUE, 0);
163           gtk_widget_show (socket->box);
164           
165           gtk_socket_add_id (GTK_SOCKET (socket->socket), xid);
166         }
167       g_free (line);
168       return TRUE;
169     case G_IO_STATUS_AGAIN:
170       return TRUE;
171     case G_IO_STATUS_EOF:
172       n_children--;
173       return FALSE;
174     case G_IO_STATUS_ERROR:
175       fprintf (stderr, "Error reading fd from child: %s\n", error->message);
176       exit (1);
177       return FALSE;
178     default:
179       g_assert_not_reached ();
180       return FALSE;
181     }
182   
183 }
184
185 void
186 add_child (GtkWidget *window,
187            gboolean   active)
188 {
189   Socket *socket;
190   char *argv[3] = { "./testsocket_child", NULL, NULL };
191   char buffer[20];
192   int out_fd;
193   GIOChannel *channel;
194   GError *error = NULL;
195
196   if (active)
197     {
198       socket = create_socket ();
199       gtk_box_pack_start (GTK_BOX (box), socket->box, TRUE, TRUE, 0);
200       gtk_widget_show (socket->box);
201       sprintf(buffer, "%#lx", (gulong) gtk_socket_get_id (GTK_SOCKET (socket->socket)));
202       argv[1] = buffer;
203     }
204   
205   if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, &out_fd, NULL, &error))
206     {
207       fprintf (stderr, "Can't exec testsocket_child: %s\n", error->message);
208       exit (1);
209     }
210
211   n_children++;
212   channel = g_io_channel_unix_new (out_fd);
213   g_io_channel_set_close_on_unref (channel, TRUE);
214   g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error);
215   if (error)
216     {
217       fprintf (stderr, "Error making channel non-blocking: %s\n", error->message);
218       exit (1);
219     }
220   
221   g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL);
222   g_io_channel_unref (channel);
223 }
224
225 void
226 add_active_child (GtkWidget *window)
227 {
228   add_child (window, TRUE);
229 }
230
231 void
232 add_passive_child (GtkWidget *window)
233 {
234   add_child (window, FALSE);
235 }
236
237 void
238 add_local_active_child (GtkWidget *window)
239 {
240   Socket *socket;
241
242   socket = create_socket ();
243   gtk_box_pack_start (GTK_BOX (box), socket->box, TRUE, TRUE, 0);
244   gtk_widget_show (socket->box);
245
246   create_child_plug (gtk_socket_get_id (GTK_SOCKET (socket->socket)), TRUE);
247 }
248
249 void
250 add_local_passive_child (GtkWidget *window)
251 {
252   Socket *socket;
253   Window xid;
254
255   socket = create_socket ();
256   gtk_box_pack_start (GTK_BOX (box), socket->box, TRUE, TRUE, 0);
257   gtk_widget_show (socket->box);
258
259   xid = create_child_plug (0, TRUE);
260   gtk_socket_add_id (GTK_SOCKET (socket->socket), xid);
261 }
262
263 static const char *
264 grab_string (int status)
265 {
266   switch (status) {
267   case GDK_GRAB_SUCCESS:          return "GrabSuccess";
268   case GDK_GRAB_ALREADY_GRABBED:  return "AlreadyGrabbed";
269   case GDK_GRAB_INVALID_TIME:     return "GrabInvalidTime";
270   case GDK_GRAB_NOT_VIEWABLE:     return "GrabNotViewable";
271   case GDK_GRAB_FROZEN:           return "GrabFrozen";
272   default:
273     {
274       static char foo [255];
275       sprintf (foo, "unknown status: %d", status);
276       return foo;
277     }
278   }
279 }
280
281 static void
282 grab_window_toggled (GtkToggleButton *button,
283                      GtkWidget       *widget)
284 {
285   GdkDevice *device = gtk_get_current_event_device ();
286
287   if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
288     device = gdk_device_get_associated_device (device);
289
290   if (gtk_toggle_button_get_active (button))
291     {
292       int status;
293
294       status = gdk_device_grab (device,
295                                 gtk_widget_get_window (widget),
296                                 GDK_OWNERSHIP_NONE,
297                                 FALSE,
298                                 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
299                                 NULL,
300                                 GDK_CURRENT_TIME);
301
302       if (status != GDK_GRAB_SUCCESS)
303         g_warning ("Could not grab keyboard!  (%s)", grab_string (status));
304
305     } 
306   else 
307     {
308       gdk_device_ungrab (device, GDK_CURRENT_TIME);
309     }
310 }
311
312 int
313 main (int argc, char *argv[])
314 {
315   GtkWidget *button;
316   GtkWidget *hbox;
317   GtkWidget *vbox;
318   GtkWidget *menubar;
319   GtkWidget *menuitem;
320   GtkWidget *menu;
321   GtkWidget *entry;
322   GtkWidget *checkbutton;
323   GtkAccelGroup *accel_group;
324
325   gtk_init (&argc, &argv);
326
327   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
328   g_signal_connect (window, "destroy",
329                     G_CALLBACK (gtk_main_quit), NULL);
330   
331   gtk_window_set_title (GTK_WINDOW (window), "Socket Test");
332   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
333
334   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
335   gtk_container_add (GTK_CONTAINER (window), vbox);
336
337   menubar = gtk_menu_bar_new ();
338   menuitem = gtk_menu_item_new_with_mnemonic ("_File");
339   gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
340
341   menu = gtk_menu_new ();
342   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
343   menuitem = gtk_menu_item_new_with_mnemonic ("_Quit");
344   g_signal_connect (menuitem, "activate", G_CALLBACK (quit_cb), window);
345   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
346
347   accel_group = gtk_accel_group_new ();
348   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
349   gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
350
351   button = gtk_button_new_with_label ("Add Active Child");
352   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
353
354   g_signal_connect_swapped (button, "clicked",
355                             G_CALLBACK (add_active_child), vbox);
356
357   button = gtk_button_new_with_label ("Add Passive Child");
358   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
359
360   g_signal_connect_swapped (button, "clicked",
361                             G_CALLBACK (add_passive_child), vbox);
362
363   button = gtk_button_new_with_label ("Add Local Active Child");
364   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
365
366   g_signal_connect_swapped (button, "clicked",
367                             G_CALLBACK (add_local_active_child), vbox);
368
369   button = gtk_button_new_with_label ("Add Local Passive Child");
370   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
371
372   g_signal_connect_swapped (button, "clicked",
373                             G_CALLBACK (add_local_passive_child), vbox);
374
375   button = gtk_button_new_with_label ("Remove Last Child");
376   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
377
378   g_signal_connect_swapped (button, "clicked",
379                             G_CALLBACK (remove_child), vbox);
380
381   checkbutton = gtk_check_button_new_with_label ("Grab keyboard");
382   gtk_box_pack_start (GTK_BOX (vbox), checkbutton, FALSE, FALSE, 0);
383
384   g_signal_connect (checkbutton, "toggled",
385                     G_CALLBACK (grab_window_toggled),
386                     window);
387
388   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
389   gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
390
391   entry = gtk_entry_new ();
392   gtk_box_pack_start (GTK_BOX(hbox), entry, FALSE, FALSE, 0);
393
394   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
395   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
396
397   box = hbox;
398   
399   gtk_widget_show_all (window);
400
401   gtk_main ();
402
403   if (n_children)
404     {
405       g_print ("Waiting for children to exit\n");
406
407       while (n_children)
408         g_main_context_iteration (NULL, TRUE);
409     }
410
411   return 0;
412 }