source: trunk/third/gtk/gtk/testinput.c @ 14482

Revision 14482, 10.1 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14481, which included commits to RCS files with non-trunk default branches.
Line 
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 Library 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 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library 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-1999.  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#include <stdio.h>
28#include "gtk.h"
29
30/* Backing pixmap for drawing area */
31
32static GdkPixmap *pixmap = NULL;
33
34/* Information about cursor */
35
36static gint need_cursor = FALSE;
37static gint cursor_proximity = TRUE;
38static gdouble cursor_x;
39static gdouble cursor_y;
40
41/* Unique ID of current device */
42static guint32 current_device = GDK_CORE_POINTER;
43
44/* Check to see if we need to draw a cursor for current device */
45static void
46check_cursor (void)
47{
48  GList *tmp_list;
49
50  /* gdk_input_list_devices returns an internal list, so we shouldn't
51     free it afterwards */
52  tmp_list = gdk_input_list_devices();
53
54  while (tmp_list)
55    {
56      GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
57
58      if (info->deviceid == current_device)
59        {
60          need_cursor = !info->has_cursor;
61          break;
62        }
63
64      tmp_list = tmp_list->next;
65    }
66}
67
68/* Erase the old cursor, and/or draw a new one, if necessary */
69static void
70update_cursor (GtkWidget *widget,  gdouble x, gdouble y)
71{
72  static gint cursor_present = 0;
73  gint state = need_cursor && cursor_proximity;
74
75  if (pixmap != NULL)
76    {
77      if (cursor_present && (cursor_present != state ||
78                             x != cursor_x || y != cursor_y))
79        {
80          gdk_draw_pixmap(widget->window,
81                          widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
82                          pixmap,
83                          cursor_x - 5, cursor_y - 5,
84                          cursor_x - 5, cursor_y - 5,
85                          10, 10);
86        }
87
88      cursor_present = state;
89      cursor_x = x;
90      cursor_y = y;
91
92      if (cursor_present)
93        {
94          gdk_draw_rectangle (widget->window,
95                              widget->style->black_gc,
96                              TRUE,
97                              cursor_x - 5, cursor_y -5,
98                              10, 10);
99        }
100    }
101}
102
103/* Create a new backing pixmap of the appropriate size */
104static gint
105configure_event (GtkWidget *widget, GdkEventConfigure *event)
106{
107  if (pixmap)
108    gdk_pixmap_unref (pixmap);
109  pixmap = gdk_pixmap_new(widget->window,
110                          widget->allocation.width,
111                          widget->allocation.height,
112                          -1);
113  gdk_draw_rectangle (pixmap,
114                      widget->style->white_gc,
115                      TRUE,
116                      0, 0,
117                      widget->allocation.width,
118                      widget->allocation.height);
119
120  return TRUE;
121}
122
123/* Refill the screen from the backing pixmap */
124static gint
125expose_event (GtkWidget *widget, GdkEventExpose *event)
126{
127  gdk_draw_pixmap(widget->window,
128                  widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
129                  pixmap,
130                  event->area.x, event->area.y,
131                  event->area.x, event->area.y,
132                  event->area.width, event->area.height);
133
134  return FALSE;
135}
136
137/* Draw a rectangle on the screen, size depending on pressure,
138   and color on the type of device */
139static void
140draw_brush (GtkWidget *widget, GdkInputSource source,
141            gdouble x, gdouble y, gdouble pressure)
142{
143  GdkGC *gc;
144  GdkRectangle update_rect;
145
146  switch (source)
147    {
148    case GDK_SOURCE_MOUSE:
149      gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
150      break;
151    case GDK_SOURCE_PEN:
152      gc = widget->style->black_gc;
153      break;
154    case GDK_SOURCE_ERASER:
155      gc = widget->style->white_gc;
156      break;
157    default:
158      gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
159    }
160
161  update_rect.x = x - 10 * pressure;
162  update_rect.y = y - 10 * pressure;
163  update_rect.width = 20 * pressure;
164  update_rect.height = 20 * pressure;
165  gdk_draw_rectangle (pixmap, gc, TRUE,
166                      update_rect.x, update_rect.y,
167                      update_rect.width, update_rect.height);
168  gtk_widget_draw (widget, &update_rect);
169}
170
171static guint32 motion_time;
172
173static gint
174button_press_event (GtkWidget *widget, GdkEventButton *event)
175{
176  if (event->deviceid != current_device)
177    {
178      current_device = event->deviceid;
179      check_cursor ();
180    }
181
182  cursor_proximity = TRUE;
183
184  if (event->button == 1 && pixmap != NULL)
185    {
186      draw_brush (widget, event->source, event->x, event->y,
187                  event->pressure);
188      motion_time = event->time;
189    }
190
191  update_cursor (widget, event->x, event->y);
192
193  return TRUE;
194}
195
196static gint
197key_press_event (GtkWidget *widget, GdkEventKey *event)
198{
199  if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
200    printf("I got a %c\n", event->keyval);
201  else
202    printf("I got some other key\n");
203
204  return TRUE;
205}
206
207static gint
208motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
209{
210  GdkTimeCoord *coords;
211  int nevents;
212  int i;
213
214  if (event->deviceid != current_device)
215    {
216      current_device = event->deviceid;
217      check_cursor ();
218    }
219
220  cursor_proximity = TRUE;
221
222  if (event->state & GDK_BUTTON1_MASK && pixmap != NULL)
223    {
224      coords = gdk_input_motion_events (event->window, event->deviceid,
225                                        motion_time, event->time,
226                                        &nevents);
227      motion_time = event->time;
228      if (coords)
229        {
230          for (i=0; i<nevents; i++)
231            draw_brush (widget,  event->source, coords[i].x, coords[i].y,
232                        coords[i].pressure);
233          g_free (coords);
234        }
235      else
236        {
237          if (event->is_hint)
238            gdk_input_window_get_pointer (event->window, event->deviceid,
239                                          NULL, NULL, NULL, NULL, NULL, NULL);
240          draw_brush (widget,  event->source, event->x, event->y,
241                      event->pressure);
242        }
243    }
244  else
245    {
246      gdk_input_window_get_pointer (event->window, event->deviceid,
247                                    &event->x, &event->y,
248                                    NULL, NULL, NULL, NULL);
249    }
250
251  update_cursor (widget, event->x, event->y);
252
253  return TRUE;
254}
255
256/* We track the next two events to know when we need to draw a
257   cursor */
258
259static gint
260proximity_out_event (GtkWidget *widget, GdkEventProximity *event)
261{
262  cursor_proximity = FALSE;
263  update_cursor (widget, cursor_x, cursor_y);
264  return TRUE;
265}
266
267static gint
268leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
269{
270  cursor_proximity = FALSE;
271  update_cursor (widget, cursor_x, cursor_y);
272  return TRUE;
273}
274
275void
276input_dialog_destroy (GtkWidget *w, gpointer data)
277{
278  *((GtkWidget **)data) = NULL;
279}
280
281void
282create_input_dialog (void)
283{
284  static GtkWidget *inputd = NULL;
285
286  if (!inputd)
287    {
288      inputd = gtk_input_dialog_new();
289
290      gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
291                          (GtkSignalFunc)input_dialog_destroy, &inputd);
292      gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
293                          "clicked",
294                          (GtkSignalFunc)gtk_widget_hide,
295                          GTK_OBJECT(inputd));
296      gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
297
298      gtk_signal_connect (GTK_OBJECT(inputd), "enable_device",
299                          (GtkSignalFunc)check_cursor, NULL);
300      gtk_widget_show (inputd);
301    }
302  else
303    {
304      if (!GTK_WIDGET_MAPPED(inputd))
305        gtk_widget_show(inputd);
306      else
307        gdk_window_raise(inputd->window);
308    }
309}
310
311void
312quit (void)
313{
314  gtk_exit (0);
315}
316
317int
318main (int argc, char *argv[])
319{
320  GtkWidget *window;
321  GtkWidget *drawing_area;
322  GtkWidget *vbox;
323
324  GtkWidget *button;
325
326  gtk_init (&argc, &argv);
327
328  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
329  gtk_widget_set_name (window, "Test Input");
330
331  vbox = gtk_vbox_new (FALSE, 0);
332  gtk_container_add (GTK_CONTAINER (window), vbox);
333  gtk_widget_show (vbox);
334
335  gtk_signal_connect (GTK_OBJECT (window), "destroy",
336                      GTK_SIGNAL_FUNC (quit), NULL);
337
338  /* Create the drawing area */
339
340  drawing_area = gtk_drawing_area_new ();
341  gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
342  gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
343
344  gtk_widget_show (drawing_area);
345
346  /* Signals used to handle backing pixmap */
347
348  gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
349                      (GtkSignalFunc) expose_event, NULL);
350  gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
351                      (GtkSignalFunc) configure_event, NULL);
352
353  /* Event signals */
354
355  gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
356                      (GtkSignalFunc) motion_notify_event, NULL);
357  gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
358                      (GtkSignalFunc) button_press_event, NULL);
359  gtk_signal_connect (GTK_OBJECT (drawing_area), "key_press_event",
360                      (GtkSignalFunc) key_press_event, NULL);
361
362  gtk_signal_connect (GTK_OBJECT (drawing_area), "leave_notify_event",
363                      (GtkSignalFunc) leave_notify_event, NULL);
364  gtk_signal_connect (GTK_OBJECT (drawing_area), "proximity_out_event",
365                      (GtkSignalFunc) proximity_out_event, NULL);
366
367  gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
368                         | GDK_LEAVE_NOTIFY_MASK
369                         | GDK_BUTTON_PRESS_MASK
370                         | GDK_KEY_PRESS_MASK
371                         | GDK_POINTER_MOTION_MASK
372                         | GDK_POINTER_MOTION_HINT_MASK
373                         | GDK_PROXIMITY_OUT_MASK);
374
375  /* The following call enables tracking and processing of extension
376     events for the drawing area */
377  gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_ALL);
378
379  GTK_WIDGET_SET_FLAGS (drawing_area, GTK_CAN_FOCUS);
380  gtk_widget_grab_focus (drawing_area);
381
382  /* .. And create some buttons */
383  button = gtk_button_new_with_label ("Input Dialog");
384  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
385
386  gtk_signal_connect (GTK_OBJECT (button), "clicked",
387                      GTK_SIGNAL_FUNC (create_input_dialog), NULL);
388  gtk_widget_show (button);
389
390  button = gtk_button_new_with_label ("Quit");
391  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
392
393  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
394                             GTK_SIGNAL_FUNC (gtk_widget_destroy),
395                             GTK_OBJECT (window));
396  gtk_widget_show (button);
397
398  gtk_widget_show (window);
399
400  gtk_main ();
401
402  return 0;
403}
Note: See TracBrowser for help on using the repository browser.