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