]> Pileus Git - ~andy/gtk/blob - tests/testinput.c
Deprecate widget flag: GTK_WIDGET_MAPPED
[~andy/gtk] / tests / testinput.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #undef GTK_DISABLE_DEPRECATED
28
29 #include "config.h"
30 #include <stdio.h>
31 #include "gtk/gtk.h"
32
33 /* Backing pixmap for drawing area */
34
35 static GdkPixmap *pixmap = NULL;
36
37 /* Information about cursor */
38
39 static gint cursor_proximity = TRUE;
40 static gdouble cursor_x;
41 static gdouble cursor_y;
42
43 /* Unique ID of current device */
44 static GdkDevice *current_device;
45
46 /* Erase the old cursor, and/or draw a new one, if necessary */
47 static void
48 update_cursor (GtkWidget *widget,  gdouble x, gdouble y)
49 {
50   static gint cursor_present = 0;
51   gint state = !current_device->has_cursor && cursor_proximity;
52
53   if (pixmap != NULL)
54     {
55       if (cursor_present && (cursor_present != state ||
56                              x != cursor_x || y != cursor_y))
57         {
58           gdk_draw_drawable (widget->window,
59                              widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
60                              pixmap,
61                              cursor_x - 5, cursor_y - 5,
62                              cursor_x - 5, cursor_y - 5,
63                              10, 10);
64         }
65
66       cursor_present = state;
67       cursor_x = x;
68       cursor_y = y;
69
70       if (cursor_present)
71         {
72           gdk_draw_rectangle (widget->window,
73                               widget->style->black_gc,
74                               TRUE,
75                               cursor_x - 5, cursor_y -5,
76                               10, 10);
77         }
78     }
79 }
80
81 /* Create a new backing pixmap of the appropriate size */
82 static gint
83 configure_event (GtkWidget *widget, GdkEventConfigure *event)
84 {
85   if (pixmap)
86     g_object_unref (pixmap);
87   pixmap = gdk_pixmap_new(widget->window,
88                           widget->allocation.width,
89                           widget->allocation.height,
90                           -1);
91   gdk_draw_rectangle (pixmap,
92                       widget->style->white_gc,
93                       TRUE,
94                       0, 0,
95                       widget->allocation.width,
96                       widget->allocation.height);
97
98   return TRUE;
99 }
100
101 /* Refill the screen from the backing pixmap */
102 static gint
103 expose_event (GtkWidget *widget, GdkEventExpose *event)
104 {
105   gdk_draw_drawable (widget->window,
106                      widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
107                      pixmap,
108                      event->area.x, event->area.y,
109                      event->area.x, event->area.y,
110                      event->area.width, event->area.height);
111
112   return FALSE;
113 }
114
115 /* Draw a rectangle on the screen, size depending on pressure,
116    and color on the type of device */
117 static void
118 draw_brush (GtkWidget *widget, GdkInputSource source,
119             gdouble x, gdouble y, gdouble pressure)
120 {
121   GdkGC *gc;
122   GdkRectangle update_rect;
123
124   switch (source)
125     {
126     case GDK_SOURCE_MOUSE:
127       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
128       break;
129     case GDK_SOURCE_PEN:
130       gc = widget->style->black_gc;
131       break;
132     case GDK_SOURCE_ERASER:
133       gc = widget->style->white_gc;
134       break;
135     default:
136       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
137     }
138
139   update_rect.x = x - 10 * pressure;
140   update_rect.y = y - 10 * pressure;
141   update_rect.width = 20 * pressure;
142   update_rect.height = 20 * pressure;
143   gdk_draw_rectangle (pixmap, gc, TRUE,
144                       update_rect.x, update_rect.y,
145                       update_rect.width, update_rect.height);
146   gtk_widget_queue_draw_area (widget,
147                               update_rect.x, update_rect.y,
148                               update_rect.width, update_rect.height);
149   gdk_window_process_updates (widget->window, TRUE);
150 }
151
152 static guint32 motion_time;
153
154 static void
155 print_axes (GdkDevice *device, gdouble *axes)
156 {
157   int i;
158   
159   if (axes)
160     {
161       g_print ("%s ", device->name);
162       
163       for (i=0; i<device->num_axes; i++)
164         g_print ("%g ", axes[i]);
165
166       g_print ("\n");
167     }
168 }
169
170 static gint
171 button_press_event (GtkWidget *widget, GdkEventButton *event)
172 {
173   current_device = event->device;
174   cursor_proximity = TRUE;
175
176   if (event->button == 1 && pixmap != NULL)
177     {
178       gdouble pressure = 0.5;
179
180       print_axes (event->device, event->axes);
181       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &pressure);
182       draw_brush (widget, event->device->source, event->x, event->y, pressure);
183       
184       motion_time = event->time;
185     }
186
187   update_cursor (widget, event->x, event->y);
188
189   return TRUE;
190 }
191
192 static gint
193 key_press_event (GtkWidget *widget, GdkEventKey *event)
194 {
195   if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
196     printf("I got a %c\n", event->keyval);
197   else
198     printf("I got some other key\n");
199
200   return TRUE;
201 }
202
203 static gint
204 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
205 {
206   GdkTimeCoord **events;
207   int n_events;
208   int i;
209
210   current_device = event->device;
211   cursor_proximity = TRUE;
212
213   if (event->state & GDK_BUTTON1_MASK && pixmap != NULL)
214     {
215       if (gdk_device_get_history (event->device, event->window, 
216                                   motion_time, event->time,
217                                   &events, &n_events))
218         {
219           for (i=0; i<n_events; i++)
220             {
221               double x = 0, y = 0, pressure = 0.5;
222
223               gdk_device_get_axis (event->device, events[i]->axes, GDK_AXIS_X, &x);
224               gdk_device_get_axis (event->device, events[i]->axes, GDK_AXIS_Y, &y);
225               gdk_device_get_axis (event->device, events[i]->axes, GDK_AXIS_PRESSURE, &pressure);
226               draw_brush (widget,  event->device->source, x, y, pressure);
227
228               print_axes (event->device, events[i]->axes);
229             }
230           gdk_device_free_history (events, n_events);
231         }
232       else
233         {
234           double pressure = 0.5;
235
236           gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &pressure);
237
238           draw_brush (widget,  event->device->source, event->x, event->y, pressure);
239         }
240       motion_time = event->time;
241     }
242
243   if (event->is_hint)
244     gdk_device_get_state (event->device, event->window, NULL, NULL);
245
246   print_axes (event->device, event->axes);
247   update_cursor (widget, event->x, event->y);
248
249   return TRUE;
250 }
251
252 /* We track the next two events to know when we need to draw a
253    cursor */
254
255 static gint
256 proximity_out_event (GtkWidget *widget, GdkEventProximity *event)
257 {
258   cursor_proximity = FALSE;
259   update_cursor (widget, cursor_x, cursor_y);
260   return TRUE;
261 }
262
263 static gint
264 leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
265 {
266   cursor_proximity = FALSE;
267   update_cursor (widget, cursor_x, cursor_y);
268   return TRUE;
269 }
270
271 void
272 input_dialog_destroy (GtkWidget *w, gpointer data)
273 {
274   *((GtkWidget **)data) = NULL;
275 }
276
277 void
278 create_input_dialog (void)
279 {
280   static GtkWidget *inputd = NULL;
281
282   if (!inputd)
283     {
284       inputd = gtk_input_dialog_new ();
285
286       g_signal_connect (inputd, "destroy",
287                         G_CALLBACK (input_dialog_destroy), &inputd);
288       g_signal_connect_swapped (GTK_INPUT_DIALOG (inputd)->close_button,
289                                 "clicked",
290                                 G_CALLBACK (gtk_widget_hide),
291                                 inputd);
292       gtk_widget_hide (GTK_INPUT_DIALOG (inputd)->save_button);
293
294       gtk_widget_show (inputd);
295     }
296   else
297     {
298       if (!gtk_widget_get_mapped(inputd))
299         gtk_widget_show(inputd);
300       else
301         gdk_window_raise(inputd->window);
302     }
303 }
304
305 void
306 quit (void)
307 {
308   gtk_main_quit ();
309 }
310
311 int
312 main (int argc, char *argv[])
313 {
314   GtkWidget *window;
315   GtkWidget *drawing_area;
316   GtkWidget *vbox;
317
318   GtkWidget *button;
319
320   gtk_init (&argc, &argv);
321
322   current_device = gdk_device_get_core_pointer ();
323
324   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
325   gtk_widget_set_name (window, "Test Input");
326
327   vbox = gtk_vbox_new (FALSE, 0);
328   gtk_container_add (GTK_CONTAINER (window), vbox);
329   gtk_widget_show (vbox);
330
331   g_signal_connect (window, "destroy",
332                     G_CALLBACK (quit), NULL);
333
334   /* Create the drawing area */
335
336   drawing_area = gtk_drawing_area_new ();
337   gtk_widget_set_size_request (drawing_area, 200, 200);
338   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
339
340   gtk_widget_show (drawing_area);
341
342   /* Signals used to handle backing pixmap */
343
344   g_signal_connect (drawing_area, "expose_event",
345                     G_CALLBACK (expose_event), NULL);
346   g_signal_connect (drawing_area, "configure_event",
347                     G_CALLBACK (configure_event), NULL);
348
349   /* Event signals */
350
351   g_signal_connect (drawing_area, "motion_notify_event",
352                     G_CALLBACK (motion_notify_event), NULL);
353   g_signal_connect (drawing_area, "button_press_event",
354                     G_CALLBACK (button_press_event), NULL);
355   g_signal_connect (drawing_area, "key_press_event",
356                     G_CALLBACK (key_press_event), NULL);
357
358   g_signal_connect (drawing_area, "leave_notify_event",
359                     G_CALLBACK (leave_notify_event), NULL);
360   g_signal_connect (drawing_area, "proximity_out_event",
361                     G_CALLBACK (proximity_out_event), NULL);
362
363   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
364                          | GDK_LEAVE_NOTIFY_MASK
365                          | GDK_BUTTON_PRESS_MASK
366                          | GDK_KEY_PRESS_MASK
367                          | GDK_POINTER_MOTION_MASK
368                          | GDK_POINTER_MOTION_HINT_MASK
369                          | GDK_PROXIMITY_OUT_MASK);
370
371   /* The following call enables tracking and processing of extension
372      events for the drawing area */
373   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL);
374
375   gtk_widget_set_can_focus (drawing_area, TRUE);
376   gtk_widget_grab_focus (drawing_area);
377
378   /* .. And create some buttons */
379   button = gtk_button_new_with_label ("Input Dialog");
380   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
381
382   g_signal_connect (button, "clicked",
383                     G_CALLBACK (create_input_dialog), NULL);
384   gtk_widget_show (button);
385
386   button = gtk_button_new_with_label ("Quit");
387   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
388
389   g_signal_connect_swapped (button, "clicked",
390                             G_CALLBACK (gtk_widget_destroy),
391                             window);
392   gtk_widget_show (button);
393
394   gtk_widget_show (window);
395
396   gtk_main ();
397
398   return 0;
399 }