mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-29 06:51:10 +00:00
df4fc36721
2000-06-20 Havoc Pennington <hp@redhat.com> * modules/linux-fb/Makefile.am: Make this compile without framebuffer enabled * gdk/linux-fb/Makefile.am: Add conditional to not build framebuffer unless specified in configure * gdk/gdkdraw.c (gdk_draw_drawable): Fix bug where I was getting the size of the target instead of source if -1 was passed for width/height * gdk/x11/gdkgeometry-x11.c (gdk_window_compute_position): Fix width/height confusion. 2000-06-19 Havoc Pennington <hp@redhat.com> * gdk/x11/gdkx.h (GDK_WINDOW_XWINDOW): change this to be GDK_DRAWABLE_XID. In the future, we probably want to make it faster with G_DISABLE_CHECKS turned on. 2000-06-14 Havoc Pennington <hp@redhat.com> * gdk/Makefile.am: add gdkpixmap.c * gdk/gdk.c: s/gdk_window_init/_gdk_windowing_window_init/ s/gdk_image_init/_gdk_windowing_image_init * gdk/gdkcolor.c: make ref/unref compat wrappers for GObject ref/unref * gdk/gdkcolor.h: make GdkColormap a GObject subclass * gdk/gdkcompat.h: remove GdkWindowType compat, since GdkWindowType is now non-deprecated; change gdk_window_get_type() compat to be gdk_window_get_window_type(). * gdk/gdkdnd.h: make GdkDragContext a GObject. * gdk/gdkdraw.c, gdk/gdkdraw.h: Convert GdkDrawable to a pure virtual GObject. Make all functions call into the vtable. Move gdk_image_put() guts in here. Remove GdkDrawableType and gdk_drawable_get_type(), these are now GdkWindow-specific. draw_image, get_depth, get_size, set_colormap, get_colormap, get_visual added to the vtable. * gdk/gdkgc.h, gdk/gdkgc.c: Convert GdkGC to a pure virtual GObject. Virtualize everything. (gdk_gc_new_with_values): remove check for destroyed window, because now GdkWindow::create_gc will check this. (gdk_gc_set_values): New function to set GC values, this was already implemented but wasn't in the header * gdk/gdkimage.h, gdk/gdkimage.c: Convert GdkImage to a GObject. * gdk/gdkinternals.h: Remove _gdk_window_alloc(), remove _gdk_window_draw_image(), remove _gdk_windowing_window_class, remove _gdk_window_class; add _gdk_window_impl_get_type() and _gdk_pixmap_impl_get_type(). Rename gdk_window_init to _gdk_windowing_window_init, rename gdk_image_init to _gdk_windowing_image_init. * gdk/gdkpango.c: Reflect GObject-ification of PangoContext. (gdk_draw_layout): Remove check for destroyed window, because all the drawable methods already check it. * gdk/gdkpixmap.h, gdk/gdkpixmap.c: Convert GdkPixmap to GObject. Add gdkpixmap.c which contains implementation of GdkDrawable virtual table (by chaining to a platform-specific implementation object). * gdk/gdkprivate.h: Remove GDK_IS_WINDOW, GDK_IS_PIXMAP, GDK_DRAWABLE_DESTROYED. Add GDK_WINDOW_DESTROYED. Replace GDK_DRAWABLE_TYPE with GDK_WINDOW_TYPE. Remove GdkDrawablePrivate, GdkWindowPrivate, GdkImageClass, GdkImagePrivate, GdkGCPrivate, GdkColormapPrivate. * gdk/gdktypes.h: #include <glib-object.h> * gdk/gdkwindow.h, gdk/gdkwindow.c: Convert GdkWindow to GObject. Move most functionality to platform-specific implementation object. GdkWindow itself now handles the backing store, then chains to the platform-specific implementation. (gdk_window_get_window_type): return GdkWindowType of the window. (gdk_window_peek_children): New routine, returns the children of a GdkWindow (gdk_window_get_children): Was in X11-specific code and did XQueryTree. Changed to simply return a copy of window->children; so it can go in cross-platform code. * gdk/x11/Makefile.am: fix broken MKINSTALLDIRS path * gdk/x11/gdkcolor-x11.c: implement X-specific parts of GdkColormap; just changed to use the new private data instead of casting to GdkColormapPrivate. * gdk/x11/gdkcursor-x11.c: added a couple typechecks to gdk_cursor_new(). * gdk/x11/gdkdnd-x11.c: Change the way we access private fields (private data member in the GObject). (xdnd_manager_source_filter): Function had broken error handling, fix it (use gdk_error_trap_push). * gdk/x11/gdkdrawable-x11.c: This file now implements a base class for GdkWindowImplX11/GdkPixmapImplX11. This base class is purely for the convenience of the X port, and not part of the interface to cross-platform GDK. * gdk/x11/gdkevents-x11.c: Reflect various renamings. * gdk/x11/gdkgc-x11.c: Implement a subclass of GdkGC that's specific to X, and returned by the create_gc virtual method of GdkDrawableImplX11. (gdk_x11_gc_set_dashes): Change this to take an array of gint8 rather than gchar, this was also changed in the GdkGC vtable. (gdk_x11_gc_values_to_xvalues): If GdkGCValues is NULL, or the mask is 0, return immediately, instead of checking every flag. This is faster, and keeps us from segfaulting if values is NULL and the mask contains some nonzero flags. * gdk/x11/gdkgeometry-x11.c: deal with all the rearranging of GdkWindow. * gdk/x11/gdkglobals-x11.c: change type of grab window, since GdkWindowPrivate is gone. * gdk/x11/gdkim-x11.c: rename things that got renamed. * gdk/x11/gdkimage-x11.c: implement in terms of GObject, and remove the image_put stuff that got transferred to GdkDrawable. * gdk/x11/gdkinput.c: renamings * gdk/x11/gdkmain-x11.c: #include <pango/pangox.h> * gdk/x11/gdkpixmap-x11.c: GObject conversion * gdk/x11/gdkprivate-x11.h: indentation fixes * gdk/x11/gdkproperty-x11.c: renamings * gdk/x11/gdkselection-x11.c: renamings * gdk/x11/gdkwindow-x11.c: Restructuring and renaming; this now implements the platform-specific "impl" object. Moved gdk_window_get_children to gdk/gdkwindow.c * gdk/x11/gdkx.h: Remove all the private structs and private datas that no longer exist. Add declaration of GdkGCX11 object here. Fix all the macros to still work. * gtk/gtk-boxed.defs: Remove GtkStyle, GdkColormap, GdkWindow, GdkDragContext from the boxed types since they are now GObjects. * gtk/gtkstyle.h, gtk/gtkstyle.c: Converted GtkStyle to a GObject, moved xthickness/ythickness into the instance. GtkStyleClass functions are now in the standard vtable for GtkStyle, so you have to create a GObject subclass to write a theme engine. (gtk_style_copy): fixed a leaked PangoFontDescription (gtk_style_init): renamed gtk_style_realize, so gtk_style_init can be the standard GObject function. * Throughout GTK: s/style->klass->[xy]thickness/style->[xy]thickness s/pango_layout_unref/g_object_unref/ * gtk/gtkrc.h, gtk/gtkrc.c: Converted GtkRcStyle to a GObject. * gtk/gtksocket.c: Use gdk_window_get_user_data() instead of accessing GDK internals. * gtk/gtkwidget.c: Use gdk_window_peek_children() instead of accessing GDK internals.
1513 lines
39 KiB
C
1513 lines
39 KiB
C
/* 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.
|
|
*/
|
|
|
|
/*
|
|
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
|
* file for a list of people on the GTK+ Team. See the ChangeLog
|
|
* files for a list of changes. These files are distributed with
|
|
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
|
*/
|
|
|
|
#include "gdk.h"
|
|
#include "gdkprivate-x11.h"
|
|
#include "gdkinternals.h"
|
|
#include "gdkx.h"
|
|
|
|
#include "gdkkeysyms.h"
|
|
|
|
#if HAVE_CONFIG_H
|
|
# include <config.h>
|
|
# if STDC_HEADERS
|
|
# include <string.h>
|
|
# endif
|
|
#endif
|
|
|
|
#include "gdkinputprivate.h"
|
|
|
|
typedef struct _GdkIOClosure GdkIOClosure;
|
|
typedef struct _GdkEventPrivate GdkEventPrivate;
|
|
|
|
#define DOUBLE_CLICK_TIME 250
|
|
#define TRIPLE_CLICK_TIME 500
|
|
#define DOUBLE_CLICK_DIST 5
|
|
#define TRIPLE_CLICK_DIST 5
|
|
|
|
typedef enum
|
|
{
|
|
/* Following flag is set for events on the event queue during
|
|
* translation and cleared afterwards.
|
|
*/
|
|
GDK_EVENT_PENDING = 1 << 0
|
|
} GdkEventFlags;
|
|
|
|
struct _GdkIOClosure
|
|
{
|
|
GdkInputFunction function;
|
|
GdkInputCondition condition;
|
|
GdkDestroyNotify notify;
|
|
gpointer data;
|
|
};
|
|
|
|
struct _GdkEventPrivate
|
|
{
|
|
GdkEvent event;
|
|
guint flags;
|
|
};
|
|
|
|
/*
|
|
* Private function declarations
|
|
*/
|
|
|
|
static gint gdk_event_apply_filters (XEvent *xevent,
|
|
GdkEvent *event,
|
|
GList *filters);
|
|
static gint gdk_event_translate (GdkEvent *event,
|
|
XEvent *xevent,
|
|
gboolean return_exposes);
|
|
#if 0
|
|
static Bool gdk_event_get_type (Display *display,
|
|
XEvent *xevent,
|
|
XPointer arg);
|
|
#endif
|
|
|
|
static gboolean gdk_event_prepare (gpointer source_data,
|
|
GTimeVal *current_time,
|
|
gint *timeout,
|
|
gpointer user_data);
|
|
static gboolean gdk_event_check (gpointer source_data,
|
|
GTimeVal *current_time,
|
|
gpointer user_data);
|
|
static gboolean gdk_event_dispatch (gpointer source_data,
|
|
GTimeVal *current_time,
|
|
gpointer user_data);
|
|
|
|
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 GList *client_filters; /* Filters for client messages */
|
|
|
|
static GSourceFuncs event_funcs = {
|
|
gdk_event_prepare,
|
|
gdk_event_check,
|
|
gdk_event_dispatch,
|
|
(GDestroyNotify)g_free
|
|
};
|
|
|
|
GPollFD event_poll_fd;
|
|
|
|
/*********************************************
|
|
* Functions for maintaining the event queue *
|
|
*********************************************/
|
|
|
|
void
|
|
gdk_events_init (void)
|
|
{
|
|
connection_number = ConnectionNumber (gdk_display);
|
|
GDK_NOTE (MISC,
|
|
g_message ("connection number: %d", connection_number));
|
|
|
|
g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);
|
|
|
|
event_poll_fd.fd = connection_number;
|
|
event_poll_fd.events = G_IO_IN;
|
|
|
|
g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);
|
|
|
|
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:
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
gboolean
|
|
gdk_events_pending (void)
|
|
{
|
|
return (gdk_event_queue_find_first() || XPending (gdk_display));
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
* 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)
|
|
{
|
|
if (xevent->xany.window == GDK_DRAWABLE_XID (arg) &&
|
|
(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, TRUE))
|
|
return event;
|
|
else
|
|
gdk_event_free (event);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static gint
|
|
gdk_event_apply_filters (XEvent *xevent,
|
|
GdkEvent *event,
|
|
GList *filters)
|
|
{
|
|
GList *tmp_list;
|
|
GdkFilterReturn result;
|
|
|
|
tmp_list = filters;
|
|
|
|
while (tmp_list)
|
|
{
|
|
GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
|
|
|
|
tmp_list = tmp_list->next;
|
|
result = filter->function (xevent, event, filter->data);
|
|
if (result != GDK_FILTER_CONTINUE)
|
|
return result;
|
|
}
|
|
|
|
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,
|
|
gboolean return_exposes)
|
|
{
|
|
|
|
GdkWindow *window;
|
|
GdkWindowObject *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;
|
|
gint xoffset, yoffset;
|
|
|
|
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);
|
|
/* FIXME: window might be a GdkPixmap!!! */
|
|
|
|
window_private = (GdkWindowObject *) window;
|
|
|
|
if (window != NULL)
|
|
gdk_window_ref (window);
|
|
|
|
event->any.window = window;
|
|
event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
|
|
|
|
if (window_private && GDK_WINDOW_DESTROYED (window))
|
|
{
|
|
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_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
#ifdef USE_XIM
|
|
if (window == NULL && gdk_xim_window && xevent->type == KeyPress &&
|
|
!GDK_WINDOW_DESTROYED (gdk_xim_window))
|
|
{
|
|
/*
|
|
* 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 = (GdkWindowObject *) 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_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
|
|
goto done;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* 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;
|
|
|
|
if (window)
|
|
{
|
|
_gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
|
|
}
|
|
else
|
|
{
|
|
xoffset = 0;
|
|
yoffset = 0;
|
|
}
|
|
|
|
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';
|
|
|
|
#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;
|
|
|
|
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:
|
|
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;
|
|
}
|
|
|
|
/* If we get a ButtonPress event where the button is 4 or 5,
|
|
it's a Scroll event */
|
|
if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5)
|
|
{
|
|
event->scroll.type = GDK_SCROLL;
|
|
event->scroll.direction = (xevent->xbutton.button == 4) ?
|
|
GDK_SCROLL_UP : GDK_SCROLL_DOWN;
|
|
event->scroll.window = window;
|
|
event->scroll.time = xevent->xbutton.x;
|
|
event->scroll.x = xevent->xbutton.x + xoffset;
|
|
event->scroll.y = xevent->xbutton.y + yoffset;
|
|
event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
|
|
event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
|
|
event->scroll.pressure = 0.5;
|
|
event->scroll.xtilt = 0;
|
|
event->scroll.ytilt = 0;
|
|
event->scroll.state = (GdkModifierType) xevent->xbutton.state;
|
|
event->scroll.source = GDK_SOURCE_MOUSE;
|
|
event->scroll.deviceid = GDK_CORE_POINTER;
|
|
}
|
|
else
|
|
{
|
|
event->button.type = GDK_BUTTON_PRESS;
|
|
event->button.window = window;
|
|
event->button.time = xevent->xbutton.time;
|
|
event->button.x = xevent->xbutton.x + xoffset;
|
|
event->button.y = xevent->xbutton.y + yoffset;
|
|
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;
|
|
|
|
gdk_event_button_generate (event);
|
|
}
|
|
|
|
break;
|
|
|
|
case ButtonRelease:
|
|
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;
|
|
}
|
|
|
|
/* We treat button presses as scroll wheel events, so ignore the release */
|
|
if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5)
|
|
{
|
|
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 + xoffset;
|
|
event->button.y = xevent->xbutton.y + yoffset;
|
|
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:
|
|
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 + xoffset;
|
|
event->motion.y = xevent->xmotion.y + yoffset;
|
|
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:
|
|
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 &&
|
|
!GDK_WINDOW_DESTROYED (window) &&
|
|
(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 + xoffset;
|
|
event->crossing.y = xevent->xcrossing.y + yoffset;
|
|
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:
|
|
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 + xoffset;
|
|
event->crossing.y = xevent->xcrossing.y + yoffset;
|
|
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:
|
|
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:
|
|
GDK_NOTE (EVENTS,
|
|
g_message ("keymap notify"));
|
|
|
|
/* Not currently handled */
|
|
return_val = FALSE;
|
|
break;
|
|
|
|
case Expose:
|
|
GDK_NOTE (EVENTS,
|
|
g_message ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d%s",
|
|
xevent->xexpose.window, xevent->xexpose.count,
|
|
xevent->xexpose.x, xevent->xexpose.y,
|
|
xevent->xexpose.width, xevent->xexpose.height,
|
|
event->any.send_event ? " (send)" : ""));
|
|
{
|
|
GdkRectangle expose_rect;
|
|
|
|
expose_rect.x = xevent->xexpose.x + xoffset;
|
|
expose_rect.y = xevent->xexpose.y + yoffset;
|
|
expose_rect.width = xevent->xexpose.width;
|
|
expose_rect.height = xevent->xexpose.height;
|
|
|
|
if (return_exposes)
|
|
{
|
|
event->expose.type = GDK_EXPOSE;
|
|
event->expose.area = expose_rect;
|
|
event->expose.window = window;
|
|
|
|
return_val = TRUE;
|
|
}
|
|
else
|
|
{
|
|
_gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
|
|
|
|
return_val = FALSE;
|
|
}
|
|
|
|
return_val = FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case GraphicsExpose:
|
|
{
|
|
GdkRectangle expose_rect;
|
|
|
|
GDK_NOTE (EVENTS,
|
|
g_message ("graphics expose:\tdrawable: %ld",
|
|
xevent->xgraphicsexpose.drawable));
|
|
|
|
expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
|
|
expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
|
|
expose_rect.width = xevent->xgraphicsexpose.width;
|
|
expose_rect.height = xevent->xgraphicsexpose.height;
|
|
|
|
if (return_exposes)
|
|
{
|
|
event->expose.type = GDK_EXPOSE;
|
|
event->expose.area = expose_rect;
|
|
event->expose.window = window;
|
|
|
|
return_val = TRUE;
|
|
}
|
|
else
|
|
{
|
|
_gdk_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
|
|
|
|
return_val = FALSE;
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case NoExpose:
|
|
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:
|
|
#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:
|
|
GDK_NOTE (EVENTS,
|
|
g_message ("create notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d parent: %ld ovr: %d",
|
|
xevent->xcreatewindow.window,
|
|
xevent->xcreatewindow.x,
|
|
xevent->xcreatewindow.y,
|
|
xevent->xcreatewindow.width,
|
|
xevent->xcreatewindow.height,
|
|
xevent->xcreatewindow.border_width,
|
|
xevent->xcreatewindow.parent,
|
|
xevent->xcreatewindow.override_redirect));
|
|
/* not really handled */
|
|
break;
|
|
|
|
case DestroyNotify:
|
|
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 && !GDK_WINDOW_DESTROYED (window);
|
|
|
|
if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW())
|
|
gdk_window_destroy_notify (window);
|
|
break;
|
|
|
|
case UnmapNotify:
|
|
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:
|
|
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:
|
|
GDK_NOTE (EVENTS,
|
|
g_message ("reparent notify:\twindow: %ld x,y: %d %d parent: %ld ovr: %d",
|
|
xevent->xreparent.window,
|
|
xevent->xreparent.x,
|
|
xevent->xreparent.y,
|
|
xevent->xreparent.parent,
|
|
xevent->xreparent.override_redirect));
|
|
|
|
/* Not currently handled */
|
|
return_val = FALSE;
|
|
break;
|
|
|
|
case ConfigureNotify:
|
|
GDK_NOTE (EVENTS,
|
|
g_message ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d b-w: %d above: %ld ovr: %d%s",
|
|
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,
|
|
!window
|
|
? " (discarding)"
|
|
: GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD
|
|
? " (discarding child)"
|
|
: ""));
|
|
if (window &&
|
|
!GDK_WINDOW_DESTROYED (window) &&
|
|
(window_private->extension_events != 0) &&
|
|
gdk_input_vtable.configure_event)
|
|
gdk_input_vtable.configure_event (&xevent->xconfigure, window);
|
|
|
|
if (!window || GDK_WINDOW_TYPE (window) == 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 &&
|
|
!GDK_WINDOW_DESTROYED (window))
|
|
{
|
|
gint tx = 0;
|
|
gint ty = 0;
|
|
Window child_window = 0;
|
|
|
|
gdk_error_trap_push ();
|
|
if (XTranslateCoordinates (GDK_DRAWABLE_XDISPLAY (window),
|
|
GDK_DRAWABLE_XID (window),
|
|
gdk_root_window,
|
|
0, 0,
|
|
&tx, &ty,
|
|
&child_window))
|
|
{
|
|
if (!gdk_error_trap_pop ())
|
|
{
|
|
event->configure.x = tx;
|
|
event->configure.y = ty;
|
|
}
|
|
}
|
|
else
|
|
gdk_error_trap_pop ();
|
|
}
|
|
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;
|
|
GDK_WINDOW_IMPL_X11 (window_private->impl)->width = xevent->xconfigure.width;
|
|
GDK_WINDOW_IMPL_X11 (window_private->impl)->height = xevent->xconfigure.height;
|
|
if (window_private->resize_count > 1)
|
|
window_private->resize_count -= 1;
|
|
}
|
|
break;
|
|
|
|
case PropertyNotify:
|
|
GDK_NOTE (EVENTS,
|
|
gchar *atom = gdk_atom_name (xevent->xproperty.atom);
|
|
g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
|
|
xevent->xproperty.window,
|
|
xevent->xproperty.atom,
|
|
atom ? "\"" : "",
|
|
atom ? atom : "unknown",
|
|
atom ? "\"" : "");
|
|
g_free (atom);
|
|
);
|
|
|
|
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:
|
|
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;
|
|
|
|
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:
|
|
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 &&
|
|
!GDK_WINDOW_DESTROYED (window_private) &&
|
|
(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;
|
|
}
|
|
|
|
done:
|
|
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, FALSE))
|
|
{
|
|
pred = (GdkPredicate*) arg;
|
|
return (* pred->func) (&event, pred->data);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
gdk_events_queue (void)
|
|
{
|
|
GList *node;
|
|
GdkEvent *event;
|
|
XEvent xevent;
|
|
|
|
while (!gdk_event_queue_find_first() && 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 = xevent.xany.send_event ? TRUE : FALSE;
|
|
|
|
((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
|
|
|
|
gdk_event_queue_append (event);
|
|
node = gdk_queued_tail;
|
|
|
|
if (gdk_event_translate (event, &xevent, FALSE))
|
|
{
|
|
((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
|
|
}
|
|
else
|
|
{
|
|
gdk_event_queue_remove_link (node);
|
|
g_list_free_1 (node);
|
|
gdk_event_free (event);
|
|
}
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gdk_event_prepare (gpointer source_data,
|
|
GTimeVal *current_time,
|
|
gint *timeout,
|
|
gpointer user_data)
|
|
{
|
|
gboolean retval;
|
|
|
|
GDK_THREADS_ENTER ();
|
|
|
|
*timeout = -1;
|
|
|
|
retval = (gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
|
|
|
|
GDK_THREADS_LEAVE ();
|
|
|
|
return retval;
|
|
}
|
|
|
|
static gboolean
|
|
gdk_event_check (gpointer source_data,
|
|
GTimeVal *current_time,
|
|
gpointer user_data)
|
|
{
|
|
gboolean retval;
|
|
|
|
GDK_THREADS_ENTER ();
|
|
|
|
if (event_poll_fd.revents & G_IO_IN)
|
|
retval = (gdk_event_queue_find_first () != NULL) || XPending (gdk_display);
|
|
else
|
|
retval = FALSE;
|
|
|
|
GDK_THREADS_LEAVE ();
|
|
|
|
return retval;
|
|
}
|
|
|
|
static gboolean
|
|
gdk_event_dispatch (gpointer source_data,
|
|
GTimeVal *current_time,
|
|
gpointer user_data)
|
|
{
|
|
GdkEvent *event;
|
|
|
|
GDK_THREADS_ENTER ();
|
|
|
|
gdk_events_queue();
|
|
event = gdk_event_unqueue();
|
|
|
|
if (event)
|
|
{
|
|
if (gdk_event_func)
|
|
(*gdk_event_func) (event, gdk_event_data);
|
|
|
|
gdk_event_free (event);
|
|
}
|
|
|
|
GDK_THREADS_LEAVE ();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* 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;
|
|
gint old_warnings = gdk_error_warnings;
|
|
gboolean send = FALSE;
|
|
gboolean found = FALSE;
|
|
int i;
|
|
|
|
if (!wm_state_atom)
|
|
wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE);
|
|
|
|
gdk_error_warnings = 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_warnings = old_warnings;
|
|
|
|
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 ||
|
|
gdk_error_code)
|
|
{
|
|
gdk_error_warnings = old_warnings;
|
|
|
|
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);
|
|
}
|
|
|
|
gdk_error_warnings = old_warnings;
|
|
|
|
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);
|
|
}
|
|
|
|
|