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 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.
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.
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.
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/.
28 #include "gdkprivate.h"
31 #include "gdkkeysyms.h"
40 #include "gdkinputprivate.h"
42 typedef struct _GdkIOClosure GdkIOClosure;
43 typedef struct _GdkEventPrivate GdkEventPrivate;
45 #define DOUBLE_CLICK_TIME 250
46 #define TRIPLE_CLICK_TIME 500
47 #define DOUBLE_CLICK_DIST 5
48 #define TRIPLE_CLICK_DIST 5
52 /* Following flag is set for events on the event queue during
53 * translation and cleared afterwards.
55 GDK_EVENT_PENDING = 1 << 0
60 GdkInputFunction function;
61 GdkInputCondition condition;
62 GdkDestroyNotify notify;
66 struct _GdkEventPrivate
73 * Private function declarations
76 static GdkEvent *gdk_event_new (void);
77 static gint gdk_event_apply_filters (XEvent *xevent,
80 static gint gdk_event_translate (GdkEvent *event,
83 static Bool gdk_event_get_type (Display *display,
87 static void gdk_events_queue (void);
88 static GdkEvent* gdk_event_unqueue (void);
90 static gboolean gdk_event_prepare (gpointer source_data,
91 GTimeVal *current_time,
94 static gboolean gdk_event_check (gpointer source_data,
95 GTimeVal *current_time,
97 static gboolean gdk_event_dispatch (gpointer source_data,
98 GTimeVal *current_time,
101 static void gdk_synthesize_click (GdkEvent *event,
104 GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
108 /* Private variable declarations
111 static int connection_number = 0; /* The file descriptor number of our
112 * connection to the X server. This
113 * is used so that we may determine
114 * when events are pending by using
115 * the "select" system call.
117 static guint32 button_click_time[2]; /* The last 2 button click times. Used
118 * to determine if the latest button click
119 * is part of a double or triple click.
121 static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
122 * Also used to determine if the latest button
123 * click is part of a double or triple click.
125 static guint button_number[2]; /* The last 2 buttons to be pressed.
127 static GdkEventFunc event_func = NULL; /* Callback for events */
128 static gpointer event_data = NULL;
129 static GDestroyNotify event_notify = NULL;
131 static GList *client_filters; /* Filters for client messages */
133 /* FIFO's for event queue, and for events put back using
136 static GList *queued_events = NULL;
137 static GList *queued_tail = NULL;
139 static GSourceFuncs event_funcs = {
143 (GDestroyNotify)g_free
146 GPollFD event_poll_fd;
148 /*********************************************
149 * Functions for maintaining the event queue *
150 *********************************************/
152 /*************************************************************
153 * gdk_event_queue_find_first:
154 * Find the first event on the queue that is not still
159 * Pointer to the list node for that event, or NULL
160 *************************************************************/
163 gdk_event_queue_find_first (void)
165 GList *tmp_list = queued_events;
169 GdkEventPrivate *event = tmp_list->data;
170 if (!(event->flags & GDK_EVENT_PENDING))
173 tmp_list = g_list_next (tmp_list);
179 /*************************************************************
180 * gdk_event_queue_remove_link:
181 * Remove a specified list node from the event queue.
183 * node: Node to remove.
185 *************************************************************/
188 gdk_event_queue_remove_link (GList *node)
191 node->prev->next = node->next;
193 queued_events = node->next;
196 node->next->prev = node->prev;
198 queued_tail = node->prev;
202 /*************************************************************
203 * gdk_event_queue_append:
204 * Append an event onto the tail of the event queue.
206 * event: Event to append.
208 *************************************************************/
211 gdk_event_queue_append (GdkEvent *event)
213 queued_tail = g_list_append (queued_tail, event);
216 queued_events = queued_tail;
218 queued_tail = queued_tail->next;
222 gdk_events_init (void)
224 connection_number = ConnectionNumber (gdk_display);
226 g_message ("connection number: %d", connection_number));
228 g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);
230 event_poll_fd.fd = connection_number;
231 event_poll_fd.events = G_IO_IN;
233 g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);
235 button_click_time[0] = 0;
236 button_click_time[1] = 0;
237 button_window[0] = NULL;
238 button_window[1] = NULL;
239 button_number[0] = -1;
240 button_number[1] = -1;
242 gdk_add_client_message_filter (gdk_wm_protocols,
243 gdk_wm_protocols_filter, NULL);
247 *--------------------------------------------------------------
250 * Returns if events are pending on the queue.
255 * Returns TRUE if events are pending
259 *--------------------------------------------------------------
263 gdk_events_pending (void)
265 return (gdk_event_queue_find_first() || XPending (gdk_display));
269 *--------------------------------------------------------------
270 * gdk_event_get_graphics_expose
272 * Waits for a GraphicsExpose or NoExpose event
277 * For GraphicsExpose events, returns a pointer to the event
278 * converted into a GdkEvent Otherwise, returns NULL.
282 *-------------------------------------------------------------- */
285 graphics_expose_predicate (Display *display,
289 if (xevent->xany.window == GDK_DRAWABLE_XID (arg) &&
290 (xevent->xany.type == GraphicsExpose ||
291 xevent->xany.type == NoExpose))
298 gdk_event_get_graphics_expose (GdkWindow *window)
303 g_return_val_if_fail (window != NULL, NULL);
305 XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer) window);
307 if (xevent.xany.type == GraphicsExpose)
309 event = gdk_event_new ();
311 if (gdk_event_translate (event, &xevent))
314 gdk_event_free (event);
320 /************************
321 * Exposure compression *
322 ************************/
325 * The following implements simple exposure compression. It is
326 * modelled after the way Xt does exposure compression - in
327 * particular compress_expose = XtExposeCompressMultiple.
328 * It compress consecutive sequences of exposure events,
329 * but not sequences that cross other events. (This is because
330 * if it crosses a ConfigureNotify, we could screw up and
331 * mistakenly compress the exposures generated for the new
332 * size - could we just check for ConfigureNotify?)
334 * Xt compresses to a region / bounding rectangle, we compress
335 * to two rectangles, and try find the two rectangles of minimal
336 * area for this - this is supposed to handle the typical
337 * L-shaped regions generated by OpaqueMove.
340 /* Given three rectangles, find the two rectangles that cover
341 * them with the smallest area.
344 gdk_add_rect_to_rects (GdkRectangle *rect1,
346 GdkRectangle *new_rect)
348 GdkRectangle t1, t2, t3;
349 gint size1, size2, size3;
351 gdk_rectangle_union (rect1, rect2, &t1);
352 gdk_rectangle_union (rect1, new_rect, &t2);
353 gdk_rectangle_union (rect2, new_rect, &t3);
355 size1 = t1.width * t1.height + new_rect->width * new_rect->height;
356 size2 = t2.width * t2.height + rect2->width * rect2->height;
357 size3 = t1.width * t1.height + rect1->width * rect1->height;
378 typedef struct _GdkExposeInfo GdkExposeInfo;
380 struct _GdkExposeInfo
383 gboolean seen_nonmatching;
387 expose_predicate (Display *display,
391 GdkExposeInfo *info = (GdkExposeInfo*) arg;
393 /* Compressing across GravityNotify events is safe, because
394 * we completely ignore them, so they can't change what
395 * we are going to draw. Compressing across GravityNotify
396 * events is necessay because during window-unshading animation
397 * we'll get a whole bunch of them interspersed with
400 if (xevent->xany.type != Expose &&
401 xevent->xany.type != GravityNotify)
403 info->seen_nonmatching = TRUE;
406 if (info->seen_nonmatching ||
407 xevent->xany.type != Expose ||
408 xevent->xany.window != info->window)
415 gdk_compress_exposures (XEvent *xevent,
422 GdkRectangle tmp_rect;
424 GdkFilterReturn result;
428 info.window = xevent->xany.window;
429 info.seen_nonmatching = FALSE;
431 rect1.x = xevent->xexpose.x;
432 rect1.y = xevent->xexpose.y;
433 rect1.width = xevent->xexpose.width;
434 rect1.height = xevent->xexpose.height;
436 event.any.type = GDK_EXPOSE;
437 event.any.window = None;
438 event.any.send_event = FALSE;
444 if (!XCheckIfEvent (gdk_display,
451 XIfEvent (gdk_display,
456 event.any.window = window;
458 /* We apply filters here, and if it was filtered, completely
461 result = gdk_event_apply_filters (xevent, &event,
463 ((GdkWindowPrivate *)window)->filters
464 : gdk_default_filters);
466 if (result != GDK_FILTER_CONTINUE)
468 if (result == GDK_FILTER_TRANSLATE)
469 gdk_event_put (&event);
475 rect2.x = tmp_event.xexpose.x;
476 rect2.y = tmp_event.xexpose.y;
477 rect2.width = tmp_event.xexpose.width;
478 rect2.height = tmp_event.xexpose.height;
484 tmp_rect.x = tmp_event.xexpose.x;
485 tmp_rect.y = tmp_event.xexpose.y;
486 tmp_rect.width = tmp_event.xexpose.width;
487 tmp_rect.height = tmp_event.xexpose.height;
489 gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
492 count = tmp_event.xexpose.count;
497 gdk_rectangle_union (&rect1, &rect2, &tmp_rect);
499 if ((tmp_rect.width * tmp_rect.height) <
500 2 * (rect1.height * rect1.width +
501 rect2.height * rect2.width))
510 event.expose.type = GDK_EXPOSE;
511 event.expose.window = window;
512 event.expose.area.x = rect2.x;
513 event.expose.area.y = rect2.y;
514 event.expose.area.width = rect2.width;
515 event.expose.area.height = rect2.height;
516 event.expose.count = 0;
518 gdk_event_put (&event);
521 xevent->xexpose.count = nrects - 1;
522 xevent->xexpose.x = rect1.x;
523 xevent->xexpose.y = rect1.y;
524 xevent->xexpose.width = rect1.width;
525 xevent->xexpose.height = rect1.height;
528 /*************************************************************
529 * gdk_event_handler_set:
532 * func: Callback function to be called for each event.
533 * data: Data supplied to the function
534 * notify: function called when function is no longer needed
537 *************************************************************/
540 gdk_event_handler_set (GdkEventFunc func,
542 GDestroyNotify notify)
545 (*event_notify) (event_data);
549 event_notify = notify;
553 *--------------------------------------------------------------
556 * Gets the next event.
561 * If an event is waiting that we care about, returns
562 * a pointer to that event, to be freed with gdk_event_free.
563 * Otherwise, returns NULL.
567 *--------------------------------------------------------------
575 return gdk_event_unqueue ();
579 *--------------------------------------------------------------
582 * Gets the next event.
587 * If an event is waiting that we care about, returns
588 * a copy of that event, but does not remove it from
589 * the queue. The pointer is to be freed with gdk_event_free.
590 * Otherwise, returns NULL.
594 *--------------------------------------------------------------
598 gdk_event_peek (void)
602 tmp_list = gdk_event_queue_find_first ();
605 return gdk_event_copy (tmp_list->data);
611 gdk_event_put (GdkEvent *event)
615 g_return_if_fail (event != NULL);
617 new_event = gdk_event_copy (event);
619 gdk_event_queue_append (new_event);
623 *--------------------------------------------------------------
626 * Copy a event structure into new storage.
629 * "event" is the event struct to copy.
632 * A new event structure. Free it with gdk_event_free.
635 * The reference count of the window in the event is increased.
637 *--------------------------------------------------------------
640 static GMemChunk *event_chunk = NULL;
645 GdkEventPrivate *new_event;
647 if (event_chunk == NULL)
648 event_chunk = g_mem_chunk_new ("events",
649 sizeof (GdkEventPrivate),
653 new_event = g_chunk_new (GdkEventPrivate, event_chunk);
654 new_event->flags = 0;
656 return (GdkEvent*) new_event;
660 gdk_event_copy (GdkEvent *event)
664 g_return_val_if_fail (event != NULL, NULL);
666 new_event = gdk_event_new ();
669 gdk_window_ref (new_event->any.window);
671 switch (event->any.type)
674 case GDK_KEY_RELEASE:
675 new_event->key.string = g_strdup (event->key.string);
678 case GDK_ENTER_NOTIFY:
679 case GDK_LEAVE_NOTIFY:
680 if (event->crossing.subwindow != NULL)
681 gdk_window_ref (event->crossing.subwindow);
686 case GDK_DRAG_MOTION:
687 case GDK_DRAG_STATUS:
689 case GDK_DROP_FINISHED:
690 gdk_drag_context_ref (event->dnd.context);
701 *--------------------------------------------------------------
704 * Free a event structure obtained from gdk_event_copy. Do not use
705 * with other event structures.
708 * "event" is the event struct to free.
713 * The reference count of the window in the event is decreased and
714 * might be freed, too.
716 *-------------------------------------------------------------- */
719 gdk_event_free (GdkEvent *event)
721 g_return_if_fail (event != NULL);
723 g_assert (event_chunk != NULL); /* paranoid */
725 if (event->any.window)
726 gdk_window_unref (event->any.window);
728 switch (event->any.type)
731 case GDK_KEY_RELEASE:
732 g_free (event->key.string);
735 case GDK_ENTER_NOTIFY:
736 case GDK_LEAVE_NOTIFY:
737 if (event->crossing.subwindow != NULL)
738 gdk_window_unref (event->crossing.subwindow);
743 case GDK_DRAG_MOTION:
744 case GDK_DRAG_STATUS:
746 case GDK_DROP_FINISHED:
747 gdk_drag_context_unref (event->dnd.context);
754 g_mem_chunk_free (event_chunk, event);
758 *--------------------------------------------------------------
759 * gdk_event_get_time:
760 * Get the timestamp from an event.
764 * The event's time stamp, if it has one, otherwise
766 *--------------------------------------------------------------
770 gdk_event_get_time (GdkEvent *event)
775 case GDK_MOTION_NOTIFY:
776 return event->motion.time;
777 case GDK_BUTTON_PRESS:
778 case GDK_2BUTTON_PRESS:
779 case GDK_3BUTTON_PRESS:
780 case GDK_BUTTON_RELEASE:
781 return event->button.time;
783 case GDK_KEY_RELEASE:
784 return event->key.time;
785 case GDK_ENTER_NOTIFY:
786 case GDK_LEAVE_NOTIFY:
787 return event->crossing.time;
788 case GDK_PROPERTY_NOTIFY:
789 return event->property.time;
790 case GDK_SELECTION_CLEAR:
791 case GDK_SELECTION_REQUEST:
792 case GDK_SELECTION_NOTIFY:
793 return event->selection.time;
794 case GDK_PROXIMITY_IN:
795 case GDK_PROXIMITY_OUT:
796 return event->proximity.time;
799 case GDK_DRAG_MOTION:
800 case GDK_DRAG_STATUS:
802 case GDK_DROP_FINISHED:
803 return event->dnd.time;
804 default: /* use current time */
808 return GDK_CURRENT_TIME;
812 *--------------------------------------------------------------
813 * gdk_set_show_events
815 * Turns on/off the showing of events.
818 * "show_events" is a boolean describing whether or
819 * not to show the events gdk receives.
824 * When "show_events" is TRUE, calls to "gdk_event_get"
825 * will output debugging informatin regarding the event
826 * received to stdout.
828 *--------------------------------------------------------------
832 gdk_set_show_events (gint show_events)
835 gdk_debug_flags |= GDK_DEBUG_EVENTS;
837 gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
841 gdk_get_show_events (void)
843 return gdk_debug_flags & GDK_DEBUG_EVENTS;
847 gdk_io_destroy (gpointer data)
849 GdkIOClosure *closure = data;
852 closure->notify (closure->data);
857 /* What do we do with G_IO_NVAL?
859 #define READ_CONDITION (G_IO_IN | G_IO_HUP | G_IO_ERR)
860 #define WRITE_CONDITION (G_IO_OUT | G_IO_ERR)
861 #define EXCEPTION_CONDITION (G_IO_PRI)
864 gdk_io_invoke (GIOChannel *source,
865 GIOCondition condition,
868 GdkIOClosure *closure = data;
869 GdkInputCondition gdk_cond = 0;
871 if (condition & READ_CONDITION)
872 gdk_cond |= GDK_INPUT_READ;
873 if (condition & WRITE_CONDITION)
874 gdk_cond |= GDK_INPUT_WRITE;
875 if (condition & EXCEPTION_CONDITION)
876 gdk_cond |= GDK_INPUT_EXCEPTION;
878 if (closure->condition & gdk_cond)
879 closure->function (closure->data, g_io_channel_unix_get_fd (source), gdk_cond);
885 gdk_input_add_full (gint source,
886 GdkInputCondition condition,
887 GdkInputFunction function,
889 GdkDestroyNotify destroy)
892 GdkIOClosure *closure = g_new (GdkIOClosure, 1);
894 GIOCondition cond = 0;
896 closure->function = function;
897 closure->condition = condition;
898 closure->notify = destroy;
899 closure->data = data;
901 if (condition & GDK_INPUT_READ)
902 cond |= READ_CONDITION;
903 if (condition & GDK_INPUT_WRITE)
904 cond |= WRITE_CONDITION;
905 if (condition & GDK_INPUT_EXCEPTION)
906 cond |= EXCEPTION_CONDITION;
908 channel = g_io_channel_unix_new (source);
909 result = g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, cond,
911 closure, gdk_io_destroy);
912 g_io_channel_unref (channel);
918 gdk_input_add (gint source,
919 GdkInputCondition condition,
920 GdkInputFunction function,
923 return gdk_input_add_full (source, condition, function, data, NULL);
927 gdk_input_remove (gint tag)
929 g_source_remove (tag);
933 gdk_event_apply_filters (XEvent *xevent,
938 GdkFilterReturn result;
944 GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
946 tmp_list = tmp_list->next;
947 result = filter->function (xevent, event, filter->data);
948 if (result != GDK_FILTER_CONTINUE)
952 return GDK_FILTER_CONTINUE;
956 gdk_add_client_message_filter (GdkAtom message_type,
960 GdkClientFilter *filter = g_new (GdkClientFilter, 1);
962 filter->type = message_type;
963 filter->function = func;
966 client_filters = g_list_prepend (client_filters, filter);
970 gdk_event_translate (GdkEvent *event,
975 GdkWindowPrivate *window_private;
976 static XComposeStatus compose;
980 static gchar* buf = NULL;
981 static gint buf_len= 0;
989 /* Find the GdkWindow that this event occurred in.
991 * We handle events with window=None
992 * specially - they are generated by XFree86's XInput under
993 * some circumstances.
996 if ((xevent->xany.window == None) &&
997 gdk_input_vtable.window_none_event)
999 return_val = gdk_input_vtable.window_none_event (event,xevent);
1001 if (return_val >= 0) /* was handled */
1007 window = gdk_window_lookup (xevent->xany.window);
1008 /* FIXME: window might be a GdkPixmap!!! */
1010 window_private = (GdkWindowPrivate *) window;
1013 gdk_window_ref (window);
1015 event->any.window = window;
1016 event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
1018 if (window_private && GDK_DRAWABLE_DESTROYED (window))
1020 if (xevent->type != DestroyNotify)
1025 /* Check for filters for this window
1027 GdkFilterReturn result;
1028 result = gdk_event_apply_filters (xevent, event,
1030 ?window_private->filters
1031 :gdk_default_filters);
1033 if (result != GDK_FILTER_CONTINUE)
1035 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1040 if (window == NULL && gdk_xim_window && xevent->type == KeyPress &&
1041 !GDK_DRAWABLE_DESTROYED (gdk_xim_window))
1044 * If user presses a key in Preedit or Status window, keypress event
1045 * is sometimes sent to these windows. These windows are not managed
1046 * by GDK, so we redirect KeyPress event to xim_window.
1048 * If someone want to use the window whitch is not managed by GDK
1049 * and want to get KeyPress event, he/she must register the filter
1050 * function to gdk_default_filters to intercept the event.
1053 GdkFilterReturn result;
1055 window = gdk_xim_window;
1056 window_private = (GdkWindowPrivate *) window;
1057 gdk_window_ref (window);
1058 event->any.window = window;
1061 g_message ("KeyPress event is redirected to xim_window: %#lx",
1062 xevent->xany.window));
1064 result = gdk_event_apply_filters (xevent, event,
1065 window_private->filters);
1066 if (result != GDK_FILTER_CONTINUE)
1067 return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
1071 /* We do a "manual" conversion of the XEvent to a
1072 * GdkEvent. The structures are mostly the same so
1073 * the conversion is fairly straightforward. We also
1074 * optionally print debugging info regarding events
1080 switch (xevent->type)
1083 /* Lookup the string corresponding to the given keysym.
1090 buf = g_new (gchar, buf_len);
1092 keysym = GDK_VoidSymbol;
1094 if (gdk_xim_ic && gdk_xim_ic->xic)
1098 /* Clear keyval. Depending on status, may not be set */
1099 charcount = XmbLookupString(gdk_xim_ic->xic,
1100 &xevent->xkey, buf, buf_len-1,
1102 if (status == XBufferOverflow)
1104 /* alloc adequate size of buffer */
1106 g_message("XIM: overflow (required %i)", charcount));
1108 while (buf_len <= charcount)
1110 buf = (gchar *) g_realloc (buf, buf_len);
1112 charcount = XmbLookupString (gdk_xim_ic->xic,
1113 &xevent->xkey, buf, buf_len-1,
1116 if (status == XLookupNone)
1123 charcount = XLookupString (&xevent->xkey, buf, buf_len,
1126 charcount = XLookupString (&xevent->xkey, buf, 16,
1129 event->key.keyval = keysym;
1131 if (charcount > 0 && buf[charcount-1] == '\0')
1134 buf[charcount] = '\0';
1136 /* Print debugging info. */
1138 #ifdef G_ENABLE_DEBUG
1139 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1141 g_message ("key press:\twindow: %ld key: %12s %d",
1142 xevent->xkey.window,
1143 event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
1146 g_message ("\t\tlength: %4d string: \"%s\"",
1149 #endif /* G_ENABLE_DEBUG */
1151 event->key.type = GDK_KEY_PRESS;
1152 event->key.window = window;
1153 event->key.time = xevent->xkey.time;
1154 event->key.state = (GdkModifierType) xevent->xkey.state;
1155 event->key.string = g_strdup (buf);
1156 event->key.length = charcount;
1161 /* Lookup the string corresponding to the given keysym.
1167 buf = g_new (gchar, buf_len);
1170 keysym = GDK_VoidSymbol;
1171 charcount = XLookupString (&xevent->xkey, buf, 16,
1173 event->key.keyval = keysym;
1175 /* Print debugging info.
1178 g_message ("key release:\t\twindow: %ld key: %12s %d",
1179 xevent->xkey.window,
1180 XKeysymToString (event->key.keyval),
1181 event->key.keyval));
1183 event->key.type = GDK_KEY_RELEASE;
1184 event->key.window = window;
1185 event->key.time = xevent->xkey.time;
1186 event->key.state = (GdkModifierType) xevent->xkey.state;
1187 event->key.length = 0;
1188 event->key.string = NULL;
1193 /* Print debugging info.
1196 g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
1197 xevent->xbutton.window,
1198 xevent->xbutton.x, xevent->xbutton.y,
1199 xevent->xbutton.button));
1201 if (window_private &&
1202 (window_private->extension_events != 0) &&
1203 gdk_input_ignore_core)
1209 event->button.type = GDK_BUTTON_PRESS;
1210 event->button.window = window;
1211 event->button.time = xevent->xbutton.time;
1212 event->button.x = xevent->xbutton.x;
1213 event->button.y = xevent->xbutton.y;
1214 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1215 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1216 event->button.pressure = 0.5;
1217 event->button.xtilt = 0;
1218 event->button.ytilt = 0;
1219 event->button.state = (GdkModifierType) xevent->xbutton.state;
1220 event->button.button = xevent->xbutton.button;
1221 event->button.source = GDK_SOURCE_MOUSE;
1222 event->button.deviceid = GDK_CORE_POINTER;
1224 if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
1225 (event->button.window == button_window[1]) &&
1226 (event->button.button == button_number[1]))
1228 gdk_synthesize_click (event, 3);
1230 button_click_time[1] = 0;
1231 button_click_time[0] = 0;
1232 button_window[1] = NULL;
1233 button_window[0] = 0;
1234 button_number[1] = -1;
1235 button_number[0] = -1;
1237 else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
1238 (event->button.window == button_window[0]) &&
1239 (event->button.button == button_number[0]))
1241 gdk_synthesize_click (event, 2);
1243 button_click_time[1] = button_click_time[0];
1244 button_click_time[0] = event->button.time;
1245 button_window[1] = button_window[0];
1246 button_window[0] = event->button.window;
1247 button_number[1] = button_number[0];
1248 button_number[0] = event->button.button;
1252 button_click_time[1] = 0;
1253 button_click_time[0] = event->button.time;
1254 button_window[1] = NULL;
1255 button_window[0] = event->button.window;
1256 button_number[1] = -1;
1257 button_number[0] = event->button.button;
1263 /* Print debugging info.
1266 g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
1267 xevent->xbutton.window,
1268 xevent->xbutton.x, xevent->xbutton.y,
1269 xevent->xbutton.button));
1271 if (window_private &&
1272 (window_private->extension_events != 0) &&
1273 gdk_input_ignore_core)
1279 event->button.type = GDK_BUTTON_RELEASE;
1280 event->button.window = window;
1281 event->button.time = xevent->xbutton.time;
1282 event->button.x = xevent->xbutton.x;
1283 event->button.y = xevent->xbutton.y;
1284 event->button.x_root = (gfloat)xevent->xbutton.x_root;
1285 event->button.y_root = (gfloat)xevent->xbutton.y_root;
1286 event->button.pressure = 0.5;
1287 event->button.xtilt = 0;
1288 event->button.ytilt = 0;
1289 event->button.state = (GdkModifierType) xevent->xbutton.state;
1290 event->button.button = xevent->xbutton.button;
1291 event->button.source = GDK_SOURCE_MOUSE;
1292 event->button.deviceid = GDK_CORE_POINTER;
1297 /* Print debugging info.
1300 g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s",
1301 xevent->xmotion.window,
1302 xevent->xmotion.x, xevent->xmotion.y,
1303 (xevent->xmotion.is_hint) ? "true" : "false"));
1305 if (window_private &&
1306 (window_private->extension_events != 0) &&
1307 gdk_input_ignore_core)
1313 event->motion.type = GDK_MOTION_NOTIFY;
1314 event->motion.window = window;
1315 event->motion.time = xevent->xmotion.time;
1316 event->motion.x = xevent->xmotion.x;
1317 event->motion.y = xevent->xmotion.y;
1318 event->motion.x_root = (gfloat)xevent->xmotion.x_root;
1319 event->motion.y_root = (gfloat)xevent->xmotion.y_root;
1320 event->motion.pressure = 0.5;
1321 event->motion.xtilt = 0;
1322 event->motion.ytilt = 0;
1323 event->motion.state = (GdkModifierType) xevent->xmotion.state;
1324 event->motion.is_hint = xevent->xmotion.is_hint;
1325 event->motion.source = GDK_SOURCE_MOUSE;
1326 event->motion.deviceid = GDK_CORE_POINTER;
1331 /* Print debugging info.
1334 g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
1335 xevent->xcrossing.window,
1336 xevent->xcrossing.detail,
1337 xevent->xcrossing.subwindow));
1339 /* Tell XInput stuff about it if appropriate */
1340 if (window_private &&
1341 !GDK_DRAWABLE_DESTROYED (window) &&
1342 (window_private->extension_events != 0) &&
1343 gdk_input_vtable.enter_event)
1344 gdk_input_vtable.enter_event (&xevent->xcrossing, window);
1346 event->crossing.type = GDK_ENTER_NOTIFY;
1347 event->crossing.window = window;
1349 /* If the subwindow field of the XEvent is non-NULL, then
1350 * lookup the corresponding GdkWindow.
1352 if (xevent->xcrossing.subwindow != None)
1353 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
1355 event->crossing.subwindow = NULL;
1357 event->crossing.time = xevent->xcrossing.time;
1358 event->crossing.x = xevent->xcrossing.x;
1359 event->crossing.y = xevent->xcrossing.y;
1360 event->crossing.x_root = xevent->xcrossing.x_root;
1361 event->crossing.y_root = xevent->xcrossing.y_root;
1363 /* Translate the crossing mode into Gdk terms.
1365 switch (xevent->xcrossing.mode)
1368 event->crossing.mode = GDK_CROSSING_NORMAL;
1371 event->crossing.mode = GDK_CROSSING_GRAB;
1374 event->crossing.mode = GDK_CROSSING_UNGRAB;
1378 /* Translate the crossing detail into Gdk terms.
1380 switch (xevent->xcrossing.detail)
1382 case NotifyInferior:
1383 event->crossing.detail = GDK_NOTIFY_INFERIOR;
1385 case NotifyAncestor:
1386 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
1389 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
1391 case NotifyNonlinear:
1392 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
1394 case NotifyNonlinearVirtual:
1395 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
1398 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1402 event->crossing.focus = xevent->xcrossing.focus;
1403 event->crossing.state = xevent->xcrossing.state;
1408 /* Print debugging info.
1411 g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
1412 xevent->xcrossing.window,
1413 xevent->xcrossing.detail, xevent->xcrossing.subwindow));
1415 event->crossing.type = GDK_LEAVE_NOTIFY;
1416 event->crossing.window = window;
1418 /* If the subwindow field of the XEvent is non-NULL, then
1419 * lookup the corresponding GdkWindow.
1421 if (xevent->xcrossing.subwindow != None)
1422 event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
1424 event->crossing.subwindow = NULL;
1426 event->crossing.time = xevent->xcrossing.time;
1427 event->crossing.x = xevent->xcrossing.x;
1428 event->crossing.y = xevent->xcrossing.y;
1429 event->crossing.x_root = xevent->xcrossing.x_root;
1430 event->crossing.y_root = xevent->xcrossing.y_root;
1432 /* Translate the crossing mode into Gdk terms.
1434 switch (xevent->xcrossing.mode)
1437 event->crossing.mode = GDK_CROSSING_NORMAL;
1440 event->crossing.mode = GDK_CROSSING_GRAB;
1443 event->crossing.mode = GDK_CROSSING_UNGRAB;
1447 /* Translate the crossing detail into Gdk terms.
1449 switch (xevent->xcrossing.detail)
1451 case NotifyInferior:
1452 event->crossing.detail = GDK_NOTIFY_INFERIOR;
1454 case NotifyAncestor:
1455 event->crossing.detail = GDK_NOTIFY_ANCESTOR;
1458 event->crossing.detail = GDK_NOTIFY_VIRTUAL;
1460 case NotifyNonlinear:
1461 event->crossing.detail = GDK_NOTIFY_NONLINEAR;
1463 case NotifyNonlinearVirtual:
1464 event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
1467 event->crossing.detail = GDK_NOTIFY_UNKNOWN;
1471 event->crossing.focus = xevent->xcrossing.focus;
1472 event->crossing.state = xevent->xcrossing.state;
1478 /* We only care about focus events that indicate that _this_
1479 * window (not a ancestor or child) got or lost the focus
1481 switch (xevent->xfocus.detail)
1483 case NotifyAncestor:
1484 case NotifyInferior:
1485 case NotifyNonlinear:
1486 /* Print debugging info.
1489 g_message ("focus %s:\t\twindow: %ld",
1490 (xevent->xany.type == FocusIn) ? "in" : "out",
1491 xevent->xfocus.window));
1493 /* gdk_keyboard_grab() causes following events. These events confuse
1494 * the XIM focus, so ignore them.
1496 if (xevent->xfocus.mode == NotifyGrab ||
1497 xevent->xfocus.mode == NotifyUngrab)
1500 event->focus_change.type = GDK_FOCUS_CHANGE;
1501 event->focus_change.window = window;
1502 event->focus_change.in = (xevent->xany.type == FocusIn);
1511 /* Print debugging info.
1514 g_message ("keymap notify"));
1516 /* Not currently handled */
1521 /* Print debugging info.
1524 g_message ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d%s",
1525 xevent->xexpose.window, xevent->xexpose.count,
1526 xevent->xexpose.x, xevent->xexpose.y,
1527 xevent->xexpose.width, xevent->xexpose.height,
1528 event->any.send_event ? " (send)" : ""));
1529 gdk_compress_exposures (xevent, window);
1531 event->expose.type = GDK_EXPOSE;
1532 event->expose.window = window;
1533 event->expose.area.x = xevent->xexpose.x;
1534 event->expose.area.y = xevent->xexpose.y;
1535 event->expose.area.width = xevent->xexpose.width;
1536 event->expose.area.height = xevent->xexpose.height;
1537 event->expose.count = xevent->xexpose.count;
1541 case GraphicsExpose:
1542 /* Print debugging info.
1545 g_message ("graphics expose:\tdrawable: %ld",
1546 xevent->xgraphicsexpose.drawable));
1548 event->expose.type = GDK_EXPOSE;
1549 event->expose.window = window;
1550 event->expose.area.x = xevent->xgraphicsexpose.x;
1551 event->expose.area.y = xevent->xgraphicsexpose.y;
1552 event->expose.area.width = xevent->xgraphicsexpose.width;
1553 event->expose.area.height = xevent->xgraphicsexpose.height;
1554 event->expose.count = xevent->xexpose.count;
1559 /* Print debugging info.
1562 g_message ("no expose:\t\tdrawable: %ld",
1563 xevent->xnoexpose.drawable));
1565 event->no_expose.type = GDK_NO_EXPOSE;
1566 event->no_expose.window = window;
1570 case VisibilityNotify:
1571 /* Print debugging info.
1573 #ifdef G_ENABLE_DEBUG
1574 if (gdk_debug_flags & GDK_DEBUG_EVENTS)
1575 switch (xevent->xvisibility.state)
1577 case VisibilityFullyObscured:
1578 g_message ("visibility notify:\twindow: %ld none",
1579 xevent->xvisibility.window);
1581 case VisibilityPartiallyObscured:
1582 g_message ("visibility notify:\twindow: %ld partial",
1583 xevent->xvisibility.window);
1585 case VisibilityUnobscured:
1586 g_message ("visibility notify:\twindow: %ld full",
1587 xevent->xvisibility.window);
1590 #endif /* G_ENABLE_DEBUG */
1592 event->visibility.type = GDK_VISIBILITY_NOTIFY;
1593 event->visibility.window = window;
1595 switch (xevent->xvisibility.state)
1597 case VisibilityFullyObscured:
1598 event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
1601 case VisibilityPartiallyObscured:
1602 event->visibility.state = GDK_VISIBILITY_PARTIAL;
1605 case VisibilityUnobscured:
1606 event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
1614 g_message ("create notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d parent: %ld ovr: %d",
1615 xevent->xcreatewindow.window,
1616 xevent->xcreatewindow.x,
1617 xevent->xcreatewindow.y,
1618 xevent->xcreatewindow.width,
1619 xevent->xcreatewindow.height,
1620 xevent->xcreatewindow.border_width,
1621 xevent->xcreatewindow.parent,
1622 xevent->xcreatewindow.override_redirect));
1623 /* not really handled */
1627 /* Print debugging info.
1630 g_message ("destroy notify:\twindow: %ld",
1631 xevent->xdestroywindow.window));
1633 event->any.type = GDK_DESTROY;
1634 event->any.window = window;
1636 return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
1638 if (window && GDK_DRAWABLE_XID (window) != GDK_ROOT_WINDOW())
1639 gdk_window_destroy_notify (window);
1643 /* Print debugging info.
1646 g_message ("unmap notify:\t\twindow: %ld",
1647 xevent->xmap.window));
1649 event->any.type = GDK_UNMAP;
1650 event->any.window = window;
1652 if (gdk_xgrab_window == window_private)
1653 gdk_xgrab_window = NULL;
1658 /* Print debugging info.
1661 g_message ("map notify:\t\twindow: %ld",
1662 xevent->xmap.window));
1664 event->any.type = GDK_MAP;
1665 event->any.window = window;
1669 case ReparentNotify:
1670 /* Print debugging info.
1673 g_message ("reparent notify:\twindow: %ld x,y: %d %d parent: %ld ovr: %d",
1674 xevent->xreparent.window,
1675 xevent->xreparent.x,
1676 xevent->xreparent.y,
1677 xevent->xreparent.parent,
1678 xevent->xreparent.override_redirect));
1680 /* Not currently handled */
1684 case ConfigureNotify:
1685 /* Print debugging info.
1688 g_message ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d%s",
1689 xevent->xconfigure.window,
1690 xevent->xconfigure.x,
1691 xevent->xconfigure.y,
1692 xevent->xconfigure.width,
1693 xevent->xconfigure.height,
1694 xevent->xconfigure.border_width,
1695 xevent->xconfigure.above,
1696 xevent->xconfigure.override_redirect,
1699 : GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_CHILD
1700 ? " (discarding child)"
1703 !GDK_DRAWABLE_DESTROYED (window) &&
1704 (window_private->extension_events != 0) &&
1705 gdk_input_vtable.configure_event)
1706 gdk_input_vtable.configure_event (&xevent->xconfigure, window);
1708 if (!window || GDK_DRAWABLE_TYPE (window) == GDK_WINDOW_CHILD)
1712 event->configure.type = GDK_CONFIGURE;
1713 event->configure.window = window;
1714 event->configure.width = xevent->xconfigure.width;
1715 event->configure.height = xevent->xconfigure.height;
1717 if (!xevent->xconfigure.x &&
1718 !xevent->xconfigure.y &&
1719 !GDK_DRAWABLE_DESTROYED (window))
1723 Window child_window = 0;
1725 gdk_error_trap_push ();
1726 if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
1727 GDK_DRAWABLE_XID (window),
1733 if (!gdk_error_trap_pop ())
1735 event->configure.x = tx;
1736 event->configure.y = ty;
1740 gdk_error_trap_pop ();
1744 event->configure.x = xevent->xconfigure.x;
1745 event->configure.y = xevent->xconfigure.y;
1747 window_private->x = event->configure.x;
1748 window_private->y = event->configure.y;
1749 window_private->drawable.width = xevent->xconfigure.width;
1750 window_private->drawable.height = xevent->xconfigure.height;
1751 if (window_private->resize_count > 1)
1752 window_private->resize_count -= 1;
1756 case PropertyNotify:
1757 /* Print debugging info.
1760 gchar *atom = gdk_atom_name (xevent->xproperty.atom);
1761 g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
1762 xevent->xproperty.window,
1763 xevent->xproperty.atom,
1765 atom ? atom : "unknown",
1770 event->property.type = GDK_PROPERTY_NOTIFY;
1771 event->property.window = window;
1772 event->property.atom = xevent->xproperty.atom;
1773 event->property.time = xevent->xproperty.time;
1774 event->property.state = xevent->xproperty.state;
1778 case SelectionClear:
1780 g_message ("selection clear:\twindow: %ld",
1781 xevent->xproperty.window));
1783 event->selection.type = GDK_SELECTION_CLEAR;
1784 event->selection.window = window;
1785 event->selection.selection = xevent->xselectionclear.selection;
1786 event->selection.time = xevent->xselectionclear.time;
1790 case SelectionRequest:
1792 g_message ("selection request:\twindow: %ld",
1793 xevent->xproperty.window));
1795 event->selection.type = GDK_SELECTION_REQUEST;
1796 event->selection.window = window;
1797 event->selection.selection = xevent->xselectionrequest.selection;
1798 event->selection.target = xevent->xselectionrequest.target;
1799 event->selection.property = xevent->xselectionrequest.property;
1800 event->selection.requestor = xevent->xselectionrequest.requestor;
1801 event->selection.time = xevent->xselectionrequest.time;
1805 case SelectionNotify:
1807 g_message ("selection notify:\twindow: %ld",
1808 xevent->xproperty.window));
1811 event->selection.type = GDK_SELECTION_NOTIFY;
1812 event->selection.window = window;
1813 event->selection.selection = xevent->xselection.selection;
1814 event->selection.target = xevent->xselection.target;
1815 event->selection.property = xevent->xselection.property;
1816 event->selection.time = xevent->xselection.time;
1820 case ColormapNotify:
1821 /* Print debugging info.
1824 g_message ("colormap notify:\twindow: %ld",
1825 xevent->xcolormap.window));
1827 /* Not currently handled */
1834 GdkFilterReturn result = GDK_FILTER_CONTINUE;
1836 /* Print debugging info.
1839 g_message ("client message:\twindow: %ld",
1840 xevent->xclient.window));
1842 tmp_list = client_filters;
1845 GdkClientFilter *filter = tmp_list->data;
1846 if (filter->type == xevent->xclient.message_type)
1848 result = (*filter->function) (xevent, event, filter->data);
1852 tmp_list = tmp_list->next;
1857 case GDK_FILTER_REMOVE:
1860 case GDK_FILTER_TRANSLATE:
1863 case GDK_FILTER_CONTINUE:
1864 /* Send unknown ClientMessage's on to Gtk for it to use */
1865 event->client.type = GDK_CLIENT_EVENT;
1866 event->client.window = window;
1867 event->client.message_type = xevent->xclient.message_type;
1868 event->client.data_format = xevent->xclient.format;
1869 memcpy(&event->client.data, &xevent->xclient.data,
1870 sizeof(event->client.data));
1877 /* Print debugging info.
1880 g_message ("mapping notify"));
1882 /* Let XLib know that there is a new keyboard mapping.
1884 XRefreshKeyboardMapping (&xevent->xmapping);
1889 /* something else - (e.g., a Xinput event) */
1891 if (window_private &&
1892 !window_private->drawable.destroyed &&
1893 (window_private->extension_events != 0) &&
1894 gdk_input_vtable.other_event)
1895 return_val = gdk_input_vtable.other_event(event, xevent, window);
1904 if (event->any.window)
1905 gdk_window_ref (event->any.window);
1906 if (((event->any.type == GDK_ENTER_NOTIFY) ||
1907 (event->any.type == GDK_LEAVE_NOTIFY)) &&
1908 (event->crossing.subwindow != NULL))
1909 gdk_window_ref (event->crossing.subwindow);
1913 /* Mark this event as having no resources to be freed */
1914 event->any.window = NULL;
1915 event->any.type = GDK_NOTHING;
1919 gdk_window_unref (window);
1925 gdk_wm_protocols_filter (GdkXEvent *xev,
1929 XEvent *xevent = (XEvent *)xev;
1931 if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
1933 /* The delete window request specifies a window
1934 * to delete. We don't actually destroy the
1935 * window because "it is only a request". (The
1936 * window might contain vital data that the
1937 * program does not want destroyed). Instead
1938 * the event is passed along to the program,
1939 * which should then destroy the window.
1942 g_message ("delete window:\t\twindow: %ld",
1943 xevent->xclient.window));
1945 event->any.type = GDK_DELETE;
1947 return GDK_FILTER_TRANSLATE;
1949 else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
1953 return GDK_FILTER_REMOVE;
1958 gdk_event_get_type (Display *display,
1965 if (gdk_event_translate (&event, xevent))
1967 pred = (GdkPredicate*) arg;
1968 return (* pred->func) (&event, pred->data);
1976 gdk_events_queue (void)
1982 while (!gdk_event_queue_find_first() && XPending (gdk_display))
1987 XNextEvent (gdk_display, &xevent);
1989 switch (xevent.type)
1995 w = GDK_WINDOW_XWINDOW (gdk_xim_window);
1999 if (XFilterEvent (&xevent, w))
2002 XNextEvent (gdk_display, &xevent);
2005 event = gdk_event_new ();
2007 event->any.type = GDK_NOTHING;
2008 event->any.window = NULL;
2009 event->any.send_event = xevent.xany.send_event ? TRUE : FALSE;
2011 ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
2013 gdk_event_queue_append (event);
2016 if (gdk_event_translate (event, &xevent))
2018 ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
2022 gdk_event_queue_remove_link (node);
2023 g_list_free_1 (node);
2024 gdk_event_free (event);
2030 gdk_event_prepare (gpointer source_data,
2031 GTimeVal *current_time,
2037 GDK_THREADS_ENTER ();
2041 retval = (gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
2043 GDK_THREADS_LEAVE ();
2049 gdk_event_check (gpointer source_data,
2050 GTimeVal *current_time,
2055 GDK_THREADS_ENTER ();
2057 if (event_poll_fd.revents & G_IO_IN)
2058 retval = (gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
2062 GDK_THREADS_LEAVE ();
2068 gdk_event_unqueue (void)
2070 GdkEvent *event = NULL;
2073 tmp_list = gdk_event_queue_find_first ();
2077 event = tmp_list->data;
2078 gdk_event_queue_remove_link (tmp_list);
2079 g_list_free_1 (tmp_list);
2086 gdk_event_dispatch (gpointer source_data,
2087 GTimeVal *current_time,
2092 GDK_THREADS_ENTER ();
2095 event = gdk_event_unqueue();
2100 (*event_func) (event, event_data);
2102 gdk_event_free (event);
2105 GDK_THREADS_LEAVE ();
2111 gdk_synthesize_click (GdkEvent *event,
2114 GdkEvent temp_event;
2116 g_return_if_fail (event != NULL);
2118 temp_event = *event;
2119 temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2121 gdk_event_put (&temp_event);
2124 /* Sends a ClientMessage to all toplevel client windows */
2126 gdk_event_send_client_message (GdkEvent *event, guint32 xid)
2130 g_return_val_if_fail(event != NULL, FALSE);
2132 /* Set up our event to send, with the exception of its target window */
2133 sev.xclient.type = ClientMessage;
2134 sev.xclient.display = gdk_display;
2135 sev.xclient.format = event->client.data_format;
2136 sev.xclient.window = xid;
2137 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
2138 sev.xclient.message_type = event->client.message_type;
2140 return gdk_send_xevent (xid, False, NoEventMask, &sev);
2143 /* Sends a ClientMessage to all toplevel client windows */
2145 gdk_event_send_client_message_to_all_recurse (XEvent *xev,
2149 static GdkAtom wm_state_atom = GDK_NONE;
2152 unsigned long nitems, after;
2153 unsigned char *data;
2154 Window *ret_children, ret_root, ret_parent;
2155 unsigned int ret_nchildren;
2156 gint old_warnings = gdk_error_warnings;
2157 gboolean send = FALSE;
2158 gboolean found = FALSE;
2162 wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
2164 gdk_error_warnings = FALSE;
2166 XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
2167 &type, &format, &nitems, &after, &data);
2171 gdk_error_warnings = old_warnings;
2183 /* OK, we're all set, now let's find some windows to send this to */
2184 if (XQueryTree (gdk_display, xid, &ret_root, &ret_parent,
2185 &ret_children, &ret_nchildren) != True ||
2188 gdk_error_warnings = old_warnings;
2193 for(i = 0; i < ret_nchildren; i++)
2194 if (gdk_event_send_client_message_to_all_recurse (xev, ret_children[i], level + 1))
2197 XFree (ret_children);
2200 if (send || (!found && (level == 1)))
2202 xev->xclient.window = xid;
2203 gdk_send_xevent (xid, False, NoEventMask, xev);
2206 gdk_error_warnings = old_warnings;
2208 return (send || found);
2212 gdk_event_send_clientmessage_toall (GdkEvent *event)
2215 gint old_warnings = gdk_error_warnings;
2217 g_return_if_fail(event != NULL);
2219 /* Set up our event to send, with the exception of its target window */
2220 sev.xclient.type = ClientMessage;
2221 sev.xclient.display = gdk_display;
2222 sev.xclient.format = event->client.data_format;
2223 memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
2224 sev.xclient.message_type = event->client.message_type;
2226 gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
2228 gdk_error_warnings = old_warnings;
2232 *--------------------------------------------------------------
2235 * Flushes the Xlib output buffer and then waits
2236 * until all requests have been received and processed
2237 * by the X server. The only real use for this function
2238 * is in dealing with XShm.
2246 *--------------------------------------------------------------
2252 XSync (gdk_display, False);