1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
27 #undef GTK_DISABLE_DEPRECATED
33 /* Backing pixmap for drawing area */
35 static GdkPixmap *pixmap = NULL;
37 /* Information about cursor */
39 static gint cursor_proximity = TRUE;
40 static gdouble cursor_x;
41 static gdouble cursor_y;
43 /* Unique ID of current device */
44 static GdkDevice *current_device;
46 /* Erase the old cursor, and/or draw a new one, if necessary */
48 update_cursor (GtkWidget *widget, gdouble x, gdouble y)
50 static gint cursor_present = 0;
51 gint state = !current_device->has_cursor && cursor_proximity;
55 if (cursor_present && (cursor_present != state ||
56 x != cursor_x || y != cursor_y))
58 gdk_draw_drawable (widget->window,
59 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
61 cursor_x - 5, cursor_y - 5,
62 cursor_x - 5, cursor_y - 5,
66 cursor_present = state;
72 gdk_draw_rectangle (widget->window,
73 widget->style->black_gc,
75 cursor_x - 5, cursor_y -5,
81 /* Create a new backing pixmap of the appropriate size */
83 configure_event (GtkWidget *widget, GdkEventConfigure *event)
86 g_object_unref (pixmap);
87 pixmap = gdk_pixmap_new(widget->window,
88 widget->allocation.width,
89 widget->allocation.height,
91 gdk_draw_rectangle (pixmap,
92 widget->style->white_gc,
95 widget->allocation.width,
96 widget->allocation.height);
101 /* Refill the screen from the backing pixmap */
103 expose_event (GtkWidget *widget, GdkEventExpose *event)
105 gdk_draw_drawable (widget->window,
106 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
108 event->area.x, event->area.y,
109 event->area.x, event->area.y,
110 event->area.width, event->area.height);
115 /* Draw a rectangle on the screen, size depending on pressure,
116 and color on the type of device */
118 draw_brush (GtkWidget *widget, GdkInputSource source,
119 gdouble x, gdouble y, gdouble pressure)
122 GdkRectangle update_rect;
126 case GDK_SOURCE_MOUSE:
127 gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
130 gc = widget->style->black_gc;
132 case GDK_SOURCE_ERASER:
133 gc = widget->style->white_gc;
136 gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
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);
152 static guint32 motion_time;
155 print_axes (GdkDevice *device, gdouble *axes)
161 g_print ("%s ", device->name);
163 for (i=0; i<device->num_axes; i++)
164 g_print ("%g ", axes[i]);
171 button_press_event (GtkWidget *widget, GdkEventButton *event)
173 current_device = event->device;
174 cursor_proximity = TRUE;
176 if (event->button == 1 && pixmap != NULL)
178 gdouble pressure = 0.5;
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);
184 motion_time = event->time;
187 update_cursor (widget, event->x, event->y);
193 key_press_event (GtkWidget *widget, GdkEventKey *event)
195 if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
196 printf("I got a %c\n", event->keyval);
198 printf("I got some other key\n");
204 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
206 GdkTimeCoord **events;
210 current_device = event->device;
211 cursor_proximity = TRUE;
213 if (event->state & GDK_BUTTON1_MASK && pixmap != NULL)
215 if (gdk_device_get_history (event->device, event->window,
216 motion_time, event->time,
219 for (i=0; i<n_events; i++)
221 double x = 0, y = 0, pressure = 0.5;
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);
228 print_axes (event->device, events[i]->axes);
230 gdk_device_free_history (events, n_events);
234 double pressure = 0.5;
236 gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &pressure);
238 draw_brush (widget, event->device->source, event->x, event->y, pressure);
240 motion_time = event->time;
244 gdk_device_get_state (event->device, event->window, NULL, NULL);
246 print_axes (event->device, event->axes);
247 update_cursor (widget, event->x, event->y);
252 /* We track the next two events to know when we need to draw a
256 proximity_out_event (GtkWidget *widget, GdkEventProximity *event)
258 cursor_proximity = FALSE;
259 update_cursor (widget, cursor_x, cursor_y);
264 leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
266 cursor_proximity = FALSE;
267 update_cursor (widget, cursor_x, cursor_y);
272 input_dialog_destroy (GtkWidget *w, gpointer data)
274 *((GtkWidget **)data) = NULL;
278 create_input_dialog (void)
280 static GtkWidget *inputd = NULL;
284 inputd = gtk_input_dialog_new ();
286 g_signal_connect (inputd, "destroy",
287 G_CALLBACK (input_dialog_destroy), &inputd);
288 g_signal_connect_swapped (GTK_INPUT_DIALOG (inputd)->close_button,
290 G_CALLBACK (gtk_widget_hide),
292 gtk_widget_hide (GTK_INPUT_DIALOG (inputd)->save_button);
294 gtk_widget_show (inputd);
298 if (!gtk_widget_get_mapped(inputd))
299 gtk_widget_show(inputd);
301 gdk_window_raise(inputd->window);
312 main (int argc, char *argv[])
315 GtkWidget *drawing_area;
320 gtk_init (&argc, &argv);
322 current_device = gdk_device_get_core_pointer ();
324 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
325 gtk_widget_set_name (window, "Test Input");
327 vbox = gtk_vbox_new (FALSE, 0);
328 gtk_container_add (GTK_CONTAINER (window), vbox);
329 gtk_widget_show (vbox);
331 g_signal_connect (window, "destroy",
332 G_CALLBACK (quit), NULL);
334 /* Create the drawing area */
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);
340 gtk_widget_show (drawing_area);
342 /* Signals used to handle backing pixmap */
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);
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);
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);
363 gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
364 | GDK_LEAVE_NOTIFY_MASK
365 | GDK_BUTTON_PRESS_MASK
367 | GDK_POINTER_MOTION_MASK
368 | GDK_POINTER_MOTION_HINT_MASK
369 | GDK_PROXIMITY_OUT_MASK);
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);
375 gtk_widget_set_can_focus (drawing_area, TRUE);
376 gtk_widget_grab_focus (drawing_area);
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);
382 g_signal_connect (button, "clicked",
383 G_CALLBACK (create_input_dialog), NULL);
384 gtk_widget_show (button);
386 button = gtk_button_new_with_label ("Quit");
387 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
389 g_signal_connect_swapped (button, "clicked",
390 G_CALLBACK (gtk_widget_destroy),
392 gtk_widget_show (button);
394 gtk_widget_show (window);