summaryrefslogtreecommitdiff
path: root/gdk/gdkevents.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>1998-12-15 13:54:20 +0000
committerOwen Taylor <otaylor@src.gnome.org>1998-12-15 13:54:20 +0000
commita2fc714adb56de007954c13941abde62ac47550c (patch)
treec49a1898051867bcae15a87b4fa44a858a771a7a /gdk/gdkevents.c
parenta0c84d6818f278d273b43c651c345f2110bc7f37 (diff)
downloadgtk+-a2fc714adb56de007954c13941abde62ac47550c.tar.gz
Remove gdk_signal, which crept back in in last commit.
Tue Dec 15 08:53:38 1998 Owen Taylor <otaylor@redhat.com> * gdk/gdk.c (gdk_get_display): Remove gdk_signal, which crept back in in last commit. gdk/gdkevents.c: File missed on last commit. CVS
Diffstat (limited to 'gdk/gdkevents.c')
-rw-r--r--gdk/gdkevents.c2055
1 files changed, 2055 insertions, 0 deletions
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
new file mode 100644
index 0000000000..9a270667bb
--- /dev/null
+++ b/gdk/gdkevents.c
@@ -0,0 +1,2055 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gdk.h"
+#include "gdkx.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+#include "gdkkeysyms.h"
+
+typedef struct _GdkIOClosure GdkIOClosure;
+
+#define DOUBLE_CLICK_TIME 250
+#define TRIPLE_CLICK_TIME 500
+#define DOUBLE_CLICK_DIST 5
+#define TRIPLE_CLICK_DIST 5
+
+struct _GdkIOClosure {
+ GdkInputFunction function;
+ GdkInputCondition condition;
+ GdkDestroyNotify notify;
+ gpointer data;
+};
+
+/*
+ * Private function declarations
+ */
+
+static GdkEvent *gdk_event_new (void);
+static gint gdk_event_apply_filters (XEvent *xevent,
+ GdkEvent *event,
+ GList *filters);
+static gint gdk_event_translate (GdkEvent *event,
+ XEvent *xevent);
+#if 0
+static Bool gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg);
+#endif
+static void gdk_events_queue (void);
+
+static gboolean gdk_event_prepare (gpointer source_data,
+ GTimeVal *current_time,
+ gint *timeout);
+static gboolean gdk_event_check (gpointer source_data,
+ GTimeVal *current_time);
+static gboolean gdk_event_dispatch (gpointer source_data,
+ GTimeVal *current_time,
+ gpointer user_data);
+
+static void gdk_synthesize_click (GdkEvent *event,
+ gint nclicks);
+
+GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
+ GdkEvent *event,
+ gpointer data);
+
+/* Private variable declarations
+ */
+
+static int connection_number = 0; /* The file descriptor number of our
+ * connection to the X server. This
+ * is used so that we may determine
+ * when events are pending by using
+ * the "select" system call.
+ */
+static guint32 button_click_time[2]; /* The last 2 button click times. Used
+ * to determine if the latest button click
+ * is part of a double or triple click.
+ */
+static GdkWindow *button_window[2]; /* The last 2 windows to receive button presses.
+ * Also used to determine if the latest button
+ * click is part of a double or triple click.
+ */
+static guint button_number[2]; /* The last 2 buttons to be pressed.
+ */
+static GdkEventFunc event_func; /* Callback for events */
+static gpointer event_data;
+static GDestroyNotify event_notify;
+
+static GList *client_filters; /* Filters for client messages */
+
+static GList *queued_events = NULL;
+
+static GSourceFuncs event_funcs = {
+ gdk_event_prepare,
+ gdk_event_check,
+ gdk_event_dispatch,
+ (GDestroyNotify)g_free
+};
+
+GPollFD event_poll_fd;
+
+void
+gdk_events_init (void)
+{
+ connection_number = ConnectionNumber (gdk_display);
+ GDK_NOTE (MISC,
+ g_message ("connection number: %d", connection_number));
+
+ g_source_add (-10, TRUE, &event_funcs, NULL, NULL, NULL);
+
+ event_poll_fd.fd = connection_number;
+ event_poll_fd.events = G_IO_IN;
+
+ g_main_poll_add (-10, &event_poll_fd);
+
+ /* This is really crappy. We have to look into the display structure
+ * to find the base resource id. This is only needed for recording
+ * and playback of events.
+ */
+ button_click_time[0] = 0;
+ button_click_time[1] = 0;
+ button_window[0] = NULL;
+ button_window[1] = NULL;
+ button_number[0] = -1;
+ button_number[1] = -1;
+
+ gdk_add_client_message_filter (gdk_wm_protocols,
+ gdk_wm_protocols_filter, NULL);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_events_pending
+ *
+ * Returns if events are pending on the queue.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns TRUE if events are pending
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_events_pending (void)
+{
+ return g_main_pending();
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_get_graphics_expose
+ *
+ * Waits for a GraphicsExpose or NoExpose event
+ *
+ * Arguments:
+ *
+ * Results:
+ * For GraphicsExpose events, returns a pointer to the event
+ * converted into a GdkEvent Otherwise, returns NULL.
+ *
+ * Side effects:
+ *
+ *-------------------------------------------------------------- */
+
+static Bool
+graphics_expose_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)arg;
+
+ g_return_val_if_fail (private != NULL, False);
+
+ if ((xevent->xany.window == private->xwindow) &&
+ ((xevent->xany.type == GraphicsExpose) ||
+ (xevent->xany.type == NoExpose)))
+ return True;
+ else
+ return False;
+}
+
+GdkEvent *
+gdk_event_get_graphics_expose (GdkWindow *window)
+{
+ XEvent xevent;
+ GdkEvent *event;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer)window);
+
+ if (xevent.xany.type == GraphicsExpose)
+ {
+ event = gdk_event_new ();
+
+ if (gdk_event_translate (event, &xevent))
+ return event;
+ else
+ gdk_event_free (event);
+ }
+
+ return NULL;
+}
+
+/************************
+ * Exposure compression *
+ ************************/
+
+/*
+ * The following implements simple exposure compression. It is
+ * modelled after the way Xt does exposure compression - in
+ * particular compress_expose = XtExposeCompressMultiple.
+ * It compress consecutive sequences of exposure events,
+ * but not sequences that cross other events. (This is because
+ * if it crosses a ConfigureNotify, we could screw up and
+ * mistakenly compress the exposures generated for the new
+ * size - could we just check for ConfigureNotify?)
+ *
+ * Xt compresses to a region / bounding rectangle, we compress
+ * to two rectangles, and try find the two rectangles of minimal
+ * area for this - this is supposed to handle the typical
+ * L-shaped regions generated by OpaqueMove.
+ */
+
+/* Given three rectangles, find the two rectangles that cover
+ * them with the smallest area.
+ */
+static void
+gdk_add_rect_to_rects (GdkRectangle *rect1,
+ GdkRectangle *rect2,
+ GdkRectangle *new_rect)
+{
+ GdkRectangle t1, t2, t3;
+ gint size1, size2, size3;
+
+ gdk_rectangle_union (rect1, rect2, &t1);
+ gdk_rectangle_union (rect1, new_rect, &t2);
+ gdk_rectangle_union (rect2, new_rect, &t3);
+
+ size1 = t1.width * t1.height + new_rect->width * new_rect->height;
+ size2 = t2.width * t2.height + rect2->width * rect2->height;
+ size3 = t1.width * t1.height + rect1->width * rect1->height;
+
+ if (size1 < size2)
+ {
+ if (size1 < size3)
+ {
+ *rect1 = t1;
+ *rect2 = *new_rect;
+ }
+ else
+ *rect2 = t3;
+ }
+ else
+ {
+ if (size2 < size3)
+ *rect1 = t2;
+ else
+ *rect2 = t3;
+ }
+}
+
+typedef struct _GdkExposeInfo GdkExposeInfo;
+
+struct _GdkExposeInfo {
+ Window window;
+ gboolean seen_nonmatching;
+};
+
+Bool
+expose_predicate (Display *display, XEvent *xevent, XPointer arg)
+{
+ GdkExposeInfo *info = (GdkExposeInfo *)arg;
+
+ if (xevent->xany.type != Expose)
+ {
+ info->seen_nonmatching = TRUE;
+ }
+
+ if (info->seen_nonmatching || (xevent->xany.window != info->window))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void
+gdk_compress_exposures (XEvent *xevent, GdkWindow *window)
+{
+ gint nrects = 1;
+ gint count = 0;
+ GdkRectangle rect1;
+ GdkRectangle rect2;
+ GdkRectangle tmp_rect;
+ XEvent tmp_event;
+ GdkFilterReturn result;
+ GdkExposeInfo info;
+ GdkEvent event;
+
+ info.window = xevent->xany.window;
+ info.seen_nonmatching = FALSE;
+
+ rect1.x = xevent->xexpose.x;
+ rect1.y = xevent->xexpose.y;
+ rect1.width = xevent->xexpose.width;
+ rect1.height = xevent->xexpose.height;
+
+ while (1)
+ {
+ if (count == 0)
+ {
+ if (!XCheckIfEvent (gdk_display,
+ &tmp_event,
+ expose_predicate,
+ (XPointer)&info))
+ break;
+ }
+ else
+ XIfEvent (gdk_display,
+ &tmp_event,
+ expose_predicate,
+ (XPointer)&info);
+
+ /* We apply filters here, and if it was filtered, completely
+ * ignore the return
+ */
+ result = gdk_event_apply_filters (xevent, &event,
+ window ?
+ ((GdkWindowPrivate *)window)->filters
+ : gdk_default_filters);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ if (result == GDK_FILTER_TRANSLATE)
+ gdk_event_put (&event);
+ continue;
+ }
+
+ if (nrects == 1)
+ {
+ rect2.x = tmp_event.xexpose.x;
+ rect2.y = tmp_event.xexpose.y;
+ rect2.width = tmp_event.xexpose.width;
+ rect2.height = tmp_event.xexpose.height;
+
+ nrects++;
+ }
+ else
+ {
+ tmp_rect.x = tmp_event.xexpose.x;
+ tmp_rect.y = tmp_event.xexpose.y;
+ tmp_rect.width = tmp_event.xexpose.width;
+ tmp_rect.height = tmp_event.xexpose.height;
+
+ gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
+ }
+
+ count = tmp_event.xexpose.count;
+ }
+
+ if (nrects == 2)
+ {
+ gdk_rectangle_union (&rect1, &rect2, &tmp_rect);
+
+ if ((tmp_rect.width * tmp_rect.height) <
+ 2 * (rect1.height * rect1.width +
+ rect2.height * rect2.width))
+ {
+ rect1 = tmp_rect;
+ nrects = 1;
+ }
+ }
+
+ if (nrects == 2)
+ {
+ event.expose.type = GDK_EXPOSE;
+ event.expose.window = window;
+ event.expose.area.x = rect2.x;
+ event.expose.area.y = rect2.y;
+ event.expose.area.width = rect2.width;
+ event.expose.area.height = rect2.height;
+ event.expose.count = 0;
+
+ gdk_event_put (&event);
+ }
+
+ xevent->xexpose.count = nrects - 1;
+ xevent->xexpose.x = rect1.x;
+ xevent->xexpose.y = rect1.y;
+ xevent->xexpose.width = rect1.width;
+ xevent->xexpose.height = rect1.height;
+}
+
+/*************************************************************
+ * gdk_event_handler_set:
+ *
+ * arguments:
+ * func: Callback function to be called for each event.
+ * data: Data supplied to the function
+ * notify: function called when function is no longer needed
+ *
+ * results:
+ *************************************************************/
+
+void
+gdk_event_handler_set (GdkEventFunc func,
+ gpointer data,
+ GDestroyNotify notify)
+{
+ if (event_func && event_notify)
+ (*event_notify) (event_data);
+
+ event_func = func;
+ event_data = data;
+ event_notify = notify;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_get
+ *
+ * Gets the next event.
+ *
+ * Arguments:
+ *
+ * Results:
+ * If an event was received that we care about, returns
+ * a pointer to that event, to be freed with gdk_event_free.
+ * Otherwise, returns NULL. This function will also return
+ * before an event is received if the timeout interval
+ * runs out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+GdkEvent *
+gdk_event_get (void)
+{
+ GdkEvent *event;
+ GList *temp_list;
+
+ gdk_events_queue();
+
+ if (queued_events)
+ {
+ event = queued_events->data;
+
+ temp_list = queued_events;
+ queued_events = g_list_remove_link (queued_events, temp_list);
+ g_list_free_1 (temp_list);
+
+ return event;
+ }
+ else
+ return NULL;
+}
+
+void
+gdk_event_put (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_if_fail (event != NULL);
+
+ new_event = gdk_event_copy (event);
+
+ queued_events = g_list_prepend (queued_events, new_event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_copy
+ *
+ * Copy a event structure into new storage.
+ *
+ * Arguments:
+ * "event" is the event struct to copy.
+ *
+ * Results:
+ * A new event structure. Free it with gdk_event_free.
+ *
+ * Side effects:
+ * The reference count of the window in the event is increased.
+ *
+ *--------------------------------------------------------------
+ */
+
+static GMemChunk *event_chunk;
+
+static GdkEvent*
+gdk_event_new (void)
+{
+ GdkEvent *new_event;
+
+ if (event_chunk == NULL)
+ event_chunk = g_mem_chunk_new ("events",
+ sizeof (GdkEvent),
+ 4096,
+ G_ALLOC_AND_FREE);
+
+ new_event = g_chunk_new (GdkEvent, event_chunk);
+
+ return new_event;
+}
+
+GdkEvent*
+gdk_event_copy (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_val_if_fail (event != NULL, NULL);
+
+ new_event = gdk_event_new ();
+
+ *new_event = *event;
+ gdk_window_ref (new_event->any.window);
+
+ switch (event->any.type)
+ {
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ new_event->key.string = g_strdup (event->key.string);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ if (event->crossing.subwindow != NULL)
+ gdk_window_ref (event->crossing.subwindow);
+ break;
+
+ case GDK_DRAG_ENTER:
+ case GDK_DRAG_LEAVE:
+ case GDK_DRAG_MOTION:
+ case GDK_DRAG_STATUS:
+ case GDK_DROP_START:
+ case GDK_DROP_FINISHED:
+ gdk_drag_context_ref (event->dnd.context);
+ break;
+
+
+ default:
+ break;
+ }
+
+ return new_event;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_free
+ *
+ * Free a event structure obtained from gdk_event_copy. Do not use
+ * with other event structures.
+ *
+ * Arguments:
+ * "event" is the event struct to free.
+ *
+ * Results:
+ *
+ * Side effects:
+ * The reference count of the window in the event is decreased and
+ * might be freed, too.
+ *
+ *-------------------------------------------------------------- */
+
+void
+gdk_event_free (GdkEvent *event)
+{
+ g_assert (event_chunk != NULL);
+ g_return_if_fail (event != NULL);
+
+ if (event->any.window)
+ gdk_window_unref (event->any.window);
+
+ switch (event->any.type)
+ {
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ g_free (event->key.string);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ if (event->crossing.subwindow != NULL)
+ gdk_window_unref (event->crossing.subwindow);
+ break;
+
+ case GDK_DRAG_ENTER:
+ case GDK_DRAG_LEAVE:
+ case GDK_DRAG_MOTION:
+ case GDK_DRAG_STATUS:
+ case GDK_DROP_START:
+ case GDK_DROP_FINISHED:
+ gdk_drag_context_unref (event->dnd.context);
+ break;
+
+
+ default:
+ break;
+ }
+
+ g_mem_chunk_free (event_chunk, event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_get_time:
+ * Get the timestamp from an event.
+ * arguments:
+ * event:
+ * results:
+ * The event's time stamp, if it has one, otherwise
+ * GDK_CURRENT_TIME.
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_event_get_time (GdkEvent *event)
+{
+ if (event)
+ switch (event->type)
+ {
+ case GDK_MOTION_NOTIFY:
+ return event->motion.time;
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ return event->button.time;
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ return event->key.time;
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ return event->crossing.time;
+ case GDK_PROPERTY_NOTIFY:
+ return event->property.time;
+ case GDK_SELECTION_CLEAR:
+ case GDK_SELECTION_REQUEST:
+ case GDK_SELECTION_NOTIFY:
+ return event->selection.time;
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ return event->proximity.time;
+ case GDK_DRAG_ENTER:
+ case GDK_DRAG_LEAVE:
+ case GDK_DRAG_MOTION:
+ case GDK_DRAG_STATUS:
+ case GDK_DROP_START:
+ case GDK_DROP_FINISHED:
+ return event->dnd.time;
+ default: /* use current time */
+ break;
+ }
+
+ return GDK_CURRENT_TIME;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_show_events
+ *
+ * Turns on/off the showing of events.
+ *
+ * Arguments:
+ * "show_events" is a boolean describing whether or
+ * not to show the events gdk receives.
+ *
+ * Results:
+ *
+ * Side effects:
+ * When "show_events" is TRUE, calls to "gdk_event_get"
+ * will output debugging informatin regarding the event
+ * received to stdout.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_set_show_events (int show_events)
+{
+ if (show_events)
+ gdk_debug_flags |= GDK_DEBUG_EVENTS;
+ else
+ gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
+}
+
+gint
+gdk_get_show_events (void)
+{
+ return gdk_debug_flags & GDK_DEBUG_EVENTS;
+}
+
+static void
+gdk_io_destroy (gpointer data)
+{
+ GdkIOClosure *closure = data;
+
+ if (closure->notify)
+ closure->notify (closure->data);
+
+ g_free (closure);
+}
+
+static gboolean
+gdk_io_invoke (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ GdkIOClosure *closure = data;
+ GdkInputCondition gdk_cond = 0;
+
+ if (condition & (G_IO_IN | G_IO_PRI))
+ gdk_cond |= GDK_INPUT_READ;
+ if (condition & G_IO_OUT)
+ gdk_cond |= GDK_INPUT_WRITE;
+ if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
+ gdk_cond |= GDK_INPUT_EXCEPTION;
+
+ if (closure->condition & gdk_cond)
+ closure->function (closure->data, g_io_channel_unix_get_fd (source), gdk_cond);
+
+ return TRUE;
+}
+
+gint
+gdk_input_add_full (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data,
+ GdkDestroyNotify destroy)
+{
+ guint result;
+ GdkIOClosure *closure = g_new (GdkIOClosure, 1);
+ GIOChannel *channel;
+ GIOCondition cond = 0;
+
+ closure->function = function;
+ closure->condition = condition;
+ closure->notify = destroy;
+ closure->data = data;
+
+ if (condition & GDK_INPUT_READ)
+ cond |= (G_IO_IN | G_IO_PRI);
+ if (condition & GDK_INPUT_WRITE)
+ cond |= G_IO_OUT;
+ /* The things that correspond to GDK_INPUT_EXCEPTION don't
+ * need to be added to events
+ */
+
+ channel = g_io_channel_unix_new (source);
+ result = g_io_add_watch_full (channel, 0, cond, gdk_io_invoke,
+ closure, gdk_io_destroy);
+ g_io_channel_unref (channel);
+
+ return result;
+}
+
+gint
+gdk_input_add (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data)
+{
+ return gdk_input_add_full (source, condition, function, data, NULL);
+}
+
+void
+gdk_input_remove (gint tag)
+{
+ g_source_remove (tag);
+}
+
+static gint
+gdk_event_apply_filters (XEvent *xevent,
+ GdkEvent *event,
+ GList *filters)
+{
+ GdkEventFilter *filter;
+ GList *tmp_list;
+ GdkFilterReturn result;
+
+ tmp_list = filters;
+
+ while (tmp_list)
+ {
+ filter = (GdkEventFilter *)tmp_list->data;
+
+ result = (*filter->function)(xevent, event, filter->data);
+ if (result != GDK_FILTER_CONTINUE)
+ return result;
+
+ tmp_list = tmp_list->next;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+void
+gdk_add_client_message_filter (GdkAtom message_type,
+ GdkFilterFunc func,
+ gpointer data)
+{
+ GdkClientFilter *filter = g_new (GdkClientFilter, 1);
+
+ filter->type = message_type;
+ filter->function = func;
+ filter->data = data;
+
+ client_filters = g_list_prepend (client_filters, filter);
+}
+
+static gint
+gdk_event_translate (GdkEvent *event,
+ XEvent *xevent)
+{
+
+ GdkWindow *window;
+ GdkWindowPrivate *window_private;
+ static XComposeStatus compose;
+ KeySym keysym;
+ int charcount;
+#ifdef USE_XIM
+ static gchar* buf = NULL;
+ static gint buf_len= 0;
+#else
+ char buf[16];
+#endif
+ gint return_val;
+
+ return_val = FALSE;
+
+ /* Find the GdkWindow that this event occurred in.
+ *
+ * We handle events with window=None
+ * specially - they are generated by XFree86's XInput under
+ * some circumstances.
+ */
+
+ if ((xevent->xany.window == None) &&
+ gdk_input_vtable.window_none_event)
+ {
+ return_val = gdk_input_vtable.window_none_event (event,xevent);
+
+ if (return_val >= 0) /* was handled */
+ return return_val;
+ else
+ return_val = FALSE;
+ }
+
+ window = gdk_window_lookup (xevent->xany.window);
+ window_private = (GdkWindowPrivate *) window;
+
+ if (window != NULL)
+ gdk_window_ref (window);
+
+ event->any.window = window;
+ event->any.send_event = xevent->xany.send_event;
+
+ if (window_private && window_private->destroyed)
+ {
+ if (xevent->type != DestroyNotify)
+ return FALSE;
+ }
+ else
+ {
+ /* Check for filters for this window
+ */
+ GdkFilterReturn result;
+ result = gdk_event_apply_filters (xevent, event,
+ window_private
+ ?window_private->filters
+ :gdk_default_filters);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ }
+ }
+
+#ifdef USE_XIM
+ if (window == NULL && gdk_xim_window && xevent->type == KeyPress &&
+ !((GdkWindowPrivate *) gdk_xim_window)->destroyed)
+ {
+ /*
+ * If user presses a key in Preedit or Status window, keypress event
+ * is sometimes sent to these windows. These windows are not managed
+ * by GDK, so we redirect KeyPress event to xim_window.
+ *
+ * If someone want to use the window whitch is not managed by GDK
+ * and want to get KeyPress event, he/she must register the filter
+ * function to gdk_default_filters to intercept the event.
+ */
+
+ GdkFilterReturn result;
+
+ window = gdk_xim_window;
+ window_private = (GdkWindowPrivate *) window;
+ gdk_window_ref (window);
+ event->any.window = window;
+
+ GDK_NOTE (XIM,
+ g_message ("KeyPress event is redirected to xim_window: %#lx",
+ xevent->xany.window));
+
+ result = gdk_event_apply_filters (xevent, event,
+ window_private->filters);
+ if (result != GDK_FILTER_CONTINUE)
+ return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ }
+#endif
+
+ if (window == NULL)
+ g_message ("Got event for unknown window: %#lx\n", xevent->xany.window);
+
+ /* We do a "manual" conversion of the XEvent to a
+ * GdkEvent. The structures are mostly the same so
+ * the conversion is fairly straightforward. We also
+ * optionally print debugging info regarding events
+ * received.
+ */
+
+ return_val = TRUE;
+
+ switch (xevent->type)
+ {
+ case KeyPress:
+ /* Lookup the string corresponding to the given keysym.
+ */
+
+#ifdef USE_XIM
+ if (buf_len == 0)
+ {
+ buf_len = 128;
+ buf = g_new (gchar, buf_len);
+ }
+ keysym = GDK_VoidSymbol;
+
+ if (gdk_xim_ic && gdk_xim_ic->xic)
+ {
+ Status status;
+
+ /* Clear keyval. Depending on status, may not be set */
+ charcount = XmbLookupString(gdk_xim_ic->xic,
+ &xevent->xkey, buf, buf_len-1,
+ &keysym, &status);
+ if (status == XBufferOverflow)
+ { /* retry */
+ /* alloc adequate size of buffer */
+ GDK_NOTE (XIM,
+ g_message("XIM: overflow (required %i)", charcount));
+
+ while (buf_len <= charcount)
+ buf_len *= 2;
+ buf = (gchar *) g_realloc (buf, buf_len);
+
+ charcount = XmbLookupString (gdk_xim_ic->xic,
+ &xevent->xkey, buf, buf_len-1,
+ &keysym, &status);
+ }
+ if (status == XLookupNone)
+ {
+ return_val = FALSE;
+ break;
+ }
+ }
+ else
+ charcount = XLookupString (&xevent->xkey, buf, buf_len,
+ &keysym, &compose);
+#else
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ &keysym, &compose);
+#endif
+ event->key.keyval = keysym;
+
+ if (charcount > 0 && buf[charcount-1] == '\0')
+ charcount --;
+ else
+ buf[charcount] = '\0';
+
+ /* Print debugging info. */
+
+#ifdef G_ENABLE_DEBUG
+ if (gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ g_message ("key press:\twindow: %ld key: %12s %d",
+ xevent->xkey.window,
+ event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
+ event->key.keyval);
+ if (charcount > 0)
+ g_message ("\t\tlength: %4d string: \"%s\"",
+ charcount, buf);
+ }
+#endif /* G_ENABLE_DEBUG */
+
+ event->key.type = GDK_KEY_PRESS;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.string = g_strdup (buf);
+ event->key.length = charcount;
+
+ break;
+
+ case KeyRelease:
+ /* Lookup the string corresponding to the given keysym.
+ */
+#ifdef USE_XIM
+ if (buf_len == 0)
+ {
+ buf_len = 128;
+ buf = g_new (gchar, buf_len);
+ }
+#endif
+ keysym = GDK_VoidSymbol;
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ &keysym, &compose);
+ event->key.keyval = keysym;
+
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("key release:\t\twindow: %ld key: %12s %d",
+ xevent->xkey.window,
+ XKeysymToString (event->key.keyval),
+ event->key.keyval));
+
+ event->key.type = GDK_KEY_RELEASE;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.length = 0;
+ event->key.string = NULL;
+
+ break;
+
+ case ButtonPress:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
+ xevent->xbutton.window,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button));
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->button.type = GDK_BUTTON_PRESS;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.x_root = (gfloat)xevent->xbutton.x_root;
+ event->button.y_root = (gfloat)xevent->xbutton.y_root;
+ event->button.pressure = 0.5;
+ event->button.xtilt = 0;
+ event->button.ytilt = 0;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.source = GDK_SOURCE_MOUSE;
+ event->button.deviceid = GDK_CORE_POINTER;
+
+ if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
+ (event->button.window == button_window[1]) &&
+ (event->button.button == button_number[1]))
+ {
+ gdk_synthesize_click (event, 3);
+
+ button_click_time[1] = 0;
+ button_click_time[0] = 0;
+ button_window[1] = NULL;
+ button_window[0] = 0;
+ button_number[1] = -1;
+ button_number[0] = -1;
+ }
+ else if ((event->button.time < (button_click_time[0] + DOUBLE_CLICK_TIME)) &&
+ (event->button.window == button_window[0]) &&
+ (event->button.button == button_number[0]))
+ {
+ gdk_synthesize_click (event, 2);
+
+ button_click_time[1] = button_click_time[0];
+ button_click_time[0] = event->button.time;
+ button_window[1] = button_window[0];
+ button_window[0] = event->button.window;
+ button_number[1] = button_number[0];
+ button_number[0] = event->button.button;
+ }
+ else
+ {
+ button_click_time[1] = 0;
+ button_click_time[0] = event->button.time;
+ button_window[1] = NULL;
+ button_window[0] = event->button.window;
+ button_number[1] = -1;
+ button_number[0] = event->button.button;
+ }
+
+ break;
+
+ case ButtonRelease:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
+ xevent->xbutton.window,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button));
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->button.type = GDK_BUTTON_RELEASE;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
+ event->button.x_root = (gfloat)xevent->xbutton.x_root;
+ event->button.y_root = (gfloat)xevent->xbutton.y_root;
+ event->button.pressure = 0.5;
+ event->button.xtilt = 0;
+ event->button.ytilt = 0;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.source = GDK_SOURCE_MOUSE;
+ event->button.deviceid = GDK_CORE_POINTER;
+
+ break;
+
+ case MotionNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s",
+ xevent->xmotion.window,
+ xevent->xmotion.x, xevent->xmotion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false"));
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = window;
+ event->motion.time = xevent->xmotion.time;
+ event->motion.x = xevent->xmotion.x;
+ event->motion.y = xevent->xmotion.y;
+ event->motion.x_root = (gfloat)xevent->xmotion.x_root;
+ event->motion.y_root = (gfloat)xevent->xmotion.y_root;
+ event->motion.pressure = 0.5;
+ event->motion.xtilt = 0;
+ event->motion.ytilt = 0;
+ event->motion.state = (GdkModifierType) xevent->xmotion.state;
+ event->motion.is_hint = xevent->xmotion.is_hint;
+ event->motion.source = GDK_SOURCE_MOUSE;
+ event->motion.deviceid = GDK_CORE_POINTER;
+
+ break;
+
+ case EnterNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
+ xevent->xcrossing.window,
+ xevent->xcrossing.detail,
+ xevent->xcrossing.subwindow));
+
+ /* Tell XInput stuff about it if appropriate */
+ if (window_private &&
+ !window_private->destroyed &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.enter_event)
+ gdk_input_vtable.enter_event (&xevent->xcrossing, window);
+
+ event->crossing.type = GDK_ENTER_NOTIFY;
+ event->crossing.window = window;
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
+ event->crossing.x_root = xevent->xcrossing.x_root;
+ event->crossing.y_root = xevent->xcrossing.y_root;
+
+ /* Translate the crossing mode into Gdk terms.
+ */
+ switch (xevent->xcrossing.mode)
+ {
+ case NotifyNormal:
+ event->crossing.mode = GDK_CROSSING_NORMAL;
+ break;
+ case NotifyGrab:
+ event->crossing.mode = GDK_CROSSING_GRAB;
+ break;
+ case NotifyUngrab:
+ event->crossing.mode = GDK_CROSSING_UNGRAB;
+ break;
+ };
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+
+ event->crossing.focus = xevent->xcrossing.focus;
+ event->crossing.state = xevent->xcrossing.state;
+
+ break;
+
+ case LeaveNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
+ xevent->xcrossing.window,
+ xevent->xcrossing.detail, xevent->xcrossing.subwindow));
+
+ event->crossing.type = GDK_LEAVE_NOTIFY;
+ event->crossing.window = window;
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup (xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
+ event->crossing.x_root = xevent->xcrossing.x_root;
+ event->crossing.y_root = xevent->xcrossing.y_root;
+
+ /* Translate the crossing mode into Gdk terms.
+ */
+ switch (xevent->xcrossing.mode)
+ {
+ case NotifyNormal:
+ event->crossing.mode = GDK_CROSSING_NORMAL;
+ break;
+ case NotifyGrab:
+ event->crossing.mode = GDK_CROSSING_GRAB;
+ break;
+ case NotifyUngrab:
+ event->crossing.mode = GDK_CROSSING_UNGRAB;
+ break;
+ };
+
+ /* Translate the crossing detail into Gdk terms.
+ */
+ switch (xevent->xcrossing.detail)
+ {
+ case NotifyInferior:
+ event->crossing.detail = GDK_NOTIFY_INFERIOR;
+ break;
+ case NotifyAncestor:
+ event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ break;
+ case NotifyVirtual:
+ event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+ break;
+ case NotifyNonlinear:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+ break;
+ case NotifyNonlinearVirtual:
+ event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ break;
+ default:
+ event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ break;
+ }
+
+ event->crossing.focus = xevent->xcrossing.focus;
+ event->crossing.state = xevent->xcrossing.state;
+
+ break;
+
+ case FocusIn:
+ case FocusOut:
+ /* We only care about focus events that indicate that _this_
+ * window (not a ancestor or child) got or lost the focus
+ */
+ switch (xevent->xfocus.detail)
+ {
+ case NotifyAncestor:
+ case NotifyInferior:
+ case NotifyNonlinear:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("focus %s:\t\twindow: %ld",
+ (xevent->xany.type == FocusIn) ? "in" : "out",
+ xevent->xfocus.window));
+
+ /* gdk_keyboard_grab() causes following events. These events confuse
+ * the XIM focus, so ignore them.
+ */
+ if (xevent->xfocus.mode == NotifyGrab ||
+ xevent->xfocus.mode == NotifyUngrab)
+ break;
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = (xevent->xany.type == FocusIn);
+
+ break;
+ default:
+ return_val = FALSE;
+ }
+ break;
+
+ case KeymapNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("keymap notify"));
+
+ /* Not currently handled */
+ return_val = FALSE;
+ break;
+
+ case Expose:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d",
+ xevent->xexpose.window, xevent->xexpose.count,
+ xevent->xexpose.x, xevent->xexpose.y,
+ xevent->xexpose.width, xevent->xexpose.height));
+ gdk_compress_exposures (xevent, window);
+
+ event->expose.type = GDK_EXPOSE;
+ event->expose.window = window;
+ event->expose.area.x = xevent->xexpose.x;
+ event->expose.area.y = xevent->xexpose.y;
+ event->expose.area.width = xevent->xexpose.width;
+ event->expose.area.height = xevent->xexpose.height;
+ event->expose.count = xevent->xexpose.count;
+
+ break;
+
+ case GraphicsExpose:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("graphics expose:\tdrawable: %ld",
+ xevent->xgraphicsexpose.drawable));
+
+ event->expose.type = GDK_EXPOSE;
+ event->expose.window = window;
+ event->expose.area.x = xevent->xgraphicsexpose.x;
+ event->expose.area.y = xevent->xgraphicsexpose.y;
+ event->expose.area.width = xevent->xgraphicsexpose.width;
+ event->expose.area.height = xevent->xgraphicsexpose.height;
+ event->expose.count = xevent->xexpose.count;
+
+ break;
+
+ case NoExpose:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("no expose:\t\tdrawable: %ld",
+ xevent->xnoexpose.drawable));
+
+ event->no_expose.type = GDK_NO_EXPOSE;
+ event->no_expose.window = window;
+
+ break;
+
+ case VisibilityNotify:
+ /* Print debugging info.
+ */
+#ifdef G_ENABLE_DEBUG
+ if (gdk_debug_flags & GDK_DEBUG_EVENTS)
+ switch (xevent->xvisibility.state)
+ {
+ case VisibilityFullyObscured:
+ g_message ("visibility notify:\twindow: %ld none",
+ xevent->xvisibility.window);
+ break;
+ case VisibilityPartiallyObscured:
+ g_message ("visibility notify:\twindow: %ld partial",
+ xevent->xvisibility.window);
+ break;
+ case VisibilityUnobscured:
+ g_message ("visibility notify:\twindow: %ld full",
+ xevent->xvisibility.window);
+ break;
+ }
+#endif /* G_ENABLE_DEBUG */
+
+ event->visibility.type = GDK_VISIBILITY_NOTIFY;
+ event->visibility.window = window;
+
+ switch (xevent->xvisibility.state)
+ {
+ case VisibilityFullyObscured:
+ event->visibility.state = GDK_VISIBILITY_FULLY_OBSCURED;
+ break;
+
+ case VisibilityPartiallyObscured:
+ event->visibility.state = GDK_VISIBILITY_PARTIAL;
+ break;
+
+ case VisibilityUnobscured:
+ event->visibility.state = GDK_VISIBILITY_UNOBSCURED;
+ break;
+ }
+
+ break;
+
+ case CreateNotify:
+ /* Not currently handled */
+ break;
+
+ case DestroyNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("destroy notify:\twindow: %ld",
+ xevent->xdestroywindow.window));
+
+ event->any.type = GDK_DESTROY;
+ event->any.window = window;
+
+ return_val = window_private && !window_private->destroyed;
+
+ if(window && window_private->xwindow != GDK_ROOT_WINDOW())
+ gdk_window_destroy_notify (window);
+ break;
+
+ case UnmapNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("unmap notify:\t\twindow: %ld",
+ xevent->xmap.window));
+
+ event->any.type = GDK_UNMAP;
+ event->any.window = window;
+
+ if (gdk_xgrab_window == window_private)
+ gdk_xgrab_window = NULL;
+
+ break;
+
+ case MapNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("map notify:\t\twindow: %ld",
+ xevent->xmap.window));
+
+ event->any.type = GDK_MAP;
+ event->any.window = window;
+
+ break;
+
+ case ReparentNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("reparent notify:\twindow: %ld",
+ xevent->xreparent.window));
+
+ /* Not currently handled */
+ return_val = FALSE;
+ break;
+
+ case ConfigureNotify:
+ /* Print debugging info.
+ */
+ while ((XPending (gdk_display) > 0) &&
+ XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
+ ConfigureNotify, xevent))
+ {
+ GdkFilterReturn result;
+
+ GDK_NOTE (EVENTS,
+ g_message ("configure notify discarded:\twindow: %ld",
+ xevent->xconfigure.window));
+
+ result = gdk_event_apply_filters (xevent, event,
+ window_private
+ ?window_private->filters
+ :gdk_default_filters);
+
+ /* If the result is GDK_FILTER_REMOVE, there will be
+ * trouble, but anybody who filtering the Configure events
+ * better know what they are doing
+ */
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ }
+
+ /*XSync (gdk_display, 0);*/
+ }
+
+
+ GDK_NOTE (EVENTS,
+ g_message ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d",
+ xevent->xconfigure.window,
+ xevent->xconfigure.x,
+ xevent->xconfigure.y,
+ xevent->xconfigure.width,
+ xevent->xconfigure.height,
+ xevent->xconfigure.border_width,
+ xevent->xconfigure.above,
+ xevent->xconfigure.override_redirect));
+
+ if (!window_private->destroyed &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.configure_event)
+ gdk_input_vtable.configure_event (&xevent->xconfigure, window);
+
+ if (window_private->window_type == GDK_WINDOW_CHILD)
+ return_val = FALSE;
+ else
+ {
+ event->configure.type = GDK_CONFIGURE;
+ event->configure.window = window;
+ event->configure.width = xevent->xconfigure.width;
+ event->configure.height = xevent->xconfigure.height;
+
+ if (!xevent->xconfigure.x &&
+ !xevent->xconfigure.y &&
+ !window_private->destroyed)
+ {
+ gint tx = 0;
+ gint ty = 0;
+ Window child_window = 0;
+
+ if (!XTranslateCoordinates (window_private->xdisplay,
+ window_private->xwindow,
+ gdk_root_window,
+ 0, 0,
+ &tx, &ty,
+ &child_window))
+ g_warning ("GdkWindow %ld doesn't share root windows display?",
+ window_private->xwindow);
+ event->configure.x = tx;
+ event->configure.y = ty;
+ }
+ else
+ {
+ event->configure.x = xevent->xconfigure.x;
+ event->configure.y = xevent->xconfigure.y;
+ }
+ window_private->x = event->configure.x;
+ window_private->y = event->configure.y;
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+ if (window_private->resize_count > 1)
+ window_private->resize_count -= 1;
+ }
+ break;
+
+ case PropertyNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("property notify:\twindow: %ld",
+ xevent->xproperty.window));
+
+ event->property.type = GDK_PROPERTY_NOTIFY;
+ event->property.window = window;
+ event->property.atom = xevent->xproperty.atom;
+ event->property.time = xevent->xproperty.time;
+ event->property.state = xevent->xproperty.state;
+
+ break;
+
+ case SelectionClear:
+ GDK_NOTE (EVENTS,
+ g_message ("selection clear:\twindow: %ld",
+ xevent->xproperty.window));
+
+ event->selection.type = GDK_SELECTION_CLEAR;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionclear.selection;
+ event->selection.time = xevent->xselectionclear.time;
+
+ break;
+
+ case SelectionRequest:
+ GDK_NOTE (EVENTS,
+ g_message ("selection request:\twindow: %ld",
+ xevent->xproperty.window));
+
+ event->selection.type = GDK_SELECTION_REQUEST;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionrequest.selection;
+ event->selection.target = xevent->xselectionrequest.target;
+ event->selection.property = xevent->xselectionrequest.property;
+ event->selection.requestor = xevent->xselectionrequest.requestor;
+ event->selection.time = xevent->xselectionrequest.time;
+
+ break;
+
+ case SelectionNotify:
+ GDK_NOTE (EVENTS,
+ g_message ("selection notify:\twindow: %ld",
+ xevent->xproperty.window));
+
+
+ event->selection.type = GDK_SELECTION_NOTIFY;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselection.selection;
+ event->selection.target = xevent->xselection.target;
+ event->selection.property = xevent->xselection.property;
+ event->selection.time = xevent->xselection.time;
+
+ break;
+
+ case ColormapNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("colormap notify:\twindow: %ld",
+ xevent->xcolormap.window));
+
+ /* Not currently handled */
+ return_val = FALSE;
+ break;
+
+ case ClientMessage:
+ {
+ GList *tmp_list;
+ GdkFilterReturn result = GDK_FILTER_CONTINUE;
+
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("client message:\twindow: %ld",
+ xevent->xclient.window));
+
+ tmp_list = client_filters;
+ while (tmp_list)
+ {
+ GdkClientFilter *filter = tmp_list->data;
+ if (filter->type == xevent->xclient.message_type)
+ {
+ result = (*filter->function) (xevent, event, filter->data);
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ switch (result)
+ {
+ case GDK_FILTER_REMOVE:
+ return_val = FALSE;
+ break;
+ case GDK_FILTER_TRANSLATE:
+ return_val = TRUE;
+ break;
+ case GDK_FILTER_CONTINUE:
+ /* Send unknown ClientMessage's on to Gtk for it to use */
+ event->client.type = GDK_CLIENT_EVENT;
+ event->client.window = window;
+ event->client.message_type = xevent->xclient.message_type;
+ event->client.data_format = xevent->xclient.format;
+ memcpy(&event->client.data, &xevent->xclient.data,
+ sizeof(event->client.data));
+ }
+ }
+
+ break;
+
+ case MappingNotify:
+ /* Print debugging info.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("mapping notify"));
+
+ /* Let XLib know that there is a new keyboard mapping.
+ */
+ XRefreshKeyboardMapping (&xevent->xmapping);
+ return_val = FALSE;
+ break;
+
+ default:
+ /* something else - (e.g., a Xinput event) */
+
+ if (window_private &&
+ !window_private->destroyed &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.other_event)
+ return_val = gdk_input_vtable.other_event(event, xevent, window);
+ else
+ return_val = FALSE;
+
+ break;
+ }
+
+ if (return_val)
+ {
+ if (event->any.window)
+ gdk_window_ref (event->any.window);
+ if (((event->any.type == GDK_ENTER_NOTIFY) ||
+ (event->any.type == GDK_LEAVE_NOTIFY)) &&
+ (event->crossing.subwindow != NULL))
+ gdk_window_ref (event->crossing.subwindow);
+ }
+ else
+ {
+ /* Mark this event as having no resources to be freed */
+ event->any.window = NULL;
+ event->any.type = GDK_NOTHING;
+ }
+
+ if (window)
+ gdk_window_unref (window);
+
+ return return_val;
+}
+
+GdkFilterReturn
+gdk_wm_protocols_filter (GdkXEvent *xev,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xevent = (XEvent *)xev;
+
+ if ((Atom) xevent->xclient.data.l[0] == gdk_wm_delete_window)
+ {
+ /* The delete window request specifies a window
+ * to delete. We don't actually destroy the
+ * window because "it is only a request". (The
+ * window might contain vital data that the
+ * program does not want destroyed). Instead
+ * the event is passed along to the program,
+ * which should then destroy the window.
+ */
+ GDK_NOTE (EVENTS,
+ g_message ("delete window:\t\twindow: %ld",
+ xevent->xclient.window));
+
+ event->any.type = GDK_DELETE;
+
+ return GDK_FILTER_TRANSLATE;
+ }
+ else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
+ {
+ }
+
+ return GDK_FILTER_REMOVE;
+}
+
+#if 0
+static Bool
+gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ GdkEvent event;
+ GdkPredicate *pred;
+
+ if (gdk_event_translate (&event, xevent))
+ {
+ pred = (GdkPredicate*) arg;
+ return (* pred->func) (&event, pred->data);
+ }
+
+ return FALSE;
+}
+#endif
+
+static void
+gdk_events_queue (void)
+{
+ GdkEvent *event;
+ XEvent xevent;
+
+ while (!queued_events && XPending (gdk_display))
+ {
+ #ifdef USE_XIM
+ Window w = None;
+
+ XNextEvent (gdk_display, &xevent);
+ if (gdk_xim_window)
+ switch (xevent.type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ case ButtonPress:
+ case ButtonRelease:
+ w = GDK_WINDOW_XWINDOW (gdk_xim_window);
+ break;
+ }
+
+ if (XFilterEvent (&xevent, w))
+ continue;
+#else
+ XNextEvent (gdk_display, &xevent);
+#endif
+
+ event = gdk_event_new ();
+
+ event->any.type = GDK_NOTHING;
+ event->any.window = NULL;
+ event->any.send_event = FALSE;
+ event->any.send_event = xevent.xany.send_event;
+
+ if (gdk_event_translate (event, &xevent))
+ queued_events = g_list_prepend (queued_events, event);
+ else
+ gdk_event_free (event);
+ }
+}
+
+static gboolean
+gdk_event_prepare (gpointer source_data,
+ GTimeVal *current_time,
+ gint *timeout)
+{
+ *timeout = -1;
+
+ gdk_events_queue ();
+ return (queued_events != NULL);
+}
+
+static gboolean
+gdk_event_check (gpointer source_data,
+ GTimeVal *current_time)
+{
+ if (event_poll_fd.revents & G_IO_IN)
+ {
+ gdk_events_queue ();
+ return (queued_events != NULL);
+ }
+ else
+ return FALSE;
+}
+
+static gboolean
+gdk_event_dispatch (gpointer source_data,
+ GTimeVal *current_time,
+ gpointer user_data)
+{
+ if (queued_events)
+ {
+ GdkEvent *event = queued_events->data;
+ GList *tmp_list = queued_events;
+ queued_events = g_list_remove_link (queued_events, queued_events);
+ g_list_free_1 (tmp_list);
+
+ if (event_func)
+ (*event_func) (event, event_data);
+
+ gdk_event_free (event);
+ }
+
+ return TRUE;
+}
+
+static void
+gdk_synthesize_click (GdkEvent *event,
+ gint nclicks)
+{
+ GdkEvent temp_event;
+
+ g_return_if_fail (event != NULL);
+
+ temp_event = *event;
+ temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
+
+ gdk_event_put (&temp_event);
+}
+
+/* Sends a ClientMessage to all toplevel client windows */
+gboolean
+gdk_event_send_client_message (GdkEvent *event, guint32 xid)
+{
+ XEvent sev;
+
+ g_return_val_if_fail(event != NULL, FALSE);
+
+ /* Set up our event to send, with the exception of its target window */
+ sev.xclient.type = ClientMessage;
+ sev.xclient.display = gdk_display;
+ sev.xclient.format = event->client.data_format;
+ sev.xclient.window = xid;
+ memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
+ sev.xclient.message_type = event->client.message_type;
+
+ return gdk_send_xevent (xid, False, NoEventMask, &sev);
+}
+
+/* Sends a ClientMessage to all toplevel client windows */
+gboolean
+gdk_event_send_client_message_to_all_recurse (XEvent *xev,
+ guint32 xid,
+ guint level)
+{
+ static GdkAtom wm_state_atom = GDK_NONE;
+
+ Atom type = None;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+
+ Window *ret_children, ret_root, ret_parent;
+ unsigned int ret_nchildren;
+ int i;
+
+ gboolean send = FALSE;
+ gboolean found = FALSE;
+
+ if (!wm_state_atom)
+ wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
+
+ gdk_error_code = 0;
+ XGetWindowProperty (gdk_display, xid, wm_state_atom, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &data);
+
+ if (gdk_error_code)
+ {
+ gdk_error_code = 0;
+ return FALSE;
+ }
+
+ if (type)
+ {
+ send = TRUE;
+ XFree (data);
+ }
+ else
+ {
+ /* OK, we're all set, now let's find some windows to send this to */
+ if (XQueryTree(gdk_display, xid, &ret_root, &ret_parent,
+ &ret_children, &ret_nchildren) != True)
+ return FALSE;
+
+ if (gdk_error_code)
+ return FALSE;
+
+ for(i = 0; i < ret_nchildren; i++)
+ if (gdk_event_send_client_message_to_all_recurse(xev, ret_children[i], level + 1))
+ found = TRUE;
+
+ XFree(ret_children);
+ }
+
+ if (send || (!found && (level == 1)))
+ {
+ xev->xclient.window = xid;
+ gdk_send_xevent (xid, False, NoEventMask, xev);
+ }
+
+ return (send || found);
+}
+
+void
+gdk_event_send_clientmessage_toall (GdkEvent *event)
+{
+ XEvent sev;
+ gint old_warnings = gdk_error_warnings;
+
+ g_return_if_fail(event != NULL);
+
+ /* Set up our event to send, with the exception of its target window */
+ sev.xclient.type = ClientMessage;
+ sev.xclient.display = gdk_display;
+ sev.xclient.format = event->client.data_format;
+ memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
+ sev.xclient.message_type = event->client.message_type;
+
+ gdk_event_send_client_message_to_all_recurse(&sev, gdk_root_window, 0);
+
+ gdk_error_warnings = old_warnings;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_flush
+ *
+ * Flushes the Xlib output buffer and then waits
+ * until all requests have been received and processed
+ * by the X server. The only real use for this function
+ * is in dealing with XShm.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void gdk_flush (void)
+{
+ XSync (gdk_display, False);
+}
+
+