1 /* GDK - The GIMP Drawing Kit
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/.
28 #include <string.h> /* For memset() */
31 #include "gdkinternals.h"
34 typedef struct _GdkIOClosure GdkIOClosure;
38 GdkInputFunction function;
39 GdkInputCondition condition;
40 GDestroyNotify notify;
44 /* Private variable declarations
47 GdkEventFunc _gdk_event_func = NULL; /* Callback for events */
48 gpointer _gdk_event_data = NULL;
49 GDestroyNotify _gdk_event_notify = NULL;
51 /*********************************************
52 * Functions for maintaining the event queue *
53 *********************************************/
56 * _gdk_event_queue_find_first:
57 * @display: a #GdkDisplay
59 * Find the first event on the queue that is not still
62 * Return value: Pointer to the list node for that event, or NULL.
65 _gdk_event_queue_find_first (GdkDisplay *display)
67 GList *tmp_list = display->queued_events;
71 GdkEventPrivate *event = tmp_list->data;
72 if (!(event->flags & GDK_EVENT_PENDING))
75 tmp_list = g_list_next (tmp_list);
82 * _gdk_event_queue_prepend:
83 * @display: a #GdkDisplay
84 * @event: Event to prepend.
86 * Prepends an event before the head of the event queue.
88 * Returns: the newly prepended list node.
91 _gdk_event_queue_prepend (GdkDisplay *display,
94 display->queued_events = g_list_prepend (display->queued_events, event);
95 if (!display->queued_tail)
96 display->queued_tail = display->queued_events;
97 return display->queued_events;
101 * _gdk_event_queue_append:
102 * @display: a #GdkDisplay
103 * @event: Event to append.
105 * Appends an event onto the tail of the event queue.
107 * Returns: the newly appended list node.
110 _gdk_event_queue_append (GdkDisplay *display,
113 display->queued_tail = g_list_append (display->queued_tail, event);
115 if (!display->queued_events)
116 display->queued_events = display->queued_tail;
118 display->queued_tail = display->queued_tail->next;
120 return display->queued_tail;
124 * _gdk_event_queue_insert_after:
125 * @display: a #GdkDisplay
126 * @sibling: Append after this event.
127 * @event: Event to append.
129 * Appends an event after the specified event, or if it isn't in
130 * the queue, onto the tail of the event queue.
132 * Returns: the newly appended list node.
137 _gdk_event_queue_insert_after (GdkDisplay *display,
141 GList *prev = g_list_find (display->queued_events, sibling);
142 if (prev && prev->next)
144 display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
148 return _gdk_event_queue_append (display, event);
152 * _gdk_event_queue_insert_after:
153 * @display: a #GdkDisplay
154 * @sibling: Append after this event.
155 * @event: Event to append.
157 * Appends an event before the specified event, or if it isn't in
158 * the queue, onto the tail of the event queue.
160 * Returns: the newly appended list node.
165 _gdk_event_queue_insert_before (GdkDisplay *display,
169 GList *next = g_list_find (display->queued_events, sibling);
172 display->queued_events = g_list_insert_before (display->queued_events, next, event);
176 return _gdk_event_queue_append (display, event);
181 * _gdk_event_queue_remove_link:
182 * @display: a #GdkDisplay
183 * @node: node to remove
185 * Removes a specified list node from the event queue.
188 _gdk_event_queue_remove_link (GdkDisplay *display,
192 node->prev->next = node->next;
194 display->queued_events = node->next;
197 node->next->prev = node->prev;
199 display->queued_tail = node->prev;
203 * _gdk_event_unqueue:
204 * @display: a #GdkDisplay
206 * Removes and returns the first event from the event
207 * queue that is not still being filled in.
209 * Return value: the event, or %NULL. Ownership is transferred
213 _gdk_event_unqueue (GdkDisplay *display)
215 GdkEvent *event = NULL;
218 tmp_list = _gdk_event_queue_find_first (display);
222 event = tmp_list->data;
223 _gdk_event_queue_remove_link (display, tmp_list);
224 g_list_free_1 (tmp_list);
231 * gdk_event_handler_set:
232 * @func: the function to call to handle events from GDK.
233 * @data: user data to pass to the function.
234 * @notify: the function to call when the handler function is removed, i.e. when
235 * gdk_event_handler_set() is called with another event handler.
237 * Sets the function to call to handle all events from GDK.
239 * Note that GTK+ uses this to install its own event handler, so it is
240 * usually not useful for GTK+ applications. (Although an application
241 * can call this function then call gtk_main_do_event() to pass
245 gdk_event_handler_set (GdkEventFunc func,
247 GDestroyNotify notify)
249 if (_gdk_event_notify)
250 (*_gdk_event_notify) (_gdk_event_data);
252 _gdk_event_func = func;
253 _gdk_event_data = data;
254 _gdk_event_notify = notify;
260 * Checks all open displays for a #GdkEvent to process,to be processed
261 * on, fetching events from the windowing system if necessary.
262 * See gdk_display_get_event().
264 * Return value: the next #GdkEvent to be processed, or %NULL if no events
265 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
272 for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
274 GdkEvent *event = gdk_display_get_event (tmp_list->data);
285 * If there is an event waiting in the event queue of some open
286 * display, returns a copy of it. See gdk_display_peek_event().
288 * Return value: a copy of the first #GdkEvent on some event queue, or %NULL if no
289 * events are in any queues. The returned #GdkEvent should be freed with
293 gdk_event_peek (void)
297 for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
299 GdkEvent *event = gdk_display_peek_event (tmp_list->data);
309 * @event: a #GdkEvent.
311 * Appends a copy of the given event onto the front of the event
312 * queue for event->any.window's display, or the default event
313 * queue if event->any.window is %NULL. See gdk_display_put_event().
316 gdk_event_put (const GdkEvent *event)
320 g_return_if_fail (event != NULL);
322 if (event->any.window)
323 display = gdk_drawable_get_display (event->any.window);
327 g_message ("Falling back to default display for gdk_event_put()"));
328 display = gdk_display_get_default ();
331 gdk_display_put_event (display, event);
334 static GHashTable *event_hash = NULL;
338 * @type: a #GdkEventType
340 * Creates a new event of the given type. All fields are set to 0.
342 * Return value: a newly-allocated #GdkEvent. The returned #GdkEvent
343 * should be freed with gdk_event_free().
348 gdk_event_new (GdkEventType type)
350 GdkEventPrivate *new_private;
354 event_hash = g_hash_table_new (g_direct_hash, NULL);
356 new_private = g_slice_new0 (GdkEventPrivate);
358 new_private->flags = 0;
359 new_private->screen = NULL;
361 g_hash_table_insert (event_hash, new_private, GUINT_TO_POINTER (1));
363 new_event = (GdkEvent *) new_private;
365 new_event->any.type = type;
368 * Bytewise 0 initialization is reasonable for most of the
369 * current event types. Explicitely initialize double fields
370 * since I trust bytewise 0 == 0. less than for integers
375 case GDK_MOTION_NOTIFY:
376 new_event->motion.x = 0.;
377 new_event->motion.y = 0.;
378 new_event->motion.x_root = 0.;
379 new_event->motion.y_root = 0.;
381 case GDK_BUTTON_PRESS:
382 case GDK_2BUTTON_PRESS:
383 case GDK_3BUTTON_PRESS:
384 case GDK_BUTTON_RELEASE:
385 new_event->button.x = 0.;
386 new_event->button.y = 0.;
387 new_event->button.x_root = 0.;
388 new_event->button.y_root = 0.;
391 new_event->scroll.x = 0.;
392 new_event->scroll.y = 0.;
393 new_event->scroll.x_root = 0.;
394 new_event->scroll.y_root = 0.;
396 case GDK_ENTER_NOTIFY:
397 case GDK_LEAVE_NOTIFY:
398 new_event->crossing.x = 0.;
399 new_event->crossing.y = 0.;
400 new_event->crossing.x_root = 0.;
401 new_event->crossing.y_root = 0.;
411 gdk_event_is_allocated (const GdkEvent *event)
414 return g_hash_table_lookup (event_hash, event) != NULL;
421 * @event: a #GdkEvent
423 * Copies a #GdkEvent, copying or incrementing the reference count of the
424 * resources associated with it (e.g. #GdkWindow's and strings).
426 * Return value: a copy of @event. The returned #GdkEvent should be freed with
430 gdk_event_copy (const GdkEvent *event)
432 GdkEventPrivate *new_private;
435 g_return_val_if_fail (event != NULL, NULL);
437 new_event = gdk_event_new (GDK_NOTHING);
438 new_private = (GdkEventPrivate *)new_event;
441 if (new_event->any.window)
442 g_object_ref (new_event->any.window);
444 if (gdk_event_is_allocated (event))
446 GdkEventPrivate *private = (GdkEventPrivate *)event;
448 new_private->screen = private->screen;
451 switch (event->any.type)
454 case GDK_KEY_RELEASE:
455 new_event->key.string = g_strdup (event->key.string);
458 case GDK_ENTER_NOTIFY:
459 case GDK_LEAVE_NOTIFY:
460 if (event->crossing.subwindow != NULL)
461 g_object_ref (event->crossing.subwindow);
466 case GDK_DRAG_MOTION:
467 case GDK_DRAG_STATUS:
469 case GDK_DROP_FINISHED:
470 g_object_ref (event->dnd.context);
475 if (event->expose.region)
476 new_event->expose.region = gdk_region_copy (event->expose.region);
480 new_event->setting.name = g_strdup (new_event->setting.name);
483 case GDK_BUTTON_PRESS:
484 case GDK_BUTTON_RELEASE:
485 if (event->button.axes)
486 new_event->button.axes = g_memdup (event->button.axes,
487 sizeof (gdouble) * event->button.device->num_axes);
490 case GDK_MOTION_NOTIFY:
491 if (event->motion.axes)
492 new_event->motion.axes = g_memdup (event->motion.axes,
493 sizeof (gdouble) * event->motion.device->num_axes);
501 if (gdk_event_is_allocated (event))
502 _gdk_windowing_event_data_copy (event, new_event);
509 * @event: a #GdkEvent.
511 * Frees a #GdkEvent, freeing or decrementing any resources associated with it.
512 * Note that this function should only be called with events returned from
513 * functions such as gdk_event_peek(), gdk_event_get(),
514 * gdk_event_get_graphics_expose() and gdk_event_copy() and gdk_event_new().
517 gdk_event_free (GdkEvent *event)
519 g_return_if_fail (event != NULL);
521 if (event->any.window)
522 g_object_unref (event->any.window);
524 switch (event->any.type)
527 case GDK_KEY_RELEASE:
528 g_free (event->key.string);
531 case GDK_ENTER_NOTIFY:
532 case GDK_LEAVE_NOTIFY:
533 if (event->crossing.subwindow != NULL)
534 g_object_unref (event->crossing.subwindow);
539 case GDK_DRAG_MOTION:
540 case GDK_DRAG_STATUS:
542 case GDK_DROP_FINISHED:
543 g_object_unref (event->dnd.context);
546 case GDK_BUTTON_PRESS:
547 case GDK_BUTTON_RELEASE:
548 g_free (event->button.axes);
553 if (event->expose.region)
554 gdk_region_destroy (event->expose.region);
557 case GDK_MOTION_NOTIFY:
558 g_free (event->motion.axes);
562 g_free (event->setting.name);
569 _gdk_windowing_event_data_free (event);
571 g_hash_table_remove (event_hash, event);
572 g_slice_free (GdkEventPrivate, (GdkEventPrivate*) event);
576 * gdk_event_get_time:
577 * @event: a #GdkEvent
579 * Returns the time stamp from @event, if there is one; otherwise
580 * returns #GDK_CURRENT_TIME. If @event is %NULL, returns #GDK_CURRENT_TIME.
582 * Return value: time stamp field from @event
585 gdk_event_get_time (const GdkEvent *event)
590 case GDK_MOTION_NOTIFY:
591 return event->motion.time;
592 case GDK_BUTTON_PRESS:
593 case GDK_2BUTTON_PRESS:
594 case GDK_3BUTTON_PRESS:
595 case GDK_BUTTON_RELEASE:
596 return event->button.time;
598 return event->scroll.time;
600 case GDK_KEY_RELEASE:
601 return event->key.time;
602 case GDK_ENTER_NOTIFY:
603 case GDK_LEAVE_NOTIFY:
604 return event->crossing.time;
605 case GDK_PROPERTY_NOTIFY:
606 return event->property.time;
607 case GDK_SELECTION_CLEAR:
608 case GDK_SELECTION_REQUEST:
609 case GDK_SELECTION_NOTIFY:
610 return event->selection.time;
611 case GDK_PROXIMITY_IN:
612 case GDK_PROXIMITY_OUT:
613 return event->proximity.time;
616 case GDK_DRAG_MOTION:
617 case GDK_DRAG_STATUS:
619 case GDK_DROP_FINISHED:
620 return event->dnd.time;
621 case GDK_CLIENT_EVENT:
622 case GDK_VISIBILITY_NOTIFY:
625 case GDK_FOCUS_CHANGE:
633 case GDK_WINDOW_STATE:
635 case GDK_OWNER_CHANGE:
636 case GDK_GRAB_BROKEN:
638 /* return current time */
642 return GDK_CURRENT_TIME;
646 * gdk_event_get_state:
647 * @event: a #GdkEvent or NULL
648 * @state: return location for state
650 * If the event contains a "state" field, puts that field in @state. Otherwise
651 * stores an empty state (0). Returns %TRUE if there was a state field
652 * in the event. @event may be %NULL, in which case it's treated
653 * as if the event had no state field.
655 * Return value: %TRUE if there was a state field in the event
658 gdk_event_get_state (const GdkEvent *event,
659 GdkModifierType *state)
661 g_return_val_if_fail (state != NULL, FALSE);
666 case GDK_MOTION_NOTIFY:
667 *state = event->motion.state;
669 case GDK_BUTTON_PRESS:
670 case GDK_2BUTTON_PRESS:
671 case GDK_3BUTTON_PRESS:
672 case GDK_BUTTON_RELEASE:
673 *state = event->button.state;
676 *state = event->scroll.state;
679 case GDK_KEY_RELEASE:
680 *state = event->key.state;
682 case GDK_ENTER_NOTIFY:
683 case GDK_LEAVE_NOTIFY:
684 *state = event->crossing.state;
686 case GDK_PROPERTY_NOTIFY:
687 *state = event->property.state;
689 case GDK_VISIBILITY_NOTIFY:
690 case GDK_CLIENT_EVENT:
693 case GDK_FOCUS_CHANGE:
694 case GDK_SELECTION_CLEAR:
695 case GDK_SELECTION_REQUEST:
696 case GDK_SELECTION_NOTIFY:
697 case GDK_PROXIMITY_IN:
698 case GDK_PROXIMITY_OUT:
702 case GDK_DRAG_MOTION:
703 case GDK_DRAG_STATUS:
705 case GDK_DROP_FINISHED:
712 case GDK_WINDOW_STATE:
714 case GDK_OWNER_CHANGE:
715 case GDK_GRAB_BROKEN:
726 * gdk_event_get_coords:
727 * @event: a #GdkEvent
728 * @x_win: location to put event window x coordinate
729 * @y_win: location to put event window y coordinate
731 * Extract the event window relative x/y coordinates from an event.
733 * Return value: %TRUE if the event delivered event window coordinates
736 gdk_event_get_coords (const GdkEvent *event,
740 gdouble x = 0, y = 0;
741 gboolean fetched = TRUE;
743 g_return_val_if_fail (event != NULL, FALSE);
748 x = event->configure.x;
749 y = event->configure.y;
751 case GDK_ENTER_NOTIFY:
752 case GDK_LEAVE_NOTIFY:
753 x = event->crossing.x;
754 y = event->crossing.y;
760 case GDK_BUTTON_PRESS:
761 case GDK_2BUTTON_PRESS:
762 case GDK_3BUTTON_PRESS:
763 case GDK_BUTTON_RELEASE:
767 case GDK_MOTION_NOTIFY:
785 * gdk_event_get_root_coords:
786 * @event: a #GdkEvent
787 * @x_root: location to put root window x coordinate
788 * @y_root: location to put root window y coordinate
790 * Extract the root window relative x/y coordinates from an event.
792 * Return value: %TRUE if the event delivered root window coordinates
795 gdk_event_get_root_coords (const GdkEvent *event,
799 gdouble x = 0, y = 0;
800 gboolean fetched = TRUE;
802 g_return_val_if_fail (event != NULL, FALSE);
806 case GDK_MOTION_NOTIFY:
807 x = event->motion.x_root;
808 y = event->motion.y_root;
811 x = event->scroll.x_root;
812 y = event->scroll.y_root;
814 case GDK_BUTTON_PRESS:
815 case GDK_2BUTTON_PRESS:
816 case GDK_3BUTTON_PRESS:
817 case GDK_BUTTON_RELEASE:
818 x = event->button.x_root;
819 y = event->button.y_root;
821 case GDK_ENTER_NOTIFY:
822 case GDK_LEAVE_NOTIFY:
823 x = event->crossing.x_root;
824 y = event->crossing.y_root;
828 case GDK_DRAG_MOTION:
829 case GDK_DRAG_STATUS:
831 case GDK_DROP_FINISHED:
832 x = event->dnd.x_root;
833 y = event->dnd.y_root;
849 * gdk_event_get_axis:
850 * @event: a #GdkEvent
851 * @axis_use: the axis use to look for
852 * @value: location to store the value found
854 * Extract the axis value for a particular axis use from
855 * an event structure.
857 * Return value: %TRUE if the specified axis was found, otherwise %FALSE
860 gdk_event_get_axis (const GdkEvent *event,
867 g_return_val_if_fail (event != NULL, FALSE);
869 if (axis_use == GDK_AXIS_X || axis_use == GDK_AXIS_Y)
875 case GDK_MOTION_NOTIFY:
883 case GDK_BUTTON_PRESS:
884 case GDK_BUTTON_RELEASE:
888 case GDK_ENTER_NOTIFY:
889 case GDK_LEAVE_NOTIFY:
890 x = event->crossing.x;
891 y = event->crossing.y;
898 if (axis_use == GDK_AXIS_X && value)
900 if (axis_use == GDK_AXIS_Y && value)
905 else if (event->type == GDK_BUTTON_PRESS ||
906 event->type == GDK_BUTTON_RELEASE)
908 device = event->button.device;
909 axes = event->button.axes;
911 else if (event->type == GDK_MOTION_NOTIFY)
913 device = event->motion.device;
914 axes = event->motion.axes;
919 return gdk_device_get_axis (device, axes, axis_use, value);
923 * gdk_event_request_motions:
924 * @event: a valid #GdkEvent
926 * Request more motion notifies if @event is a motion notify hint event.
927 * This function should be used instead of gdk_window_get_pointer() to
928 * request further motion notifies, because it also works for extension
929 * events where motion notifies are provided for devices other than the
930 * core pointer. Coordinate extraction, processing and requesting more
931 * motion events from a %GDK_MOTION_NOTIFY event usually works like this:
935 * /* motion_event handler */
936 * x = motion_event->x;
937 * y = motion_event->y;
938 * /* handle (x,y) motion */
939 * gdk_event_request_motions (motion_event); /* handles is_hint events */
946 gdk_event_request_motions (const GdkEventMotion *event)
950 g_return_if_fail (event != NULL);
952 if (event->type == GDK_MOTION_NOTIFY && event->is_hint)
954 gdk_device_get_state (event->device, event->window, NULL, NULL);
956 display = gdk_drawable_get_display (event->window);
957 _gdk_display_enable_motion_hints (display);
962 * gdk_event_set_screen:
963 * @event: a #GdkEvent
964 * @screen: a #GdkScreen
966 * Sets the screen for @event to @screen. The event must
967 * have been allocated by GTK+, for instance, by
973 gdk_event_set_screen (GdkEvent *event,
976 GdkEventPrivate *private;
978 g_return_if_fail (gdk_event_is_allocated (event));
980 private = (GdkEventPrivate *)event;
982 private->screen = screen;
986 * gdk_event_get_screen:
987 * @event: a #GdkEvent
989 * Returns the screen for the event. The screen is
990 * typically the screen for <literal>event->any.window</literal>, but
991 * for events such as mouse events, it is the screen
992 * where the pointer was when the event occurs -
993 * that is, the screen which has the root window
994 * to which <literal>event->motion.x_root</literal> and
995 * <literal>event->motion.y_root</literal> are relative.
997 * Return value: the screen for the event
1002 gdk_event_get_screen (const GdkEvent *event)
1004 if (gdk_event_is_allocated (event))
1006 GdkEventPrivate *private = (GdkEventPrivate *)event;
1008 if (private->screen)
1009 return private->screen;
1012 if (event->any.window)
1013 return gdk_drawable_get_screen (event->any.window);
1019 * gdk_set_show_events:
1020 * @show_events: %TRUE to output event debugging information.
1022 * Sets whether a trace of received events is output.
1023 * Note that GTK+ must be compiled with debugging (that is,
1024 * configured using the <option>--enable-debug</option> option)
1025 * to use this option.
1028 gdk_set_show_events (gboolean show_events)
1031 _gdk_debug_flags |= GDK_DEBUG_EVENTS;
1033 _gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
1037 * gdk_get_show_events:
1039 * Gets whether event debugging output is enabled.
1041 * Return value: %TRUE if event debugging output is enabled.
1044 gdk_get_show_events (void)
1046 return (_gdk_debug_flags & GDK_DEBUG_EVENTS) != 0;
1050 gdk_io_destroy (gpointer data)
1052 GdkIOClosure *closure = data;
1054 if (closure->notify)
1055 closure->notify (closure->data);
1060 /* What do we do with G_IO_NVAL?
1062 #define READ_CONDITION (G_IO_IN | G_IO_HUP | G_IO_ERR)
1063 #define WRITE_CONDITION (G_IO_OUT | G_IO_ERR)
1064 #define EXCEPTION_CONDITION (G_IO_PRI)
1067 gdk_io_invoke (GIOChannel *source,
1068 GIOCondition condition,
1071 GdkIOClosure *closure = data;
1072 GdkInputCondition gdk_cond = 0;
1074 if (condition & READ_CONDITION)
1075 gdk_cond |= GDK_INPUT_READ;
1076 if (condition & WRITE_CONDITION)
1077 gdk_cond |= GDK_INPUT_WRITE;
1078 if (condition & EXCEPTION_CONDITION)
1079 gdk_cond |= GDK_INPUT_EXCEPTION;
1081 if (closure->condition & gdk_cond)
1082 closure->function (closure->data, g_io_channel_unix_get_fd (source), gdk_cond);
1088 * gdk_input_add_full:
1089 * @source: a file descriptor.
1090 * @condition: the condition.
1091 * @function: the callback function.
1092 * @data: callback data passed to @function.
1093 * @destroy: callback function to call with @data when the input
1094 * handler is removed.
1096 * Establish a callback when a condition becomes true on
1097 * a file descriptor.
1099 * Returns: a tag that can later be used as an argument to
1100 * gdk_input_remove().
1102 * Deprecated: 2.14: Use g_io_add_watch_full() on a #GIOChannel
1105 gdk_input_add_full (gint source,
1106 GdkInputCondition condition,
1107 GdkInputFunction function,
1109 GDestroyNotify destroy)
1112 GdkIOClosure *closure = g_new (GdkIOClosure, 1);
1113 GIOChannel *channel;
1114 GIOCondition cond = 0;
1116 closure->function = function;
1117 closure->condition = condition;
1118 closure->notify = destroy;
1119 closure->data = data;
1121 if (condition & GDK_INPUT_READ)
1122 cond |= READ_CONDITION;
1123 if (condition & GDK_INPUT_WRITE)
1124 cond |= WRITE_CONDITION;
1125 if (condition & GDK_INPUT_EXCEPTION)
1126 cond |= EXCEPTION_CONDITION;
1128 channel = g_io_channel_unix_new (source);
1129 result = g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, cond,
1131 closure, gdk_io_destroy);
1132 g_io_channel_unref (channel);
1139 * @source: a file descriptor.
1140 * @condition: the condition.
1141 * @function: the callback function.
1142 * @data: callback data passed to @function.
1144 * Establish a callback when a condition becomes true on
1145 * a file descriptor.
1147 * Returns: a tag that can later be used as an argument to
1148 * gdk_input_remove().
1150 * Deprecated: 2.14: Use g_io_add_watch() on a #GIOChannel
1153 gdk_input_add (gint source,
1154 GdkInputCondition condition,
1155 GdkInputFunction function,
1158 return gdk_input_add_full (source, condition, function, data, NULL);
1162 gdk_input_remove (gint tag)
1164 g_source_remove (tag);
1168 gdk_synthesize_click (GdkDisplay *display,
1172 GdkEvent temp_event;
1173 GdkEvent *event_copy;
1176 g_return_if_fail (event != NULL);
1178 temp_event = *event;
1179 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
1181 event_copy = gdk_event_copy (&temp_event);
1182 link = _gdk_event_queue_append (display, event_copy);
1186 _gdk_event_button_generate (GdkDisplay *display,
1189 if ((event->button.time < (display->button_click_time[1] + 2*display->double_click_time)) &&
1190 (event->button.window == display->button_window[1]) &&
1191 (event->button.button == display->button_number[1]) &&
1192 (ABS (event->button.x - display->button_x[1]) <= display->double_click_distance) &&
1193 (ABS (event->button.y - display->button_y[1]) <= display->double_click_distance))
1195 gdk_synthesize_click (display, event, 3);
1197 display->button_click_time[1] = 0;
1198 display->button_click_time[0] = 0;
1199 display->button_window[1] = NULL;
1200 display->button_window[0] = NULL;
1201 display->button_number[1] = -1;
1202 display->button_number[0] = -1;
1203 display->button_x[0] = display->button_x[1] = 0;
1204 display->button_y[0] = display->button_y[1] = 0;
1206 else if ((event->button.time < (display->button_click_time[0] + display->double_click_time)) &&
1207 (event->button.window == display->button_window[0]) &&
1208 (event->button.button == display->button_number[0]) &&
1209 (ABS (event->button.x - display->button_x[0]) <= display->double_click_distance) &&
1210 (ABS (event->button.y - display->button_y[0]) <= display->double_click_distance))
1212 gdk_synthesize_click (display, event, 2);
1214 display->button_click_time[1] = display->button_click_time[0];
1215 display->button_click_time[0] = event->button.time;
1216 display->button_window[1] = display->button_window[0];
1217 display->button_window[0] = event->button.window;
1218 display->button_number[1] = display->button_number[0];
1219 display->button_number[0] = event->button.button;
1220 display->button_x[1] = display->button_x[0];
1221 display->button_x[0] = event->button.x;
1222 display->button_y[1] = display->button_y[0];
1223 display->button_y[0] = event->button.y;
1227 display->button_click_time[1] = 0;
1228 display->button_click_time[0] = event->button.time;
1229 display->button_window[1] = NULL;
1230 display->button_window[0] = event->button.window;
1231 display->button_number[1] = -1;
1232 display->button_number[0] = event->button.button;
1233 display->button_x[1] = 0;
1234 display->button_x[0] = event->button.x;
1235 display->button_y[1] = 0;
1236 display->button_y[0] = event->button.y;
1241 gdk_synthesize_window_state (GdkWindow *window,
1242 GdkWindowState unset_flags,
1243 GdkWindowState set_flags)
1245 GdkEvent temp_event;
1248 g_return_if_fail (window != NULL);
1250 temp_event.window_state.window = window;
1251 temp_event.window_state.type = GDK_WINDOW_STATE;
1252 temp_event.window_state.send_event = FALSE;
1254 old = ((GdkWindowObject*) temp_event.window_state.window)->state;
1256 temp_event.window_state.new_window_state = old;
1257 temp_event.window_state.new_window_state |= set_flags;
1258 temp_event.window_state.new_window_state &= ~unset_flags;
1259 temp_event.window_state.changed_mask = temp_event.window_state.new_window_state ^ old;
1261 if (temp_event.window_state.new_window_state == old)
1262 return; /* No actual work to do, nothing changed. */
1264 /* Actually update the field in GdkWindow, this is sort of an odd
1265 * place to do it, but seems like the safest since it ensures we expose no
1266 * inconsistent state to the user.
1269 ((GdkWindowObject*) window)->state = temp_event.window_state.new_window_state;
1271 if (temp_event.window_state.changed_mask & GDK_WINDOW_STATE_WITHDRAWN)
1272 _gdk_window_update_viewable (window);
1274 /* We only really send the event to toplevels, since
1275 * all the window states don't apply to non-toplevels.
1276 * Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag
1277 * internally so we needed to update window->state.
1279 switch (((GdkWindowObject*) window)->window_type)
1281 case GDK_WINDOW_TOPLEVEL:
1282 case GDK_WINDOW_DIALOG:
1283 case GDK_WINDOW_TEMP: /* ? */
1284 gdk_display_put_event (gdk_drawable_get_display (window), &temp_event);
1287 case GDK_WINDOW_FOREIGN:
1288 case GDK_WINDOW_ROOT:
1289 case GDK_WINDOW_CHILD:
1295 * gdk_display_set_double_click_time:
1296 * @display: a #GdkDisplay
1297 * @msec: double click time in milliseconds (thousandths of a second)
1299 * Sets the double click time (two clicks within this time interval
1300 * count as a double click and result in a #GDK_2BUTTON_PRESS event).
1301 * Applications should <emphasis>not</emphasis> set this, it is a global
1302 * user-configured setting.
1307 gdk_display_set_double_click_time (GdkDisplay *display,
1310 display->double_click_time = msec;
1314 * gdk_set_double_click_time:
1315 * @msec: double click time in milliseconds (thousandths of a second)
1317 * Set the double click time for the default display. See
1318 * gdk_display_set_double_click_time().
1319 * See also gdk_display_set_double_click_distance().
1320 * Applications should <emphasis>not</emphasis> set this, it is a
1321 * global user-configured setting.
1324 gdk_set_double_click_time (guint msec)
1326 gdk_display_set_double_click_time (gdk_display_get_default (), msec);
1330 * gdk_display_set_double_click_distance:
1331 * @display: a #GdkDisplay
1332 * @distance: distance in pixels
1334 * Sets the double click distance (two clicks within this distance
1335 * count as a double click and result in a #GDK_2BUTTON_PRESS event).
1336 * See also gdk_display_set_double_click_time().
1337 * Applications should <emphasis>not</emphasis> set this, it is a global
1338 * user-configured setting.
1343 gdk_display_set_double_click_distance (GdkDisplay *display,
1346 display->double_click_distance = distance;
1350 gdk_event_get_type (void)
1352 static GType our_type = 0;
1355 our_type = g_boxed_type_register_static (g_intern_static_string ("GdkEvent"),
1356 (GBoxedCopyFunc)gdk_event_copy,
1357 (GBoxedFreeFunc)gdk_event_free);
1363 * @name: the name of the setting.
1364 * @value: location to store the value of the setting.
1366 * Obtains a desktop-wide setting, such as the double-click time,
1367 * for the default screen. See gdk_screen_get_setting().
1369 * Returns: %TRUE if the setting existed and a value was stored
1370 * in @value, %FALSE otherwise.
1373 gdk_setting_get (const gchar *name,
1376 return gdk_screen_get_setting (gdk_screen_get_default (), name, value);
1379 #define __GDK_EVENTS_C__
1380 #include "gdkaliasdef.c"