summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorElliot Lee <sopwith@src.gnome.org>1997-11-24 22:37:52 +0000
committerElliot Lee <sopwith@src.gnome.org>1997-11-24 22:37:52 +0000
commit9508b76bd2401b6b9e289b5c8ec9fc0e08909283 (patch)
tree53c88a9e5ac09e1a027e56df33bdaa66d670901b /gdk
downloadgdk-pixbuf-9508b76bd2401b6b9e289b5c8ec9fc0e08909283.tar.gz
Initial revision
Diffstat (limited to 'gdk')
-rw-r--r--gdk/.cvsignore6
-rw-r--r--gdk/Makefile.am75
-rw-r--r--gdk/gdk.c2897
-rw-r--r--gdk/gdk.h614
-rw-r--r--gdk/gdkcolor.c718
-rw-r--r--gdk/gdkcursor.c52
-rw-r--r--gdk/gdkdraw.c383
-rw-r--r--gdk/gdkfont.c379
-rw-r--r--gdk/gdkgc.c636
-rw-r--r--gdk/gdkglobals.c47
-rw-r--r--gdk/gdkimage.c492
-rw-r--r--gdk/gdkinput.c324
-rw-r--r--gdk/gdkinput.h143
-rw-r--r--gdk/gdkinputcommon.h687
-rw-r--r--gdk/gdkinputgxi.h628
-rw-r--r--gdk/gdkinputnone.h72
-rw-r--r--gdk/gdkinputxfree.h368
-rw-r--r--gdk/gdkpixmap.c657
-rw-r--r--gdk/gdkprivate.h197
-rw-r--r--gdk/gdkproperty.c194
-rw-r--r--gdk/gdkrectangle.c83
-rw-r--r--gdk/gdkselection.c168
-rw-r--r--gdk/gdktypes.h967
-rw-r--r--gdk/gdkvisual.c431
-rw-r--r--gdk/gdkwindow.c1358
-rw-r--r--gdk/gdkx.h48
-rw-r--r--gdk/gdkxid.c74
-rw-r--r--gdk/gxid.c844
-rw-r--r--gdk/gxid_lib.c116
-rw-r--r--gdk/gxid_lib.h6
-rw-r--r--gdk/gxid_proto.h39
-rwxr-xr-xgdk/makecursors5
-rw-r--r--gdk/makecursors.sed3
-rwxr-xr-xgdk/makekeysyms5
-rw-r--r--gdk/makekeysyms.sed3
-rw-r--r--gdk/x11/gdkcolor-x11.c718
-rw-r--r--gdk/x11/gdkcursor-x11.c52
-rw-r--r--gdk/x11/gdkfont-x11.c379
-rw-r--r--gdk/x11/gdkglobals-x11.c47
-rw-r--r--gdk/x11/gdkimage-x11.c492
-rw-r--r--gdk/x11/gdkinput-gxi.c628
-rw-r--r--gdk/x11/gdkinput-none.c72
-rw-r--r--gdk/x11/gdkinput-x11.c687
-rw-r--r--gdk/x11/gdkinput-xfree.c368
-rw-r--r--gdk/x11/gdkinput.c324
-rw-r--r--gdk/x11/gdkmain-x11.c2897
-rw-r--r--gdk/x11/gdkpixmap-x11.c657
-rw-r--r--gdk/x11/gdkproperty-x11.c194
-rw-r--r--gdk/x11/gdkselection-x11.c168
-rw-r--r--gdk/x11/gdkvisual-x11.c431
-rw-r--r--gdk/x11/gdkwindow-x11.c1358
-rw-r--r--gdk/x11/gdkx.h48
-rw-r--r--gdk/x11/gdkxid.c74
-rw-r--r--gdk/x11/gxid.c844
-rw-r--r--gdk/x11/gxid_lib.c116
-rw-r--r--gdk/x11/gxid_lib.h6
-rw-r--r--gdk/x11/gxid_proto.h39
57 files changed, 24318 insertions, 0 deletions
diff --git a/gdk/.cvsignore b/gdk/.cvsignore
new file mode 100644
index 000000000..79680c82c
--- /dev/null
+++ b/gdk/.cvsignore
@@ -0,0 +1,6 @@
+*.lo
+Makefile
+.deps
+_libs
+libgdk.la
+
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
new file mode 100644
index 000000000..f298e2c3a
--- /dev/null
+++ b/gdk/Makefile.am
@@ -0,0 +1,75 @@
+## Process this file with automake to produce Makefile.in
+
+gdkincludedir = $(includedir)/gdk
+
+lib_LTLIBRARIES = libgdk.la
+
+libgdk_la_SOURCES = \
+ gdk.c \
+ gdkcolor.c \
+ gdkcursor.c \
+ gdkdraw.c \
+ gdkfont.c \
+ gdkgc.c \
+ gdkglobals.c \
+ gdkimage.c \
+ gdkinput.c \
+ gdkpixmap.c \
+ gdkproperty.c \
+ gdkrectangle.c \
+ gdkselection.c \
+ gdkvisual.c \
+ gdkwindow.c \
+ gdkxid.c \
+ gxid_lib.c
+## this last one is ifdef'd out unless XINPUT_GXI is defined
+## It's easier than trying to get automake to handle compiling
+## it conditionally
+
+gdkinclude_HEADERS = \
+ gdk.h \
+ gdkcursors.h \
+ gdkkeysyms.h \
+ gdkprivate.h \
+ gdktypes.h \
+ gdkinput.h \
+ gdkinputnone.h \
+ gdkinputcommon.h\
+ gdkinputgxi.h \
+ gdkinputxfree.h \
+ gxid_lib.h \
+ gxid_proto.h \
+ gdkx.h
+
+libgdk_la_LDFLAGS = -version-info 1:0:0 \
+ @x_ldflags@ @x_libs@
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/glib @x_cflags@
+
+EXTRA_PROGRAMS = gxid
+
+bin_PROGRAMS = @xinput_progs@
+
+gxid_SOURCES = gxid.c
+
+gxid_LDADD = \
+ @x_ldflags@ \
+ @x_libs@ \
+ -lm
+
+BUILT_SOURCES = gdkcursors.h gdkkeysyms.h
+
+EXTRA_DIST = makecursors makecursors.sed makekeysyms makekeysyms.sed
+
+gdkcursors.h:
+ $(srcdir)/makecursors @x_includes@/X11/cursorfont.h > $@
+
+gdkkeysyms.h:
+ $(srcdir)/makekeysyms @x_includes@/X11/keysymdef.h > $@
+
+.PHONY: files
+
+files:
+ @files=`ls $(DISTFILES) 2> /dev/null `; for p in $$files; do \
+ echo $$p; \
+ done
diff --git a/gdk/gdk.c b/gdk/gdk.c
new file mode 100644
index 000000000..d5f85dd1e
--- /dev/null
+++ b/gdk/gdk.c
@@ -0,0 +1,2897 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <ctype.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H_ */
+
+#define XLIB_ILLEGAL_ACCESS
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/WinUtil.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+#ifndef X_GETTIMEOFDAY
+#define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
+#endif /* X_GETTIMEOFDAY */
+
+
+#define DOUBLE_CLICK_TIME 250
+#define TRIPLE_CLICK_TIME 500
+#define DOUBLE_CLICK_DIST 5
+#define TRIPLE_CLICK_DIST 5
+
+
+#ifndef NO_FD_SET
+# define SELECT_MASK fd_set
+#else
+# ifndef _AIX
+ typedef long fd_mask;
+# endif
+# if defined(_IBMR2)
+# define SELECT_MASK void
+# else
+# define SELECT_MASK int
+# endif
+#endif
+
+
+typedef struct _GdkInput GdkInput;
+typedef struct _GdkPredicate GdkPredicate;
+
+struct _GdkInput
+{
+ gint tag;
+ gint source;
+ GdkInputCondition condition;
+ GdkInputFunction function;
+ gpointer data;
+};
+
+struct _GdkPredicate
+{
+ GdkEventFunc func;
+ gpointer data;
+};
+
+/*
+ * Private function declarations
+ */
+static gint gdk_event_wait (void);
+static gint gdk_event_translate (GdkEvent *event,
+ XEvent *xevent);
+static Bool gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg);
+static void gdk_synthesize_click (GdkEvent *event,
+ gint nclicks);
+
+static void gdk_dnd_drag_begin (GdkWindow *initial_window);
+static void gdk_dnd_drag_enter (Window dest);
+static void gdk_dnd_drag_leave (Window dest);
+static void gdk_dnd_drag_end (Window dest,
+ GdkPoint coords);
+static GdkAtom gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent);
+static void gdk_print_atom (GdkAtom anatom);
+
+/*
+ * old junk from offix, we might use it though so leave it
+ */
+static Window gdk_drop_get_client_window (Display *dpy,
+ Window win);
+static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y);
+static void gdk_exit_func (void);
+static int gdk_x_error (Display *display,
+ XErrorEvent *error);
+static int gdk_x_io_error (Display *display);
+static RETSIGTYPE gdk_signal (int signum);
+
+
+/* Private variable declarations
+ */
+static int initialized = 0; /* 1 if the library is initialized,
+ * 0 otherwise.
+ */
+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 gint received_destroy_notify = FALSE; /* Did we just receive a destroy notify
+ * event? If so, we need to actually
+ * destroy the window which received
+ * it now.
+ */
+static GdkWindow *window_to_destroy = NULL; /* If we previously received a destroy
+ * notify event then this is the window
+ * which received that event.
+ */
+
+static struct timeval start; /* The time at which the library was
+ * last initialized.
+ */
+static struct timeval timer; /* Timeout interval to use in the call
+ * to "select". This is used in
+ * conjunction with "timerp" to create
+ * a maximum time to wait for an event
+ * to arrive.
+ */
+static struct timeval *timerp; /* The actual timer passed to "select"
+ * This may be NULL, in which case
+ * "select" will block until an event
+ * arrives.
+ */
+static guint32 timer_val; /* The timeout length as specified by
+ * the user in milliseconds.
+ */
+static GList *inputs; /* A list of the input file descriptors
+ * that we care about. Each list node
+ * contains a GdkInput struct that describes
+ * when we are interested in the specified
+ * file descriptor. That is, when it is
+ * available for read, write or has an
+ * exception pending.
+ */
+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.
+ */
+
+#define OTHER_XEVENT_BUFSIZE 4
+static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
+static int other_xevent_i = 0;
+static GList *putback_events = NULL;
+
+static gulong base_id;
+static gint autorepeat;
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_init
+ *
+ * Initialize the library for use.
+ *
+ * Arguments:
+ * "argc" is the number of arguments.
+ * "argv" is an array of strings.
+ *
+ * Results:
+ * "argc" and "argv" are modified to reflect any arguments
+ * which were not handled. (Such arguments should either
+ * be handled by the application or dismissed).
+ *
+ * Side effects:
+ * The library is initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_init (int *argc,
+ char ***argv)
+{
+ XKeyboardState keyboard_state;
+ int synchronize;
+ int i, j, k;
+ XClassHint *class_hint;
+ int argc_orig = *argc;
+ char **argv_orig;
+
+ argv_orig = malloc ((argc_orig + 1) * sizeof (char*));
+ for (i = 0; i < argc_orig; i++)
+ argv_orig[i] = g_strdup ((*argv)[i]);
+ argv_orig[argc_orig] = NULL;
+
+ X_GETTIMEOFDAY (&start);
+
+ signal (SIGHUP, gdk_signal);
+ signal (SIGINT, gdk_signal);
+ signal (SIGQUIT, gdk_signal);
+ signal (SIGBUS, gdk_signal);
+ signal (SIGSEGV, gdk_signal);
+ signal (SIGPIPE, gdk_signal);
+ signal (SIGTERM, gdk_signal);
+
+ gdk_display_name = NULL;
+
+ XSetErrorHandler (gdk_x_error);
+ XSetIOErrorHandler (gdk_x_io_error);
+
+ synchronize = FALSE;
+
+ if (argc && argv)
+ {
+ if (*argc > 0)
+ gdk_progname = (*argv)[0];
+
+ for (i = 1; i < *argc;)
+ {
+ if (strcmp ("--display", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+
+ if ((i + 1) < *argc)
+ {
+ gdk_display_name = g_strdup ((*argv)[i + 1]);
+ (*argv)[i + 1] = NULL;
+ i += 1;
+ }
+ }
+ else if (strcmp ("--sync", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ synchronize = TRUE;
+ }
+ else if (strcmp ("--show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = TRUE;
+ }
+ else if (strcmp ("--no-show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = FALSE;
+ }
+ else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_use_xshm = FALSE;
+ }
+ else if (strcmp ("--debug-level", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_debug_level = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-name", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progname = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-class", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progclass = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+#ifdef XINPUT_GXI
+ else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_host = ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_port = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+#endif
+ i += 1;
+ }
+
+ for (i = 1; i < *argc; i++)
+ {
+ for (k = i; k < *argc; k++)
+ if ((*argv)[k] != NULL)
+ break;
+
+ if (k > i)
+ {
+ k -= i;
+ for (j = i + k; j < *argc; j++)
+ (*argv)[j-k] = (*argv)[j];
+ *argc -= k;
+ }
+ }
+ }
+ else
+ {
+ gdk_progname = "<unknown>";
+ }
+
+ gdk_display = XOpenDisplay (gdk_display_name);
+ if (!gdk_display)
+ g_error ("cannot open display: %s", XDisplayName (gdk_display_name));
+
+ /* 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.
+ */
+ /* base_id = RESOURCE_BASE; */
+ base_id = 0;
+ if (gdk_show_events)
+ g_print ("base id: %lu\n", base_id);
+
+ connection_number = ConnectionNumber (gdk_display);
+ if (gdk_debug_level >= 1)
+ g_print ("connection number: %d\n", connection_number);
+
+ if (synchronize)
+ XSynchronize (gdk_display, True);
+
+ gdk_screen = DefaultScreen (gdk_display);
+ gdk_root_window = RootWindow (gdk_display, gdk_screen);
+
+ gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
+ 10, 10, 10, 10, 0, 0 , 0);
+ class_hint = XAllocClassHint();
+ class_hint->res_name = gdk_progname;
+ class_hint->res_class = gdk_progclass;
+ XSetClassHint(gdk_display, gdk_leader_window, class_hint);
+ XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
+ XFree (class_hint);
+
+ gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
+ gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
+ gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
+ gdk_wm_window_protocols[0] = gdk_wm_delete_window;
+ gdk_wm_window_protocols[1] = gdk_wm_take_focus;
+ gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
+
+ gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
+ gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
+ gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
+ gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
+ gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
+ gdk_dnd.gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
+ gdk_dnd.gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
+
+ XGetKeyboardControl (gdk_display, &keyboard_state);
+ autorepeat = keyboard_state.global_auto_repeat;
+
+ timer.tv_sec = 0;
+ timer.tv_usec = 0;
+ timerp = NULL;
+
+ 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;
+
+ if (ATEXIT (gdk_exit_func))
+ g_warning ("unable to register exit function");
+
+ gdk_visual_init ();
+ gdk_window_init ();
+ gdk_image_init ();
+ gdk_input_init ();
+
+ initialized = 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit
+ *
+ * Restores the library to an un-itialized state and exits
+ * the program using the "exit" system call.
+ *
+ * Arguments:
+ * "errorcode" is the error value to pass to "exit".
+ *
+ * Results:
+ * Allocated structures are freed and the program exits
+ * cleanly.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_exit (int errorcode)
+{
+ /* de-initialisation is done by the gdk_exit_funct(),
+ no need to do this here (Alex J.) */
+ exit (errorcode);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_locale
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gchar*
+gdk_set_locale ()
+{
+ if (!setlocale (LC_ALL,""))
+ g_print ("locale not supported by C library\n");
+
+ if (!XSupportsLocale ())
+ {
+ g_print ("locale not supported by Xlib, locale set to C\n");
+ setlocale (LC_ALL, "C");
+ }
+
+ if (!XSetLocaleModifiers (""))
+ {
+ g_print ("can not set locale modifiers\n");
+ }
+
+ return setlocale (LC_ALL,NULL);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_events_pending
+ *
+ * Returns the number of events pending on the queue.
+ * These events have already been read from the server
+ * connection.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the number of events on XLib's event queue.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_events_pending ()
+{
+ return XPending (gdk_display);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_get
+ *
+ * Gets the next event.
+ *
+ * Arguments:
+ * "event" is used to hold the received event.
+ * If "event" is NULL an event is received as normal
+ * however it is not placed in "event" (and thus no
+ * error occurs).
+ *
+ * Results:
+ * Returns TRUE if an event was received that we care about
+ * and FALSE otherwise. This function will also return
+ * before an event is received if the timeout interval
+ * runs out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_event_get (GdkEvent *event,
+ GdkEventFunc pred,
+ gpointer data)
+{
+ GdkEvent *temp_event;
+ GdkPredicate event_pred;
+ GList *temp_list;
+ XEvent xevent;
+
+ /* If the last event we received was a destroy notify
+ * event then we will actually destroy the "gdk" data
+ * structures now. We don't want to destroy them at the
+ * time of receiving the event since the main program
+ * may try to access them and may need to destroy user
+ * data that has been attached to the window
+ */
+ if (received_destroy_notify)
+ {
+ if (gdk_show_events)
+ g_print ("destroying window:\twindow: %ld\n",
+ ((GdkWindowPrivate*) window_to_destroy)->xwindow - base_id);
+
+ gdk_window_real_destroy (window_to_destroy);
+ received_destroy_notify = FALSE;
+ window_to_destroy = NULL;
+ }
+
+ /* Initially we haven't received an event and want to
+ * return FALSE. If "event" is non-NULL, then initialize
+ * it to the nothing event.
+ */
+ if (event)
+ {
+ event->any.type = GDK_NOTHING;
+ event->any.window = NULL;
+ event->any.send_event = FALSE;
+ }
+
+ if (pred)
+ {
+ temp_list = putback_events;
+ while (temp_list)
+ {
+ temp_event = temp_list->data;
+
+ if ((* pred) (temp_event, data))
+ {
+ if (event)
+ *event = *temp_event;
+ putback_events = g_list_remove_link (putback_events, temp_list);
+ g_list_free (temp_list);
+ return TRUE;
+ }
+
+ temp_list = temp_list->next;
+ }
+
+ event_pred.func = pred;
+ event_pred.data = data;
+
+ if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) &event_pred))
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ else
+ {
+ if (putback_events)
+ {
+ temp_event = putback_events->data;
+ *event = *temp_event;
+
+ temp_list = putback_events;
+ putback_events = putback_events->next;
+ if (putback_events)
+ putback_events->prev = NULL;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+ g_list_free (temp_list);
+ g_free (temp_event);
+
+ return TRUE;
+ }
+
+ /* Wait for an event to occur or the timeout to elapse.
+ * If an event occurs "gdk_event_wait" will return TRUE.
+ * If the timeout elapses "gdk_event_wait" will return
+ * FALSE.
+ */
+ if (gdk_event_wait ())
+ {
+ /* If we get here we can rest assurred that an event
+ * has occurred. Read it.
+ */
+ XNextEvent (gdk_display, &xevent);
+
+ event->any.send_event = xevent.xany.send_event;
+
+ /* If "event" non-NULL.
+ */
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ }
+
+ return FALSE;
+}
+
+void
+gdk_event_put (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_if_fail (event != NULL);
+
+ new_event = g_new (GdkEvent, 1);
+ *new_event = *event;
+
+ putback_events = g_list_prepend (putback_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;
+
+GdkEvent*
+gdk_event_copy (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_val_if_fail (event != NULL, NULL);
+
+ 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);
+ *new_event = *event;
+ gdk_window_ref (new_event->any.window);
+ 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);
+
+ gdk_window_unref (event->any.window);
+ g_mem_chunk_free (event_chunk, event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_debug_level
+ *
+ * Sets the debugging level.
+ *
+ * Arguments:
+ * "level" is the new debugging level.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Other function calls to "gdk" use the debugging
+ * level to determine what kind of debugging information
+ * to print out.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_set_debug_level (int level)
+{
+ gdk_debug_level = level;
+}
+
+/*
+ *--------------------------------------------------------------
+ * 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)
+{
+ gdk_show_events = show_events;
+}
+
+void
+gdk_set_use_xshm (gint use_xshm)
+{
+ gdk_use_xshm = use_xshm;
+}
+
+gint
+gdk_get_debug_level ()
+{
+ return gdk_debug_level;
+}
+
+gint
+gdk_get_show_events ()
+{
+ return gdk_show_events;
+}
+
+gint
+gdk_get_use_xshm ()
+{
+ return gdk_use_xshm;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_time_get
+ *
+ * Get the number of milliseconds since the library was
+ * initialized.
+ *
+ * Arguments:
+ *
+ * Results:
+ * The time since the library was initialized is returned.
+ * This time value is accurate to milliseconds even though
+ * a more accurate time down to the microsecond could be
+ * returned.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_time_get ()
+{
+ struct timeval end;
+ struct timeval elapsed;
+ guint32 milliseconds;
+
+ X_GETTIMEOFDAY (&end);
+
+ if (start.tv_usec > end.tv_usec)
+ {
+ end.tv_usec += 1000000;
+ end.tv_sec--;
+ }
+ elapsed.tv_sec = end.tv_sec - start.tv_sec;
+ elapsed.tv_usec = end.tv_usec - start.tv_usec;
+
+ milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
+
+ return milliseconds;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_get
+ *
+ * Returns the current timer.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the current timer interval. This interval is
+ * in units of milliseconds.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_timer_get ()
+{
+ return timer_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_set
+ *
+ * Sets the timer interval.
+ *
+ * Arguments:
+ * "milliseconds" is the new value for the timer.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Calls to "gdk_event_get" will last for a maximum
+ * of time of "milliseconds". However, a value of 0
+ * milliseconds will cause "gdk_event_get" to block
+ * indefinately until an event is received.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_timer_set (guint32 milliseconds)
+{
+ timer_val = milliseconds;
+ timer.tv_sec = milliseconds / 1000;
+ timer.tv_usec = (milliseconds % 1000) * 1000;
+
+}
+
+void
+gdk_timer_enable ()
+{
+ timerp = &timer;
+}
+
+void
+gdk_timer_disable ()
+{
+ timerp = NULL;
+}
+
+gint
+gdk_input_add (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data)
+{
+ static gint next_tag = 1;
+ GList *list;
+ GdkInput *input;
+ gint tag;
+
+ tag = 0;
+ list = inputs;
+
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if ((input->source == source) && (input->condition == condition))
+ {
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+ }
+ }
+
+ if (!tag)
+ {
+ input = g_new (GdkInput, 1);
+ input->tag = next_tag++;
+ input->source = source;
+ input->condition = condition;
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+
+ inputs = g_list_prepend (inputs, input);
+ }
+
+ return tag;
+}
+
+void
+gdk_input_remove (gint tag)
+{
+ GList *list;
+ GList *temp_list;
+ GdkInput *input;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+
+ if (input->tag == tag)
+ {
+ temp_list = list;
+
+ if (list->next)
+ list->next->prev = list->prev;
+ if (list->prev)
+ list->prev->next = list->next;
+ if (inputs == list)
+ inputs = list->next;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+
+ g_free (temp_list->data);
+ g_list_free (temp_list);
+ break;
+ }
+
+ list = list->next;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
+ *
+ * Grabs the pointer to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "event_mask" masks only interesting events
+ * "confine_to" limits the cursor movement to the specified window
+ * "cursor" changes the cursor for the duration of the grab
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_pointer_grab (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ GdkCursor * cursor,
+ guint32 time)
+{
+ /* From gdkwindow.c */
+ extern int nevent_masks;
+ extern int event_mask_table[];
+
+ gint return_val;
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *confine_to_private;
+ GdkCursorPrivate *cursor_private;
+ guint xevent_mask;
+ Window xwindow;
+ Window xconfine_to;
+ Cursor xcursor;
+ int i;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ confine_to_private = (GdkWindowPrivate*) confine_to;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ xwindow = window_private->xwindow;
+
+ if (!confine_to)
+ xconfine_to = None;
+ else
+ xconfine_to = confine_to_private->xwindow;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+
+ xevent_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ if (((GdkWindowPrivate *)window)->extension_events &&
+ gdk_input_vtable.grab_pointer)
+ return_val = gdk_input_vtable.grab_pointer (window,
+ owner_events,
+ event_mask,
+ confine_to,
+ time);
+ else
+ return_val = Success;;
+
+ if (return_val == Success)
+ return_val = XGrabPointer (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ xevent_mask,
+ GrabModeAsync, GrabModeAsync,
+ xconfine_to,
+ xcursor,
+ time);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_ungrab
+ *
+ * Releases any pointer grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_pointer_ungrab (guint32 time)
+{
+ if (gdk_input_vtable.ungrab_pointer)
+ gdk_input_vtable.ungrab_pointer (time);
+
+ XUngrabPointer (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_grab
+ *
+ * Grabs the keyboard to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_keyboard_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_keyboard_grab (GdkWindow * window,
+ gint owner_events,
+ guint32 time)
+{
+ GdkWindowPrivate *window_private;
+ Window xwindow;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ xwindow = window_private->xwindow;
+
+ return XGrabKeyboard (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ GrabModeAsync, GrabModeAsync,
+ time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_ungrab
+ *
+ * Releases any keyboard grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_keyboard_ungrab (guint32 time)
+{
+ XUngrabKeyboard (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_width
+ *
+ * Return the width of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_width ()
+{
+ gint return_val;
+
+ return_val = DisplayWidth (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_height
+ *
+ * Return the height of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_height ()
+{
+ gint return_val;
+
+ return_val = DisplayHeight (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+void
+gdk_key_repeat_disable ()
+{
+ XAutoRepeatOff (gdk_display);
+}
+
+void
+gdk_key_repeat_restore ()
+{
+ if (autorepeat)
+ XAutoRepeatOn (gdk_display);
+ else
+ XAutoRepeatOff (gdk_display);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * 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 ()
+{
+ XSync (gdk_display, False);
+}
+
+
+void
+gdk_beep ()
+{
+ XBell(gdk_display, 100);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_wait
+ *
+ * Waits until an event occurs or the timer runs out.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns TRUE if an event is ready to be read and FALSE
+ * if the timer ran out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static gint
+gdk_event_wait ()
+{
+ GList *list;
+ GdkInput *input;
+ GdkInputCondition condition;
+ SELECT_MASK readfds;
+ SELECT_MASK writefds;
+ SELECT_MASK exceptfds;
+ int max_input;
+ int nfd;
+
+ /* If there are no events pending we will wait for an event.
+ * The time we wait is dependant on the "timer". If no timer
+ * has been specified then we'll block until an event arrives.
+ * If a timer has been specified we'll block until an event
+ * arrives or the timer expires. (This is all done using the
+ * "select" system call).
+ */
+
+ if (XPending (gdk_display) == 0)
+ {
+ FD_ZERO (&readfds);
+ FD_ZERO (&writefds);
+ FD_ZERO (&exceptfds);
+
+ FD_SET (connection_number, &readfds);
+ max_input = connection_number;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if (input->condition & GDK_INPUT_READ)
+ FD_SET (input->source, &readfds);
+ if (input->condition & GDK_INPUT_WRITE)
+ FD_SET (input->source, &writefds);
+ if (input->condition & GDK_INPUT_EXCEPTION)
+ FD_SET (input->source, &exceptfds);
+
+ max_input = MAX (max_input, input->source);
+ }
+
+ nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
+
+ timerp = NULL;
+ timer_val = 0;
+
+ if (nfd > 0)
+ {
+ if (FD_ISSET (connection_number, &readfds))
+ {
+ if (XPending (gdk_display) == 0)
+ {
+ if (nfd == 1)
+ {
+ XNoOp (gdk_display);
+ XFlush (gdk_display);
+ }
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ condition = 0;
+ if (FD_ISSET (input->source, &readfds))
+ condition |= GDK_INPUT_READ;
+ if (FD_ISSET (input->source, &writefds))
+ condition |= GDK_INPUT_WRITE;
+ if (FD_ISSET (input->source, &exceptfds))
+ condition |= GDK_INPUT_EXCEPTION;
+
+ if (condition && input->function)
+ (* input->function) (input->data, input->source, condition);
+ }
+ }
+ }
+ else
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+gdk_event_translate (GdkEvent *event,
+ XEvent *xevent)
+{
+
+ GdkWindow *window;
+ GdkWindowPrivate *window_private;
+ XComposeStatus compose;
+ int charcount;
+ char buf[16];
+ gint return_val;
+
+ /* Are static variables used for this purpose thread-safe? */
+ static GdkPoint dnd_drag_start = {0,0},
+ dnd_drag_oldpos = {0,0};
+ static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
+ static gint dnd_drag_perhaps = 0;
+ static GdkWindowPrivate *real_sw = NULL;
+ static Window dnd_drag_curwin = None, dnd_drag_target = None;
+
+ return_val = FALSE;
+
+ /* Find the GdkWindow that this event occurred in.
+ * All events occur in some GdkWindow (otherwise, why
+ * would we be receiving them). It really is an error
+ * to receive an event for which we cannot find the
+ * corresponding GdkWindow. 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;
+
+ /* 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.
+ */
+ /* Addendum:
+ * During drag & drop you get events where the pointer is
+ * in other windows. Need to just do finer-grained checking
+ */
+ switch (xevent->type)
+ {
+ case KeyPress:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key press:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ XKeysymToString (event->key.keyval),
+ event->key.keyval);
+
+ event->key.type = GDK_KEY_PRESS;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeyRelease:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key release:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ButtonPress:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ 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.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;
+ }
+ if(window_private
+ && window_private->dnd_drag_enabled
+ && !dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ dnd_drag_perhaps = 1;
+ dnd_drag_start.x = xevent->xbutton.x_root;
+ dnd_drag_start.y = xevent->xbutton.y_root;
+ real_sw = window_private;
+
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+ gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
+
+ {
+ /* Set motion mask for first DnD'd window, since it
+ will be the one that is actually dragged */
+ XWindowAttributes dnd_winattr;
+ XSetWindowAttributes dnd_setwinattr;
+ Status rv;
+
+ /* We need to get motion events while the button is down, so
+ we can know whether to really start dragging or not... */
+ XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
+ &dnd_winattr);
+
+ window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
+ dnd_setwinattr.event_mask =
+ window_private->dnd_drag_eventmask = ButtonMotionMask;
+ XChangeWindowAttributes(gdk_display, window_private->xwindow,
+ CWEventMask, &dnd_setwinattr);
+ }
+ }
+ return_val = window_private?(!window_private->destroyed):FALSE;
+ break;
+
+ case ButtonRelease:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ 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.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(dnd_drag_perhaps)
+ {
+ if(gdk_dnd.drag_really)
+ {
+ GdkPoint foo = {xevent->xbutton.x_root,
+ xevent->xbutton.y_root};
+ XUngrabPointer(gdk_display, CurrentTime);
+
+ if(dnd_drag_target != None)
+ gdk_dnd_drag_end(dnd_drag_target, foo);
+ gdk_dnd.drag_really = 0;
+
+ if(gdk_dnd.drag_numwindows)
+ {
+ XSetWindowAttributes attrs;
+ /* Reset event mask to pre-drag value, assuming event_mask
+ doesn't change during drag */
+ attrs.event_mask = real_sw->dnd_drag_savedeventmask;
+ XChangeWindowAttributes(gdk_display, real_sw->xwindow,
+ CWEventMask, &attrs);
+ }
+
+ gdk_dnd.drag_numwindows = 0;
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+
+ real_sw = NULL;
+ }
+
+ dnd_drag_perhaps = 0;
+ dnd_drag_start.x = dnd_drag_start.y = 0;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_curwin = None;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case MotionNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
+ xevent->xmotion.window - base_id,
+ xevent->xmotion.x, xevent->xmotion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false",
+ dnd_drag_perhaps, gdk_dnd.drag_really);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ 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.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;
+
+#define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
+ && cy >= dnd_drag_dropzone.y \
+ && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
+ && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
+
+ if(dnd_drag_perhaps && gdk_dnd.drag_really)
+ {
+ /* First, we have to find what window the motion was in... */
+ /* XXX there has to be a better way to do this, perhaps with
+ XTranslateCoordinates or XQueryTree - I don't know how,
+ and this sort of works */
+ Window curwin, childwin = gdk_root_window, rootwinret;
+ int x, y;
+ unsigned int mask;
+ while(childwin != None)
+ {
+ curwin = childwin;
+ XQueryPointer(gdk_display, curwin, &rootwinret, &childwin,
+ &x, &y, &x, &y, &mask);
+ }
+ if(curwin != dnd_drag_curwin)
+ {
+ /* We have left one window and entered another
+ (do leave & enter bits) */
+ if(dnd_drag_curwin != real_sw->xwindow && dnd_drag_curwin != None)
+ gdk_dnd_drag_leave(dnd_drag_curwin);
+ dnd_drag_curwin = curwin;
+ gdk_dnd_drag_enter(dnd_drag_curwin);
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_target = None;
+ XChangeActivePointerGrab(gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragdefault,
+ CurrentTime);
+ }
+ else if(dnd_drag_dropzone.width > 0
+ && dnd_drag_dropzone.height > 0)
+ {
+ /* Handle all that dropzone stuff - thanks John ;-) */
+ if(dnd_drag_target != None
+ && IS_IN_ZONE(dnd_drag_oldpos.x, dnd_drag_oldpos.y)
+ && !IS_IN_ZONE(xevent->xmotion.x_root,
+ xevent->xmotion.y_root))
+ {
+ /* We were in the drop zone and moved out */
+ dnd_drag_target = None;
+ gdk_dnd_drag_leave(curwin);
+ }
+ else
+ {
+ /* We were outside drop zone but in the window
+ - have to send enter events */
+ gdk_dnd_drag_enter(curwin);
+ dnd_drag_curwin = curwin;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_target = None;
+ }
+ } else
+ dnd_drag_curwin = None;
+ return_val = FALSE;
+ }
+ else
+ return_val = window?(!window_private->destroyed):FALSE;
+ break;
+
+ case EnterNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail,
+ xevent->xcrossing.subwindow - base_id);
+
+ /* Tell XInput stuff about it if appropriate */
+ if (window_private &&
+ (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;
+
+ /* 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;
+ }
+
+ if(dnd_drag_perhaps
+ && gdk_dnd.drag_really
+ && xevent->xcrossing.window == real_sw->xwindow)
+ {
+ gdk_dnd.drag_really = 0;
+ XUngrabPointer(gdk_display, CurrentTime);
+ }
+
+ return_val = (window ? !window_private->destroyed : FALSE);
+ break;
+
+ case LeaveNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id);
+
+ event->crossing.type = GDK_LEAVE_NOTIFY;
+ event->crossing.window = window;
+
+ /* 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;
+ }
+ if(dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
+ gdk_dnd_drag_begin((GdkWindow *) real_sw);
+ XGrabPointer(gdk_display, real_sw->xwindow, False,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ GrabModeAsync, GrabModeAsync, gdk_root_window,
+ gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
+ gdk_dnd.drag_really = 1;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case FocusIn:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus in:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = TRUE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case FocusOut:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus out:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = FALSE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeymapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("keymap notify\n");
+
+ /* Not currently handled */
+ break;
+
+ case Expose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
+ xevent->xexpose.window - base_id, xevent->xexpose.count,
+ xevent->xexpose.x, xevent->xexpose.y,
+ xevent->xexpose.width, xevent->xexpose.height);
+
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case GraphicsExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("graphics expose:\tdrawable: %ld\n",
+ xevent->xgraphicsexpose.drawable - base_id);
+
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case NoExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("no expose:\t\tdrawable: %ld\n",
+ xevent->xnoexpose.drawable - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case VisibilityNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ switch (xevent->xvisibility.state)
+ {
+ case VisibilityFullyObscured:
+ g_print ("visibility notify:\twindow: %ld none\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityPartiallyObscured:
+ g_print ("visibility notify:\twindow: %ld partial\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityUnobscured:
+ g_print ("visibility notify:\twindow: %ld full\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ }
+
+ /* Not currently handled */
+ break;
+
+ case CreateNotify:
+ /* Not currently handled */
+ break;
+
+ case DestroyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("destroy notify:\twindow: %ld\n",
+ xevent->xdestroywindow.window - base_id);
+
+ event->any.type = GDK_DESTROY;
+ event->any.window = window;
+
+ /* Remeber which window received the destroy notify
+ * event so that we can destroy our associated
+ * data structures the next time the user asks
+ * us for an event.
+ */
+ received_destroy_notify = TRUE;
+ window_to_destroy = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case UnmapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("unmap notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_UNMAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case MapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("map notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_MAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ReparentNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("reparent notify:\twindow: %ld\n",
+ xevent->xreparent.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ConfigureNotify:
+ /* Print debugging info.
+ */
+ while ((XPending(gdk_display) > 0) &&
+ XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
+ ConfigureNotify, xevent))
+ /*XSync(gdk_display, 0)*/;
+
+ if (gdk_show_events)
+ g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d\n",
+ xevent->xconfigure.window - base_id,
+ xevent->xconfigure.x, xevent->xconfigure.y,
+ xevent->xconfigure.width, xevent->xconfigure.height);
+
+ if (window_private &&
+ (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) &&
+ ((window_private->width != xevent->xconfigure.width) ||
+ (window_private->height != xevent->xconfigure.height)))
+ {
+ event->configure.type = GDK_CONFIGURE;
+ event->configure.window = window;
+ event->configure.x = xevent->xconfigure.x;
+ event->configure.y = xevent->xconfigure.y;
+ event->configure.width = xevent->xconfigure.width;
+ event->configure.height = xevent->xconfigure.height;
+
+ window_private->x = xevent->xconfigure.x;
+ window_private->y = xevent->xconfigure.y;
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+ if (window_private->resize_count > 1)
+ window_private->resize_count -= 1;
+
+ return_val = !window_private->destroyed;
+ }
+ break;
+
+ case PropertyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("property notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case SelectionClear:
+ if (gdk_show_events)
+ g_print ("selection clear:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->selection.type = GDK_SELECTION_CLEAR;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionclear.selection;
+ event->selection.time = xevent->xselectionclear.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionRequest:
+ if (gdk_show_events)
+ g_print ("selection request:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ 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;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionNotify:
+ if (gdk_show_events)
+ g_print ("selection notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+
+ 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;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case ColormapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("colormap notify:\twindow: %ld\n",
+ xevent->xcolormap.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ClientMessage:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("client message:\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ /* Client messages are the means of the window manager
+ * communicating with a program. We'll first check to
+ * see if this is really the window manager talking
+ * to us.
+ */
+ if (xevent->xclient.message_type == gdk_wm_protocols)
+ {
+ 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.
+ */
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("delete window:\t\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ event->any.type = GDK_DELETE;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ }
+ else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
+ {
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
+ {
+ Atom reptype = 0;
+
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ if (gdk_show_events)
+ g_print ("GDK_DROP_ENTER\n");
+ return_val = FALSE;
+
+ /* Now figure out if we really want this drop...
+ * If someone is trying funky clipboard stuff, ignore
+ */
+ if (window_private
+ && window_private->dnd_drop_enabled
+ && event->dropenter.u.flags.sendreply
+ && (reptype = gdk_dnd_check_types (window, xevent)))
+ {
+ XEvent replyev;
+
+ replyev.xclient.type = ClientMessage;
+ replyev.xclient.window = xevent->xclient.data.l[0];
+ replyev.xclient.format = 32;
+ replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
+ replyev.xclient.data.l[0] = window_private->xwindow;
+
+ event->dragrequest.u.allflags = 0;
+ event->dragrequest.u.flags.protocol_version =
+ DND_PROTOCOL_VERSION;
+ event->dragrequest.u.flags.willaccept = 1;
+ event->dragrequest.u.flags.delete_data =
+ (window_private->dnd_drop_destructive_op) ? 1 : 0;
+
+ replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
+ replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
+ replyev.xclient.data.l[4] = reptype;
+
+ XSendEvent (gdk_display, replyev.xclient.window,
+ False, NoEventMask, &replyev);
+
+ event->any.type = GDK_DROP_ENTER;
+ event->dropenter.requestor = replyev.xclient.window;
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
+ {
+ if (gdk_show_events)
+ g_print ("GDK_DROP_LEAVE\n");
+ if (window_private && window_private->dnd_drop_enabled)
+ {
+ event->dropleave.type = GDK_DROP_LEAVE;
+ event->dropleave.window = window;
+ event->dropleave.requestor = xevent->xclient.data.l[0];
+ event->dropleave.u.allflags = xevent->xclient.data.l[1];
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
+ {
+ /*
+ * make sure to only handle requests from the window the cursor is
+ * over
+ */
+ if (gdk_show_events)
+ g_print ("GDK_DRAG_REQUEST\n");
+ event->dragrequest.u.allflags = xevent->xclient.data.l[1];
+ return_val = FALSE;
+
+ if (window && gdk_dnd.drag_really &&
+ xevent->xclient.data.l[0] == dnd_drag_curwin &&
+ event->dragrequest.u.flags.sendreply == 0)
+ {
+ /* Got request - do we need to ask user? */
+ if (!event->dragrequest.u.flags.willaccept
+ && event->dragrequest.u.flags.senddata)
+ {
+ /* Yes we do :) */
+ event->dragrequest.type = GDK_DRAG_REQUEST;
+ event->dragrequest.window = window;
+ event->dragrequest.requestor = xevent->xclient.data.l[0];
+ event->dragrequest.isdrop = 0;
+ event->dragrequest.drop_coords.x =
+ event->dragrequest.drop_coords.y = 0;
+ return_val = TRUE;
+ }
+ else if (event->dragrequest.u.flags.willaccept)
+ {
+ window_private->dnd_drag_destructive_op =
+ event->dragrequest.u.flags.delete_data;
+ window_private->dnd_drag_accepted = 1;
+ window_private->dnd_drag_data_type =
+ xevent->xclient.data.l[4];
+
+ dnd_drag_target = dnd_drag_curwin;
+ XChangeActivePointerGrab (gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragok,
+ CurrentTime);
+ }
+ dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
+ dnd_drag_dropzone.y =
+ (xevent->xclient.data.l[2] >> 16) & 65535;
+ dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
+ dnd_drag_dropzone.height =
+ (xevent->xclient.data.l[3] >> 16) & 65535;
+ }
+ }
+ else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
+ {
+ gint tmp_int; Atom tmp_atom;
+ gulong tmp_long;
+ guchar *tmp_charptr;
+ gpointer tmp_ptr;
+
+ if(gdk_show_events)
+ g_print("GDK_DROP_DATA_AVAIL\n");
+ event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
+ if(window
+ /* No preview of data ATM */
+ && event->dropdataavailable.u.flags.isdrop)
+ {
+ event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
+ event->dropdataavailable.window = window;
+ event->dropdataavailable.requestor = xevent->xclient.data.l[0];
+ event->dropdataavailable.data_type =
+ gdk_atom_name(xevent->xclient.data.l[2]);
+ if(XGetWindowProperty (gdk_display,
+ event->dropdataavailable.requestor,
+ xevent->xclient.data.l[2],
+ 0, LONG_MAX - 1,
+ False, XA_PRIMARY, &tmp_atom,
+ &tmp_int,
+ &event->dropdataavailable.data_numbytes,
+ &tmp_long,
+ &tmp_charptr)
+ != Success)
+ {
+ g_warning("XGetWindowProperty on %#x may have failed\n",
+ event->dropdataavailable.requestor);
+ event->dropdataavailable.data = NULL;
+ }
+ else
+ {
+ g_print("XGetWindowProperty got us %d bytes\n",
+ event->dropdataavailable.data_numbytes);
+ event->dropdataavailable.data =
+ g_malloc(event->dropdataavailable.data_numbytes);
+ memcpy(event->dropdataavailable.data,
+ tmp_charptr, event->dropdataavailable.data_numbytes);
+ XFree(tmp_charptr);
+ return_val = TRUE;
+ }
+ return_val = TRUE;
+ }
+ } else {
+ /* 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));
+ return_val = TRUE;
+ }
+ return_val = return_val && !window_private->destroyed;
+ break;
+
+ case MappingNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("mapping notify\n");
+
+ /* Let XLib know that there is a new keyboard mapping.
+ */
+ XRefreshKeyboardMapping (&xevent->xmapping);
+ break;
+
+ default:
+ /* something else - (e.g., a Xinput event) */
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.other_event)
+ return_val = gdk_input_vtable.other_event(event, xevent, window);
+
+ if (return_val < 0) /* not an XInput event, convert */
+ {
+ event->other.type = GDK_OTHER_EVENT;
+ event->other.window = window;
+ event->other.xevent = &other_xevent[other_xevent_i];
+ memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
+ other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
+ return_val = TRUE;
+ }
+
+ return_val = return_val && !window_private->destroyed;
+ break;
+ }
+
+ return return_val;
+}
+
+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;
+}
+
+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);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit_func
+ *
+ * This is the "atexit" function that makes sure the
+ * library gets a chance to cleanup.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ * The library is un-initialized and the program exits.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+gdk_exit_func ()
+{
+ if (initialized)
+ {
+ gdk_image_exit ();
+ gdk_input_exit ();
+ gdk_key_repeat_restore ();
+
+ XCloseDisplay (gdk_display);
+ initialized = 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_error
+ *
+ * The X error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ * "error" is the XErrorEvent that we are handling.
+ *
+ * Results:
+ * Either we were expecting some sort of error to occur,
+ * in which case we set the "gdk_error_code" flag, or this
+ * error was unexpected, in which case we will print an
+ * error message and exit. (Since trying to continue will
+ * most likely simply lead to more errors).
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_error (Display *display,
+ XErrorEvent *error)
+{
+ char buf[64];
+
+ if (gdk_error_warnings)
+ {
+ XGetErrorText (display, error->error_code, buf, 63);
+ g_error ("%s", buf);
+ }
+
+ gdk_error_code = -1;
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_io_error
+ *
+ * The X I/O error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ *
+ * Results:
+ * An X I/O error basically means we lost our connection
+ * to the X server. There is not much we can do to
+ * continue, so simply print an error message and exit.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_io_error (Display *display)
+{
+ g_error ("an x io error occurred");
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_signal
+ *
+ * The signal handler.
+ *
+ * Arguments:
+ * "sig_num" is the number of the signal we received.
+ *
+ * Results:
+ * The signals we catch are all fatal. So we simply build
+ * up a nice little error message and print it and exit.
+ * If in the process of doing so another signal is received
+ * we notice that we are already exiting and simply kill
+ * our process.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static RETSIGTYPE
+gdk_signal (int sig_num)
+{
+ static int caught_fatal_sig = 0;
+ char *sig;
+
+ if (caught_fatal_sig)
+ kill (getpid (), sig_num);
+ caught_fatal_sig = 1;
+
+ switch (sig_num)
+ {
+ case SIGHUP:
+ sig = "sighup";
+ break;
+ case SIGINT:
+ sig = "sigint";
+ break;
+ case SIGQUIT:
+ sig = "sigquit";
+ break;
+ case SIGBUS:
+ sig = "sigbus";
+ break;
+ case SIGSEGV:
+ sig = "sigsegv";
+ break;
+ case SIGPIPE:
+ sig = "sigpipe";
+ break;
+ case SIGTERM:
+ sig = "sigterm";
+ break;
+ default:
+ sig = "unknown signal";
+ break;
+ }
+
+ g_print ("\n** ERROR **: %s caught\n", sig);
+ gdk_exit (1);
+}
+
+static void
+gdk_dnd_drag_begin (GdkWindow *initial_window)
+{
+ GdkEventDragBegin tev;
+ tev.type = GDK_DRAG_BEGIN;
+ tev.window = initial_window;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+
+ gdk_event_put ((GdkEvent *) &tev);
+}
+
+static void
+gdk_dnd_drag_enter (Window dest)
+{
+ XEvent sev;
+ GdkEventDropEnter tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
+ sev.xclient.window = dest;
+
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.u.flags.sendreply = 1;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_data_numtypesavail)
+ {
+ sev.xclient.data.l[0] = wp->xwindow;
+ tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
+ if (wp->dnd_drag_data_numtypesavail > 1)
+ {
+ sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
+ if (wp->dnd_drag_data_numtypesavail > 2)
+ {
+ sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
+ }
+ else
+ sev.xclient.data.l[4] = None;
+ }
+ else
+ sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
+ XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
+ }
+
+ }
+}
+
+static void
+gdk_dnd_drag_leave (Window dest)
+{
+ XEvent sev;
+ GdkEventDropLeave tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ tev.u.allflags = 0;
+
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ sev.xclient.type = ClientMessage;
+ sev.xclient.window = dest;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ sev.xclient.data.l[0] = wp->xwindow;
+ XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
+ wp->dnd_drag_accepted = 0;
+ }
+}
+
+/*
+ * when a drop occurs, we go through the list of windows being dragged and
+ * tell them that it has occurred, so that they can set things up and reply
+ * to 'dest' window
+ */
+static void
+gdk_dnd_drag_end (Window dest,
+ GdkPoint coords)
+{
+ GdkWindowPrivate *wp;
+ GdkEventDragRequest tev;
+ gchar *tmp_cptr;
+ int i;
+
+ tev.type = GDK_DRAG_REQUEST;
+ tev.drop_coords = coords;
+ tev.requestor = dest;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.isdrop = 1;
+
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_accepted)
+ {
+ tev.window = (GdkWindow *) wp;
+ tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
+ tev.data_type =
+ gdk_atom_name(wp->dnd_drag_data_type);
+
+ gdk_event_put((GdkEvent *) &tev);
+ }
+ }
+}
+
+static GdkAtom
+gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent)
+{
+ GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
+ int i, j;
+ GdkEventDropEnter event;
+
+ g_return_val_if_fail(window != NULL, 0);
+ g_return_val_if_fail(xevent != NULL, 0);
+ g_return_val_if_fail(xevent->type == ClientMessage, 0);
+ g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
+
+ if(wp->dnd_drop_data_numtypesavail <= 0 ||
+ !wp->dnd_drop_data_typesavail)
+ return 0;
+
+ for (i = 2; i <= 4; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
+ return xevent->xclient.data.l[i];
+ }
+ }
+
+ /* Now we get the extended type list if it's available */
+ event.u.allflags = xevent->xclient.data.l[1];
+ if (event.u.flags.extended_typelist)
+ {
+ Atom *exttypes, realtype;
+ gulong nitems, nbar;
+ gint realfmt;
+
+ if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
+ gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
+ False, AnyPropertyType, &realtype, &realfmt,
+ &nitems, &nbar, (unsigned char **) &exttypes)
+ != Success)
+ return 0;
+
+ if (realfmt != (sizeof(Atom) * 8))
+ {
+ g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
+ realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
+ return 0;
+ }
+
+ for (i = 0; i <= nitems; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
+ {
+ XFree (exttypes);
+ return exttypes[i];
+ }
+ }
+ }
+ XFree (exttypes);
+ }
+ return 0;
+}
+
+/*
+ * used for debugging only
+ */
+static void
+gdk_print_atom (GdkAtom anatom)
+{
+ gchar *tmpstr = NULL;
+ tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
+ g_print("Atom %lu has name %s\n", anatom, tmpstr);
+ if(tmpstr)
+ g_free(tmpstr);
+}
+
+/*
+ * used only by below routine and itself
+ */
+static Window
+getchildren (Display *dpy,
+ Window win,
+ Atom WM_STATE)
+{
+ Window root, parent, *children, inf = 0;
+ Atom type = None;
+ unsigned int nchildren, i;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+
+ if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
+ return 0;
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ {
+ XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
+ AnyPropertyType, &type, &format, &nitems,
+ &after, &data);
+ if (type != 0)
+ inf = children[i];
+ }
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ inf = getchildren (dpy, children[i], WM_STATE);
+
+ if (children != 0)
+ XFree ((char *) children);
+
+ return inf;
+}
+
+/*
+ * find a window with WM_STATE, else return win itself, as per ICCCM
+ *
+ * modification of the XmuClientWindow() routine from X11R6.3
+ */
+Window
+gdk_get_client_window (Display *dpy,
+ Window win)
+{
+ Atom WM_STATE;
+ Atom type = None;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+ Window inf;
+
+ if (win == 0)
+ return DefaultRootWindow(dpy);
+
+ if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
+ return win;
+
+ XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &data);
+ if (type)
+ return win;
+
+ inf = getchildren (dpy, win, WM_STATE);
+
+ if (inf == 0)
+ return win;
+ else
+ return inf;
+}
+
+static GdkWindow *
+gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y)
+{
+ GdkWindow *retval = w;
+ GdkWindowPrivate *awin;
+ GList *children;
+ gint16 myx = *x, myy = *y;
+
+ g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
+
+ myx = *x;
+ myy = *y;
+
+descend:
+ for (children = gdk_window_get_children(retval);
+ children && children->next;
+ children = children->next)
+ {
+ awin = (GdkWindowPrivate *) children->data;
+ if ((myx >= awin->x) && (myy >= awin->y)
+ && (myx < (awin->x + awin->width))
+ && (myy < (awin->y + awin->height)))
+ {
+ retval = (GdkWindow *) awin;
+ myx -= awin->x;
+ myy -= awin->y;
+ goto descend;
+ }
+ }
+
+ *x = myx;
+ *y = myy;
+
+ return retval;
+}
+
+/* Sends a ClientMessage to all toplevel client windows */
+void
+gdk_event_send_clientmessage_toall(GdkEvent *event)
+{
+ XEvent sev;
+ Window *ret_children, ret_root, ret_parent, curwin;
+ unsigned int ret_nchildren;
+ int i;
+
+ 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;
+ sev.xclient.serial = CurrentTime;
+ memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
+ sev.xclient.message_type = event->client.message_type;
+
+ /* OK, we're all set, now let's find some windows to send this to */
+ if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
+ &ret_children, &ret_nchildren) != True)
+ return;
+
+ /* foreach true child window of the root window, send an event to it */
+ for(i = 0; i < ret_nchildren; i++) {
+ curwin = gdk_get_client_window(gdk_display, ret_children[i]);
+ sev.xclient.window = curwin;
+ XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
+ }
+
+ XFree(ret_children);
+}
diff --git a/gdk/gdk.h b/gdk/gdk.h
new file mode 100644
index 000000000..ac341b206
--- /dev/null
+++ b/gdk/gdk.h
@@ -0,0 +1,614 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_H__
+#define __GDK_H__
+
+
+#include <gdk/gdktypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Initialization, exit and events
+ */
+void gdk_init (int *argc,
+ char ***argv);
+void gdk_exit (int error_code);
+gchar* gdk_set_locale (void);
+
+gint gdk_events_pending (void);
+gint gdk_event_get (GdkEvent *event,
+ GdkEventFunc pred,
+ gpointer data);
+void gdk_event_put (GdkEvent *event);
+
+GdkEvent *gdk_event_copy (GdkEvent *event);
+void gdk_event_free (GdkEvent *event);
+
+void gdk_set_debug_level (gint level);
+void gdk_set_show_events (gint show_events);
+void gdk_set_use_xshm (gint use_xshm);
+
+gint gdk_get_debug_level (void);
+gint gdk_get_show_events (void);
+gint gdk_get_use_xshm (void);
+
+guint32 gdk_time_get (void);
+guint32 gdk_timer_get (void);
+void gdk_timer_set (guint32 milliseconds);
+void gdk_timer_enable (void);
+void gdk_timer_disable (void);
+
+gint gdk_input_add (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data);
+void gdk_input_remove (gint tag);
+
+gint gdk_pointer_grab (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ GdkCursor * cursor,
+ guint32 time);
+void gdk_pointer_ungrab (guint32 time);
+
+gint gdk_keyboard_grab (GdkWindow * window,
+ gint owner_events,
+ guint32 time);
+void gdk_keyboard_ungrab (guint32 time);
+
+gint gdk_screen_width (void);
+gint gdk_screen_height (void);
+
+void gdk_flush (void);
+void gdk_beep (void);
+
+void gdk_key_repeat_disable (void);
+void gdk_key_repeat_restore (void);
+
+
+/* Visuals
+ */
+gint gdk_visual_get_best_depth (void);
+GdkVisualType gdk_visual_get_best_type (void);
+GdkVisual* gdk_visual_get_system (void);
+GdkVisual* gdk_visual_get_best (void);
+GdkVisual* gdk_visual_get_best_with_depth (gint depth);
+GdkVisual* gdk_visual_get_best_with_type (GdkVisualType visual_type);
+GdkVisual* gdk_visual_get_best_with_both (gint depth,
+ GdkVisualType visual_type);
+
+/* Actually, these are no-ops... */
+GdkVisual* gdk_visual_ref (GdkVisual *visual);
+void gdk_visual_unref (GdkVisual *visual);
+
+void gdk_query_depths (gint **depths,
+ gint *count);
+void gdk_query_visual_types (GdkVisualType **visual_types,
+ gint *count);
+void gdk_query_visuals (GdkVisual **visuals,
+ gint *count);
+
+
+/* Windows
+ */
+GdkWindow* gdk_window_new (GdkWindow *parent,
+ GdkWindowAttr *attributes,
+ gint attributes_mask);
+
+GdkWindow * gdk_window_foreign_new (guint32 anid);
+void gdk_window_destroy (GdkWindow *window);
+GdkWindow* gdk_window_ref (GdkWindow *window);
+void gdk_window_unref (GdkWindow *window);
+
+void gdk_window_show (GdkWindow *window);
+void gdk_window_hide (GdkWindow *window);
+void gdk_window_move (GdkWindow *window,
+ gint x,
+ gint y);
+void gdk_window_resize (GdkWindow *window,
+ gint width,
+ gint height);
+void gdk_window_move_resize (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y);
+void gdk_window_clear (GdkWindow *window);
+void gdk_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_window_clear_area_e(GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_window_copy_area (GdkWindow *window,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ GdkWindow *source_window,
+ gint source_x,
+ gint source_y,
+ gint width,
+ gint height);
+void gdk_window_raise (GdkWindow *window);
+void gdk_window_lower (GdkWindow *window);
+
+void gdk_window_set_user_data (GdkWindow *window,
+ gpointer user_data);
+
+
+/*
+ * This allows for making shaped (partially transparent) windows
+ * - cool feature, needed for Drag and Drag for example.
+ * The shape_mask can be the mask
+ * from gdk_pixmap_create_from_xpm. Stefan Wille
+ */
+void gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *shape_mask,
+ gint offset_x,
+ gint offset_y);
+
+/*
+ * Drag & Drop
+ * Algorithm (drop source):
+ * A window being dragged will be sent a GDK_DRAG_BEGIN message.
+ * It will then do gdk_dnd_drag_addwindow() for any other windows that are to be
+ * dragged.
+ * When we get a DROP_ENTER incoming, we send it on to the window in question.
+ * That window needs to use gdk_dnd_drop_enter_reply() to indicate the state of
+ * things (it must call that even if it's not going to accept the drop)
+ *
+ * These two turn on/off drag or drop, and if enabling it also
+ * sets the list of types supported. The list of types passed in
+ * should be in order of decreasing preference.
+ */
+void gdk_window_dnd_drag_set (GdkWindow *window,
+ guint8 drag_enable,
+ gchar **typelist,
+ guint numtypes);
+
+/*
+ *XXX todo: add a GDK_DROP_ENTER which can look at actual data
+ */
+void gdk_window_dnd_drop_set (GdkWindow *window,
+ guint8 drop_enable,
+ gchar **typelist,
+ guint numtypes,
+ guint8 destructive_op);
+
+/*
+ * This is used by the GDK_DRAG_BEGIN handler. An example of usage would be a
+ * file manager where multiple icons were selected and the drag began.
+ * The icon that the drag actually began on would gdk_dnd_drag_addwindow
+ * for all the other icons that were being dragged...
+ */
+void gdk_dnd_drag_addwindow (GdkWindow *window);
+void gdk_window_dnd_data_set (GdkWindow *window,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes);
+
+
+void gdk_window_set_hints (GdkWindow *window,
+ gint x,
+ gint y,
+ gint min_width,
+ gint min_height,
+ gint max_width,
+ gint max_height,
+ gint flags);
+void gdk_window_set_title (GdkWindow *window,
+ const gchar *title);
+void gdk_window_set_background (GdkWindow *window,
+ GdkColor *color);
+void gdk_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap,
+ gint parent_relative);
+void gdk_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor);
+void gdk_window_set_colormap (GdkWindow *window,
+ GdkColormap *colormap);
+void gdk_window_get_user_data (GdkWindow *window,
+ gpointer *data);
+void gdk_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth);
+void gdk_window_get_position (GdkWindow *window,
+ gint *x,
+ gint *y);
+void gdk_window_get_size (GdkWindow *window,
+ gint *width,
+ gint *height);
+GdkVisual* gdk_window_get_visual (GdkWindow *window);
+GdkColormap* gdk_window_get_colormap (GdkWindow *window);
+GdkWindowType gdk_window_get_type (GdkWindow *window);
+gint gdk_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y);
+GdkWindow* gdk_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask);
+GdkWindow* gdk_window_get_parent (GdkWindow *window);
+GdkWindow* gdk_window_get_toplevel (GdkWindow *window);
+GList* gdk_window_get_children (GdkWindow *window);
+GdkEventMask gdk_window_get_events (GdkWindow *window);
+void gdk_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask);
+
+/* Cursors
+ */
+GdkCursor* gdk_cursor_new (GdkCursorType cursor_type);
+void gdk_cursor_destroy (GdkCursor *cursor);
+
+
+/* GCs
+ */
+GdkGC* gdk_gc_new (GdkWindow *window);
+GdkGC* gdk_gc_new_with_values (GdkWindow *window,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask);
+void gdk_gc_destroy (GdkGC *gc);
+void gdk_gc_get_values (GdkGC *gc,
+ GdkGCValues *values);
+void gdk_gc_set_foreground (GdkGC *gc,
+ GdkColor *color);
+void gdk_gc_set_background (GdkGC *gc,
+ GdkColor *color);
+void gdk_gc_set_font (GdkGC *gc,
+ GdkFont *font);
+void gdk_gc_set_function (GdkGC *gc,
+ GdkFunction function);
+void gdk_gc_set_fill (GdkGC *gc,
+ GdkFill fill);
+void gdk_gc_set_tile (GdkGC *gc,
+ GdkPixmap *tile);
+void gdk_gc_set_stipple (GdkGC *gc,
+ GdkPixmap *stipple);
+void gdk_gc_set_ts_origin (GdkGC *gc,
+ gint x,
+ gint y);
+void gdk_gc_set_clip_origin (GdkGC *gc,
+ gint x,
+ gint y);
+void gdk_gc_set_clip_mask (GdkGC *gc,
+ GdkBitmap *mask);
+void gdk_gc_set_clip_rectangle (GdkGC *gc,
+ GdkRectangle *rectangle);
+void gdk_gc_set_subwindow (GdkGC *gc,
+ GdkSubwindowMode mode);
+void gdk_gc_set_exposures (GdkGC *gc,
+ gint exposures);
+void gdk_gc_set_line_attributes (GdkGC *gc,
+ gint line_width,
+ GdkLineStyle line_style,
+ GdkCapStyle cap_style,
+ GdkJoinStyle join_style);
+
+
+/* Pixmaps
+ */
+GdkPixmap* gdk_pixmap_new (GdkWindow *window,
+ gint width,
+ gint height,
+ gint depth);
+GdkBitmap* gdk_bitmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height);
+GdkPixmap* gdk_pixmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ GdkColor *fg,
+ GdkColor *bg);
+GdkPixmap* gdk_pixmap_create_from_xpm (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ const gchar *filename);
+GdkPixmap* gdk_pixmap_create_from_xpm_d (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ gchar **data);
+void gdk_pixmap_destroy (GdkPixmap *pixmap);
+
+
+
+/* Images
+ */
+GdkImage* gdk_image_new_bitmap(GdkVisual *,
+ gpointer,
+ gint,
+ gint);
+GdkImage* gdk_image_new (GdkImageType type,
+ GdkVisual *visual,
+ gint width,
+ gint height);
+GdkImage* gdk_image_get (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_image_put_pixel (GdkImage *image,
+ gint x,
+ gint y,
+ guint32 pixel);
+guint32 gdk_image_get_pixel (GdkImage *image,
+ gint x,
+ gint y);
+void gdk_image_destroy (GdkImage *image);
+
+
+/* Color
+ */
+GdkColormap* gdk_colormap_new (GdkVisual *visual,
+ gint allocate);
+void gdk_colormap_destroy (GdkColormap *colormap);
+
+GdkColormap* gdk_colormap_ref (GdkColormap *cmap);
+void gdk_colormap_unref (GdkColormap *cmap);
+
+GdkColormap* gdk_colormap_get_system (void);
+gint gdk_colormap_get_system_size (void);
+
+void gdk_colormap_change (GdkColormap *colormap,
+ gint ncolors);
+void gdk_colors_store (GdkColormap *colormap,
+ GdkColor *colors,
+ gint ncolors);
+gint gdk_colors_alloc (GdkColormap *colormap,
+ gint contiguous,
+ gulong *planes,
+ gint nplanes,
+ gulong *pixels,
+ gint npixels);
+void gdk_colors_free (GdkColormap *colormap,
+ gulong *pixels,
+ gint npixels,
+ gulong planes);
+gint gdk_color_white (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_black (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_parse (const gchar *spec,
+ GdkColor *color);
+gint gdk_color_alloc (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_change (GdkColormap *colormap,
+ GdkColor *color);
+gint gdk_color_equal (GdkColor *colora,
+ GdkColor *colorb);
+
+
+/* Fonts
+ */
+GdkFont* gdk_font_load (const gchar *font_name);
+GdkFont* gdk_fontset_load (gchar *fontset_name);
+void gdk_font_free (GdkFont *font);
+void gdk_fontset_free (GdkFont *font);
+GdkFont* gdk_font_ref (GdkFont *font);
+gint gdk_font_id (GdkFont *font);
+gint gdk_font_equal (GdkFont *fonta,
+ GdkFont *fontb);
+gint gdk_string_width (GdkFont *font,
+ const gchar *string);
+gint gdk_text_width (GdkFont *font,
+ const gchar *text,
+ gint text_length);
+gint gdk_char_width (GdkFont *font,
+ gchar character);
+gint gdk_string_measure (GdkFont *font,
+ const gchar *string);
+gint gdk_text_measure (GdkFont *font,
+ const gchar *text,
+ gint text_length);
+gint gdk_char_measure (GdkFont *font,
+ gchar character);
+
+
+/* Drawing
+ */
+void gdk_draw_point (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x,
+ gint y);
+void gdk_draw_line (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2);
+void gdk_draw_rectangle (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+void gdk_draw_arc (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2);
+void gdk_draw_polygon (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ GdkPoint *points,
+ gint npoints);
+void gdk_draw_string (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *string);
+void gdk_draw_text (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length);
+void gdk_draw_pixmap (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkDrawable *src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+void gdk_draw_bitmap (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkDrawable *src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+void gdk_draw_image (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+void gdk_draw_points (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints);
+void gdk_draw_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs);
+
+
+/* Selections
+ */
+gint gdk_selection_owner_set (GdkWindow *owner,
+ GdkAtom selection,
+ guint32 time,
+ gint send_event);
+GdkWindow* gdk_selection_owner_get (GdkAtom selection);
+void gdk_selection_convert (GdkWindow *requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time);
+gint gdk_selection_property_get (GdkWindow *requestor,
+ guchar **data,
+ GdkAtom *prop_type,
+ gint *prop_format);
+void gdk_selection_send_notify (guint32 requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ GdkAtom property,
+ guint32 time);
+
+/* Properties
+ */
+GdkAtom gdk_atom_intern (const gchar *atom_name,
+ gint only_if_exists);
+gchar* gdk_atom_name (GdkAtom atom);
+gint gdk_property_get (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gulong offset,
+ gulong length,
+ gint pdelete,
+ GdkAtom *actual_property_type,
+ gint *actual_format,
+ gint *actual_length,
+ guchar **data);
+
+void gdk_property_change (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gint format,
+ GdkPropMode mode,
+ guchar *data,
+ gint nelements);
+void gdk_property_delete (GdkWindow *window,
+ GdkAtom property);
+
+
+/* Rectangle utilities
+ */
+gint gdk_rectangle_intersect (GdkRectangle *src1,
+ GdkRectangle *src2,
+ GdkRectangle *dest);
+
+/* XInput support
+ */
+
+void gdk_input_init (void);
+void gdk_input_exit (void);
+GList *gdk_input_list_devices (void);
+void gdk_input_set_extension_events (GdkWindow *window,
+ gint mask,
+ GdkExtensionMode mode);
+void gdk_input_set_source (guint32 deviceid,
+ GdkInputSource source);
+gint gdk_input_set_mode (guint32 deviceid,
+ GdkInputMode mode);
+void gdk_input_set_axes (guint32 deviceid,
+ GdkAxisUse *axes);
+void gdk_input_window_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+GdkTimeCoord *gdk_input_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+
+/* Miscellaneous */
+void gdk_event_send_clientmessage_toall(GdkEvent *event);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GDK_H__ */
diff --git a/gdk/gdkcolor.c b/gdk/gdkcolor.c
new file mode 100644
index 000000000..5e66f089b
--- /dev/null
+++ b/gdk/gdkcolor.c
@@ -0,0 +1,718 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static gint gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available);
+static void gdk_colormap_add (GdkColormap *cmap);
+static void gdk_colormap_remove (GdkColormap *cmap);
+static guint gdk_colormap_hash (Colormap *cmap);
+static gint gdk_colormap_cmp (Colormap *a,
+ Colormap *b);
+
+static GHashTable *colormap_hash = NULL;
+
+
+GdkColormap*
+gdk_colormap_new (GdkVisual *visual,
+ gint private_cmap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ Visual *xvisual;
+ XColor default_colors[256];
+ int size;
+ int i;
+
+ g_return_val_if_fail (visual != NULL, NULL);
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->visual = visual;
+ private->next_color = 0;
+ private->ref_count = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ private->private_val = private_cmap;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
+
+ if (private_cmap)
+ {
+ for (i = 0; i < 256; i++)
+ default_colors[i].pixel = i;
+
+ XQueryColors (private->xdisplay,
+ DefaultColormap (private->xdisplay, gdk_screen),
+ default_colors, visual->colormap_size);
+
+ for (i = 0; i < visual->colormap_size; i++)
+ {
+ colormap->colors[i].pixel = default_colors[i].pixel;
+ colormap->colors[i].red = default_colors[i].red;
+ colormap->colors[i].green = default_colors[i].green;
+ colormap->colors[i].blue = default_colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ private->private_val = TRUE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocAll);
+
+ size = 1 << visual->red_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].red = i * 65535 / (size - 1);
+
+ size = 1 << visual->green_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].green = i * 65535 / (size - 1);
+
+ size = 1 << visual->blue_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].blue = i * 65535 / (size - 1);
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ private->private_val = FALSE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocNone);
+ break;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+void
+gdk_colormap_real_destroy (GdkColormap *colormap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
+
+ g_return_if_fail (colormap != NULL);
+
+ if (private->ref_count > 0)
+ return;
+
+ gdk_colormap_remove (colormap);
+ XFreeColormap (private->xdisplay, private->xcolormap);
+ g_free (colormap);
+}
+
+void
+gdk_colormap_destroy (GdkColormap *colormap)
+{
+ gdk_colormap_unref (colormap);
+}
+
+GdkColormap*
+gdk_colormap_ref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_val_if_fail (cmap != NULL, NULL);
+
+ private->ref_count += 1;
+ return cmap;
+}
+
+void
+gdk_colormap_unref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_if_fail (cmap != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_colormap_real_destroy (cmap);
+}
+
+GdkColormap*
+gdk_colormap_get_system (void)
+{
+ static GdkColormap *colormap = NULL;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ if (!colormap)
+ {
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = DefaultColormap (gdk_display, gdk_screen);
+ private->visual = gdk_visual_get_system ();
+ private->private_val = FALSE;
+ private->next_color = 0;
+ private->ref_count = 1;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+ }
+
+ return colormap;
+}
+
+gint
+gdk_colormap_get_system_size (void)
+{
+ return DisplayCells (gdk_display, gdk_screen);
+}
+
+void
+gdk_colormap_change (GdkColormap *colormap,
+ gint ncolors)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor palette[256];
+ gint shift;
+ int max_colors;
+ int size;
+ int i;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ for (i = 0; i < ncolors; i++)
+ {
+ palette[i].pixel = colormap->colors[i].pixel;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoRed | DoGreen | DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors);
+ private->next_color = MAX (private->next_color, ncolors);
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+
+ shift = visual->red_shift;
+ max_colors = 1 << visual->red_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].flags = DoRed;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->green_shift;
+ max_colors = 1 << visual->green_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].flags = DoGreen;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->blue_shift;
+ max_colors = 1 << visual->blue_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+gdk_colors_store (GdkColormap *colormap,
+ GdkColor *colors,
+ gint ncolors)
+{
+ gint i;
+
+ for (i = 0; i < ncolors; i++)
+ {
+ colormap->colors[i].pixel = colors[i].pixel;
+ colormap->colors[i].red = colors[i].red;
+ colormap->colors[i].green = colors[i].green;
+ colormap->colors[i].blue = colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, ncolors);
+}
+
+gint
+gdk_colors_alloc (GdkColormap *colormap,
+ gint contiguous,
+ gulong *planes,
+ gint nplanes,
+ gulong *pixels,
+ gint npixels)
+{
+ GdkColormapPrivate *private;
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, 0);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ return_val = XAllocColorCells (private->xdisplay, private->xcolormap,
+ contiguous, planes, nplanes, pixels, npixels);
+
+ return return_val;
+}
+
+void
+gdk_colors_free (GdkColormap *colormap,
+ gulong *pixels,
+ gint npixels,
+ gulong planes)
+{
+ GdkColormapPrivate *private;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ XFreeColors (private->xdisplay, private->xcolormap,
+ pixels, npixels, planes);
+}
+
+gint
+gdk_color_white (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = WhitePixel (gdk_display, gdk_screen);
+ color->red = 65535;
+ color->green = 65535;
+ color->blue = 65535;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_black (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = BlackPixel (gdk_display, gdk_screen);
+ color->red = 0;
+ color->green = 0;
+ color->blue = 0;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_parse (const gchar *spec,
+ GdkColor *color)
+{
+ Colormap xcolormap;
+ XColor xcolor;
+ gint return_val;
+
+ g_return_val_if_fail (spec != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolormap = DefaultColormap (gdk_display, gdk_screen);
+
+ if (XParseColor (gdk_display, xcolormap, spec, &xcolor))
+ {
+ return_val = TRUE;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_alloc (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor xcolor;
+ gchar available[256];
+ gint available_init;
+ gint return_val;
+ gint i, index;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.pixel = color->pixel;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ return_val = FALSE;
+ private = (GdkColormapPrivate*) colormap;
+
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ if (private->private_val)
+ {
+ if (private->next_color > 255)
+ {
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ *color = colormap->colors[index];
+ return_val = TRUE;
+ }
+ else
+ {
+ return_val = FALSE;
+ }
+ }
+ else
+ {
+ xcolor.pixel = 255 - private->next_color;
+ color->pixel = xcolor.pixel;
+ private->next_color += 1;
+
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+ return_val = TRUE;
+ }
+ }
+ else
+ {
+ available_init = 1;
+
+ while (1)
+ {
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+
+ colormap->colors[color->pixel] = *color;
+
+ return_val = TRUE;
+ break;
+ }
+ else
+ {
+ if (available_init)
+ {
+ available_init = 0;
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+ }
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ xcolor.red = colormap->colors[index].red;
+ xcolor.green = colormap->colors[index].green;
+ xcolor.blue = colormap->colors[index].blue;
+ }
+ else
+ {
+ return_val = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+ xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) +
+ ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) +
+ ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift));
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ break;
+ }
+
+ return return_val;
+}
+
+gint
+gdk_color_change (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ XColor xcolor;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.pixel = color->pixel;
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ private = (GdkColormapPrivate*) colormap;
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+
+ return TRUE;
+}
+
+gint
+gdk_color_equal (GdkColor *colora,
+ GdkColor *colorb)
+{
+ g_return_val_if_fail (colora != NULL, FALSE);
+ g_return_val_if_fail (colorb != NULL, FALSE);
+
+ return ((colora->red == colorb->red) &&
+ (colora->green == colorb->green) &&
+ (colora->blue == colorb->blue));
+}
+
+GdkColormap*
+gdkx_colormap_get (Colormap xcolormap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ colormap = gdk_colormap_lookup (xcolormap);
+ if (colormap)
+ return colormap;
+
+ if (xcolormap == DefaultColormap (gdk_display, gdk_screen))
+ return gdk_colormap_get_system ();
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = xcolormap;
+ private->visual = NULL;
+ private->private_val = TRUE;
+ private->next_color = 0;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+
+static gint
+gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available)
+{
+ GdkColor *colors;
+ guint sum, max;
+ gint rdiff, gdiff, bdiff;
+ gint i, index;
+
+ g_return_val_if_fail (cmap != NULL, 0);
+ g_return_val_if_fail (color != NULL, 0);
+
+ colors = cmap->colors;
+ max = 3 * (65536);
+ index = -1;
+
+ for (i = 0; i < 256; i++)
+ {
+ if ((!available) || (available && available[i]))
+ {
+ rdiff = (color->red - colors[i].red);
+ gdiff = (color->green - colors[i].green);
+ bdiff = (color->blue - colors[i].blue);
+
+ sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
+
+ if (sum < max)
+ {
+ index = i;
+ max = sum;
+ }
+ }
+ }
+
+ return index;
+}
+
+
+GdkColormap*
+gdk_colormap_lookup (Colormap xcolormap)
+{
+ GdkColormap *cmap;
+
+ if (!colormap_hash)
+ return NULL;
+
+ cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
+ return cmap;
+}
+
+static void
+gdk_colormap_add (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
+}
+
+static void
+gdk_colormap_remove (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_remove (colormap_hash, &private->xcolormap);
+}
+
+static guint
+gdk_colormap_hash (Colormap *cmap)
+{
+ return *cmap;
+}
+
+static gint
+gdk_colormap_cmp (Colormap *a,
+ Colormap *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/gdkcursor.c b/gdk/gdkcursor.c
new file mode 100644
index 000000000..22bfd250b
--- /dev/null
+++ b/gdk/gdkcursor.c
@@ -0,0 +1,52 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkCursor*
+gdk_cursor_new (GdkCursorType cursor_type)
+{
+ GdkCursorPrivate *private;
+ GdkCursor *cursor;
+ Cursor xcursor;
+
+ xcursor = XCreateFontCursor (gdk_display, cursor_type);
+ private = g_new (GdkCursorPrivate, 1);
+ private->xdisplay = gdk_display;
+ private->xcursor = xcursor;
+ cursor = (GdkCursor*) private;
+ cursor->type = cursor_type;
+
+ return cursor;
+}
+
+void
+gdk_cursor_destroy (GdkCursor *cursor)
+{
+ GdkCursorPrivate *private;
+
+ g_return_if_fail (cursor != NULL);
+
+ private = (GdkCursorPrivate *) cursor;
+ XFreeCursor (private->xdisplay, private->xcursor);
+
+ g_free (private);
+}
diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c
new file mode 100644
index 000000000..47482f72e
--- /dev/null
+++ b/gdk/gdkdraw.c
@@ -0,0 +1,383 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+void
+gdk_draw_point (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawPoint (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y);
+}
+
+void
+gdk_draw_line (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawLine (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x1, y1, x2, y2);
+}
+
+void
+gdk_draw_rectangle (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (width == -1)
+ width = drawable_private->width;
+ if (height == -1)
+ height = drawable_private->height;
+
+ if (filled)
+ XFillRectangle (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height);
+ else
+ XDrawRectangle (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height);
+}
+
+void
+gdk_draw_arc (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (width == -1)
+ width = drawable_private->width;
+ if (height == -1)
+ height = drawable_private->height;
+
+ if (filled)
+ XFillArc (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height, angle1, angle2);
+ else
+ XDrawArc (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, width, height, angle1, angle2);
+}
+
+void
+gdk_draw_polygon (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint filled,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (filled)
+ {
+ XFillPolygon (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, (XPoint*) points, npoints, Complex, CoordModeOrigin);
+ }
+ else
+ {
+ XDrawLines (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, (XPoint*) points, npoints, CoordModeOrigin);
+
+ if ((points[0].x != points[npoints-1].x) ||
+ (points[0].y != points[npoints-1].y))
+ XDrawLine (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, points[npoints-1].x, points[npoints-1].y,
+ points[0].x, points[0].y);
+ }
+}
+
+/* gdk_draw_string
+ *
+ * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
+ *
+ * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
+ */
+void
+gdk_draw_string (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *string)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkFontPrivate *font_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (string != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ XFontStruct *xfont = (XFontStruct *) font_private->xfont;
+ XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, string, strlen (string));
+ }
+ else
+ {
+ XDrawString16 (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, (XChar2b *) string,
+ strlen (string) / 2);
+ }
+ }
+ else if (font->type == GDK_FONT_FONTSET)
+ {
+ XFontSet fontset = (XFontSet) font_private->xfont;
+ XmbDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ fontset, gc_private->xgc, x, y, string, strlen (string));
+ }
+ else
+ g_error("undefined font type\n");
+}
+
+/* gdk_draw_text
+ *
+ * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
+ *
+ * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
+ */
+void
+gdk_draw_text (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkFontPrivate *font_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (text != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ XFontStruct *xfont = (XFontStruct *) font_private->xfont;
+ XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, text, text_length);
+ }
+ else
+ {
+ XDrawString16 (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, x, y, (XChar2b *) text, text_length / 2);
+ }
+ }
+ else if (font->type == GDK_FONT_FONTSET)
+ {
+ XFontSet fontset = (XFontSet) font_private->xfont;
+ XmbDrawString (drawable_private->xdisplay, drawable_private->xwindow,
+ fontset, gc_private->xgc, x, y, text, text_length);
+ }
+ else
+ g_error("undefined font type\n");
+}
+
+void
+gdk_draw_pixmap (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixmap *src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkWindowPrivate *src_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (src != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ src_private = (GdkWindowPrivate*) src;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (width == -1)
+ width = src_private->width;
+ if (height == -1)
+ height = src_private->height;
+
+ XCopyArea (drawable_private->xdisplay,
+ src_private->xwindow,
+ drawable_private->xwindow,
+ gc_private->xgc,
+ xsrc, ysrc,
+ width, height,
+ xdest, ydest);
+}
+
+void
+gdk_draw_image (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkImagePrivate *image_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ image_private = (GdkImagePrivate*) image;
+
+ g_return_if_fail (image_private->image_put != NULL);
+
+ if (width == -1)
+ width = image->width;
+ if (height == -1)
+ height = image->height;
+
+ (* image_private->image_put) (drawable, gc, image, xsrc, ysrc,
+ xdest, ydest, width, height);
+}
+
+void
+gdk_draw_points (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail ((points != NULL) && (npoints > 0));
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawPoints (drawable_private->xdisplay,
+ drawable_private->xwindow,
+ gc_private->xgc,
+ (XPoint *) points,
+ npoints,
+ CoordModeOrigin);
+}
+
+void
+gdk_draw_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkGCPrivate *gc_private;
+
+ if (nsegs <= 0)
+ return;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (segs != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ gc_private = (GdkGCPrivate*) gc;
+
+ XDrawSegments (drawable_private->xdisplay,
+ drawable_private->xwindow,
+ gc_private->xgc,
+ (XSegment *) segs,
+ nsegs);
+}
diff --git a/gdk/gdkfont.c b/gdk/gdkfont.c
new file mode 100644
index 000000000..e1b1e7254
--- /dev/null
+++ b/gdk/gdkfont.c
@@ -0,0 +1,379 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+GdkFont*
+gdk_font_load (const gchar *font_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ private->xfont = XLoadQueryFont (private->xdisplay, font_name);
+ private->ref_count = 1;
+
+ if (!private->xfont)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ font->type = GDK_FONT_FONT;
+ font->ascent = ((XFontStruct *) private->xfont)->ascent;
+ font->descent = ((XFontStruct *) private->xfont)->descent;
+ }
+
+ gdk_xid_table_insert (&((XFontStruct *) private->xfont)->fid, font);
+
+ return font;
+}
+
+GdkFont*
+gdk_fontset_load(gchar *fontset_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+ XFontSet fontset;
+ gint missing_charset_count;
+ gchar **missing_charset_list;
+ gchar *def_string;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ fontset = XCreateFontSet (gdk_display, fontset_name,
+ &missing_charset_list, &missing_charset_count,
+ &def_string);
+
+ if (missing_charset_count)
+ {
+ g_print ("Missing charsets in FontSet creation");
+ XFreeStringList (missing_charset_list);
+ }
+
+ private->ref_count = 1;
+
+ if (!fontset)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ XFontSetExtents *extent = XExtentsOfFontSet(fontset);
+
+ private->xfont = fontset;
+ font->type = GDK_FONT_FONTSET;
+ /* how to define ascent and descent for fontset ??? */
+ font->ascent = extent->max_logical_extent.height;
+ font->descent = font->ascent / 4 ;
+ }
+ return font;
+}
+void
+gdk_font_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (((XFontStruct *) private->xfont)->fid);
+ XFreeFont (private->xdisplay, (XFontStruct *) private->xfont);
+ g_free (font);
+ }
+}
+
+void
+gdk_fontset_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ XFreeFontSet (private->xdisplay, (XFontSet) private->xfont);
+ g_free (font);
+ }
+}
+
+GdkFont*
+gdk_font_ref (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ private = (GdkFontPrivate*) font;
+ private->ref_count += 1;
+ return font;
+}
+
+gint
+gdk_font_id (GdkFont *font)
+{
+ GdkFontPrivate *font_private;
+
+ g_return_val_if_fail (font != NULL, 0);
+
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ return ((XFontStruct *) font_private->xfont)->fid;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+gint
+gdk_font_equal (GdkFont *fonta,
+ GdkFont *fontb)
+{
+ GdkFontPrivate *privatea;
+ GdkFontPrivate *privateb;
+
+ g_return_val_if_fail (fonta != NULL, FALSE);
+ g_return_val_if_fail (fontb != NULL, FALSE);
+
+ privatea = (GdkFontPrivate*) fonta;
+ privateb = (GdkFontPrivate*) fontb;
+
+ if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
+ {
+ return (((XFontStruct *) privatea->xfont)->fid ==
+ ((XFontStruct *) privateb->xfont)->fid);
+ }
+ else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
+ {
+ /* how to compare two fontsets ?? by basename or XFontSet ?? */
+ return (((XFontSet) privatea->xfont) == ((XFontSet) privateb->xfont));
+ }
+ else
+ /* fontset != font */
+ return 0;
+}
+
+gint
+gdk_string_width (GdkFont *font,
+ const gchar *string)
+{
+ GdkFontPrivate *font_private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ font_private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) font_private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, string, strlen (string));
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) string, strlen (string) / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) font_private->xfont;
+ width = XmbTextEscapement (fontset, string, strlen(string));
+ break;
+ default:
+ width = 0;
+ }
+
+ return width;
+}
+
+gint
+gdk_text_width (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, text, text_length);
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) text, text_length / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, text, text_length);
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+/* Problem: What if a character is a 16 bits character ?? */
+gint
+gdk_char_width (GdkFont *font,
+ gchar character)
+{
+ GdkFontPrivate *private;
+ XCharStruct *chars;
+ gint width;
+ guint ch = character & 0xff; /* get rid of sign-extension */
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ /* only 8 bits characters are considered here */
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) &&
+ (xfont->max_byte1 == 0) &&
+ (ch >= xfont->min_char_or_byte2) &&
+ (ch <= xfont->max_char_or_byte2))
+ {
+ chars = xfont->per_char;
+ if (chars)
+ width = chars[ch - xfont->min_char_or_byte2].width;
+ else
+ width = xfont->min_bounds.width;
+ }
+ else
+ {
+ width = XTextWidth (xfont, &character, 1);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, &character, 1) ;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_string_measure (GdkFont *font,
+ const gchar *string)
+{
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ return gdk_text_measure (font, string, strlen (string));
+}
+
+gint
+gdk_text_measure (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ XCharStruct overall;
+ XFontStruct *xfont;
+ XFontSet fontset;
+ XRectangle ink, log;
+ int direction;
+ int font_ascent;
+ int font_descent;
+ gint width;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XTextExtents (xfont, text, text_length,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ else
+ {
+ XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ width = overall.rbearing;
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ XmbTextExtents (fontset, text, text_length, &ink, &log);
+ width = log.width;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_char_measure (GdkFont *font,
+ gchar character)
+{
+ g_return_val_if_fail (font != NULL, -1);
+
+ return gdk_text_measure (font, &character, 1);
+}
diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c
new file mode 100644
index 000000000..3dc11ce6c
--- /dev/null
+++ b/gdk/gdkgc.c
@@ -0,0 +1,636 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include <X11/Xlib.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkGC*
+gdk_gc_new (GdkWindow *window)
+{
+ return gdk_gc_new_with_values (window, NULL, 0);
+}
+
+GdkGC*
+gdk_gc_new_with_values (GdkWindow *window,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask)
+{
+ GdkGC *gc;
+ GdkGCPrivate *private;
+ Window xwindow;
+ XGCValues xvalues;
+ unsigned long xvalues_mask;
+
+ private = g_new (GdkGCPrivate, 1);
+ gc = (GdkGC*) private;
+
+ xwindow = ((GdkWindowPrivate*) window)->xwindow;
+ private->xdisplay = ((GdkWindowPrivate*) window)->xdisplay;
+
+ xvalues.function = GXcopy;
+ xvalues.fill_style = FillSolid;
+ xvalues.arc_mode = ArcPieSlice;
+ xvalues.subwindow_mode = ClipByChildren;
+ xvalues.graphics_exposures = True;
+ xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
+
+ if (values_mask & GDK_GC_FOREGROUND)
+ {
+ xvalues.foreground = values->foreground.pixel;
+ xvalues_mask |= GCForeground;
+ }
+ if (values_mask & GDK_GC_BACKGROUND)
+ {
+ xvalues.background = values->background.pixel;
+ xvalues_mask |= GCBackground;
+ }
+ if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
+ {
+ xvalues.font = ((XFontStruct *) ((GdkFontPrivate*) values->font)->xfont)->fid;
+ xvalues_mask |= GCFont;
+ }
+ if (values_mask & GDK_GC_FUNCTION)
+ {
+ switch (values->function)
+ {
+ case GDK_COPY:
+ xvalues.function = GXcopy;
+ break;
+ case GDK_INVERT:
+ xvalues.function = GXinvert;
+ break;
+ case GDK_XOR:
+ xvalues.function = GXxor;
+ break;
+ }
+ xvalues_mask |= GCFunction;
+ }
+ if (values_mask & GDK_GC_FILL)
+ {
+ switch (values->fill)
+ {
+ case GDK_SOLID:
+ xvalues.fill_style = FillSolid;
+ break;
+ case GDK_TILED:
+ xvalues.fill_style = FillTiled;
+ break;
+ case GDK_STIPPLED:
+ xvalues.fill_style = FillStippled;
+ break;
+ case GDK_OPAQUE_STIPPLED:
+ xvalues.fill_style = FillOpaqueStippled;
+ break;
+ }
+ xvalues_mask |= GCFillStyle;
+ }
+ if (values_mask & GDK_GC_TILE)
+ {
+ xvalues.tile = ((GdkPixmapPrivate*) values->tile)->xwindow;
+ xvalues_mask |= GCTile;
+ }
+ if (values_mask & GDK_GC_STIPPLE)
+ {
+ xvalues.stipple = ((GdkPixmapPrivate*) values->stipple)->xwindow;
+ xvalues_mask |= GCStipple;
+ }
+ if (values_mask & GDK_GC_CLIP_MASK)
+ {
+ xvalues.clip_mask = ((GdkPixmapPrivate*) values->clip_mask)->xwindow;
+ xvalues_mask |= GCClipMask;
+ }
+ if (values_mask & GDK_GC_SUBWINDOW)
+ {
+ xvalues.subwindow_mode = values->subwindow_mode;
+ xvalues_mask |= GCSubwindowMode;
+ }
+ if (values_mask & GDK_GC_TS_X_ORIGIN)
+ {
+ xvalues.ts_x_origin = values->ts_x_origin;
+ xvalues_mask |= GCTileStipXOrigin;
+ }
+ if (values_mask & GDK_GC_TS_Y_ORIGIN)
+ {
+ xvalues.ts_y_origin = values->ts_y_origin;
+ xvalues_mask |= GCTileStipYOrigin;
+ }
+ if (values_mask & GDK_GC_CLIP_X_ORIGIN)
+ {
+ xvalues.clip_x_origin = values->clip_x_origin;
+ xvalues_mask |= GCClipXOrigin;
+ }
+ if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
+ {
+ xvalues.clip_y_origin = values->clip_y_origin;
+ xvalues_mask |= GCClipYOrigin;
+ }
+ if (values_mask & GDK_GC_EXPOSURES)
+ {
+ xvalues.graphics_exposures = values->graphics_exposures;
+ xvalues_mask |= GCGraphicsExposures;
+ }
+ if (values_mask & GDK_GC_LINE_WIDTH)
+ {
+ xvalues.line_width = values->line_width;
+ xvalues_mask |= GCLineWidth;
+ }
+ if (values_mask & GDK_GC_LINE_STYLE)
+ {
+ switch (values->line_style)
+ {
+ case GDK_LINE_SOLID:
+ xvalues.line_style = LineSolid;
+ break;
+ case GDK_LINE_ON_OFF_DASH:
+ xvalues.line_style = LineOnOffDash;
+ break;
+ case GDK_LINE_DOUBLE_DASH:
+ xvalues.line_style = LineDoubleDash;
+ break;
+ }
+ xvalues_mask |= GCLineStyle;
+ }
+ if (values_mask & GDK_GC_CAP_STYLE)
+ {
+ switch (values->cap_style)
+ {
+ case GDK_CAP_NOT_LAST:
+ xvalues.cap_style = CapNotLast;
+ break;
+ case GDK_CAP_BUTT:
+ xvalues.cap_style = CapButt;
+ break;
+ case GDK_CAP_ROUND:
+ xvalues.cap_style = CapRound;
+ break;
+ case GDK_CAP_PROJECTING:
+ xvalues.cap_style = CapProjecting;
+ break;
+ }
+ xvalues_mask |= GCCapStyle;
+ }
+ if (values_mask & GDK_GC_JOIN_STYLE)
+ {
+ switch (values->join_style)
+ {
+ case GDK_JOIN_MITER:
+ xvalues.join_style = JoinMiter;
+ break;
+ case GDK_JOIN_ROUND:
+ xvalues.join_style = JoinRound;
+ break;
+ case GDK_JOIN_BEVEL:
+ xvalues.join_style = JoinBevel;
+ break;
+ }
+ xvalues_mask |= GCJoinStyle;
+ }
+
+ private->xgc = XCreateGC (private->xdisplay, xwindow, xvalues_mask, &xvalues);
+
+ return gc;
+}
+
+void
+gdk_gc_destroy (GdkGC *gc)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+ XFreeGC (private->xdisplay, private->xgc);
+
+ memset (gc, 0, sizeof (GdkGCPrivate));
+ g_free (gc);
+}
+
+void
+gdk_gc_get_values (GdkGC *gc,
+ GdkGCValues *values)
+{
+ GdkGCPrivate *private;
+ XGCValues xvalues;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (values != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ if (XGetGCValues (private->xdisplay, private->xgc,
+ GCForeground | GCBackground | GCFont |
+ GCFunction | GCTile | GCStipple | /* GCClipMask | */
+ GCSubwindowMode | GCGraphicsExposures |
+ GCTileStipXOrigin | GCTileStipYOrigin |
+ GCClipXOrigin | GCClipYOrigin |
+ GCLineWidth | GCLineStyle | GCCapStyle |
+ GCFillStyle | GCJoinStyle, &xvalues))
+ {
+ values->foreground.pixel = xvalues.foreground;
+ values->background.pixel = xvalues.background;
+ values->font = gdk_font_lookup (xvalues.font);
+
+ switch (xvalues.function)
+ {
+ case GXcopy:
+ values->function = GDK_COPY;
+ break;
+ case GXinvert:
+ values->function = GDK_INVERT;
+ break;
+ case GXxor:
+ values->function = GDK_XOR;
+ break;
+ }
+
+ switch (xvalues.fill_style)
+ {
+ case FillSolid:
+ values->fill = GDK_SOLID;
+ break;
+ case FillTiled:
+ values->fill = GDK_TILED;
+ break;
+ case FillStippled:
+ values->fill = GDK_STIPPLED;
+ break;
+ case FillOpaqueStippled:
+ values->fill = GDK_OPAQUE_STIPPLED;
+ break;
+ }
+
+ values->tile = gdk_pixmap_lookup (xvalues.tile);
+ values->stipple = gdk_pixmap_lookup (xvalues.stipple);
+ values->clip_mask = NULL;
+ values->subwindow_mode = xvalues.subwindow_mode;
+ values->ts_x_origin = xvalues.ts_x_origin;
+ values->ts_y_origin = xvalues.ts_y_origin;
+ values->clip_x_origin = xvalues.clip_x_origin;
+ values->clip_y_origin = xvalues.clip_y_origin;
+ values->graphics_exposures = xvalues.graphics_exposures;
+ values->line_width = xvalues.line_width;
+
+ switch (xvalues.line_style)
+ {
+ case LineSolid:
+ values->line_style = GDK_LINE_SOLID;
+ break;
+ case LineOnOffDash:
+ values->line_style = GDK_LINE_ON_OFF_DASH;
+ break;
+ case LineDoubleDash:
+ values->line_style = GDK_LINE_DOUBLE_DASH;
+ break;
+ }
+
+ switch (xvalues.cap_style)
+ {
+ case CapNotLast:
+ values->cap_style = GDK_CAP_NOT_LAST;
+ break;
+ case CapButt:
+ values->cap_style = GDK_CAP_BUTT;
+ break;
+ case CapRound:
+ values->cap_style = GDK_CAP_ROUND;
+ break;
+ case CapProjecting:
+ values->cap_style = GDK_CAP_PROJECTING;
+ break;
+ }
+
+ switch (xvalues.join_style)
+ {
+ case JoinMiter:
+ values->join_style = GDK_JOIN_MITER;
+ break;
+ case JoinRound:
+ values->join_style = GDK_JOIN_ROUND;
+ break;
+ case JoinBevel:
+ values->join_style = GDK_JOIN_BEVEL;
+ break;
+ }
+ }
+ else
+ {
+ memset (values, 0, sizeof (GdkGCValues));
+ }
+}
+
+void
+gdk_gc_set_foreground (GdkGC *gc,
+ GdkColor *color)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (color != NULL);
+
+ private = (GdkGCPrivate*) gc;
+ XSetForeground (private->xdisplay, private->xgc, color->pixel);
+}
+
+void
+gdk_gc_set_background (GdkGC *gc,
+ GdkColor *color)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (color != NULL);
+
+ private = (GdkGCPrivate*) gc;
+ XSetBackground (private->xdisplay, private->xgc, color->pixel);
+}
+
+void
+gdk_gc_set_font (GdkGC *gc,
+ GdkFont *font)
+{
+ GdkGCPrivate *gc_private;
+ GdkFontPrivate *font_private;
+
+ g_return_if_fail (gc != NULL);
+ g_return_if_fail (font != NULL);
+
+ gc_private = (GdkGCPrivate*) gc;
+ font_private = (GdkFontPrivate*) font;
+
+ XSetFont (gc_private->xdisplay, gc_private->xgc,
+ ((XFontStruct *) font_private->xfont)->fid);
+}
+
+void
+gdk_gc_set_function (GdkGC *gc,
+ GdkFunction function)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ switch (function)
+ {
+ case GDK_COPY:
+ XSetFunction (private->xdisplay, private->xgc, GXcopy);
+ break;
+ case GDK_INVERT:
+ XSetFunction (private->xdisplay, private->xgc, GXinvert);
+ break;
+ case GDK_XOR:
+ XSetFunction (private->xdisplay, private->xgc, GXor);
+ break;
+ }
+}
+
+void
+gdk_gc_set_fill (GdkGC *gc,
+ GdkFill fill)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ switch (fill)
+ {
+ case GDK_SOLID:
+ XSetFillStyle (private->xdisplay, private->xgc, FillSolid);
+ break;
+ case GDK_TILED:
+ XSetFillStyle (private->xdisplay, private->xgc, FillTiled);
+ break;
+ case GDK_STIPPLED:
+ XSetFillStyle (private->xdisplay, private->xgc, FillStippled);
+ break;
+ case GDK_OPAQUE_STIPPLED:
+ XSetFillStyle (private->xdisplay, private->xgc, FillOpaqueStippled);
+ break;
+ }
+}
+
+void
+gdk_gc_set_tile (GdkGC *gc,
+ GdkPixmap *tile)
+{
+ GdkGCPrivate *private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap pixmap;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ pixmap = None;
+ if (tile)
+ {
+ pixmap_private = (GdkPixmapPrivate*) tile;
+ pixmap = pixmap_private->xwindow;
+ }
+
+ XSetTile (private->xdisplay, private->xgc, pixmap);
+}
+
+void
+gdk_gc_set_stipple (GdkGC *gc,
+ GdkPixmap *stipple)
+{
+ GdkGCPrivate *private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap pixmap;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ pixmap = None;
+ if (stipple)
+ {
+ pixmap_private = (GdkPixmapPrivate*) stipple;
+ pixmap = pixmap_private->xwindow;
+ }
+
+ XSetStipple (private->xdisplay, private->xgc, pixmap);
+}
+
+void
+gdk_gc_set_ts_origin (GdkGC *gc,
+ gint x,
+ gint y)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetTSOrigin (private->xdisplay, private->xgc, x, y);
+}
+
+void
+gdk_gc_set_clip_origin (GdkGC *gc,
+ gint x,
+ gint y)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetClipOrigin (private->xdisplay, private->xgc, x, y);
+}
+
+void
+gdk_gc_set_clip_mask (GdkGC *gc,
+ GdkBitmap *mask)
+{
+ GdkGCPrivate *private;
+ Pixmap xmask;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ if (mask)
+ xmask = ((GdkWindowPrivate*) mask)->xwindow;
+ else
+ xmask = None;
+
+ XSetClipMask (private->xdisplay, private->xgc, xmask);
+}
+
+
+void
+gdk_gc_set_clip_rectangle (GdkGC *gc,
+ GdkRectangle *rectangle)
+{
+ GdkGCPrivate *private;
+ XRectangle xrectangle;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ xrectangle.x = rectangle->x;
+ xrectangle.y = rectangle->y;
+ xrectangle.width = rectangle->width;
+ xrectangle.height = rectangle->height;
+
+ XSetClipRectangles (private->xdisplay, private->xgc, 0, 0,
+ &xrectangle, 1, Unsorted);
+}
+
+void
+gdk_gc_set_subwindow (GdkGC *gc,
+ GdkSubwindowMode mode)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetSubwindowMode (private->xdisplay, private->xgc, mode);
+}
+
+void
+gdk_gc_set_exposures (GdkGC *gc,
+ gint exposures)
+{
+ GdkGCPrivate *private;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ XSetGraphicsExposures (private->xdisplay, private->xgc, exposures);
+}
+
+void
+gdk_gc_set_line_attributes (GdkGC *gc,
+ gint line_width,
+ GdkLineStyle line_style,
+ GdkCapStyle cap_style,
+ GdkJoinStyle join_style)
+{
+ GdkGCPrivate *private;
+ int xline_style;
+ int xcap_style;
+ int xjoin_style;
+
+ g_return_if_fail (gc != NULL);
+
+ private = (GdkGCPrivate*) gc;
+
+ switch (line_style)
+ {
+ case GDK_LINE_SOLID:
+ xline_style = LineSolid;
+ break;
+ case GDK_LINE_ON_OFF_DASH:
+ xline_style = LineOnOffDash;
+ break;
+ case GDK_LINE_DOUBLE_DASH:
+ xline_style = LineDoubleDash;
+ break;
+ default:
+ xline_style = None;
+ }
+
+ switch (cap_style)
+ {
+ case GDK_CAP_NOT_LAST:
+ xcap_style = CapNotLast;
+ break;
+ case GDK_CAP_BUTT:
+ xcap_style = CapButt;
+ break;
+ case GDK_CAP_ROUND:
+ xcap_style = CapRound;
+ break;
+ case GDK_CAP_PROJECTING:
+ xcap_style = CapProjecting;
+ break;
+ default:
+ xcap_style = None;
+ }
+
+ switch (join_style)
+ {
+ case GDK_JOIN_MITER:
+ xjoin_style = JoinMiter;
+ break;
+ case GDK_JOIN_ROUND:
+ xjoin_style = JoinRound;
+ break;
+ case GDK_JOIN_BEVEL:
+ xjoin_style = JoinBevel;
+ break;
+ default:
+ xjoin_style = None;
+ }
+
+ XSetLineAttributes (private->xdisplay, private->xgc, line_width,
+ xline_style, xcap_style, xjoin_style);
+}
diff --git a/gdk/gdkglobals.c b/gdk/gdkglobals.c
new file mode 100644
index 000000000..58f7bf844
--- /dev/null
+++ b/gdk/gdkglobals.c
@@ -0,0 +1,47 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include "gdktypes.h"
+#include "gdkprivate.h"
+
+gint gdk_debug_level = 0;
+gint gdk_show_events = FALSE;
+gint gdk_use_xshm = TRUE;
+gchar *gdk_display_name = NULL;
+Display *gdk_display = NULL;
+gint gdk_screen;
+Window gdk_root_window;
+Window gdk_leader_window;
+GdkWindowPrivate gdk_root_parent;
+Atom gdk_wm_delete_window;
+Atom gdk_wm_take_focus;
+Atom gdk_wm_protocols;
+Atom gdk_wm_window_protocols[2];
+Atom gdk_selection_property;
+GdkDndGlobals gdk_dnd = {None,None,None,
+ None,None,None,
+ None,
+ None,None,
+ NULL,
+ 0, 0,
+ {0,0}};
+gchar *gdk_progname = NULL;
+gchar *gdk_progclass = NULL;
+gint gdk_error_code;
+gint gdk_error_warnings = TRUE;
diff --git a/gdk/gdkimage.c b/gdk/gdkimage.c
new file mode 100644
index 000000000..bcda3119f
--- /dev/null
+++ b/gdk/gdkimage.c
@@ -0,0 +1,492 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <sys/types.h>
+
+#if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
+#define USE_SHM
+#endif
+
+#ifdef USE_SHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* USE_SHM */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef USE_SHM
+#include <X11/extensions/XShm.h>
+#endif /* USE_SHM */
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+static void gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+
+
+static GList *image_list = NULL;
+
+
+void
+gdk_image_exit ()
+{
+ GdkImage *image;
+
+ while (image_list)
+ {
+ image = image_list->data;
+ gdk_image_destroy (image);
+ }
+}
+
+GdkImage *
+gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
+/*
+ * Desc: create a new bitmap image
+ */
+{
+ Visual *xvisual;
+ GdkImage *image;
+ GdkImagePrivate *private;
+ private = g_new(GdkImagePrivate, 1);
+ image = (GdkImage *) private;
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = visual;
+ image->width = w;
+ image->height = h;
+ image->depth = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+ private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
+ 0, 0, w ,h, 8, 0);
+ private->ximage->data = data;
+ private->ximage->bitmap_bit_order = MSBFirst;
+ private->ximage->byte_order = MSBFirst;
+ image->byte_order = MSBFirst;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+ return(image);
+} /* gdk_image_new_bitmap() */
+
+static int
+gdk_image_check_xshm(Display *display)
+/*
+ * Desc: query the server for support for the MIT_SHM extension
+ * Return: 0 = not available
+ * 1 = shared XImage support available
+ * 2 = shared Pixmap support available also
+ */
+{
+#ifdef USE_SHM
+ int major, minor, ignore;
+ Bool pixmaps;
+
+ if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
+ {
+ if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
+ {
+ return (pixmaps==True) ? 2 : 1;
+ }
+ }
+#endif /* USE_SHM */
+ return 0;
+}
+
+void
+gdk_image_init ()
+{
+ if (gdk_use_xshm)
+ {
+ if (!gdk_image_check_xshm (gdk_display))
+ {
+ g_warning ("MIT-SHM Extension not availible on server");
+ gdk_use_xshm = False;
+ }
+ }
+}
+
+GdkImage*
+gdk_image_new (GdkImageType type,
+ GdkVisual *visual,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+ Visual *xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_FASTEST:
+ image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
+
+ if (!image)
+ image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
+ break;
+
+ default:
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = NULL;
+
+ image->type = type;
+ image->visual = visual;
+ image->width = width;
+ image->height = height;
+ image->depth = visual->depth;
+
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ if (gdk_use_xshm)
+ {
+ private->image_put = gdk_image_put_shared;
+
+ private->x_shm_info = g_new (XShmSegmentInfo, 1);
+ x_shm_info = private->x_shm_info;
+
+ private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, NULL, x_shm_info, width, height);
+ if (private->ximage == NULL)
+ {
+ g_warning ("XShmCreateImage failed");
+
+ g_free (image);
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->shmid = shmget (IPC_PRIVATE,
+ private->ximage->bytes_per_line * private->ximage->height,
+ IPC_CREAT | 0777);
+
+ if (x_shm_info->shmid == -1)
+ {
+ g_warning ("shmget failed!");
+
+ XDestroyImage (private->ximage);
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->readOnly = False;
+ x_shm_info->shmaddr = shmat (x_shm_info->shmid, 0, 0);
+ private->ximage->data = x_shm_info->shmaddr;
+
+ if (x_shm_info->shmaddr == (char*) -1)
+ {
+ g_warning ("shmat failed!");
+
+ XDestroyImage (private->ximage);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ return NULL;
+ }
+
+#ifdef IPC_RMID_DEFERRED_RELEASE
+ if (x_shm_info->shmaddr != (char*) -1)
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+#endif
+
+ gdk_error_code = 0;
+ gdk_error_warnings = 0;
+
+ XShmAttach (private->xdisplay, x_shm_info);
+ XSync (private->xdisplay, False);
+
+ gdk_error_warnings = 1;
+ if (gdk_error_code == -1)
+ {
+ g_warning ("XShmAttach failed!");
+
+ XDestroyImage (private->ximage);
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ if (image)
+ image_list = g_list_prepend (image_list, image);
+ }
+ else
+ {
+ g_free (image);
+ return NULL;
+ }
+ break;
+#else /* USE_SHM */
+ g_free (image);
+ return NULL;
+#endif /* USE_SHM */
+ case GDK_IMAGE_NORMAL:
+ private->image_put = gdk_image_put_normal;
+
+ private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, 0, 0, width, height, 32, 0);
+
+ private->ximage->data = g_new (char, private->ximage->bytes_per_line *
+ private->ximage->height);
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ if (image)
+ {
+ image->byte_order = private->ximage->byte_order;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+
+ switch (private->ximage->bits_per_pixel)
+ {
+ case 8:
+ image->bpp = 1;
+ break;
+ case 16:
+ image->bpp = 2;
+ break;
+ case 24:
+ image->bpp = 3;
+ break;
+ case 32:
+ image->bpp = 4;
+ break;
+ }
+ }
+ }
+
+ return image;
+}
+
+GdkImage*
+gdk_image_get (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+ GdkWindowPrivate *win_private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ win_private = (GdkWindowPrivate *) window;
+
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ private->ximage = XGetImage (private->xdisplay,
+ win_private->xwindow,
+ x, y, width, height,
+ AllPlanes, ZPixmap);
+
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = gdk_window_get_visual (window);
+ image->width = width;
+ image->height = height;
+ image->depth = private->ximage->depth;
+
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+
+ return image;
+}
+
+guint32
+gdk_image_get_pixel (GdkImage *image,
+ gint x,
+ gint y)
+{
+ guint32 pixel;
+ GdkImagePrivate *private;
+
+ g_return_val_if_fail (image != NULL, 0);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XGetPixel (private->ximage, x, y);
+
+ return pixel;
+}
+
+void
+gdk_image_put_pixel (GdkImage *image,
+ gint x,
+ gint y,
+ guint32 pixel)
+{
+ GdkImagePrivate *private;
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XPutPixel (private->ximage, x, y, pixel);
+}
+
+void
+gdk_image_destroy (GdkImage *image)
+{
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate*) image;
+ switch (image->type)
+ {
+ case GDK_IMAGE_NORMAL:
+ XDestroyImage (private->ximage);
+ break;
+
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ XShmDetach (private->xdisplay, private->x_shm_info);
+ XDestroyImage (private->ximage);
+
+ x_shm_info = private->x_shm_info;
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+
+ image_list = g_list_remove (image_list, image);
+#else /* USE_SHM */
+ g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ g_free (image);
+}
+
+static void
+gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
+
+ XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height);
+}
+
+static void
+gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+#ifdef USE_SHM
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_SHARED);
+
+ XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height, False);
+#else /* USE_SHM */
+ g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+}
diff --git a/gdk/gdkinput.c b/gdk/gdkinput.c
new file mode 100644
index 000000000..ad4b1fcc9
--- /dev/null
+++ b/gdk/gdkinput.c
@@ -0,0 +1,324 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "../config.h"
+#include "gdk.h"
+#include "gdkx.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+/* Forward declarations */
+
+static gint gdk_input_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
+static GdkDevicePrivate *gdk_input_find_device (guint32 id);
+
+
+/* Incorporate the specific routines depending on compilation options */
+
+static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
+
+static GdkDeviceInfo gdk_input_core_info =
+{
+ GDK_CORE_POINTER,
+ "Core Pointer",
+ GDK_SOURCE_MOUSE,
+ GDK_MODE_SCREEN,
+ TRUE,
+ 2,
+ gdk_input_core_axes
+};
+
+/* Global variables */
+
+GdkInputVTable gdk_input_vtable;
+/* information about network port and host for gxid daemon */
+gchar *gdk_input_gxid_host;
+gint gdk_input_gxid_port;
+gint gdk_input_ignore_core;
+
+/* Local variables */
+
+static GList *gdk_input_devices;
+static GList *gdk_input_windows;
+
+#include "gdkinputnone.h"
+#include "gdkinputcommon.h"
+#include "gdkinputxfree.h"
+#include "gdkinputgxi.h"
+
+GList *
+gdk_input_list_devices ()
+{
+ return gdk_input_devices;
+}
+
+void
+gdk_input_set_source (guint32 deviceid, GdkInputSource source)
+{
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ gdkdev->info.source = source;
+}
+
+gint
+gdk_input_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ if (gdk_input_vtable.set_mode)
+ return gdk_input_vtable.set_mode(deviceid,mode);
+ else
+ return FALSE;
+}
+
+void
+gdk_input_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_axes)
+ gdk_input_vtable.set_axes (deviceid, axes);
+}
+
+GdkTimeCoord *
+gdk_input_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ XTimeCoord *xcoords;
+ GdkTimeCoord *coords;
+ int i;
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ xcoords = XGetMotionEvents (gdk_display,
+ ((GdkWindowPrivate *)window)->xwindow,
+ start, stop, nevents_return);
+ if (xcoords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+ for (i=0; i<*nevents_return; i++)
+ {
+ coords[i].time = xcoords[i].time;
+ coords[i].x = xcoords[i].x;
+ coords[i].y = xcoords[i].y;
+ coords[i].pressure = 0.5;
+ coords[i].xtilt = 0.0;
+ coords[i].ytilt = 0.0;
+ }
+
+ XFree(xcoords);
+
+ return coords;
+ }
+ else
+ return NULL;
+ }
+ else
+ {
+ if (gdk_input_vtable.motion_events)
+ {
+ return gdk_input_vtable.motion_events(window,
+ deviceid, start, stop,
+ nevents_return);
+ }
+ else
+ {
+ *nevents_return = 0;
+ return NULL;
+ }
+ }
+}
+
+static gint
+gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.enable_window)
+ return gdk_input_vtable.enable_window (window, gdkdev);
+ else
+ return TRUE;
+}
+
+static gint
+gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.disable_window)
+ return gdk_input_vtable.disable_window(window,gdkdev);
+ else
+ return TRUE;
+}
+
+
+static GdkInputWindow *
+gdk_input_window_find(GdkWindow *window)
+{
+ GList *tmp_list;
+
+ for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
+ if (((GdkInputWindow *)(tmp_list->data))->window == window)
+ return (GdkInputWindow *)(tmp_list->data);
+
+ return NULL; /* Not found */
+}
+
+/* FIXME: this routine currently needs to be called between creation
+ and the corresponding configure event (because it doesn't get the
+ root_relative_geometry). This should work with
+ gtk_window_set_extension_events, but will likely fail in other
+ cases */
+
+void
+gdk_input_set_extension_events (GdkWindow *window, gint mask,
+ GdkExtensionMode mode)
+{
+ GList *tmp_list;
+ GdkInputWindow *iw;
+
+ g_return_if_fail (window != NULL);
+
+ if (mode == GDK_EXTENSION_EVENTS_NONE)
+ mask = 0;
+
+ if (mask != 0)
+ {
+ iw = g_new(GdkInputWindow,1);
+
+ iw->window = window;
+ iw->mode = mode;
+
+ iw->obscuring = NULL;
+ iw->num_obscuring = 0;
+ iw->grabbed = FALSE;
+
+ gdk_input_windows = g_list_append(gdk_input_windows,iw);
+ ((GdkWindowPrivate *)window)->extension_events = mask;
+
+ /* Add enter window events to the event mask */
+ /* FIXME, this is not needed for XINPUT_NONE */
+ gdk_window_set_events (window,
+ gdk_window_get_events (window) |
+ GDK_ENTER_NOTIFY_MASK);
+ }
+ else
+ {
+ iw = gdk_input_window_find (window);
+ if (iw)
+ {
+ gdk_input_windows = g_list_remove(gdk_input_windows,iw);
+ g_free(iw);
+ }
+
+ ((GdkWindowPrivate *)window)->extension_events = 0;
+ }
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
+ && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
+ gdk_input_enable_window(window,gdkdev);
+ else
+ gdk_input_disable_window(window,gdkdev);
+ }
+ }
+}
+
+void
+gdk_input_window_destroy (GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_windows = g_list_remove(gdk_input_windows,input_window);
+ g_free(input_window);
+}
+
+void
+gdk_input_exit (void)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ gdk_input_set_mode(gdkdev->info.deviceid,GDK_MODE_DISABLED);
+
+ g_free(gdkdev->info.name);
+#ifndef XINPUT_NONE
+ g_free(gdkdev->axes);
+#endif
+ g_free(gdkdev->info.axes);
+ g_free(gdkdev);
+ }
+ }
+
+ g_list_free(gdk_input_devices);
+
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ g_free(tmp_list->data);
+ }
+ g_list_free(gdk_input_windows);
+}
+
+static GdkDevicePrivate *
+gdk_input_find_device(guint32 id)
+{
+ GList *tmp_list = gdk_input_devices;
+ GdkDevicePrivate *gdkdev;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid == id)
+ return gdkdev;
+ tmp_list = tmp_list->next;
+ }
+ return NULL;
+}
+
+void
+gdk_input_window_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ if (gdk_input_vtable.get_pointer)
+ gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
+ xtilt, ytilt, mask);
+}
diff --git a/gdk/gdkinput.h b/gdk/gdkinput.h
new file mode 100644
index 000000000..21aee6000
--- /dev/null
+++ b/gdk/gdkinput.h
@@ -0,0 +1,143 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GDK_INPUT_H__
+#define __GDK_INPUT_H__
+
+#ifndef XINPUT_NONE
+#include <X11/extensions/XInput.h>
+#endif
+
+typedef struct _GdkAxisInfo GdkAxisInfo;
+typedef struct _GdkInputVTable GdkInputVTable;
+typedef struct _GdkDevicePrivate GdkDevicePrivate;
+typedef struct _GdkInputWindow GdkInputWindow;
+
+struct _GdkInputVTable {
+ gint (*set_mode) (guint32 deviceid, GdkInputMode mode);
+ void (*set_axes) (guint32 deviceid, GdkAxisUse *axes);
+ GdkTimeCoord* (*motion_events) (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+ void (*get_pointer) (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+ gint (*grab_pointer) (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+ void (*ungrab_pointer) (guint32 time);
+
+ void (*configure_event) (XConfigureEvent *xevent, GdkWindow *window);
+ void (*enter_event) (XCrossingEvent *xevent, GdkWindow *window);
+ gint (*other_event) (GdkEvent *event, XEvent *xevent, GdkWindow *window);
+ /* Handle an unidentified event. Returns TRUE if handled, FALSE
+ otherwise */
+ gint (*window_none_event) (GdkEvent *event, XEvent *xevent);
+ gint (*enable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev);
+ gint (*disable_window) (GdkWindow *window, GdkDevicePrivate *gdkdev);
+};
+
+/* information about a device axis */
+struct _GdkAxisInfo
+{
+ /* reported x resolution */
+ gint xresolution;
+
+ /* reported x minimum/maximum values */
+ gint xmin_value, xmax_value;
+
+ /* calibrated resolution (for aspect ration) - only relative values
+ between axes used */
+ gint resolution;
+
+ /* calibrated minimum/maximum values */
+ gint min_value, max_value;
+};
+
+#define GDK_INPUT_NUM_EVENTC 6
+
+struct _GdkDevicePrivate {
+ GdkDeviceInfo info;
+
+#ifndef XINPUT_NONE
+ /* information about the axes */
+ GdkAxisInfo *axes;
+
+ /* reverse lookup on axis use type */
+ gint axis_for_use[GDK_AXIS_LAST];
+
+ /* Information about XInput device */
+ XDevice *xdevice;
+
+ int buttonpress_type, buttonrelease_type, motionnotify_type,
+ proximityin_type, proximityout_type, changenotify_type;
+
+ /* true if we need to select a different set of events, but
+ can't because this is the core pointer */
+ gint needs_update;
+
+ /* Mask of buttons (used for button grabs) */
+ gint button_state;
+
+ /* true if we've claimed the device as active. (used only for XINPUT_GXI) */
+ gint claimed;
+#endif /* !XINPUT_NONE */
+};
+
+struct _GdkInputWindow
+{
+ /* gdk window */
+ GdkWindow *window;
+
+ /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */
+ GdkExtensionMode mode;
+
+ /* position relative to root window */
+ gint16 root_x;
+ gint16 root_y;
+
+ /* rectangles relative to window of windows obscuring this one */
+ GdkRectangle *obscuring;
+ gint num_obscuring;
+
+ /* Is there a pointer grab for this window ? */
+ gint grabbed;
+};
+
+/* Global data */
+
+extern GdkInputVTable gdk_input_vtable;
+/* information about network port and host for gxid daemon */
+extern gchar *gdk_input_gxid_host;
+extern gint gdk_input_gxid_port;
+extern gint gdk_input_ignore_core;
+
+/* Function declarations */
+
+void gdk_input_window_destroy (GdkWindow *window);
+
+#endif __GDK_INPUT_H__
diff --git a/gdk/gdkinputcommon.h b/gdk/gdkinputcommon.h
new file mode 100644
index 000000000..5e457e0aa
--- /dev/null
+++ b/gdk/gdkinputcommon.h
@@ -0,0 +1,687 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(XINPUT_GXI) || defined(XINPUT_XFREE)
+
+/* Forward declarations */
+static void gdk_input_get_root_relative_geometry (Display *dpy, Window w,
+ int *x_ret, int *y_ret,
+ int *width_ret,
+ int *height_ret);
+static GdkDevicePrivate *gdk_input_device_new(XDeviceInfo *device,
+ gint include_core);
+static void gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes);
+static void gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_translate_coordinates(GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt);
+static guint gdk_input_translate_state(guint state, guint device_state);
+static gint gdk_input_common_init(gint include_core);
+static gint gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes);
+static GdkTimeCoord * gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+/* Global variables */
+
+static gint gdk_input_root_width;
+static gint gdk_input_root_height;
+
+static void
+gdk_input_get_root_relative_geometry(Display *dpy, Window w, int *x_ret, int *y_ret,
+ int *width_ret, int *height_ret)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&x,&y,&width,&height,&border_widthc,
+ &depthc);
+ x += border_widthc;
+ y += border_widthc;
+
+ while (root != parent)
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc,&depthc);
+ x += xc + border_widthc;
+ y += yc + border_widthc;
+ }
+
+ if (x_ret)
+ *x_ret = x;
+ if (y_ret)
+ *y_ret = y;
+ if (width_ret)
+ *width_ret = width;
+ if (height_ret)
+ *height_ret = height;
+}
+
+static GdkDevicePrivate *
+gdk_input_device_new(XDeviceInfo *device, gint include_core)
+{
+ GdkDevicePrivate *gdkdev;
+ gchar *tmp_name, *p;
+ XAnyClassPtr class;
+ gint i,j;
+
+ gdkdev = g_new(GdkDevicePrivate,1);
+
+ gdkdev->info.deviceid = device->id;
+ if (device->name[0]) {
+ gdkdev->info.name = g_new(char, strlen(device->name)+1);
+ strcpy(gdkdev->info.name,device->name);
+ } else {
+ /* XFree86 3.2 gives an empty name to the default core devices,
+ (fixed in 3.2A) */
+ gdkdev->info.name = g_strdup("pointer");
+ strcpy(gdkdev->info.name,"pointer");
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ }
+
+ gdkdev->info.mode = GDK_MODE_DISABLED;
+
+ /* Try to figure out what kind of device this is by its name -
+ could invite a very, very, long list... Lowercase name
+ for comparison purposes */
+
+ tmp_name = g_strdup(gdkdev->info.name);
+ for (p = tmp_name; *p; p++)
+ {
+ if (*p >= 'A' && *p <= 'Z')
+ *p += 'a' - 'A';
+ }
+
+ if (!strcmp (tmp_name, "pointer"))
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ else if (!strcmp (tmp_name, "wacom") ||
+ !strcmp (tmp_name, "pen"))
+ gdkdev->info.source = GDK_SOURCE_PEN;
+ else if (!strcmp (tmp_name, "eraser"))
+ gdkdev->info.source = GDK_SOURCE_ERASER;
+ else if (!strcmp (tmp_name, "cursor"))
+ gdkdev->info.source = GDK_SOURCE_CURSOR;
+ else
+ gdkdev->info.source = GDK_SOURCE_PEN;
+
+ g_free(tmp_name);
+
+ gdkdev->xdevice = NULL;
+
+ /* step through the classes */
+
+ gdkdev->info.num_axes = 0;
+ gdkdev->axes = 0;
+ gdkdev->info.has_cursor = 0;
+ gdkdev->needs_update = FALSE;
+ gdkdev->claimed = FALSE;
+ gdkdev->button_state = 0;
+
+ class = device->inputclassinfo;
+ for (i=0;i<device->num_classes;i++)
+ {
+ switch (class->class) {
+ case ButtonClass:
+ {
+ break;
+ }
+ case ValuatorClass:
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ gdkdev->info.num_axes = xvi->num_axes;
+ gdkdev->axes = g_new(GdkAxisInfo, xvi->num_axes);
+ gdkdev->info.axes = g_new(GdkAxisUse, xvi->num_axes);
+ for (j=0;j<xvi->num_axes;j++)
+ {
+ gdkdev->axes[j].resolution =
+ gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
+ gdkdev->axes[j].min_value =
+ gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
+ gdkdev->axes[j].max_value =
+ gdkdev->axes[j].xmax_value = xvi->axes[j].max_value;
+ gdkdev->info.axes[j] = GDK_AXIS_IGNORE;
+ }
+ j=0;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_X;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_Y;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_PRESSURE;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_XTILT;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_YTILT;
+
+ /* set up reverse lookup on axis use */
+ for (j=GDK_AXIS_IGNORE;j<GDK_AXIS_LAST;j++)
+ gdkdev->axis_for_use[j] = -1;
+
+ for (j=0;j<xvi->num_axes;j++)
+ if (gdkdev->info.axes[j] != GDK_AXIS_IGNORE)
+ gdkdev->axis_for_use[gdkdev->info.axes[j]] = j;
+
+ break;
+ }
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+ /* return NULL if no axes */
+ if (!gdkdev->info.num_axes || !gdkdev->axes ||
+ (!include_core && device->use == IsXPointer))
+ {
+ g_free(gdkdev->info.name);
+ if (gdkdev->axes)
+ g_free(gdkdev->axes);
+ g_free(gdkdev);
+ return NULL;
+ }
+
+ if (device->use != IsXPointer)
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+
+ return gdkdev;
+}
+
+static void
+gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes)
+{
+ gint i;
+ XEventClass class;
+
+ i = 0;
+ /* We have to track press and release events in pairs to keep
+ track of button state correctly and implement grabbing */
+ if (mask & GDK_BUTTON_PRESS_MASK || mask & GDK_BUTTON_RELEASE_MASK)
+ {
+ DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ DeviceButtonRelease (gdkdev->xdevice, gdkdev->buttonrelease_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_MASK)
+ {
+ DeviceMotionNotify (gdkdev->xdevice, gdkdev->motionnotify_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_HINT_MASK)
+ {
+ /* We'll get into trouble if the macros change, but at least we'll
+ know about it, and we avoid warnings now */
+ DevicePointerMotionHint (gdkdev->xdevice, 0, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_IN_MASK)
+ {
+ ProximityIn (gdkdev->xdevice, gdkdev->proximityin_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_OUT_MASK)
+ {
+ ProximityOut (gdkdev->xdevice, gdkdev->proximityout_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ *num_classes = i;
+}
+
+static void
+gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev)
+{
+ XEventClass classes[6];
+ gint num_classes;
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED)
+ gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
+ else
+ gdk_input_common_find_events(window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ classes, &num_classes);
+
+ XSelectExtensionEvent (gdk_display,
+ GDK_WINDOW_XWINDOW(window),
+ classes, num_classes);
+}
+
+gint
+gdk_input_common_init(gint include_core)
+{
+ char **extensions;
+ XDeviceInfo *devices;
+ int num_devices;
+ int num_extensions, loop;
+ Display *display = gdk_display;
+
+ /* Init global vars */
+ gdk_window_get_geometry(NULL, /* use root window */
+ NULL,NULL,
+ &gdk_input_root_width,&gdk_input_root_height,
+ NULL);
+
+ /* Init XInput extension */
+
+ extensions = XListExtensions(display, &num_extensions);
+ for (loop = 0; loop < num_extensions &&
+ (strcmp(extensions[loop], "XInputExtension") != 0); loop++);
+ XFreeExtensionList(extensions);
+ if (loop == num_extensions) /* XInput extension not found */
+ return FALSE;
+
+ gdk_input_devices = 0;
+ devices = XListInputDevices(display, &num_devices);
+
+ for(loop=0; loop<num_devices; loop++)
+ {
+ GdkDevicePrivate *gdkdev = gdk_input_device_new(&devices[loop],
+ include_core);
+ if (gdkdev)
+ gdk_input_devices = g_list_append(gdk_input_devices, gdkdev);
+ }
+ XFreeDeviceList(devices);
+
+ gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
+
+ return TRUE;
+}
+
+static void
+gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y, gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt)
+{
+ GdkWindowPrivate *win_priv;
+
+ int x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
+
+ double device_width, device_height;
+ double x_offset, y_offset, x_scale, y_scale;
+
+ win_priv = (GdkWindowPrivate *) input_window->window;
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+ pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
+ xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
+ ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
+
+ device_width = gdkdev->axes[x_axis].max_value -
+ gdkdev->axes[x_axis].min_value;
+ device_height = gdkdev->axes[y_axis].max_value -
+ gdkdev->axes[y_axis].min_value;
+
+ if (gdkdev->info.mode == GDK_MODE_SCREEN)
+ {
+ x_scale = gdk_input_root_width / device_width;
+ y_scale = gdk_input_root_height / device_height;
+
+ x_offset = - input_window->root_x;
+ y_offset = - input_window->root_y;
+ }
+ else /* GDK_MODE_WINDOW */
+ {
+ double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
+ (device_width*gdkdev->axes[x_axis].resolution);
+
+ if (device_aspect * win_priv->width >= win_priv->height)
+ {
+ /* device taller than window */
+ x_scale = win_priv->width / device_width;
+ y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
+ / gdkdev->axes[y_axis].resolution;
+
+ x_offset = 0;
+ y_offset = -(device_height * y_scale -
+ win_priv->height)/2;
+ }
+ else
+ {
+ /* window taller than device */
+ y_scale = win_priv->height / device_height;
+ x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
+ / gdkdev->axes[x_axis].resolution;
+
+ y_offset = 0;
+ x_offset = - (device_width * x_scale - win_priv->width)/2;
+ }
+ }
+
+ if (x) *x = x_offset + x_scale*axis_data[x_axis];
+ if (y) *y = y_offset + y_scale*axis_data[y_axis];
+
+ if (pressure)
+ {
+ if (pressure_axis != -1)
+ *pressure = ((double)axis_data[pressure_axis]
+ - gdkdev->axes[pressure_axis].min_value)
+ / (gdkdev->axes[pressure_axis].max_value
+ - gdkdev->axes[pressure_axis].min_value);
+ else
+ *pressure = 0.5;
+ }
+
+ if (xtilt)
+ {
+ if (xtilt_axis != -1)
+ {
+ *xtilt = 2. * (double)(axis_data[xtilt_axis] -
+ (gdkdev->axes[xtilt_axis].min_value +
+ gdkdev->axes[xtilt_axis].max_value)/2) /
+ (gdkdev->axes[xtilt_axis].max_value -
+ gdkdev->axes[xtilt_axis].min_value);
+ }
+ else *xtilt = 0;
+ }
+
+ if (ytilt)
+ {
+ if (ytilt_axis != -1)
+ {
+ *ytilt = 2. * (double)(axis_data[ytilt_axis] -
+ (gdkdev->axes[ytilt_axis].min_value +
+ gdkdev->axes[ytilt_axis].max_value)/2) /
+ (gdkdev->axes[ytilt_axis].max_value -
+ gdkdev->axes[ytilt_axis].min_value);
+ }
+ else
+ *ytilt = 0;
+ }
+}
+
+/* combine the state of the core device and the device state
+ into one - for now we do this in a simple-minded manner -
+ we just take the keyboard portion of the core device and
+ the button portion (all of?) the device state.
+ Any button remapping should go on here. */
+static guint
+gdk_input_translate_state(guint state, guint device_state)
+{
+ return device_state | (state & 0xFF);
+}
+
+static gint
+gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev)
+{
+ if ((xevent->type == gdkdev->buttonpress_type) ||
+ (xevent->type == gdkdev->buttonrelease_type))
+ {
+ XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
+
+ if (xdbe->type == gdkdev->buttonpress_type)
+ {
+ event->button.type = GDK_BUTTON_PRESS;
+ gdkdev->button_state |= 1 << xdbe->button;
+ }
+ else
+ {
+ event->button.type = GDK_BUTTON_RELEASE;
+ gdkdev->button_state &= ~(1 << xdbe->button);
+ }
+ event->button.window = input_window->window;
+ event->button.time = xdbe->time;
+ event->button.source = gdkdev->info.source;
+ event->button.deviceid = xdbe->deviceid;
+
+ gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
+ &event->button.x,&event->button.y,
+ &event->button.pressure,
+ &event->button.xtilt,
+ &event->button.ytilt);
+ event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
+ event->button.button = xdbe->button;
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->motionnotify_type)
+ {
+ XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
+
+ gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
+ &event->motion.x,&event->motion.y,
+ &event->motion.pressure,
+ &event->motion.xtilt,
+ &event->motion.ytilt);
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = input_window->window;
+ event->motion.time = xdme->time;
+ event->motion.deviceid = xdme->deviceid;
+ event->motion.state = gdk_input_translate_state(xdme->state,
+ xdme->device_state);
+ event->motion.source = gdkdev->info.source;
+ event->motion.deviceid = xdme->deviceid;
+
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld device: %ld x,y: %f %f hint: %s\n",
+ xdme->window,
+ xdme->deviceid,
+ event->motion.x, event->motion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false");
+
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->proximityin_type ||
+ xevent->type == gdkdev->proximityout_type)
+ {
+ XProximityNotifyEvent *xpne = (XProximityNotifyEvent *)(xevent);
+
+ event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
+ GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
+ event->proximity.window = input_window->window;
+ event->proximity.time = xpne->time;
+ event->proximity.source = gdkdev->info.source;
+ event->proximity.deviceid = xpne->deviceid;
+
+ return TRUE;
+ }
+
+ return -1; /* wasn't one of our event types */
+}
+
+static void
+gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ int i;
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ for (i=GDK_AXIS_IGNORE;i<GDK_AXIS_LAST;i++)
+ {
+ gdkdev->axis_for_use[i] = -1;
+ }
+
+ for (i=0;i<gdkdev->info.num_axes;i++)
+ {
+ gdkdev->info.axes[i] = axes[i];
+ gdkdev->axis_for_use[axes[i]] = i;
+ }
+}
+
+static GdkTimeCoord *
+gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkTimeCoord *coords;
+ XDeviceTimeCoord *device_coords;
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+
+ int mode_return;
+ int axis_count_return;
+ int i;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+ g_return_val_if_fail (gdkdev->xdevice != NULL, NULL);
+ g_return_val_if_fail (input_window != NULL, NULL);
+
+ device_coords = XGetDeviceMotionEvents (gdk_display,
+ gdkdev->xdevice,
+ start, stop,
+ nevents_return, &mode_return,
+ &axis_count_return);
+
+ if (device_coords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+
+ for (i=0; i<*nevents_return; i++)
+ {
+ gdk_input_translate_coordinates (gdkdev, input_window,
+ device_coords[i].data,
+ &coords[i].x, &coords[i].y,
+ &coords[i].pressure,
+ &coords[i].xtilt, &coords[i].ytilt);
+ }
+ XFreeDeviceMotionEvents (device_coords);
+
+ return coords;
+ }
+ else
+ return NULL;
+}
+
+static void
+gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+ GdkInputWindow *input_window;
+ XDeviceState *state;
+ XInputClass *input_class;
+ gint x_int, y_int;
+ gint i;
+
+ /* we probably need to get the mask in any case */
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+ }
+ else
+ {
+ if (mask)
+ gdk_window_get_pointer (window, NULL, NULL, mask);
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_if_fail (gdkdev != NULL);
+ g_return_if_fail (gdkdev->xdevice != NULL);
+ g_return_if_fail (input_window != NULL);
+
+ state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
+ input_class = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ switch (input_class->class)
+ {
+ case ValuatorClass:
+ gdk_input_translate_coordinates(gdkdev, input_window,
+ ((XValuatorState *)input_class)->valuators,
+ x, y, pressure,
+ xtilt, ytilt);
+
+
+ break;
+ case ButtonClass:
+ if (mask)
+ {
+ *mask &= ~(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK);
+ for (i=0; i < ((XButtonState *)input_class)->num_buttons; i++)
+ {
+ if (((XButtonState *)input_class)->buttons[i])
+ *mask |= GDK_BUTTON1_MASK << i;
+ }
+ }
+ break;
+ }
+ input_class = (XInputClass *)(((char *)input_class)+input_class->length);
+ }
+ }
+}
+
+#endif
diff --git a/gdk/gdkinputgxi.h b/gdk/gdkinputgxi.h
new file mode 100644
index 000000000..a30e05f95
--- /dev/null
+++ b/gdk/gdkinputgxi.h
@@ -0,0 +1,628 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_GXI
+
+/* #define DEBUG_SWITCHING */
+
+#include <gxid_lib.h>
+
+/* Forward declarations */
+static void gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode);
+static gint gdk_input_is_extension_device (guint32 deviceid);
+static void gdk_input_gxi_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev);
+
+static gint gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent);
+static gint gdk_input_gxi_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static Window gdk_input_find_root_child(Display *dpy, Window w);
+static void gdk_input_compute_obscuring(GdkInputWindow *input_window);
+static gint gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x,
+ gdouble y);
+static GdkTimeCoord *gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+static gint gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_gxi_ungrab_pointer (guint32 time);
+
+/* Local variables */
+
+static GdkDevicePrivate *gdk_input_current_device;
+static GdkDevicePrivate *gdk_input_core_pointer;
+
+void
+gdk_input_init(void)
+{
+ GList *tmp_list;
+
+ gdk_input_vtable.set_mode = gdk_input_gxi_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_gxi_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_gxi_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_gxi_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_gxi_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_gxi_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_gxi_enter_event;
+ gdk_input_vtable.other_event = gdk_input_gxi_other_event;
+ gdk_input_vtable.window_none_event = gdk_input_gxi_window_none_event;
+ gdk_input_vtable.enable_window = gdk_input_gxi_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_gxi_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_core_pointer = NULL;
+
+ if (!gdk_input_gxid_host)
+ {
+ gdk_input_gxid_host = getenv("GXID_HOST");
+ }
+ if (!gdk_input_gxid_port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ gdk_input_gxid_port = atoi(t);
+ }
+
+ gdk_input_common_init(TRUE);
+
+ /* find initial core pointer */
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdk_input_is_extension_device(gdkdev->info.deviceid))
+ {
+ gdk_input_gxi_select_notify (gdkdev);
+ }
+ else
+ {
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+}
+
+static void
+gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev)
+{
+ XEventClass class;
+
+ ChangeDeviceNotify (gdkdev->xdevice, gdkdev->changenotify_type, class);
+
+ XSelectExtensionEvent (gdk_display, gdk_root_window, &class, 1);
+}
+
+/* Set the core pointer. Device should already be enabled. */
+static gint
+gdk_input_gxi_set_core_pointer(GdkDevicePrivate *gdkdev)
+{
+ int x_axis,y_axis;
+
+ g_return_val_if_fail(gdkdev->xdevice,FALSE);
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+
+ g_return_val_if_fail(x_axis != -1 && y_axis != -1,FALSE);
+
+ /* core_pointer might not be up to date so we check with the server
+ before change the pointer */
+
+ if ( !gdk_input_is_extension_device(gdkdev->info.deviceid) )
+ {
+#if 0
+ if (gdkdev != gdk_input_core_pointer)
+ g_warning("core pointer inconsistency");
+#endif
+ return TRUE;
+ }
+
+ if ( XChangePointerDevice(gdk_display,gdkdev->xdevice, x_axis, y_axis)
+ != Success )
+ {
+ return FALSE;
+ }
+ else
+ {
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ return TRUE;
+ }
+}
+
+
+/* FIXME, merge with gdk_input_xfree_set_mode */
+
+static gint
+gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (old_mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ if (mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ if (!gdk_input_enable_window(input_window->window, gdkdev))
+ {
+ gdk_input_set_mode(deviceid, old_mode);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+gint
+gdk_input_is_extension_device (guint32 deviceid)
+{
+ XDeviceInfo *devices;
+ int num_devices, loop;
+
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ devices = XListInputDevices(gdk_display, &num_devices);
+ for(loop=0; loop<num_devices; loop++)
+ {
+ if ((devices[loop].id == deviceid) && (devices[loop].use == IsXExtensionDevice))
+ {
+ XFreeDeviceList(devices);
+ return TRUE;
+ }
+ }
+
+ XFreeDeviceList(devices);
+ return FALSE;
+}
+
+static void
+gdk_input_gxi_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_get_root_relative_geometry(gdk_display,GDK_WINDOW_XWINDOW(window),
+ &root_x, &root_y, NULL, NULL);
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+ gdk_input_compute_obscuring(input_window);
+}
+
+static void
+gdk_input_gxi_enter_event (XCrossingEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_compute_obscuring(input_window);
+}
+
+static gint
+gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
+ return FALSE;
+
+ if (gdkdev != gdk_input_current_device &&
+ xevent->type != gdkdev->changenotify_type)
+ {
+ gdk_input_current_device = gdkdev;
+ }
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_MOTION_NOTIFY &&
+ (!gdkdev->button_state) && (!input_window->grabbed) &&
+ ((event->motion.x < 0) || (event->motion.y < 0) ||
+ (event->motion.x > ((GdkWindowPrivate *)window)->width) ||
+ (event->motion.y > ((GdkWindowPrivate *)window)->height) ||
+ gdk_input_is_obscured(input_window,event->motion.x,event->motion.y)))
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("gdkinput: Setting core pointer to %d on motion at (%f,%f)\n",
+ gdkdev->info.deviceid,event->motion.x,event->motion.y);
+ g_print(" window geometry is: %dx%d\n",
+ ((GdkWindowPrivate *)window)->width,
+ ((GdkWindowPrivate *)window)->height);
+#endif
+ gdk_input_gxi_set_core_pointer(gdkdev);
+ return FALSE;
+ }
+ else
+ return return_val;
+
+}
+
+static void
+gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev)
+{
+ GList *t;
+
+ if (gdk_input_is_extension_device (gdkdev->info.deviceid))
+ {
+ if (!gdkdev->xdevice)
+ {
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+ gdk_input_gxi_select_notify (gdkdev);
+ gdkdev->needs_update = 1;
+ }
+ if (gdkdev->needs_update && gdkdev->xdevice)
+ {
+ for (t = gdk_input_windows; t; t = t->next)
+ gdk_input_common_select_events (((GdkInputWindow *)t->data)->window,
+ gdkdev);
+ gdkdev->needs_update = 0;
+ }
+ }
+}
+
+static gint
+gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent)
+{
+ GdkDevicePrivate *gdkdev =
+ gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (xevent->type == gdkdev->changenotify_type)
+ {
+ if (gdk_input_core_pointer != gdkdev)
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("ChangeNotify from %d to %d:\n",
+ gdk_input_core_pointer->info.deviceid,
+ gdkdev->info.deviceid);
+#endif
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gdk_input_gxi_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (!gdkdev->claimed)
+ {
+ if (gxid_claim_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window), FALSE) !=
+ GXID_RETURN_OK)
+ {
+ g_warning("Could not get device (is gxid running?)\n");
+ return FALSE;
+ }
+ gdkdev->claimed = TRUE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_gxi_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (gdkdev->claimed)
+ {
+ gxid_release_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window));
+
+ gdkdev->claimed = FALSE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x, gdouble y)
+{
+ int i;
+ for (i=0;i<input_window->num_obscuring;i++)
+ {
+ GdkRectangle *rect = &input_window->obscuring[i];
+ if ((x >= rect->x) &&
+ (y >= rect->y) &&
+ (x < rect->x + rect->width) &&
+ (y < rect->y + rect->height))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gxid.c will need it too. */
+
+static Window
+gdk_input_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+void
+gdk_input_compute_obscuring(GdkInputWindow *input_window)
+{
+ int i;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ Window w = GDK_WINDOW_XWINDOW(input_window->window);
+ Window root_child = gdk_input_find_root_child(gdk_display,w);
+ gdk_input_get_root_relative_geometry(gdk_display,w,&x,&y,&width,&height);
+
+ input_window->root_x = x;
+ input_window->root_y = y;
+
+ XQueryTree(gdk_display,GDK_ROOT_WINDOW(),
+ &root,&parent,&children,&nchildren);
+
+
+ if (input_window->obscuring)
+ g_free(input_window->obscuring);
+ input_window->obscuring = 0;
+ input_window->num_obscuring = 0;
+
+ for (i=0;i<nchildren;i++)
+ if (children[i] == root_child)
+ break;
+
+ if (i>=nchildren-1)
+ {
+ if (nchildren)
+ XFree(children);
+ return;
+ }
+
+ input_window->obscuring = g_new(GdkRectangle,(nchildren-i-1));
+
+ for (i=i+1;i<nchildren;i++)
+ {
+ int xmin, xmax, ymin, ymax;
+ XGetGeometry(gdk_display,children[i],&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc, &depthc);
+ xmin = xc>x ? xc : x;
+ xmax = (xc+widthc)<(x+width) ? xc+widthc : x+width;
+ ymin = yc>y ? yc : y;
+ ymax = (yc+heightc)<(y+height) ? yc+heightc : y+height;
+ if ((xmin < xmax) && (ymin < ymax))
+ {
+ XWindowAttributes attributes;
+ XGetWindowAttributes(gdk_display,children[i],&attributes);
+ if (attributes.map_state == IsViewable)
+ {
+ GdkRectangle *rect = &input_window->obscuring[input_window->num_obscuring];
+
+ /* we store the whole window, not just the obscuring part */
+ rect->x = xc - x;
+ rect->y = yc - y;
+ rect->width = widthc;
+ rect->height = heightc;
+ input_window->num_obscuring++;
+ }
+ }
+ }
+
+ if (nchildren)
+ XFree(children);
+}
+
+static void
+gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ if (gdkdev == gdk_input_core_pointer)
+ gdk_input_common_get_pointer (window, GDK_CORE_POINTER, x, y,
+ pressure, xtilt, ytilt, mask);
+ else
+ gdk_input_common_get_pointer (window, deviceid, x, y,
+ pressure, xtilt, ytilt, mask);
+}
+
+static GdkTimeCoord *
+gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+
+
+ if (gdkdev == gdk_input_core_pointer)
+ return gdk_input_motion_events (window, GDK_CORE_POINTER, start, stop,
+ nevents_return);
+ else
+ return gdk_input_common_motion_events (window, deviceid, start, stop,
+ nevents_return);
+
+}
+
+static gint
+gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ new_window = input_window;
+
+ tmp_list = tmp_list->next;
+ }
+
+ new_window->grabbed = TRUE;
+ return Success;
+}
+
+static void
+gdk_input_gxi_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ input_window->grabbed = FALSE;
+ tmp_list = tmp_list->next;
+ }
+}
+
+#endif /* XINPUT_GXI */
diff --git a/gdk/gdkinputnone.h b/gdk/gdkinputnone.h
new file mode 100644
index 000000000..8ae8c4189
--- /dev/null
+++ b/gdk/gdkinputnone.h
@@ -0,0 +1,72 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_NONE
+
+static void gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+void
+gdk_input_init ()
+{
+ gdk_input_vtable.set_mode = NULL;
+ gdk_input_vtable.set_axes = NULL;
+ gdk_input_vtable.motion_events = NULL;
+ gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
+ gdk_input_vtable.grab_pointer = NULL;
+ gdk_input_vtable.ungrab_pointer = NULL;
+ gdk_input_vtable.configure_event = NULL;
+ gdk_input_vtable.enter_event = NULL;
+ gdk_input_vtable.other_event = NULL;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = NULL;
+ gdk_input_vtable.disable_window = NULL;
+
+ gdk_input_devices = g_list_append (NULL, &gdk_input_core_info);
+
+ gdk_input_ignore_core = FALSE;
+}
+
+static void
+gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ gint x_int, y_int;
+
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+}
+
+#endif /* XINPUT_NONE */
diff --git a/gdk/gdkinputxfree.h b/gdk/gdkinputxfree.h
new file mode 100644
index 000000000..f74249008
--- /dev/null
+++ b/gdk/gdkinputxfree.h
@@ -0,0 +1,368 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_XFREE
+
+/* forward declarations */
+
+static gint gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode);
+static void gdk_input_check_proximity();
+static void gdk_input_xfree_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_enable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_disable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_xfree_ungrab_pointer (guint32 time);
+
+void
+gdk_input_init(void)
+{
+ gdk_input_vtable.set_mode = gdk_input_xfree_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_common_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_common_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_xfree_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_xfree_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_xfree_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_xfree_enter_event;
+ gdk_input_vtable.other_event = gdk_input_xfree_other_event;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = gdk_input_xfree_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_xfree_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_common_init(FALSE);
+}
+
+static gint
+gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (mode == GDK_MODE_WINDOW)
+ {
+ gdkdev->info.has_cursor = FALSE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_enable_window (input_window->window, gdkdev);
+ else
+ if (old_mode != GDK_MODE_DISABLED)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+ else if (mode == GDK_MODE_SCREEN)
+ {
+ gdkdev->info.has_cursor = TRUE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
+ gdkdev);
+ }
+ else /* mode == GDK_MODE_DISABLED */
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (old_mode != GDK_MODE_WINDOW ||
+ input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ return TRUE;
+
+}
+
+static void
+gdk_input_check_proximity()
+{
+ gint new_proximity = 0;
+ GList *tmp_list = gdk_input_devices;
+
+ while (tmp_list && !new_proximity)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.mode != GDK_MODE_DISABLED
+ && gdkdev->info.deviceid != GDK_CORE_POINTER
+ && gdkdev->xdevice)
+ {
+ XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
+ gdkdev->xdevice);
+ XInputClass *xic;
+ int i;
+
+ xic = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ if (xic->class == ValuatorClass)
+ {
+ XValuatorState *xvs = (XValuatorState *)xic;
+ if ((xvs->mode & ProximityState) == InProximity)
+ {
+ new_proximity = TRUE;
+ }
+ break;
+ }
+ xic = (XInputClass *)((char *)xic + xic->length);
+ }
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ gdk_input_ignore_core = new_proximity;
+}
+
+static void
+gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static void
+gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_check_proximity();
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static gint
+gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ /* FIXME: It would be nice if we could just get rid of the events
+ entirely, instead of having to ignore them */
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ (gdkdev->info.mode == GDK_MODE_WINDOW
+ && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+ return FALSE;
+
+ if (!gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
+ gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ /* Do a passive button grab. We have to be careful not to release
+ an explicit grab, if any. Doubling the grab should be harmless,
+ but we check anyways. */
+
+ /* FIXME, finding the proper events here is going to be SLOW - but
+ we might have different sets for each window/device combination */
+
+ if (return_val> 0 && !input_window->grabbed)
+ {
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, event->button.time);
+ }
+ else if (event->type == GDK_BUTTON_RELEASE)
+ XUngrabDevice( GDK_DISPLAY(), gdkdev->xdevice, event->button.time);
+ }
+
+ return return_val;
+}
+
+static gint
+gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ /* FIXME: watchout, gdkdev might be core pointer, never opened */
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ tmp_list = gdk_input_windows;
+ new_window = NULL;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ {
+ new_window = input_window;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_return_if_fail (new_window == NULL);
+
+ new_window->grabbed = TRUE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ /* FIXME: we should do something on failure */
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ return Success;
+}
+
+static void
+gdk_input_xfree_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list) /* we found a grabbed window */
+ {
+ input_window->grabbed = FALSE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ XUngrabDevice( gdk_display, gdkdev->xdevice, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+#endif /* XINPUT_XFREE */
diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c
new file mode 100644
index 000000000..d2d96b6da
--- /dev/null
+++ b/gdk/gdkpixmap.c
@@ -0,0 +1,657 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+typedef struct
+{
+ gchar *color_string;
+ GdkColor color;
+ gint transparent;
+} _GdkPixmapColor;
+
+GdkPixmap*
+gdk_pixmap_new (GdkWindow *window,
+ gint width,
+ gint height,
+ gint depth)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow,
+ width, height, depth);
+ private->parent = NULL;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = 0;
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreateBitmapFromData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ GdkColor *fg,
+ GdkColor *bg)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (fg != NULL, NULL);
+ g_return_val_if_fail (bg != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height,
+ fg->pixel, bg->pixel, depth);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+gint
+gdk_pixmap_seek_string (FILE *infile,
+ const gchar *str,
+ gint skip_comments)
+{
+ char instr[1024];
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%s", instr);
+ if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
+ {
+ fscanf (infile, "%s", instr);
+ while (!feof (infile) && strcmp (instr, "*/") != 0)
+ fscanf (infile, "%s", instr);
+ fscanf(infile, "%s", instr);
+ }
+ if (strcmp (instr, str)==0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_seek_char (FILE *infile,
+ gchar c)
+{
+ gchar b, oldb;
+
+ while (!feof (infile))
+ {
+ fscanf(infile, "%c", &b);
+ if (c != b && b == '/')
+ {
+ fscanf (infile, "%c", &b);
+ if (b == '*')
+ {
+ oldb = b;
+ while (!feof (infile) && !(oldb == '*' && b == '/'))
+ {
+ oldb = b;
+ fscanf (infile, "%c", &b);
+ }
+ fscanf (infile, "%c", &b);
+ }
+ }
+ if (c == b)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_read_string (FILE *infile,
+ gchar **buffer,
+ int *buffer_size)
+{
+ gchar c;
+ gint cnt = 0;
+
+ if ((*buffer) == NULL)
+ {
+ (*buffer_size) = 10 * sizeof (gchar);
+ (*buffer) = (gchar *) malloc (*buffer_size);
+ }
+
+ do
+ fscanf (infile, "%c", &c);
+ while (!feof (infile) && c != '"');
+
+ if (c != '"')
+ return FALSE;
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%c", &c);
+
+ if (cnt == (*buffer_size))
+ {
+ (*buffer_size) *= 2;
+ (*buffer) = (gchar *) realloc ((*buffer), *buffer_size);
+ }
+
+ if (c != '"')
+ (*buffer)[cnt++] = c;
+ else
+ {
+ (*buffer)[cnt++] = 0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gchar*
+gdk_pixmap_skip_whitespaces (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_skip_string (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_extract_color (gchar *buffer)
+{
+ gint counter, finished = FALSE, numnames;
+ gchar *ptr = NULL, ch, temp[128];
+ gchar color[128], *retcol;
+
+ counter = 0;
+ while (ptr == NULL)
+ {
+ if (buffer[counter] == 'c')
+ {
+ ch = buffer[counter + 1];
+ if (ch == 0x20 || ch == 0x09)
+ ptr = &buffer[counter + 1];
+ }
+ else if (buffer[counter] == 0)
+ return NULL;
+
+ counter++;
+ }
+
+ if (ptr == NULL)
+ return NULL;
+
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+
+ if (ptr[0] == 0)
+ return NULL;
+ else if (ptr[0] == '#')
+ {
+ retcol = g_new(gchar, strlen (ptr) + 1);
+ strcpy (retcol, ptr);
+ return retcol;
+ }
+
+ color[0] = 0;
+ numnames = 0;
+
+ while (finished == FALSE)
+ {
+ sscanf (ptr, "%s", temp);
+
+ if ((gint)ptr[0] == 0 || strcmp ("s", temp) == 0 || strcmp ("m", temp) == 0 ||
+ strcmp ("g", temp) == 0 || strcmp ("g4", temp) == 0)
+ finished = TRUE;
+ else
+ {
+ if (numnames > 0)
+ strcat (color, " ");
+ strcat (color, temp);
+ ptr = gdk_pixmap_skip_string (ptr);
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+ numnames++;
+ }
+ }
+
+ retcol = g_new(gchar, strlen (color) + 1);
+ strcpy (retcol, color);
+ return retcol;
+}
+
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ const gchar *filename)
+{
+ FILE *infile = NULL;
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt;
+ gchar *buffer = NULL, *color_name = NULL, pixel_str[32];
+ guint buffer_size = 0;
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ infile = fopen (filename, "rb");
+ if (infile != NULL)
+ {
+ if (gdk_pixmap_seek_string (infile, "XPM", FALSE) == TRUE)
+ {
+ if (gdk_pixmap_seek_char (infile,'{') == TRUE)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+ }
+ }
+
+ fclose (infile);
+ free (buffer);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+ }
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm_d (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ gchar **data)
+{
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
+ gchar *buffer, *color_name = NULL, pixel_str[32];
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ i = 0;
+ buffer = data[i++];
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ buffer = data[i++];
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ buffer = data[i++];
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+
+ return pixmap;
+}
+
+void
+gdk_pixmap_destroy (GdkPixmap *pixmap)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (pixmap != NULL);
+
+ private = (GdkPixmapPrivate*) pixmap;
+ if (private->ref_count <= 0)
+ {
+ XFreePixmap (private->xdisplay, private->xwindow);
+ gdk_xid_table_remove (private->xwindow);
+ g_free (pixmap);
+ }
+ else
+ {
+ private->ref_count -= 1;
+ }
+}
diff --git a/gdk/gdkprivate.h b/gdk/gdkprivate.h
new file mode 100644
index 000000000..3c1677e41
--- /dev/null
+++ b/gdk/gdkprivate.h
@@ -0,0 +1,197 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_PRIVATE_H__
+#define __GDK_PRIVATE_H__
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <gdk/gdktypes.h>
+
+#define DND_PROTOCOL_VERSION 0
+
+#define gdk_window_lookup(xid) ((GdkWindow*) gdk_xid_table_lookup (xid))
+#define gdk_pixmap_lookup(xid) ((GdkPixmap*) gdk_xid_table_lookup (xid))
+#define gdk_font_lookup(xid) ((GdkFont*) gdk_xid_table_lookup (xid))
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct _GdkWindowPrivate GdkWindowPrivate;
+typedef struct _GdkWindowPrivate GdkPixmapPrivate;
+typedef struct _GdkImagePrivate GdkImagePrivate;
+typedef struct _GdkGCPrivate GdkGCPrivate;
+typedef struct _GdkColormapPrivate GdkColormapPrivate;
+typedef struct _GdkVisualPrivate GdkVisualPrivate;
+typedef struct _GdkFontPrivate GdkFontPrivate;
+typedef struct _GdkCursorPrivate GdkCursorPrivate;
+
+
+struct _GdkWindowPrivate
+{
+ GdkWindow window;
+ GdkWindow *parent;
+ Window xwindow;
+ Display *xdisplay;
+ gint16 x;
+ gint16 y;
+ guint16 width;
+ guint16 height;
+ guint8 resize_count;
+ guint8 ref_count;
+ guint8 window_type;
+ guint8 destroyed : 2;
+ guint8 dnd_drag_enabled : 1,
+ dnd_drag_datashow : 1,
+ dnd_drag_destructive_op : 1,
+ dnd_drag_accepted : 1,
+ dnd_drop_enabled : 1,
+ dnd_drop_destructive_op : 1;
+ GdkAtom dnd_drag_data_type, *dnd_drag_data_typesavail;
+ guint dnd_drag_data_numtypesavail;
+ /* We have to turn on MotionMask/EnterWindowMask/LeaveWindowMask
+ during drags, then set it back to what it was after */
+ glong dnd_drag_savedeventmask, dnd_drag_eventmask;
+ GdkAtom *dnd_drop_data_typesavail;
+ guint dnd_drop_data_numtypesavail;
+ /* need to allow custom drag/drop cursors */
+
+ gint extension_events;
+};
+
+struct _GdkImagePrivate
+{
+ GdkImage image;
+ XImage *ximage;
+ Display *xdisplay;
+ gpointer x_shm_info;
+
+ void (*image_put) (GdkDrawable *window,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+};
+
+struct _GdkGCPrivate
+{
+ GdkGC gc;
+ GC xgc;
+ Display *xdisplay;
+};
+
+struct _GdkColormapPrivate
+{
+ GdkColormap colormap;
+ Colormap xcolormap;
+ Display *xdisplay;
+ GdkVisual *visual;
+ gint private_val;
+ gint next_color;
+ gint ref_count;
+};
+
+struct _GdkVisualPrivate
+{
+ GdkVisual visual;
+ Visual *xvisual;
+};
+
+struct _GdkFontPrivate
+{
+ GdkFont font;
+ /* XFontStruct *xfont; */
+ /* generic pointer point to XFontStruct or XFontSet */
+ gpointer xfont;
+ Display *xdisplay;
+ gint ref_count;
+};
+
+struct _GdkCursorPrivate
+{
+ GdkCursor cursor;
+ Cursor xcursor;
+ Display *xdisplay;
+};
+
+struct _GdkDndGlobals {
+ GdkAtom gdk_XdeEnter, gdk_XdeLeave, gdk_XdeRequest;
+ GdkAtom gdk_XdeDataAvailable, gdk_XdeDataShow, gdk_XdeCancel;
+ GdkAtom gdk_XdeTypelist;
+ Cursor gdk_cursor_dragdefault, gdk_cursor_dragok;
+ GdkWindow **drag_startwindows;
+ guint drag_numwindows;
+ guint8 drag_really;
+ GdkPoint drag_dropcoords;
+};
+typedef struct _GdkDndGlobals GdkDndGlobals;
+
+void gdk_window_init (void);
+void gdk_visual_init (void);
+
+void gdk_image_init (void);
+void gdk_image_exit (void);
+
+GdkColormap* gdk_colormap_lookup (Colormap xcolormap);
+GdkVisual* gdk_visual_lookup (Visual *xvisual);
+
+void gdk_window_real_destroy (GdkWindow *window);
+void gdk_window_add_colormap_windows (GdkWindow *window);
+
+void gdk_xid_table_insert (XID *xid,
+ gpointer data);
+void gdk_xid_table_remove (XID xid);
+gpointer gdk_xid_table_lookup (XID xid);
+
+
+extern gint gdk_debug_level;
+extern gint gdk_show_events;
+extern gint gdk_use_xshm;
+extern gint gdk_stack_trace;
+extern gchar *gdk_display_name;
+extern Display *gdk_display;
+extern gint gdk_screen;
+extern Window gdk_root_window;
+extern Window gdk_leader_window;
+extern GdkWindowPrivate gdk_root_parent;
+extern Atom gdk_wm_delete_window;
+extern Atom gdk_wm_take_focus;
+extern Atom gdk_wm_protocols;
+extern Atom gdk_wm_window_protocols[];
+extern Atom gdk_selection_property;
+extern GdkDndGlobals gdk_dnd;
+extern GdkWindow *selection_owner[];
+extern gchar *gdk_progname;
+extern gchar *gdk_progclass;
+extern gint gdk_error_code;
+extern gint gdk_error_warnings;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GDK_PRIVATE_H__ */
diff --git a/gdk/gdkproperty.c b/gdk/gdkproperty.c
new file mode 100644
index 000000000..35d8a50cf
--- /dev/null
+++ b/gdk/gdkproperty.c
@@ -0,0 +1,194 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkAtom
+gdk_atom_intern (const gchar *atom_name,
+ gint only_if_exists)
+{
+ return XInternAtom (gdk_display, atom_name, only_if_exists);
+}
+
+gchar *
+gdk_atom_name (GdkAtom atom)
+{
+ gchar *t;
+ gchar *name;
+
+ /* If this atom doesn't exist, we'll die with an X error unless
+ we take precautions */
+
+ gdk_error_warnings = 0;
+ t = XGetAtomName (gdk_display, atom);
+ gdk_error_warnings = 1;
+
+ if (gdk_error_code == -1)
+ {
+ return NULL;
+ }
+ else
+ {
+ name = g_strdup (t);
+ XFree (t);
+
+ return name;
+ }
+}
+
+gint
+gdk_property_get (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gulong offset,
+ gulong length,
+ gint pdelete,
+ GdkAtom *actual_property_type,
+ gint *actual_format_type,
+ gint *actual_length,
+ guchar **data)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+ Atom ret_prop_type;
+ gint ret_format;
+ gulong ret_nitems;
+ gulong ret_bytes_after;
+ gulong ret_length;
+ guchar *ret_data;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XGetWindowProperty (xdisplay, xwindow, property,
+ offset, (length + 3) / 4, pdelete,
+ type, &ret_prop_type, &ret_format,
+ &ret_nitems, &ret_bytes_after,
+ &ret_data);
+
+ if ((ret_prop_type == None) && (ret_format == 0))
+ return FALSE;
+
+ if (actual_property_type)
+ *actual_property_type = ret_prop_type;
+ if (actual_format_type)
+ *actual_format_type = ret_format;
+
+ if (ret_prop_type != property)
+ {
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ /* FIXME: ignoring bytes_after could have very bad effects */
+
+ if (data)
+ {
+ switch (ret_format)
+ {
+ case 8:
+ ret_length = ret_nitems;
+ break;
+ case 16:
+ ret_length = 2 * ret_nitems;
+ break;
+ case 32:
+ ret_length = 4 * ret_nitems;
+ break;
+ default:
+ g_warning ("unknown property return format: %d", ret_format);
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ *data = g_new (guchar, ret_length);
+ memcpy (*data, ret_data, ret_length);
+ if (actual_length)
+ *actual_length = ret_length;
+ }
+
+ XFree (ret_data);
+
+ return TRUE;
+}
+
+void
+gdk_property_change (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gint format,
+ GdkPropMode mode,
+ guchar *data,
+ gint nelements)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XChangeProperty (xdisplay, xwindow, property, type,
+ format, mode, data, nelements);
+}
+
+void
+gdk_property_delete (GdkWindow *window,
+ GdkAtom property)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XDeleteProperty (xdisplay, xwindow, property);
+}
diff --git a/gdk/gdkrectangle.c b/gdk/gdkrectangle.c
new file mode 100644
index 000000000..dbb35b664
--- /dev/null
+++ b/gdk/gdkrectangle.c
@@ -0,0 +1,83 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gdk.h"
+
+
+gint
+gdk_rectangle_intersect (GdkRectangle *src1,
+ GdkRectangle *src2,
+ GdkRectangle *dest)
+{
+ GdkRectangle *temp;
+ gint src1_x2, src1_y2;
+ gint src2_x2, src2_y2;
+ gint return_val;
+
+ g_return_val_if_fail (src1 != NULL, FALSE);
+ g_return_val_if_fail (src2 != NULL, FALSE);
+ g_return_val_if_fail (dest != NULL, FALSE);
+
+ return_val = FALSE;
+
+ if (src2->x < src1->x)
+ {
+ temp = src1;
+ src1 = src2;
+ src2 = temp;
+ }
+ dest->x = src2->x;
+
+ src1_x2 = src1->x + src1->width;
+ src2_x2 = src2->x + src2->width;
+
+ if (src2->x < src1_x2)
+ {
+ if (src1_x2 < src2_x2)
+ dest->width = src1_x2 - dest->x;
+ else
+ dest->width = src2_x2 - dest->x;
+
+ if (src2->y < src1->y)
+ {
+ temp = src1;
+ src1 = src2;
+ src2 = temp;
+ }
+ dest->y = src2->y;
+
+ src1_y2 = src1->y + src1->height;
+ src2_y2 = src2->y + src2->height;
+
+ if (src2->y < src1_y2)
+ {
+ return_val = TRUE;
+
+ if (src1_y2 < src2_y2)
+ dest->height = src1_y2 - dest->y;
+ else
+ dest->height = src2_y2 - dest->y;
+
+ if (dest->height == 0)
+ return_val = FALSE;
+ if (dest->width == 0)
+ return_val = FALSE;
+ }
+ }
+
+ return return_val;
+}
diff --git a/gdk/gdkselection.c b/gdk/gdkselection.c
new file mode 100644
index 000000000..6bd425110
--- /dev/null
+++ b/gdk/gdkselection.c
@@ -0,0 +1,168 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+gint
+gdk_selection_owner_set (GdkWindow *owner,
+ GdkAtom selection,
+ guint32 time,
+ gint send_event)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (owner)
+ {
+ private = (GdkWindowPrivate*) owner;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = None;
+ }
+
+ XSetSelectionOwner (xdisplay, selection, xwindow, time);
+
+ return (XGetSelectionOwner (xdisplay, selection) == xwindow);
+}
+
+GdkWindow*
+gdk_selection_owner_get (GdkAtom selection)
+{
+ Window xwindow;
+
+ xwindow = XGetSelectionOwner (gdk_display, selection);
+ if (xwindow == None)
+ return NULL;
+
+ return gdk_window_lookup (xwindow);
+}
+
+void
+gdk_selection_convert (GdkWindow *requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (requestor != NULL);
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XConvertSelection (private->xdisplay, selection, target,
+ gdk_selection_property, private->xwindow, time);
+}
+
+gint
+gdk_selection_property_get (GdkWindow *requestor,
+ guchar **data,
+ GdkAtom *ret_type,
+ gint *ret_format)
+{
+ GdkWindowPrivate *private;
+ gulong nitems;
+ gulong nbytes;
+ gulong length;
+ GdkAtom prop_type;
+ gint prop_format;
+ guchar *t;
+
+ g_return_val_if_fail (requestor != NULL, 0);
+
+ /* If retrieved chunks are typically small, (and the ICCM says the
+ should be) it would be a win to try first with a buffer of
+ moderate length, to avoid two round trips to the server */
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, 0, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (ret_type)
+ *ret_type = prop_type;
+ if (ret_format)
+ *ret_format = prop_format;
+
+ if (prop_type == None)
+ {
+ *data = NULL;
+ return 0;
+ }
+
+ XFree (t);
+
+ /* Add on an extra byte to handle null termination. X guarantees
+ that t will be 1 longer than nbytes and null terminated */
+ length = nbytes + 1;
+
+ /* We can't delete the selection here, because it might be the INCR
+ protocol, in which case the client has to make sure they'll be
+ notified of PropertyChange events _before_ the property is deleted.
+ Otherwise there's no guarantee we'll win the race ... */
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, (nbytes + 3) / 4, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (prop_type != None)
+ {
+ *data = g_new (guchar, length);
+ memcpy (*data, t, length);
+ XFree (t);
+ return length-1;
+ }
+ else
+ {
+ *data = NULL;
+ return 0;
+ }
+}
+
+
+void
+gdk_selection_send_notify (guint32 requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ GdkAtom property,
+ guint32 time)
+{
+ XSelectionEvent xevent;
+
+ xevent.type = SelectionNotify;
+ xevent.serial = 0;
+ xevent.send_event = True;
+ xevent.display = gdk_display;
+ xevent.requestor = requestor;
+ xevent.selection = selection;
+ xevent.target = target;
+ xevent.property = property;
+ xevent.time = time;
+
+ XSendEvent (gdk_display, requestor, False, NoEventMask, (XEvent*) &xevent);
+}
diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h
new file mode 100644
index 000000000..7fc7434ac
--- /dev/null
+++ b/gdk/gdktypes.h
@@ -0,0 +1,967 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_TYPES_H__
+#define __GDK_TYPES_H__
+
+
+/* GDK uses "glib". (And so does GTK).
+ */
+#include <glib.h>
+
+
+#define GDK_NONE 0L
+#define GDK_CURRENT_TIME 0L
+#define GDK_PARENT_RELATIVE 1L
+
+/* special deviceid for core pointer events */
+#define GDK_CORE_POINTER 0xfedc
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Type definitions for the basic structures.
+ */
+
+typedef gulong GdkAtom;
+typedef struct _GdkColor GdkColor;
+typedef struct _GdkColormap GdkColormap;
+typedef struct _GdkVisual GdkVisual;
+typedef struct _GdkWindowAttr GdkWindowAttr;
+typedef struct _GdkWindow GdkWindow;
+typedef struct _GdkWindow GdkPixmap;
+typedef struct _GdkWindow GdkBitmap;
+typedef struct _GdkWindow GdkDrawable;
+typedef struct _GdkImage GdkImage;
+typedef struct _GdkGCValues GdkGCValues;
+typedef struct _GdkGC GdkGC;
+typedef struct _GdkPoint GdkPoint;
+typedef struct _GdkRectangle GdkRectangle;
+typedef struct _GdkSegment GdkSegment;
+typedef struct _GdkFont GdkFont;
+typedef struct _GdkCursor GdkCursor;
+
+typedef struct _GdkEventAny GdkEventAny;
+typedef struct _GdkEventExpose GdkEventExpose;
+typedef struct _GdkEventMotion GdkEventMotion;
+typedef struct _GdkEventButton GdkEventButton;
+typedef struct _GdkEventKey GdkEventKey;
+typedef struct _GdkEventFocus GdkEventFocus;
+typedef struct _GdkEventCrossing GdkEventCrossing;
+typedef struct _GdkEventConfigure GdkEventConfigure;
+typedef struct _GdkEventProperty GdkEventProperty;
+typedef struct _GdkEventSelection GdkEventSelection;
+typedef struct _GdkEventProximity GdkEventProximity;
+typedef struct _GdkEventOther GdkEventOther;
+typedef struct _GdkEventDragBegin GdkEventDragBegin;
+typedef struct _GdkEventDragRequest GdkEventDragRequest;
+typedef struct _GdkEventDropEnter GdkEventDropEnter;
+typedef struct _GdkEventDropDataAvailable GdkEventDropDataAvailable;
+typedef struct _GdkEventDropLeave GdkEventDropLeave;
+typedef struct _GdkEventClient GdkEventClient;
+typedef union _GdkEvent GdkEvent;
+typedef struct _GdkDeviceInfo GdkDeviceInfo;
+typedef struct _GdkTimeCoord GdkTimeCoord;
+typedef gint (*GdkEventFunc) (GdkEvent *event,
+ gpointer data);
+
+
+/* Types of windows.
+ * Root: There is only 1 root window and it is initialized
+ * at startup. Creating a window of type GDK_WINDOW_ROOT
+ * is an error.
+ * Toplevel: Windows which interact with the window manager.
+ * Child: Windows which are children of some other type of window.
+ * (Any other type of window). Most windows are child windows.
+ * Dialog: A special kind of toplevel window which interacts with
+ * the window manager slightly differently than a regular
+ * toplevel window. Dialog windows should be used for any
+ * transient window.
+ * Pixmap: Pixmaps are really just another kind of window which
+ * doesn't actually appear on the screen. It can't have
+ * children, either and is really just a convenience so
+ * that the drawing functions can work on both windows
+ * and pixmaps transparently. (ie. You shouldn't pass a
+ * pixmap to any procedure which accepts a window with the
+ * exception of the drawing functions).
+ */
+typedef enum
+{
+ GDK_WINDOW_ROOT,
+ GDK_WINDOW_TOPLEVEL,
+ GDK_WINDOW_CHILD,
+ GDK_WINDOW_DIALOG,
+ GDK_WINDOW_TEMP,
+ GDK_WINDOW_PIXMAP
+} GdkWindowType;
+
+/* Classes of windows.
+ * InputOutput: Almost every window should be of this type. Such windows
+ * receive events and are also displayed on screen.
+ * InputOnly: Used only in special circumstances when events need to be
+ * stolen from another window or windows. Input only windows
+ * have no visible output, so they are handy for placing over
+ * top of a group of windows in order to grab the events (or
+ * filter the events) from those windows.
+ */
+typedef enum
+{
+ GDK_INPUT_OUTPUT,
+ GDK_INPUT_ONLY
+} GdkWindowClass;
+
+/* Types of images.
+ * Normal: Normal X image type. These are slow as they involve passing
+ * the entire image through the X connection each time a draw
+ * request is required.
+ * Shared: Shared memory X image type. These are fast as the X server
+ * and the program actually use the same piece of memory. They
+ * should be used with care though as there is the possibility
+ * for both the X server and the program to be reading/writing
+ * the image simultaneously and producing undesired results.
+ */
+typedef enum
+{
+ GDK_IMAGE_NORMAL,
+ GDK_IMAGE_SHARED,
+ GDK_IMAGE_FASTEST
+} GdkImageType;
+
+/* Types of visuals.
+ * StaticGray:
+ * Grayscale:
+ * StaticColor:
+ * PseudoColor:
+ * TrueColor:
+ * DirectColor:
+ */
+typedef enum
+{
+ GDK_VISUAL_STATIC_GRAY,
+ GDK_VISUAL_GRAYSCALE,
+ GDK_VISUAL_STATIC_COLOR,
+ GDK_VISUAL_PSEUDO_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_DIRECT_COLOR
+} GdkVisualType;
+
+/* Types of font.
+ * GDK_FONT_FONT: the font is an XFontStruct.
+ * GDK_FONT_FONTSET: the font is an XFontSet used for I18N.
+ */
+typedef enum
+{
+ GDK_FONT_FONT,
+ GDK_FONT_FONTSET
+} GdkFontType;
+
+/* Window attribute mask values.
+ * GDK_WA_TITLE: The "title" field is valid.
+ * GDK_WA_X: The "x" field is valid.
+ * GDK_WA_Y: The "y" field is valid.
+ * GDK_WA_CURSOR: The "cursor" field is valid.
+ * GDK_WA_COLORMAP: The "colormap" field is valid.
+ * GDK_WA_VISUAL: The "visual" field is valid.
+ */
+typedef enum
+{
+ GDK_WA_TITLE = 1 << 1,
+ GDK_WA_X = 1 << 2,
+ GDK_WA_Y = 1 << 3,
+ GDK_WA_CURSOR = 1 << 4,
+ GDK_WA_COLORMAP = 1 << 5,
+ GDK_WA_VISUAL = 1 << 6,
+ GDK_WA_WMCLASS = 1 << 7
+} GdkWindowAttributesType;
+
+/* Size restriction enumeration.
+ */
+typedef enum
+{
+ GDK_HINT_POS = 1 << 0,
+ GDK_HINT_MIN_SIZE = 1 << 1,
+ GDK_HINT_MAX_SIZE = 1 << 2
+} GdkWindowHints;
+
+/* GC function types.
+ * Copy: Overwrites destination pixels with the source pixels.
+ * Invert: Inverts the destination pixels.
+ * Xor: Xor's the destination pixels with the source pixels.
+ */
+typedef enum
+{
+ GDK_COPY,
+ GDK_INVERT,
+ GDK_XOR
+} GdkFunction;
+
+/* GC fill types.
+ * Solid:
+ * Tiled:
+ * Stippled:
+ * OpaqueStippled:
+ */
+typedef enum
+{
+ GDK_SOLID,
+ GDK_TILED,
+ GDK_STIPPLED,
+ GDK_OPAQUE_STIPPLED
+} GdkFill;
+
+/* GC line styles
+ * Solid:
+ * OnOffDash:
+ * DoubleDash:
+ */
+typedef enum
+{
+ GDK_LINE_SOLID,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_LINE_DOUBLE_DASH
+} GdkLineStyle;
+
+/* GC cap styles
+ * CapNotLast:
+ * CapButt:
+ * CapRound:
+ * CapProjecting:
+ */
+typedef enum
+{
+ GDK_CAP_NOT_LAST,
+ GDK_CAP_BUTT,
+ GDK_CAP_ROUND,
+ GDK_CAP_PROJECTING
+} GdkCapStyle;
+
+/* GC join styles
+ * JoinMiter:
+ * JoinRound:
+ * JoinBevel:
+ */
+typedef enum
+{
+ GDK_JOIN_MITER,
+ GDK_JOIN_ROUND,
+ GDK_JOIN_BEVEL
+} GdkJoinStyle;
+
+/* Cursor types.
+ */
+typedef enum
+{
+#include <gdk/gdkcursors.h>
+ GDK_LAST_CURSOR
+} GdkCursorType;
+
+/* Event types.
+ * Nothing: No event occurred.
+ * Delete: A window delete event was sent by the window manager.
+ * The specified window should be deleted.
+ * Destroy: A window has been destroyed.
+ * Expose: Part of a window has been uncovered.
+ * MotionNotify: The mouse has moved.
+ * ButtonPress: A mouse button was pressed.
+ * ButtonRelease: A mouse button was release.
+ * KeyPress: A key was pressed.
+ * KeyRelease: A key was released.
+ * EnterNotify: A window was entered.
+ * LeaveNotify: A window was exited.
+ * FocusChange: The focus window has changed. (The focus window gets
+ * keyboard events).
+ * Resize: A window has been resized.
+ * Map: A window has been mapped. (It is now visible on the screen).
+ * Unmap: A window has been unmapped. (It is no longer visible on
+ * the screen).
+ */
+typedef enum
+{
+ GDK_NOTHING = -1,
+ GDK_DELETE = 0,
+ GDK_DESTROY = 1,
+ GDK_EXPOSE = 2,
+ GDK_MOTION_NOTIFY = 3,
+ GDK_BUTTON_PRESS = 4,
+ GDK_2BUTTON_PRESS = 5,
+ GDK_3BUTTON_PRESS = 6,
+ GDK_BUTTON_RELEASE = 7,
+ GDK_KEY_PRESS = 8,
+ GDK_KEY_RELEASE = 9,
+ GDK_ENTER_NOTIFY = 10,
+ GDK_LEAVE_NOTIFY = 11,
+ GDK_FOCUS_CHANGE = 12,
+ GDK_CONFIGURE = 13,
+ GDK_MAP = 14,
+ GDK_UNMAP = 15,
+ GDK_PROPERTY_NOTIFY = 16,
+ GDK_SELECTION_CLEAR = 17,
+ GDK_SELECTION_REQUEST = 18,
+ GDK_SELECTION_NOTIFY = 19,
+ GDK_PROXIMITY_IN = 20,
+ GDK_PROXIMITY_OUT = 21,
+ GDK_DRAG_BEGIN = 22,
+ GDK_DRAG_REQUEST = 23,
+ GDK_DROP_ENTER = 24,
+ GDK_DROP_LEAVE = 25,
+ GDK_DROP_DATA_AVAIL = 26,
+ GDK_CLIENT_EVENT = 27,
+ GDK_OTHER_EVENT = 9999
+} GdkEventType;
+
+/* Event masks. (Used to select what types of events a window
+ * will receive).
+ */
+typedef enum
+{
+ GDK_EXPOSURE_MASK = 1 << 1,
+ GDK_POINTER_MOTION_MASK = 1 << 2,
+ GDK_POINTER_MOTION_HINT_MASK = 1 << 3,
+ GDK_BUTTON_MOTION_MASK = 1 << 4,
+ GDK_BUTTON1_MOTION_MASK = 1 << 5,
+ GDK_BUTTON2_MOTION_MASK = 1 << 6,
+ GDK_BUTTON3_MOTION_MASK = 1 << 7,
+ GDK_BUTTON_PRESS_MASK = 1 << 8,
+ GDK_BUTTON_RELEASE_MASK = 1 << 9,
+ GDK_KEY_PRESS_MASK = 1 << 10,
+ GDK_KEY_RELEASE_MASK = 1 << 11,
+ GDK_ENTER_NOTIFY_MASK = 1 << 12,
+ GDK_LEAVE_NOTIFY_MASK = 1 << 13,
+ GDK_FOCUS_CHANGE_MASK = 1 << 14,
+ GDK_STRUCTURE_MASK = 1 << 15,
+ GDK_PROPERTY_CHANGE_MASK = 1 << 16,
+ GDK_PROXIMITY_IN_MASK = 1 << 17,
+ GDK_PROXIMITY_OUT_MASK = 1 << 18,
+ GDK_ALL_EVENTS_MASK = 0x07FFFF
+} GdkEventMask;
+
+/* Types of enter/leave notifications.
+ * Ancestor:
+ * Virtual:
+ * Inferior:
+ * Nonlinear:
+ * NonlinearVirtual:
+ * Unknown: An unknown type of enter/leave event occurred.
+ */
+typedef enum
+{
+ GDK_NOTIFY_ANCESTOR = 0,
+ GDK_NOTIFY_VIRTUAL = 1,
+ GDK_NOTIFY_INFERIOR = 2,
+ GDK_NOTIFY_NONLINEAR = 3,
+ GDK_NOTIFY_NONLINEAR_VIRTUAL = 4,
+ GDK_NOTIFY_UNKNOWN = 5
+} GdkNotifyType;
+
+/* Types of modifiers.
+ */
+typedef enum
+{
+ GDK_SHIFT_MASK = 1 << 0,
+ GDK_LOCK_MASK = 1 << 1,
+ GDK_CONTROL_MASK = 1 << 2,
+ GDK_MOD1_MASK = 1 << 3,
+ GDK_MOD2_MASK = 1 << 4,
+ GDK_MOD3_MASK = 1 << 5,
+ GDK_MOD4_MASK = 1 << 6,
+ GDK_MOD5_MASK = 1 << 7,
+ GDK_BUTTON1_MASK = 1 << 8,
+ GDK_BUTTON2_MASK = 1 << 9,
+ GDK_BUTTON3_MASK = 1 << 10,
+ GDK_BUTTON4_MASK = 1 << 11,
+ GDK_BUTTON5_MASK = 1 << 12
+} GdkModifierType;
+
+typedef enum
+{
+ GDK_CLIP_BY_CHILDREN = 0,
+ GDK_INCLUDE_INFERIORS = 1
+} GdkSubwindowMode;
+
+typedef enum
+{
+ GDK_INPUT_READ = 1 << 0,
+ GDK_INPUT_WRITE = 1 << 1,
+ GDK_INPUT_EXCEPTION = 1 << 2
+} GdkInputCondition;
+
+typedef enum
+{
+ GDK_OK = 0,
+ GDK_ERROR = -1,
+ GDK_ERROR_PARAM = -2,
+ GDK_ERROR_FILE = -3,
+ GDK_ERROR_MEM = -4
+} GdkStatus;
+
+typedef enum
+{
+ GDK_LSB_FIRST,
+ GDK_MSB_FIRST
+} GdkByteOrder;
+
+typedef enum
+{
+ GDK_GC_FOREGROUND = 1 << 0,
+ GDK_GC_BACKGROUND = 1 << 1,
+ GDK_GC_FONT = 1 << 2,
+ GDK_GC_FUNCTION = 1 << 3,
+ GDK_GC_FILL = 1 << 4,
+ GDK_GC_TILE = 1 << 5,
+ GDK_GC_STIPPLE = 1 << 6,
+ GDK_GC_CLIP_MASK = 1 << 7,
+ GDK_GC_SUBWINDOW = 1 << 8,
+ GDK_GC_TS_X_ORIGIN = 1 << 9,
+ GDK_GC_TS_Y_ORIGIN = 1 << 10,
+ GDK_GC_CLIP_X_ORIGIN = 1 << 11,
+ GDK_GC_CLIP_Y_ORIGIN = 1 << 12,
+ GDK_GC_EXPOSURES = 1 << 13,
+ GDK_GC_LINE_WIDTH = 1 << 14,
+ GDK_GC_LINE_STYLE = 1 << 15,
+ GDK_GC_CAP_STYLE = 1 << 16,
+ GDK_GC_JOIN_STYLE = 1 << 17
+} GdkGCValuesMask;
+
+typedef enum
+{
+ GDK_SELECTION_PRIMARY = 1,
+ GDK_SELECTION_SECONDARY = 2
+} GdkSelection;
+
+typedef enum
+{
+ GDK_PROPERTY_NEW_VALUE,
+ GDK_PROPERTY_DELETE
+} GdkPropertyState;
+
+typedef enum
+{
+ GDK_PROP_MODE_REPLACE,
+ GDK_PROP_MODE_PREPEND,
+ GDK_PROP_MODE_APPEND
+} GdkPropMode;
+
+/* These definitions are for version 1 of the OffiX D&D protocol,
+ taken from <OffiX/DragAndDropTypes.h> */
+typedef enum
+{
+ GDK_DNDTYPE_NOTDND = -1,
+ GDK_DNDTYPE_UNKNOWN = 0,
+ GDK_DNDTYPE_RAWDATA = 1,
+ GDK_DNDTYPE_FILE = 2,
+ GDK_DNDTYPE_FILES = 3,
+ GDK_DNDTYPE_TEXT = 4,
+ GDK_DNDTYPE_DIR = 5,
+ GDK_DNDTYPE_LINK = 6,
+ GDK_DNDTYPE_EXE = 7,
+ GDK_DNDTYPE_URL = 8,
+ GDK_DNDTYPE_MIME = 9,
+ GDK_DNDTYPE_END = 10
+} GdkDndType;
+
+/* Enums for XInput support */
+
+typedef enum
+{
+ GDK_SOURCE_MOUSE,
+ GDK_SOURCE_PEN,
+ GDK_SOURCE_ERASER,
+ GDK_SOURCE_CURSOR
+} GdkInputSource;
+
+typedef enum
+{
+ GDK_MODE_DISABLED,
+ GDK_MODE_SCREEN,
+ GDK_MODE_WINDOW
+} GdkInputMode;
+
+typedef enum
+{
+ GDK_AXIS_IGNORE,
+ GDK_AXIS_X,
+ GDK_AXIS_Y,
+ GDK_AXIS_PRESSURE,
+ GDK_AXIS_XTILT,
+ GDK_AXIS_YTILT,
+ GDK_AXIS_LAST
+} GdkAxisUse;
+
+/* The next two types define enums for predefined atoms relating
+ to selections. In general, one will need to use gdk_intern_atom */
+
+typedef enum
+{
+ GDK_TARGET_BITMAP = 5,
+ GDK_TARGET_COLORMAP = 7,
+ GDK_TARGET_DRAWABLE = 17,
+ GDK_TARGET_PIXMAP = 20,
+ GDK_TARGET_STRING = 31
+} GdkTarget;
+
+typedef enum
+{
+ GDK_SELECTION_TYPE_ATOM = 4,
+ GDK_SELECTION_TYPE_BITMAP = 5,
+ GDK_SELECTION_TYPE_COLORMAP = 7,
+ GDK_SELECTION_TYPE_DRAWABLE = 17,
+ GDK_SELECTION_TYPE_INTEGER = 19,
+ GDK_SELECTION_TYPE_PIXMAP = 20,
+ GDK_SELECTION_TYPE_WINDOW = 33,
+ GDK_SELECTION_TYPE_STRING = 31
+} GdkSelectionType;
+
+typedef enum
+{
+ GDK_EXTENSION_EVENTS_NONE,
+ GDK_EXTENSION_EVENTS_ALL,
+ GDK_EXTENSION_EVENTS_CURSOR
+} GdkExtensionMode;
+
+typedef void (*GdkInputFunction) (gpointer data,
+ gint source,
+ GdkInputCondition condition);
+
+/* The color type.
+ * A color consists of red, green and blue values in the
+ * range 0-65535 and a pixel value. The pixel value is highly
+ * dependent on the depth and colormap which this color will
+ * be used to draw into. Therefore, sharing colors between
+ * colormaps is a bad idea.
+ */
+struct _GdkColor
+{
+ gulong pixel;
+ gushort red;
+ gushort green;
+ gushort blue;
+};
+
+/* The colormap type.
+ * Colormaps consist of 256 colors.
+ */
+struct _GdkColormap
+{
+ GdkColor colors[256];
+};
+
+/* The visual type.
+ * "type" is the type of visual this is (PseudoColor, TrueColor, etc).
+ * "depth" is the bit depth of this visual.
+ * "colormap_size" is the size of a colormap for this visual.
+ * "bits_per_rgb" is the number of significant bits per red, green and blue.
+ * The red, green and blue masks, shifts and precisions refer
+ * to value needed to calculate pixel values in TrueColor and DirectColor
+ * visuals. The "mask" is the significant bits within the pixel. The
+ * "shift" is the number of bits left we must shift a primary for it
+ * to be in position (according to the "mask"). "prec" refers to how
+ * much precision the pixel value contains for a particular primary.
+ */
+struct _GdkVisual
+{
+ GdkVisualType type;
+ gint depth;
+ GdkByteOrder byte_order;
+ gint colormap_size;
+ gint bits_per_rgb;
+
+ guint32 red_mask;
+ gint red_shift;
+ gint red_prec;
+
+ guint32 green_mask;
+ gint green_shift;
+ gint green_prec;
+
+ guint32 blue_mask;
+ gint blue_shift;
+ gint blue_prec;
+};
+
+struct _GdkWindowAttr
+{
+ gchar *title;
+ gint event_mask;
+ gint16 x, y;
+ gint16 width;
+ gint16 height;
+ GdkWindowClass wclass;
+ GdkVisual *visual;
+ GdkColormap *colormap;
+ GdkWindowType window_type;
+ GdkCursor *cursor;
+ gchar *wmclass_name;
+ gchar *wmclass_class;
+};
+
+struct _GdkWindow
+{
+ gpointer user_data;
+};
+
+struct _GdkImage
+{
+ GdkImageType type;
+ GdkVisual *visual; /* visual used to create the image */
+ GdkByteOrder byte_order;
+ guint16 width;
+ guint16 height;
+ guint16 depth;
+ guint16 bpp; /* bytes per pixel */
+ guint16 bpl; /* bytes per line */
+ gpointer mem;
+};
+
+struct _GdkGCValues
+{
+ GdkColor foreground;
+ GdkColor background;
+ GdkFont *font;
+ GdkFunction function;
+ GdkFill fill;
+ GdkPixmap *tile;
+ GdkPixmap *stipple;
+ GdkPixmap *clip_mask;
+ GdkSubwindowMode subwindow_mode;
+ gint ts_x_origin;
+ gint ts_y_origin;
+ gint clip_x_origin;
+ gint clip_y_origin;
+ gint graphics_exposures;
+ gint line_width;
+ GdkLineStyle line_style;
+ GdkCapStyle cap_style;
+ GdkJoinStyle join_style;
+};
+
+struct _GdkGC
+{
+ gint dummy_var;
+};
+
+struct _GdkPoint
+{
+ gint16 x;
+ gint16 y;
+};
+
+struct _GdkRectangle
+{
+ gint16 x;
+ gint16 y;
+ guint16 width;
+ guint16 height;
+};
+
+struct _GdkSegment
+{
+ gint16 x1;
+ gint16 y1;
+ gint16 x2;
+ gint16 y2;
+};
+
+struct _GdkFont
+{
+ GdkFontType type;
+ gint ascent;
+ gint descent;
+};
+
+struct _GdkCursor
+{
+ GdkCursorType type;
+};
+
+/* Types for XInput support */
+
+struct _GdkDeviceInfo
+{
+ guint32 deviceid;
+ gchar *name;
+ GdkInputSource source;
+ GdkInputMode mode;
+ gint has_cursor; /* TRUE if the X pointer follows device motion */
+ gint num_axes;
+ GdkAxisUse *axes; /* Specifies use for each axis */
+};
+
+struct _GdkTimeCoord
+{
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+};
+
+struct _GdkEventAny
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+};
+
+struct _GdkEventExpose
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkRectangle area;
+ gint count; /* If non-zero, how many more events follow. */
+};
+
+struct _GdkEventMotion
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ gint16 is_hint;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventButton
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ guint button;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventKey
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ guint state;
+ guint keyval;
+};
+
+struct _GdkEventCrossing
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkWindow *subwindow;
+ GdkNotifyType detail;
+};
+
+struct _GdkEventFocus
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint16 in;
+};
+
+struct _GdkEventConfigure
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint16 x, y;
+ gint16 width;
+ gint16 height;
+};
+
+struct _GdkEventProperty
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkAtom atom;
+ guint32 time;
+ guint state;
+};
+
+struct _GdkEventSelection
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkAtom selection;
+ GdkAtom target;
+ GdkAtom property;
+ guint32 requestor;
+ guint32 time;
+};
+
+/* This event type will be used pretty rarely. It only is important
+ for XInput aware programs that are drawing their own cursor */
+
+struct _GdkEventProximity
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 time;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventDragRequest
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint willaccept:1;
+ guint delete_data:1; /* Do *not* delete if link is sent, only
+ if data is sent */
+ guint senddata:1;
+ guint reserved:22;
+ } flags;
+ glong allflags;
+ } u;
+ guint8 isdrop; /* This gdk event can be generated by a couple of
+ X events - this lets the app know whether the
+ drop really occurred or we just set the data */
+
+ GdkPoint drop_coords;
+ gchar *data_type;
+};
+
+struct _GdkEventDragBegin
+{
+ GdkEventType type;
+ GdkWindow *window;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
+};
+
+struct _GdkEventDropEnter
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint extended_typelist:1;
+ guint reserved:26;
+ } flags;
+ glong allflags;
+ } u;
+};
+
+struct _GdkEventDropLeave
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
+};
+
+struct _GdkEventDropDataAvailable
+{
+ GdkEventType type;
+ GdkWindow *window;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint isdrop:1;
+ guint reserved:25;
+ } flags;
+ glong allflags;
+ } u;
+ gchar *data_type; /* MIME type */
+ gulong data_numbytes;
+ gpointer data;
+};
+
+struct _GdkEventClient
+{
+ GdkEventType type;
+ GdkWindow *window;
+ GdkAtom message_type;
+ gushort data_format;
+ union {
+ char b[20];
+ short s[10];
+ long l[5];
+ } data;
+};
+
+#ifndef _XLIB_H_
+#define XEvent void
+#endif
+
+struct _GdkEventOther
+{
+ GdkEventType type;
+ GdkWindow *window;
+ XEvent *xevent;
+};
+
+union _GdkEvent
+{
+ GdkEventType type;
+ GdkEventAny any;
+ GdkEventExpose expose;
+ GdkEventMotion motion;
+ GdkEventButton button;
+ GdkEventKey key;
+ GdkEventCrossing crossing;
+ GdkEventFocus focus_change;
+ GdkEventConfigure configure;
+ GdkEventProperty property;
+ GdkEventSelection selection;
+ GdkEventProximity proximity;
+ GdkEventDragBegin dragbegin;
+ GdkEventDragRequest dragrequest;
+ GdkEventDropEnter dropenter;
+ GdkEventDropLeave dropleave;
+ GdkEventDropDataAvailable dropdataavailable;
+ GdkEventClient client;
+ GdkEventOther other;
+};
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GDK_TYPES_H__ */
diff --git a/gdk/gdkvisual.c b/gdk/gdkvisual.c
new file mode 100644
index 000000000..22acee6f1
--- /dev/null
+++ b/gdk/gdkvisual.c
@@ -0,0 +1,431 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_visual_add (GdkVisual *visual);
+static void gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec);
+static guint gdk_visual_hash (Visual *key);
+static gint gdk_visual_compare (Visual *a,
+ Visual *b);
+
+
+static GdkVisualPrivate *system_visual;
+static GdkVisualPrivate *visuals;
+static gint nvisuals;
+
+static gint available_depths[4];
+static gint navailable_depths;
+
+static GdkVisualType available_types[6];
+static gint navailable_types;
+
+static char* visual_names[] =
+{
+ "static gray",
+ "grayscale",
+ "static color",
+ "pseudo color",
+ "true color",
+ "direct color",
+};
+
+static GHashTable *visual_hash = NULL;
+
+void
+gdk_visual_init ()
+{
+ static gint possible_depths[5] = { 32, 24, 16, 15, 8 };
+ static GdkVisualType possible_types[6] =
+ {
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_PSEUDO_COLOR,
+ GDK_VISUAL_STATIC_COLOR,
+ GDK_VISUAL_GRAYSCALE,
+ GDK_VISUAL_STATIC_GRAY
+ };
+
+ static gint npossible_depths = 5;
+ static gint npossible_types = 6;
+
+ XVisualInfo *visual_list;
+ XVisualInfo visual_template;
+ GdkVisualPrivate temp_visual;
+ Visual *default_xvisual;
+ int nxvisuals;
+ int i, j;
+
+ visual_template.screen = gdk_screen;
+ visual_list = XGetVisualInfo (gdk_display, VisualScreenMask, &visual_template, &nxvisuals);
+ visuals = g_new (GdkVisualPrivate, nxvisuals);
+
+ default_xvisual = DefaultVisual (gdk_display, gdk_screen);
+
+ nvisuals = 0;
+ for (i = 0; i < nxvisuals; i++)
+ {
+ if (visual_list[i].depth >= 8)
+ {
+#ifdef __cplusplus
+ switch (visual_list[i].c_class)
+#else /* __cplusplus */
+ switch (visual_list[i].class)
+#endif /* __cplusplus */
+ {
+ case StaticGray:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_GRAY;
+ break;
+ case GrayScale:
+ visuals[nvisuals].visual.type = GDK_VISUAL_GRAYSCALE;
+ break;
+ case StaticColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
+ break;
+ case PseudoColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_PSEUDO_COLOR;
+ break;
+ case TrueColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
+ break;
+ case DirectColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_DIRECT_COLOR;
+ break;
+ }
+
+ visuals[nvisuals].visual.depth = visual_list[i].depth;
+ visuals[nvisuals].visual.byte_order =
+ (ImageByteOrder(gdk_display) == LSBFirst) ?
+ GDK_LSB_FIRST : GDK_MSB_FIRST;
+ visuals[nvisuals].visual.red_mask = visual_list[i].red_mask;
+ visuals[nvisuals].visual.green_mask = visual_list[i].green_mask;
+ visuals[nvisuals].visual.blue_mask = visual_list[i].blue_mask;
+ visuals[nvisuals].visual.colormap_size = visual_list[i].colormap_size;
+ visuals[nvisuals].visual.bits_per_rgb = visual_list[i].bits_per_rgb;
+ visuals[nvisuals].xvisual = visual_list[i].visual;
+
+ if ((visuals[nvisuals].visual.type == GDK_VISUAL_TRUE_COLOR) ||
+ (visuals[nvisuals].visual.type == GDK_VISUAL_DIRECT_COLOR))
+ {
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.red_mask,
+ &visuals[nvisuals].visual.red_shift,
+ &visuals[nvisuals].visual.red_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.green_mask,
+ &visuals[nvisuals].visual.green_shift,
+ &visuals[nvisuals].visual.green_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.blue_mask,
+ &visuals[nvisuals].visual.blue_shift,
+ &visuals[nvisuals].visual.blue_prec);
+ }
+ else
+ {
+ visuals[nvisuals].visual.red_mask = 0;
+ visuals[nvisuals].visual.red_shift = 0;
+ visuals[nvisuals].visual.red_prec = 0;
+
+ visuals[nvisuals].visual.green_mask = 0;
+ visuals[nvisuals].visual.green_shift = 0;
+ visuals[nvisuals].visual.green_prec = 0;
+
+ visuals[nvisuals].visual.blue_mask = 0;
+ visuals[nvisuals].visual.blue_shift = 0;
+ visuals[nvisuals].visual.blue_prec = 0;
+ }
+
+ nvisuals += 1;
+ }
+ }
+
+ XFree (visual_list);
+
+ for (i = 0; i < nvisuals; i++)
+ {
+ for (j = i+1; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth >= visuals[i].visual.depth)
+ {
+ if ((visuals[j].visual.depth == 8) && (visuals[i].visual.depth == 8))
+ {
+ if (visuals[j].visual.type == GDK_VISUAL_PSEUDO_COLOR)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ else if ((visuals[i].visual.type != GDK_VISUAL_PSEUDO_COLOR) &&
+ visuals[j].visual.type > visuals[i].visual.type)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ else if ((visuals[j].visual.depth > visuals[i].visual.depth) ||
+ ((visuals[j].visual.depth == visuals[i].visual.depth) &&
+ (visuals[j].visual.type > visuals[i].visual.type)))
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ if (default_xvisual->visualid == visuals[i].xvisual->visualid)
+ {
+ system_visual = &visuals[i];
+ break;
+ }
+
+ if (gdk_debug_level >= 1)
+ for (i = 0; i < nvisuals; i++)
+ g_print ("visual: %s: %d\n",
+ visual_names[visuals[i].visual.type],
+ visuals[i].visual.depth);
+
+ navailable_depths = 0;
+ for (i = 0; i < npossible_depths; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth == possible_depths[i])
+ {
+ available_depths[navailable_depths++] = visuals[j].visual.depth;
+ break;
+ }
+ }
+ }
+
+ if (navailable_depths == 0)
+ g_error ("unable to find a usable depth");
+
+ navailable_types = 0;
+ for (i = 0; i < npossible_types; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.type == possible_types[i])
+ {
+ available_types[navailable_types++] = visuals[j].visual.type;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ gdk_visual_add ((GdkVisual*) &visuals[i]);
+
+ if (npossible_types == 0)
+ g_error ("unable to find a usable visual type");
+}
+
+GdkVisual*
+gdk_visual_ref (GdkVisual *visual)
+{
+ return visual;
+}
+
+void
+gdk_visual_unref (GdkVisual *visual)
+{
+ return;
+}
+
+gint
+gdk_visual_get_best_depth ()
+{
+ return available_depths[0];
+}
+
+GdkVisualType
+gdk_visual_get_best_type ()
+{
+ return available_types[0];
+}
+
+GdkVisual*
+gdk_visual_get_system ()
+{
+ return ((GdkVisual*) system_visual);
+}
+
+GdkVisual*
+gdk_visual_get_best ()
+{
+ return ((GdkVisual*) &(visuals[0]));
+}
+
+GdkVisual*
+gdk_visual_get_best_with_depth (gint depth)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (depth == visuals[i].visual.depth)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_type (GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (visual_type == visuals[i].visual.type)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_both (gint depth,
+ GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if ((depth == visuals[i].visual.depth) &&
+ (visual_type == visuals[i].visual.type))
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+void
+gdk_query_depths (gint **depths,
+ gint *count)
+{
+ *count = navailable_depths;
+ *depths = available_depths;
+}
+
+void
+gdk_query_visual_types (GdkVisualType **visual_types,
+ gint *count)
+{
+ *count = navailable_types;
+ *visual_types = available_types;
+}
+
+void
+gdk_query_visuals (GdkVisual **visual_return,
+ gint *count)
+{
+ *count = nvisuals;
+ *visual_return = (GdkVisual*) visuals;
+}
+
+
+GdkVisual*
+gdk_visual_lookup (Visual *xvisual)
+{
+ GdkVisual *visual;
+
+ if (!visual_hash)
+ return NULL;
+
+ visual = g_hash_table_lookup (visual_hash, xvisual);
+ return visual;
+}
+
+GdkVisual*
+gdkx_visual_get (VisualID xvisualid)
+{
+ int i;
+
+ for (i = 0; i < nvisuals; i++)
+ if (xvisualid == visuals[i].xvisual->visualid)
+ return (GdkVisual*) &visuals[i];
+
+ return NULL;
+}
+
+
+static void
+gdk_visual_add (GdkVisual *visual)
+{
+ GdkVisualPrivate *private;
+
+ if (!visual_hash)
+ visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
+ (GCompareFunc) gdk_visual_compare);
+
+ private = (GdkVisualPrivate*) visual;
+
+ g_hash_table_insert (visual_hash, private->xvisual, visual);
+}
+
+static void
+gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec)
+{
+ *shift = 0;
+ *prec = 0;
+
+ while (!(mask & 0x1))
+ {
+ (*shift)++;
+ mask >>= 1;
+ }
+
+ while (mask & 0x1)
+ {
+ (*prec)++;
+ mask >>= 1;
+ }
+}
+
+static guint
+gdk_visual_hash (Visual *key)
+{
+ return key->visualid;
+}
+
+static gint
+gdk_visual_compare (Visual *a,
+ Visual *b)
+{
+ return (a->visualid == b->visualid);
+}
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
new file mode 100644
index 000000000..aef1367d9
--- /dev/null
+++ b/gdk/gdkwindow.c
@@ -0,0 +1,1358 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+#include <netinet/in.h>
+#include "gdk.h"
+#include "gdkinput.h"
+#include "gdkprivate.h"
+#include <stdlib.h>
+
+int nevent_masks = 16;
+int event_mask_table[18] =
+{
+ ExposureMask,
+ PointerMotionMask,
+ PointerMotionHintMask,
+ ButtonMotionMask,
+ Button1MotionMask,
+ Button2MotionMask,
+ Button3MotionMask,
+ ButtonPressMask | OwnerGrabButtonMask,
+ ButtonReleaseMask | OwnerGrabButtonMask,
+ KeyPressMask,
+ KeyReleaseMask,
+ EnterWindowMask,
+ LeaveWindowMask,
+ FocusChangeMask,
+ StructureNotifyMask,
+ PropertyChangeMask,
+ 0, /* PROXIMITY_IN */
+ 0 /* PROXIMTY_OUT */
+};
+
+
+void
+gdk_window_init ()
+{
+ XWindowAttributes xattributes;
+ unsigned int width;
+ unsigned int height;
+ unsigned int border_width;
+ unsigned int depth;
+ int x, y;
+
+ XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
+ &x, &y, &width, &height, &border_width, &depth);
+ XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
+
+ gdk_root_parent.xdisplay = gdk_display;
+ gdk_root_parent.xwindow = gdk_root_window;
+ gdk_root_parent.window_type = GDK_WINDOW_ROOT;
+ gdk_root_parent.window.user_data = NULL;
+}
+
+GdkWindow*
+gdk_window_new (GdkWindow *parent,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *parent_private;
+ GdkVisual *visual;
+ GdkColormap *colormap;
+ Display *parent_display;
+ Window xparent;
+ Visual *xvisual;
+ XSetWindowAttributes xattributes;
+ long xattributes_mask;
+ XSizeHints size_hints;
+ XWMHints wm_hints;
+ XTextProperty text_property;
+ XClassHint *class_hint;
+ int x, y, depth;
+ unsigned int class;
+ char *title;
+ int i;
+
+ g_return_val_if_fail (attributes != NULL, NULL);
+
+ if (!parent)
+ parent = (GdkWindow*) &gdk_root_parent;
+
+ parent_private = (GdkWindowPrivate*) parent;
+ xparent = parent_private->xwindow;
+ parent_display = parent_private->xdisplay;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ private->parent = parent;
+ private->xdisplay = parent_display;
+ private->destroyed = FALSE;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ xattributes_mask = 0;
+
+ if (attributes_mask & GDK_WA_X)
+ x = attributes->x;
+ else
+ x = 0;
+
+ if (attributes_mask & GDK_WA_Y)
+ y = attributes->y;
+ else
+ y = 0;
+
+ private->x = x;
+ private->y = y;
+ private->width = (attributes->width > 1) ? (attributes->width) : (1);
+ private->height = (attributes->height > 1) ? (attributes->height) : (1);
+ private->window_type = attributes->window_type;
+ private->extension_events = FALSE;
+ private->dnd_drag_data_type = None;
+ private->dnd_drag_data_typesavail =
+ private->dnd_drop_data_typesavail = NULL;
+ private->dnd_drop_enabled = private->dnd_drag_enabled =
+ private->dnd_drag_accepted = private->dnd_drag_datashow =
+ private->dnd_drop_data_numtypesavail =
+ private->dnd_drag_data_numtypesavail = 0;
+ private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
+
+ window->user_data = NULL;
+
+ if (attributes_mask & GDK_WA_VISUAL)
+ visual = attributes->visual;
+ else
+ visual = gdk_visual_get_system ();
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ xattributes.event_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attributes->event_mask & (1 << (i + 1)))
+ xattributes.event_mask |= event_mask_table[i];
+ }
+
+ if (xattributes.event_mask)
+ xattributes_mask |= CWEventMask;
+
+ if (attributes->wclass == GDK_INPUT_OUTPUT)
+ {
+ class = InputOutput;
+ depth = visual->depth;
+
+ if (attributes_mask & GDK_WA_COLORMAP)
+ colormap = attributes->colormap;
+ else
+ colormap = gdk_colormap_get_system ();
+
+ xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes_mask |= CWBorderPixel | CWBackPixel;
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_CHILD:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+ break;
+
+ case GDK_WINDOW_DIALOG:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_TEMP:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+
+ xattributes.save_under = True;
+ xattributes.override_redirect = True;
+ xattributes.cursor = None;
+ xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+ break;
+ case GDK_WINDOW_ROOT:
+ g_error ("cannot make windows of type GDK_WINDOW_ROOT");
+ break;
+ case GDK_WINDOW_PIXMAP:
+ g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
+ break;
+ }
+ }
+ else
+ {
+ depth = 1;
+ class = InputOnly;
+ colormap = NULL;
+ }
+
+ private->xwindow = XCreateWindow (private->xdisplay, xparent,
+ x, y, private->width, private->height,
+ 0, depth, class, xvisual,
+ xattributes_mask, &xattributes);
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_DIALOG:
+ XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_TEMP:
+ XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
+ break;
+ case GDK_WINDOW_CHILD:
+ if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+ (colormap != gdk_colormap_get_system ()) &&
+ (colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
+ {
+ g_print ("adding colormap window\n");
+ gdk_window_add_colormap_windows (window);
+ }
+ break;
+ default:
+ break;
+ }
+
+ size_hints.flags = PSize | PBaseSize;
+ size_hints.width = private->width;
+ size_hints.height = private->height;
+ size_hints.base_width = private->width;
+ size_hints.base_height = private->height;
+
+ wm_hints.flags = InputHint | StateHint | WindowGroupHint;
+ wm_hints.window_group = gdk_leader_window;
+ wm_hints.input = True;
+ wm_hints.initial_state = NormalState;
+
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+ XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
+
+ if (attributes_mask & GDK_WA_TITLE)
+ title = attributes->title;
+ else
+ title = gdk_progname;
+
+ if (XStringListToTextProperty (&title, 1, &text_property))
+ {
+ XSetWMName (private->xdisplay, private->xwindow, &text_property);
+ XSetWMIconName (private->xdisplay, private->xwindow, &text_property);
+ XFree (text_property.value);
+ }
+
+ if (attributes_mask & GDK_WA_WMCLASS)
+ {
+ class_hint = XAllocClassHint ();
+ class_hint->res_name = attributes->wmclass_name;
+ class_hint->res_class = attributes->wmclass_class;
+ XSetClassHint (private->xdisplay, private->xwindow, class_hint);
+ XFree (class_hint);
+ }
+
+ gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+ (attributes->cursor) :
+ NULL));
+
+ return window;
+}
+
+GdkWindow *
+gdk_window_foreign_new (guint32 anid)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ XWindowAttributes attrs;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ XGetWindowAttributes (gdk_display, anid, &attrs);
+
+ private->parent = NULL;
+ private->xwindow = anid;
+ private->xdisplay = gdk_display;
+ private->x = attrs.x;
+ private->y = attrs.y;
+ private->width = attrs.width;
+ private->height = attrs.height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ if (anid == attrs.root)
+ private->window_type = GDK_WINDOW_ROOT;
+ else
+ private->window_type = GDK_WINDOW_TOPLEVEL;
+ /* the above is probably wrong, but it may not be worth the extra
+ X call to get it right */
+
+ private->destroyed = FALSE;
+ private->extension_events = 0;
+
+ window->user_data = NULL;
+
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ return window;
+}
+
+void
+gdk_window_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *temp_private;
+ GdkWindow *temp_window;
+ GList *children;
+ GList *tmp;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if(private->dnd_drag_data_numtypesavail > 0)
+ {
+ free(private->dnd_drag_data_typesavail);
+ private->dnd_drag_data_typesavail = NULL;
+ }
+ if(private->dnd_drop_data_numtypesavail > 0)
+ {
+ free(private->dnd_drop_data_typesavail);
+ private->dnd_drop_data_typesavail = NULL;
+ }
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (private->ref_count >= 1)
+ private->ref_count -= 1;
+
+ if (!private->destroyed || (private->destroyed == 2))
+ {
+ children = gdk_window_get_children (window);
+ tmp = children;
+
+ while (tmp)
+ {
+ temp_window = tmp->data;
+ tmp = tmp->next;
+
+ temp_private = (GdkWindowPrivate*) temp_window;
+ if (temp_private && !temp_private->destroyed)
+ /* Removes some nice coredumps... /David */
+ {
+ temp_private->destroyed = 2;
+ temp_private->ref_count += 1;
+ gdk_window_destroy (temp_window);
+ }
+ }
+
+ g_list_free (children);
+
+ if (!private->destroyed)
+ XDestroyWindow (private->xdisplay, private->xwindow);
+ private->destroyed = TRUE;
+ }
+ break;
+
+ case GDK_WINDOW_ROOT:
+ g_error ("attempted to destroy root window");
+ break;
+
+ case GDK_WINDOW_PIXMAP:
+ g_warning ("called gdk_window_destroy on a pixmap (use gdk_pixmap_destroy)");
+ gdk_pixmap_destroy (window);
+ break;
+ }
+}
+
+void
+gdk_window_real_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (private->extension_events != 0)
+ gdk_input_window_destroy (window);
+
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (private->xwindow);
+ g_free (window);
+ }
+}
+
+GdkWindow*
+gdk_window_ref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count += 1;
+ return window;
+}
+
+void
+gdk_window_unref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_window_real_destroy (window);
+}
+
+void
+gdk_window_show (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ {
+ XRaiseWindow (private->xdisplay, private->xwindow);
+ XMapWindow (private->xdisplay, private->xwindow);
+ }
+}
+
+void
+gdk_window_hide (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ XUnmapWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_move (GdkWindow *window,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XMoveWindow (private->xdisplay, private->xwindow, x, y);
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->x = x;
+ private->y = y;
+ }
+}
+
+void
+gdk_window_resize (GdkWindow *window,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed &&
+ ((private->resize_count > 0) ||
+ (private->width != (guint16) width) ||
+ (private->height != (guint16) height)))
+ {
+ XResizeWindow (private->xdisplay, private->xwindow, width, height);
+ private->resize_count += 1;
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->width = width;
+ private->height = height;
+ }
+ }
+}
+
+void
+gdk_window_move_resize (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+ XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
+
+ if (!private->destroyed &&
+ (private->window_type == GDK_WINDOW_CHILD))
+ {
+ private->x = x;
+ private->y = y;
+ private->width = width;
+ private->height = height;
+ }
+}
+
+void
+gdk_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *parent_private;
+
+ g_return_if_fail (window != NULL);
+
+ if (!new_parent)
+ new_parent = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+ parent_private = (GdkWindowPrivate*) new_parent;
+
+ XReparentWindow (window_private->xdisplay,
+ window_private->xwindow,
+ parent_private->xwindow,
+ x, y);
+}
+
+void
+gdk_window_clear (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XClearWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, False);
+}
+
+void
+gdk_window_clear_area_e (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, True);
+}
+
+void
+gdk_window_copy_area (GdkWindow *window,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ GdkWindow *source_window,
+ gint source_x,
+ gint source_y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *src_private;
+ GdkWindowPrivate *dest_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (gc != NULL);
+
+ if (source_window == NULL)
+ source_window = window;
+
+ src_private = (GdkWindowPrivate*) source_window;
+ dest_private = (GdkWindowPrivate*) window;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (!src_private->destroyed && !dest_private->destroyed)
+ {
+ XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
+ gc_private->xgc,
+ source_x, source_y,
+ width, height,
+ x, y);
+ }
+}
+
+void
+gdk_window_raise (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XRaiseWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_lower (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XLowerWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_set_user_data (GdkWindow *window,
+ gpointer user_data)
+{
+ g_return_if_fail (window != NULL);
+
+ window->user_data = user_data;
+}
+
+void
+gdk_window_set_hints (GdkWindow *window,
+ gint x,
+ gint y,
+ gint min_width,
+ gint min_height,
+ gint max_width,
+ gint max_height,
+ gint flags)
+{
+ GdkWindowPrivate *private;
+ XSizeHints size_hints;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ size_hints.flags = 0;
+
+ if (flags & GDK_HINT_POS)
+ {
+ size_hints.flags |= PPosition;
+ size_hints.x = x;
+ size_hints.y = y;
+ }
+
+ if (flags & GDK_HINT_MIN_SIZE)
+ {
+ size_hints.flags |= PMinSize;
+ size_hints.min_width = min_width;
+ size_hints.min_height = min_height;
+ }
+
+ if (flags & GDK_HINT_MAX_SIZE)
+ {
+ size_hints.flags |= PMaxSize;
+ size_hints.max_width = max_width;
+ size_hints.max_height = max_height;
+ }
+
+ if (flags)
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+}
+
+void
+gdk_window_set_title (GdkWindow *window,
+ const gchar *title)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XStoreName (private->xdisplay, private->xwindow, title);
+ XSetIconName (private->xdisplay, private->xwindow, title);
+}
+
+void
+gdk_window_set_background (GdkWindow *window,
+ GdkColor *color)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
+}
+
+void
+gdk_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap,
+ gint parent_relative)
+{
+ GdkWindowPrivate *window_private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap xpixmap;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkPixmapPrivate*) pixmap;
+
+ if (pixmap)
+ xpixmap = pixmap_private->xwindow;
+ else
+ xpixmap = None;
+
+ if (parent_relative)
+ xpixmap = ParentRelative;
+
+ XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
+}
+
+void
+gdk_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkWindowPrivate *window_private;
+ GdkCursorPrivate *cursor_private;
+ Cursor xcursor;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+ XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
+}
+
+void
+gdk_window_set_colormap (GdkWindow *window,
+ GdkColormap *colormap)
+{
+ GdkWindowPrivate *window_private;
+ GdkColormapPrivate *colormap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (colormap != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ colormap_private = (GdkColormapPrivate*) colormap;
+
+ XSetWindowColormap (window_private->xdisplay,
+ window_private->xwindow,
+ colormap_private->xcolormap);
+
+ if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
+ gdk_window_add_colormap_windows (window);
+}
+
+void
+gdk_window_get_user_data (GdkWindow *window,
+ gpointer *data)
+{
+ g_return_if_fail (window != NULL);
+
+ *data = window->user_data;
+}
+
+void
+gdk_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth)
+{
+ GdkWindowPrivate *window_private;
+ Window root;
+ gint tx;
+ gint ty;
+ guint twidth;
+ guint theight;
+ guint tborder_width;
+ guint tdepth;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetGeometry (window_private->xdisplay, window_private->xwindow,
+ &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+ if (width)
+ *width = twidth;
+ if (height)
+ *height = theight;
+ if (depth)
+ *depth = tdepth;
+}
+
+void
+gdk_window_get_position (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (x)
+ *x = window_private->x;
+ if (y)
+ *y = window_private->y;
+}
+
+void
+gdk_window_get_size (GdkWindow *window,
+ gint *width,
+ gint *height)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (width)
+ *width = window_private->width;
+ if (height)
+ *height = window_private->height;
+}
+
+
+GdkVisual*
+gdk_window_get_visual (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
+ window_private = (GdkWindowPrivate*) window_private->parent;
+
+ if (window_private)
+ {
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_visual_lookup (window_attributes.visual);
+ }
+
+ return NULL;
+}
+
+GdkColormap*
+gdk_window_get_colormap (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_colormap_lookup (window_attributes.colormap);
+}
+
+GdkWindowType
+gdk_window_get_type (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
+
+ window_private = (GdkWindowPrivate*) window;
+ return window_private->window_type;
+}
+
+gint
+gdk_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *private;
+ gint return_val;
+ Window child;
+ gint tx, ty;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = XTranslateCoordinates (private->xdisplay,
+ private->xwindow,
+ gdk_root_window,
+ 0, 0, &tx, &ty,
+ &child);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *return_val;
+ Window root;
+ Window child;
+ int rootx, rooty;
+ int winx, winy;
+ unsigned int xmask;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = NULL;
+ if (XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
+ &rootx, &rooty, &winx, &winy, &xmask))
+ {
+ if (x) *x = winx;
+ if (y) *y = winy;
+ if (mask) *mask = xmask;
+
+ if (child)
+ return_val = gdk_window_lookup (child);
+ }
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_parent (GdkWindow *window)
+{
+ g_return_val_if_fail (window != NULL, NULL);
+
+ return ((GdkWindowPrivate*) window)->parent;
+}
+
+GdkWindow*
+gdk_window_get_toplevel (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ while (private->window_type == GDK_WINDOW_CHILD)
+ {
+ window = ((GdkWindowPrivate*) window)->parent;
+ private = (GdkWindowPrivate*) window;
+ }
+
+ return window;
+}
+
+GList*
+gdk_window_get_children (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *child;
+ GList *children;
+ Window root;
+ Window parent;
+ Window *xchildren;
+ unsigned int nchildren;
+ unsigned int i;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XQueryTree (private->xdisplay, private->xwindow,
+ &root, &parent, &xchildren, &nchildren);
+
+ children = NULL;
+
+ if (nchildren > 0)
+ {
+ for (i = 0; i < nchildren; i++)
+ {
+ child = gdk_window_lookup (xchildren[i]);
+ if (child)
+ children = g_list_prepend (children, child);
+ }
+
+ XFree (xchildren);
+ }
+
+ return children;
+}
+
+GdkEventMask
+gdk_window_get_events (GdkWindow *window)
+{
+ XWindowAttributes attrs;
+ GdkEventMask event_mask;
+ int i;
+
+ XGetWindowAttributes (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ &attrs);
+
+ event_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attrs.your_event_mask & event_mask_table[i])
+ event_mask |= 1 << (i + 1);
+ }
+
+ return event_mask;
+}
+
+void
+gdk_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ long xevent_mask;
+ int i;
+
+ xevent_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ XSelectInput (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ xevent_mask);
+}
+
+void
+gdk_window_add_colormap_windows (GdkWindow *window)
+{
+ GdkWindow *toplevel;
+ GdkWindowPrivate *toplevel_private;
+ GdkWindowPrivate *window_private;
+ Window *old_windows;
+ Window *new_windows;
+ int i, count;
+
+ g_return_if_fail (window != NULL);
+
+ toplevel = gdk_window_get_toplevel (window);
+ toplevel_private = (GdkWindowPrivate*) toplevel;
+ window_private = (GdkWindowPrivate*) window;
+
+ if (!XGetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ &old_windows, &count))
+ {
+ old_windows = NULL;
+ count = 0;
+ }
+
+ for (i = 0; i < count; i++)
+ if (old_windows[i] == window_private->xwindow)
+ return;
+
+ new_windows = g_new (Window, count + 1);
+
+ for (i = 0; i < count; i++)
+ new_windows[i] = old_windows[i];
+ new_windows[count] = window_private->xwindow;
+
+ XSetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ new_windows, count + 1);
+
+ g_free (new_windows);
+ if (old_windows)
+ XFree (old_windows);
+}
+
+/*
+ * This needs the X11 shape extension.
+ * If not available, simply remove the call to
+ * XShapeCombineMask. Shaped windows will look
+ * ugly, but programs still work. Stefan Wille
+ */
+void
+gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x, gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *pixmap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (mask != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkWindowPrivate*) mask;
+
+ XShapeCombineMask (window_private->xdisplay,
+ window_private->xwindow,
+ ShapeBounding,
+ x, y, /* offset */
+ (Pixmap)pixmap_private->xwindow,
+ ShapeSet);
+}
+
+void
+gdk_dnd_drag_addwindow (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
+ {
+ gdk_dnd.drag_numwindows++;
+ gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
+ gdk_dnd.drag_numwindows
+ * sizeof(GdkWindow *));
+ gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
+ window_private->dnd_drag_accepted = 0;
+ }
+ else
+ g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
+}
+
+void
+gdk_window_dnd_drag_set (GdkWindow *window,
+ guint8 drag_enable,
+ gchar **typelist,
+ guint numtypes)
+{
+ GdkWindowPrivate *window_private;
+ int i, wasset = 0;
+
+ g_return_if_fail (window != NULL);
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
+
+ if (drag_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ if (window_private->dnd_drag_data_numtypesavail > 3)
+ wasset = 1;
+ window_private->dnd_drag_data_numtypesavail = numtypes;
+
+ window_private->dnd_drag_data_typesavail =
+ g_realloc (window_private->dnd_drag_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ {
+ /* Allow blanket use of ALL to get anything... */
+ if (strcmp (typelist[i], "ALL"))
+ window_private->dnd_drag_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+ else
+ window_private->dnd_drag_data_typesavail[i] = None;
+ }
+
+ /*
+ * set our extended type list if we need to
+ */
+ if (numtypes > 3)
+ gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
+ XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
+ (guchar *)(window_private->dnd_drag_data_typesavail
+ + (sizeof(GdkAtom) * 3)),
+ (numtypes - 3) * sizeof(GdkAtom));
+ else if (wasset)
+ gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
+ }
+ else
+ {
+ free (window_private->dnd_drag_data_typesavail);
+ window_private->dnd_drag_data_typesavail = NULL;
+ window_private->dnd_drag_data_numtypesavail = 0;
+ }
+}
+
+void
+gdk_window_dnd_drop_set (GdkWindow *window,
+ guint8 drop_enable,
+ gchar **typelist,
+ guint numtypes,
+ guint8 destructive_op)
+{
+ GdkWindowPrivate *window_private;
+ int i;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
+ if (drop_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ window_private->dnd_drop_data_numtypesavail = numtypes;
+
+ window_private->dnd_drop_data_typesavail =
+ g_realloc (window_private->dnd_drop_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ window_private->dnd_drop_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+
+ window_private->dnd_drop_destructive_op = destructive_op;
+ }
+}
+
+/*
+ * This is used to reply to a GDK_DRAG_REQUEST event
+ * (which may be generated by XdeRequest or a confirmed drop...
+ */
+void
+gdk_window_dnd_data_set (GdkWindow *window,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes)
+{
+ GdkWindowPrivate *window_private;
+ XEvent sev;
+ GdkEventDropDataAvailable tmp_ev;
+ gchar *tmp;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (event != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (data_numbytes > 0);
+ g_return_if_fail (event->type == GDK_DRAG_REQUEST);
+
+ g_free (event->dragrequest.data_type);
+ event->dragrequest.data_type = NULL;
+
+ window_private = (GdkWindowPrivate *) window;
+ g_return_if_fail (window_private->dnd_drag_accepted != 0);
+
+ /* We set the property on our window... */
+ gdk_property_change (window, window_private->dnd_drag_data_type,
+ XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
+ data_numbytes);
+ tmp = gdk_atom_name(window_private->dnd_drag_data_type);
+ g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
+ g_free(tmp);
+
+ /*
+ * Then we send the event to tell the receiving window that the
+ * drop has happened
+ */
+ tmp_ev.u.allflags = 0;
+ tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.window = event->dragrequest.requestor;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
+ sev.xclient.data.l[0] = window_private->xwindow;
+ sev.xclient.data.l[1] = tmp_ev.u.allflags;
+ sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
+
+ if (event->dragrequest.isdrop)
+ sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
+ (event->dragrequest.drop_coords.y << 16);
+ else
+ sev.xclient.data.l[3] = 0;
+
+ sev.xclient.data.l[4] = 0;
+
+ XSendEvent (gdk_display, event->dragrequest.requestor, False,
+ NoEventMask, &sev);
+}
diff --git a/gdk/gdkx.h b/gdk/gdkx.h
new file mode 100644
index 000000000..cb8e33b44
--- /dev/null
+++ b/gdk/gdkx.h
@@ -0,0 +1,48 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_X_H__
+#define __GDK_X_H__
+
+#include <gdk/gdkprivate.h>
+
+
+#define GDK_ROOT_WINDOW() gdk_root_window
+#define GDK_ROOT_PARENT() &gdk_root_parent
+#define GDK_DISPLAY() gdk_display
+#define GDK_WINDOW_XDISPLAY(win) (((GdkWindowPrivate*) win)->xdisplay)
+#define GDK_WINDOW_XWINDOW(win) (((GdkWindowPrivate*) win)->xwindow)
+#define GDK_IMAGE_XDISPLAY(image) (((GdkImagePrivate*) image)->xdisplay)
+#define GDK_IMAGE_XIMAGE(image) (((GdkImagePrivate*) image)->ximage)
+#define GDK_GC_XDISPLAY(gc) (((GdkGCPrivate*) gc)->xdisplay)
+#define GDK_GC_XGC(gc) (((GdkGCPrivate*) gc)->xgc)
+#define GDK_COLORMAP_XDISPLAY(cmap) (((GdkColormapPrivate*) cmap)->xdisplay)
+#define GDK_COLORMAP_XCOLORMAP(cmap) (((GdkColormapPrivate*) cmap)->xcolormap)
+#define GDK_VISUAL_XVISUAL(vis) (((GdkVisualPrivate*) vis)->xvisual)
+#define GDK_FONT_XDISPLAY(font) (((GdkFontPrivate*) font)->xdisplay)
+#define GDK_FONT_XFONT(font) (((GdkFontPrivate*) font)->xfont)
+
+
+GdkVisual* gdkx_visual_get (VisualID xvisualid);
+GdkColormap* gdkx_colormap_get (Colormap xcolormap);
+/* Utility function in gdk.c - not sure where it belongs, but it's
+ needed in more than one place, so make it public */
+Window gdk_get_client_window (Display *dpy,
+ Window win);
+
+
+#endif /* __GDK_X_H__ */
diff --git a/gdk/gdkxid.c b/gdk/gdkxid.c
new file mode 100644
index 000000000..7ee6075c5
--- /dev/null
+++ b/gdk/gdkxid.c
@@ -0,0 +1,74 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gdkprivate.h"
+
+
+static guint gdk_xid_hash (XID *xid);
+static gint gdk_xid_compare (XID *a,
+ XID *b);
+
+
+GHashTable *xid_ht = NULL;
+
+
+void
+gdk_xid_table_insert (XID *xid,
+ gpointer data)
+{
+ g_return_if_fail (xid != NULL);
+
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_insert (xid_ht, xid, data);
+}
+
+void
+gdk_xid_table_remove (XID xid)
+{
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_remove (xid_ht, &xid);
+}
+
+gpointer
+gdk_xid_table_lookup (XID xid)
+{
+ gpointer data;
+
+ data = g_hash_table_lookup (xid_ht, &xid);
+
+ return data;
+}
+
+
+static guint
+gdk_xid_hash (XID *xid)
+{
+ return *xid;
+}
+
+static gint
+gdk_xid_compare (XID *a,
+ XID *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/gxid.c b/gdk/gxid.c
new file mode 100644
index 000000000..219c08bfe
--- /dev/null
+++ b/gdk/gxid.c
@@ -0,0 +1,844 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+
+#include "gxid_proto.h"
+
+/* #define DEBUG_CLIENTS */
+/* #define DEBUG_EVENTS */
+
+char *program_name;
+Display *dpy;
+Window root_window; /* default root window of dpy */
+int port = 0; /* port to listen on */
+int socket_fd = 0; /* file descriptor of socket */
+typedef struct GxidWindow_ GxidWindow;
+
+typedef struct GxidDevice_ GxidDevice;
+struct GxidDevice_ {
+ XID id;
+ int exclusive;
+ int ispointer;
+
+ XDevice *xdevice;
+ int motionnotify_type;
+ int changenotify_type;
+};
+
+struct GxidWindow_ {
+ Window xwindow;
+ /* Immediate child of root that is ancestor of window */
+ Window root_child;
+ int num_devices;
+ GxidDevice **devices;
+};
+
+GxidDevice **devices = NULL;
+int num_devices = 0;
+GxidWindow **windows = NULL;
+int num_windows = 0;
+
+void
+handler(int signal)
+{
+ fprintf(stderr,"%s: dying on signal %d\n",program_name,signal);
+ if (socket_fd)
+ close(socket_fd);
+ exit(1);
+}
+
+void
+init_socket()
+{
+ struct sockaddr_in sin;
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
+ if (socket_fd < 0)
+ {
+ fprintf (stderr, "%s: error getting socket\n",
+ program_name);
+ exit(1);
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(socket_fd,(struct sockaddr *)(&sin),
+ sizeof(struct sockaddr_in)) < 0)
+ {
+ fprintf (stderr,"%s: cannot bind to port %d\n",
+ program_name,port);
+ exit(1);
+ }
+
+ if (listen(socket_fd,5) < 0)
+ {
+ fprintf (stderr,"%s: error listening on socket\n",
+ program_name);
+ exit(1);
+ };
+}
+
+#define NUM_EVENTC 2
+static void
+enable_device(GxidDevice *dev)
+{
+ XEventClass xevc[NUM_EVENTC];
+ int num_eventc = NUM_EVENTC;
+ int i,j;
+
+ if (!dev->xdevice)
+ {
+ if (dev->ispointer) return;
+
+ dev->xdevice = XOpenDevice(dpy, dev->id);
+ if (!dev->xdevice) return;
+
+ DeviceMotionNotify (dev->xdevice, dev->motionnotify_type,
+ xevc[0]);
+ ChangeDeviceNotify (dev->xdevice, dev->changenotify_type,
+ xevc[1]);
+
+ /* compress out zero event classes */
+ for (i=0,j=0;i<NUM_EVENTC;i++)
+ {
+ if (xevc[i]) {
+ xevc[j] = xevc[i];
+ j++;
+ }
+ }
+ num_eventc = j;
+
+ XSelectExtensionEvent (dpy, root_window, xevc, num_eventc);
+ }
+}
+
+/* switch the core pointer from whatever it is now to something else,
+ return true on success, false otherwise */
+static int
+switch_core_pointer()
+{
+ GxidDevice *old_pointer = 0;
+ GxidDevice *new_pointer = 0;
+ int result;
+ int i;
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ old_pointer = devices[i];
+ else
+ if (!new_pointer && !devices[i]->exclusive)
+ new_pointer = devices[i];
+ }
+
+ if (!old_pointer || !new_pointer)
+ return 0;
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Switching core from %ld to %ld\n",
+ old_pointer->id,new_pointer->id);
+#endif
+ result = XChangePointerDevice(dpy,new_pointer->xdevice, 0, 1);
+ if (result != Success)
+ {
+ fprintf(stderr,"gxid: Error %d switching core from %ld to %ld\n",
+ result, old_pointer->id, new_pointer->id);
+ }
+ else
+ {
+ new_pointer->ispointer = 1;
+ old_pointer->ispointer = 0;
+ if (!old_pointer->xdevice)
+ enable_device(old_pointer);
+ }
+
+ return 1;
+}
+
+void
+disable_device(GxidDevice *dev)
+{
+ if (dev->xdevice)
+ {
+ if (dev->ispointer)
+ return;
+ XCloseDevice(dpy,dev->xdevice);
+ dev->xdevice = 0;
+ }
+}
+
+GxidDevice *
+init_device(XDeviceInfo *xdevice)
+{
+ GxidDevice *dev = (GxidDevice *)malloc(sizeof(GxidDevice));
+ XAnyClassPtr class;
+ int num_axes, i;
+
+ dev->id = xdevice->id;
+ dev->exclusive = 0;
+ dev->xdevice = NULL;
+
+ dev->ispointer = (xdevice->use == IsXPointer);
+
+ /* step through the classes */
+
+ num_axes = 0;
+ class = xdevice->inputclassinfo;
+ for (i=0;i<xdevice->num_classes;i++)
+ {
+ if (class->class == ValuatorClass)
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ num_axes = xvi->num_axes;
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+
+ /* return NULL if insufficient axes */
+ if (num_axes < 2)
+ {
+ free((void *)dev);
+ return NULL;
+ }
+
+ if (!dev->ispointer)
+ enable_device(dev);
+ return dev;
+}
+
+void
+init_xinput()
+{
+ char **extensions;
+ XDeviceInfo *xdevices;
+ int num_xdevices;
+ int num_extensions;
+ int i;
+
+ extensions = XListExtensions(dpy, &num_extensions);
+ for (i = 0; i < num_extensions &&
+ (strcmp(extensions[i], "XInputExtension") != 0); i++);
+ XFreeExtensionList(extensions);
+ if (i == num_extensions) /* XInput extension not found */
+ {
+ fprintf(stderr,"XInput extension not found\n");
+ exit(1);
+ }
+
+ xdevices = XListInputDevices(dpy, &num_xdevices);
+ devices = (GxidDevice **)malloc(num_xdevices * sizeof(GxidDevice *));
+
+ num_devices = 0;
+ for(i=0; i<num_xdevices; i++)
+ {
+ GxidDevice *dev = init_device(&xdevices[i]);
+ if (dev)
+ devices[num_devices++] = dev;
+ }
+ XFreeDeviceList(xdevices);
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gdkinputgxi.h will need it too. */
+
+Window
+gxi_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+int
+handle_claim_device(GxidClaimDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+ int exclusive = ntohl(msg->exclusive);
+ GxidDevice *device = NULL;
+ GxidWindow *window = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld claimed (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (device->exclusive)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Device %ld already claimed in exclusive mode\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (exclusive)
+ {
+ for (i=0;i<num_windows;i++)
+ {
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j]->id == devid)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Can't establish exclusive use of device %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+ }
+ if (device->ispointer)
+ if (!switch_core_pointer())
+ {
+ fprintf(stderr,
+ "%s: Can't free up core pointer %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ device->exclusive = 1;
+ disable_device(device);
+ XSelectInput(dpy,winid,StructureNotifyMask);
+ }
+ else /* !exclusive */
+ {
+ /* FIXME: this is a bit improper. We probably should do this only
+ when a window is first claimed. But we might be fooled if
+ an old client died without releasing it's windows. So until
+ we look for client-window closings, do it here
+
+ (We do look for closings now...)
+ */
+
+ XSelectInput(dpy,winid,EnterWindowMask|StructureNotifyMask);
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ if (windows[i]->xwindow == winid)
+ {
+ window = windows[i];
+ break;
+ }
+ }
+
+ /* Create window structure if no devices have been previously
+ claimed on it */
+ if (!window)
+ {
+ num_windows++;
+ windows = (GxidWindow **)realloc(windows,
+ sizeof(GxidWindow*)*num_windows);
+ window = (GxidWindow *)malloc(sizeof(GxidWindow));
+ windows[num_windows-1] = window;
+
+ window->xwindow = winid;
+ window->root_child = gxi_find_root_child(dpy,winid);
+ window->num_devices = 0;
+ window->devices = 0;
+ }
+
+
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == device)
+ return GXID_RETURN_OK;
+ }
+
+ window->num_devices++;
+ window->devices = (GxidDevice **)realloc(window->devices,
+ sizeof(GxidDevice*)*num_devices);
+ /* we need add the device to the window */
+ window->devices[i] = device;
+
+ return GXID_RETURN_OK;
+}
+
+int
+handle_release_device(GxidReleaseDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+
+ GxidDevice *device = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ GxidWindow *w = windows[i];
+
+ if (w->xwindow == winid)
+ for (j=0;j<w->num_devices;j++)
+ if (w->devices[j]->id == devid)
+ {
+ if (j<w->num_devices-1)
+ w->devices[j] = w->devices[w->num_devices-1];
+ w->num_devices--;
+
+ if (w->num_devices == 0)
+ {
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+ }
+
+ if (device->exclusive)
+ {
+ device->exclusive = 0;
+ enable_device(device);
+ }
+ return GXID_RETURN_OK;
+ }
+ }
+
+ /* device/window combination not found */
+ fprintf(stderr,
+ "%s: Device %ld not claimed for window 0x%lx\n",
+ program_name,devid,winid);
+ return GXID_RETURN_ERROR;
+}
+
+void
+handle_connection()
+{
+ GxidMessage msg;
+ GxidU32 type;
+ int length;
+ GxidI32 retval;
+
+ int conn_fd;
+ struct sockaddr_in sin;
+ int sin_length;
+ int count;
+
+ sin_length = sizeof(struct sockaddr_in);
+ conn_fd = accept(socket_fd,(struct sockaddr *)&sin,&sin_length);
+ if (conn_fd < 0)
+ {
+ fprintf(stderr,"%s: Error accepting connection\n",
+ program_name);
+ exit(1);
+ }
+
+ /* read type and length of message */
+
+ count = read(conn_fd,(char *)&msg,2*sizeof(GxidU32));
+ if (count != 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message header\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+ type = ntohl(msg.any.type);
+ length = ntohl(msg.any.length);
+
+ /* read rest of message */
+
+ if (length > sizeof(GxidMessage))
+ {
+ fprintf(stderr,"%s: Bad message length\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ count = read(conn_fd,2*sizeof(GxidU32) + (char *)&msg,
+ length - 2*sizeof(GxidU32));
+ if (count != length - 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message body\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ switch (type)
+ {
+ case GXID_CLAIM_DEVICE:
+ retval = handle_claim_device((GxidClaimDevice *)&msg);
+ break;
+ case GXID_RELEASE_DEVICE:
+ retval = handle_release_device((GxidReleaseDevice *)&msg);
+ break;
+ default:
+ fprintf(stderr,"%s: Unknown message type: %ld (ignoring)\n",
+ program_name,type);
+ close(conn_fd);
+ return;
+ }
+
+ count = write(conn_fd,&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"%s: Error writing return code\n",
+ program_name);
+ }
+
+ close(conn_fd);
+}
+
+void
+handle_motion_notify(XDeviceMotionEvent *event)
+{
+ int i,j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+ Window w, root, child;
+ int root_x, root_y, x, y, mask;
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+ if (new_device && !new_device->exclusive && !new_device->ispointer)
+ {
+ /* make sure we aren't stealing the pointer back from a slow
+ client */
+ child = root_window;
+ do
+ {
+ w = child;
+ /* FIXME: this fails disasterously if child vanishes between
+ calls. (Which is prone to happening since we get events
+ on root just as the client exits) */
+
+ XQueryPointer(dpy,w,&root,&child,&root_x,&root_y,
+ &x,&y,&mask);
+ }
+ while (child != None);
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == w)
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j] == new_device)
+ return;
+
+ /* FIXME: do something smarter with axes */
+ XChangePointerDevice(dpy,new_device->xdevice, 0, 1);
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_change_notify(XChangeDeviceNotifyEvent *event)
+{
+ int j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: ChangeNotify event; old = %ld; new = %ld\n",
+ old_device->id, new_device->id);
+#endif
+
+ if (old_device != new_device)
+ {
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_enter_notify(XEnterWindowEvent *event, GxidWindow *window)
+{
+ int i;
+ GxidDevice *old_pointer = NULL;
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ {
+ old_pointer = devices[i];
+ break;
+ }
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Enter event; oldpointer = %ld\n",
+ old_pointer->id);
+#endif
+
+ if (old_pointer)
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == old_pointer)
+ {
+ switch_core_pointer();
+ break;
+ }
+ }
+}
+
+void
+handle_destroy_notify(XDestroyWindowEvent *event)
+{
+ int i,j;
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == event->window)
+ {
+ GxidWindow *w = windows[i];
+
+ for (j=0;j<w->num_devices;j++)
+ {
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released on destruction of window 0x%lx.\n",
+ w->devices[j]->id,w->xwindow);
+#endif
+
+ if (w->devices[j]->exclusive)
+ {
+ w->devices[j]->exclusive = 0;
+ enable_device(devices[j]);
+ }
+ }
+
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ if (w->devices)
+ free((void *)w->devices);
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+
+ return;
+ }
+}
+
+void
+handle_xevent()
+{
+ int i;
+ XEvent event;
+
+ XNextEvent (dpy, &event);
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"Event - type = %d; window = 0x%lx\n",
+ event.type,event.xany.window);
+#endif
+
+ if (event.type == ConfigureNotify)
+ {
+#ifdef DEBUG_EVENTS
+ XConfigureEvent *xce = (XConfigureEvent *)&event;
+ fprintf(stderr," configureNotify: window = 0x%lx\n",xce->window);
+#endif
+ }
+ else if (event.type == EnterNotify)
+ {
+ /* pointer entered a claimed window */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_enter_notify((XEnterWindowEvent *)&event,windows[i]);
+ }
+ }
+ else if (event.type == DestroyNotify)
+ {
+ /* A claimed window was destroyed */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_destroy_notify((XDestroyWindowEvent *)&event);
+ }
+ }
+ else
+ for (i=0;i<num_devices;i++)
+ {
+ if (event.type == devices[i]->motionnotify_type)
+ {
+ handle_motion_notify((XDeviceMotionEvent *)&event);
+ break;
+ }
+ else if (event.type == devices[i]->changenotify_type)
+ {
+ handle_change_notify((XChangeDeviceNotifyEvent *)&event);
+ break;
+ }
+ }
+}
+
+void
+usage()
+{
+ fprintf(stderr,"Usage: %s [-d display] [-p --gxid-port port]\n",
+ program_name);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ char *display_name = NULL;
+ fd_set readfds;
+
+ program_name = argv[0];
+
+ for (i=1;i<argc;i++)
+ {
+ if (!strcmp(argv[i],"-d"))
+ {
+ if (++i >= argc) usage();
+ display_name = argv[i];
+ }
+ else if (!strcmp(argv[i],"--gxid-port") ||
+ !strcmp(argv[i],"-p"))
+ {
+ if (++i >= argc) usage();
+ port = atoi(argv[i]);
+ break;
+ }
+ else
+ usage();
+ }
+
+ if (!port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ port = atoi(t);
+ else
+ port = 6951;
+ }
+ /* set up a signal handler so we can clean up if killed */
+
+ signal(SIGTERM,handler);
+ signal(SIGINT,handler);
+
+ /* initialize the X connection */
+
+ dpy = XOpenDisplay (display_name);
+ if (!dpy)
+ {
+ fprintf (stderr, "%s: unable to open display '%s'\n",
+ program_name, XDisplayName (display_name));
+ exit (1);
+ }
+
+ root_window = DefaultRootWindow(dpy);
+
+ /* We'll want to do this in the future if we are to support
+ gxid monitoring visibility information for clients */
+#if 0
+ XSelectInput(dpy,root_window,SubstructureNotifyMask);
+#endif
+ init_xinput();
+
+ /* set up our server connection */
+
+ init_socket();
+
+ /* main loop */
+
+ if (XPending(dpy)) /* this seems necessary to get things
+ in sync */
+ handle_xevent();
+ while (1)
+ {
+
+ FD_ZERO(&readfds);
+ FD_SET(ConnectionNumber(dpy),&readfds);
+ FD_SET(socket_fd,&readfds);
+
+ if (select(8*sizeof(readfds),&readfds,
+ (fd_set *)0,(fd_set *)0, (struct timeval *)0) < 0)
+ {
+ fprintf(stderr,"Error in select\n");
+ exit(1);
+ }
+
+ if (FD_ISSET(socket_fd,&readfds))
+ handle_connection(socket_fd);
+
+ while (XPending(dpy))
+ handle_xevent();
+ }
+
+ XCloseDisplay (dpy);
+ exit (0);
+}
diff --git a/gdk/gxid_lib.c b/gdk/gxid_lib.c
new file mode 100644
index 000000000..357b76451
--- /dev/null
+++ b/gdk/gxid_lib.c
@@ -0,0 +1,116 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include "../config.h"
+
+#ifdef XINPUT_GXI
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "gxid_lib.h"
+
+/* handles mechanics of communicating with a client */
+static int
+gxid_send_message(char *host, int port, GxidMessage *msg)
+{
+ int socket_fd;
+ struct sockaddr_in sin;
+ int count;
+ GxidI32 retval;
+ struct hostent *he;
+
+ if (!port) port = 6951;
+
+ if (!host || strcmp(host,"localhost") )
+ {
+ /* looking it up as localhost can be _SLOW_ on ppp systems */
+ /* FIXME: Could localhost be anything other than loopback? */
+ host = "127.0.0.1";
+ }
+
+ he = gethostbyname(host);
+ if (!he)
+ {
+ fprintf(stderr,"gxid_lib: error looking up %s\n",host);
+ return GXID_RETURN_ERROR;
+ }
+
+ sin.sin_family = he->h_addrtype;
+ sin.sin_port = htons(port);
+ memcpy(&sin.sin_addr,he->h_addr_list[0],he->h_length);
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,0);
+ if (socket_fd < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't get socket");
+ return GXID_RETURN_ERROR;
+ }
+
+ if (connect(socket_fd, (struct sockaddr *)&sin,
+ sizeof sin) < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't connect to %s:%d\n",host,port);
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ count = write(socket_fd,(char *)msg,ntohl(msg->any.length));
+ if (count != ntohl(msg->any.length))
+ {
+ fprintf(stderr,"gxid_lib: error writing");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ /* now read the return code */
+ count = read(socket_fd,(char *)&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"gxid_lib: error reading return code");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ close (socket_fd);
+ return ntohl(retval);
+}
+
+/* claim a device. If exclusive, device is claimed exclusively */
+int
+gxid_claim_device(char *host, int port, GxidU32 device, GxidU32 window,
+ int exclusive)
+{
+ GxidClaimDevice msg;
+ msg.type = htonl(GXID_CLAIM_DEVICE);
+ msg.length = htonl(sizeof(GxidClaimDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+ msg.exclusive = htonl(exclusive);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+/* release a device/window pair */
+int
+gxid_release_device(char *host, int port, GxidU32 device, GxidU32 window)
+{
+ GxidReleaseDevice msg;
+ msg.type = htonl(GXID_RELEASE_DEVICE);
+ msg.length = htonl(sizeof(GxidReleaseDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+#endif /* XINPUT_GXI */
+
diff --git a/gdk/gxid_lib.h b/gdk/gxid_lib.h
new file mode 100644
index 000000000..6a7103bbe
--- /dev/null
+++ b/gdk/gxid_lib.h
@@ -0,0 +1,6 @@
+#include "gxid_proto.h"
+
+int gxid_claim_device(char *host, int port,
+ GxidU32 device, GxidU32 window, int exclusive);
+int gxid_release_device(char *host, int port, GxidU32 device,
+ GxidU32 window);
diff --git a/gdk/gxid_proto.h b/gdk/gxid_proto.h
new file mode 100644
index 000000000..24959b806
--- /dev/null
+++ b/gdk/gxid_proto.h
@@ -0,0 +1,39 @@
+#define GXID_CLAIM_DEVICE 1
+#define GXID_RELEASE_DEVICE 2
+
+#define GXID_RETURN_OK 0
+#define GXID_RETURN_ERROR -1
+
+typedef struct GxidClaimDevice_ GxidClaimDevice;
+typedef struct GxidReleaseDevice_ GxidReleaseDevice;
+typedef struct GxidMessageAny_ GxidMessageAny;
+typedef union GxidMessage_ GxidMessage;
+
+typedef unsigned long GxidU32;
+typedef long GxidI32;
+
+struct GxidClaimDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+ GxidU32 exclusive;
+};
+
+struct GxidReleaseDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+};
+
+struct GxidMessageAny_ {
+ GxidU32 type;
+ GxidU32 length;
+};
+
+union GxidMessage_ {
+ GxidMessageAny any;
+ GxidClaimDevice claim;
+ GxidReleaseDevice release;
+};
diff --git a/gdk/makecursors b/gdk/makecursors
new file mode 100755
index 000000000..664776a2b
--- /dev/null
+++ b/gdk/makecursors
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+sed -f makecursors.sed $1 > .makecursors.tmp
+awk '{printf "%s = %s,\n", $1, $2}' .makecursors.tmp
+rm .makecursors.tmp
diff --git a/gdk/makecursors.sed b/gdk/makecursors.sed
new file mode 100644
index 000000000..107d13f8d
--- /dev/null
+++ b/gdk/makecursors.sed
@@ -0,0 +1,3 @@
+/define/ ! d
+/define/ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
+s/^.*XC_/GDK_/g
diff --git a/gdk/makekeysyms b/gdk/makekeysyms
new file mode 100755
index 000000000..40b49d4e8
--- /dev/null
+++ b/gdk/makekeysyms
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+sed -f makekeysyms.sed $1 > .makekeysms.tmp
+awk '{printf "#define %s %s\n", $1, $2}' .makekeysms.tmp
+rm .makekeysms.tmp
diff --git a/gdk/makekeysyms.sed b/gdk/makekeysyms.sed
new file mode 100644
index 000000000..bafbf76c0
--- /dev/null
+++ b/gdk/makekeysyms.sed
@@ -0,0 +1,3 @@
+/define/ ! d
+s/^.*XK_/GDK_/g
+s/0X/0x/g
diff --git a/gdk/x11/gdkcolor-x11.c b/gdk/x11/gdkcolor-x11.c
new file mode 100644
index 000000000..5e66f089b
--- /dev/null
+++ b/gdk/x11/gdkcolor-x11.c
@@ -0,0 +1,718 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static gint gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available);
+static void gdk_colormap_add (GdkColormap *cmap);
+static void gdk_colormap_remove (GdkColormap *cmap);
+static guint gdk_colormap_hash (Colormap *cmap);
+static gint gdk_colormap_cmp (Colormap *a,
+ Colormap *b);
+
+static GHashTable *colormap_hash = NULL;
+
+
+GdkColormap*
+gdk_colormap_new (GdkVisual *visual,
+ gint private_cmap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ Visual *xvisual;
+ XColor default_colors[256];
+ int size;
+ int i;
+
+ g_return_val_if_fail (visual != NULL, NULL);
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->visual = visual;
+ private->next_color = 0;
+ private->ref_count = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ private->private_val = private_cmap;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, (private_cmap) ? (AllocAll) : (AllocNone));
+
+ if (private_cmap)
+ {
+ for (i = 0; i < 256; i++)
+ default_colors[i].pixel = i;
+
+ XQueryColors (private->xdisplay,
+ DefaultColormap (private->xdisplay, gdk_screen),
+ default_colors, visual->colormap_size);
+
+ for (i = 0; i < visual->colormap_size; i++)
+ {
+ colormap->colors[i].pixel = default_colors[i].pixel;
+ colormap->colors[i].red = default_colors[i].red;
+ colormap->colors[i].green = default_colors[i].green;
+ colormap->colors[i].blue = default_colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ private->private_val = TRUE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocAll);
+
+ size = 1 << visual->red_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].red = i * 65535 / (size - 1);
+
+ size = 1 << visual->green_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].green = i * 65535 / (size - 1);
+
+ size = 1 << visual->blue_prec;
+ for (i = 0; i < size; i++)
+ colormap->colors[i].blue = i * 65535 / (size - 1);
+
+ gdk_colormap_change (colormap, visual->colormap_size);
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ private->private_val = FALSE;
+ private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window,
+ xvisual, AllocNone);
+ break;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+void
+gdk_colormap_real_destroy (GdkColormap *colormap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate*) colormap;
+
+ g_return_if_fail (colormap != NULL);
+
+ if (private->ref_count > 0)
+ return;
+
+ gdk_colormap_remove (colormap);
+ XFreeColormap (private->xdisplay, private->xcolormap);
+ g_free (colormap);
+}
+
+void
+gdk_colormap_destroy (GdkColormap *colormap)
+{
+ gdk_colormap_unref (colormap);
+}
+
+GdkColormap*
+gdk_colormap_ref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_val_if_fail (cmap != NULL, NULL);
+
+ private->ref_count += 1;
+ return cmap;
+}
+
+void
+gdk_colormap_unref (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap;
+ g_return_if_fail (cmap != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_colormap_real_destroy (cmap);
+}
+
+GdkColormap*
+gdk_colormap_get_system (void)
+{
+ static GdkColormap *colormap = NULL;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ if (!colormap)
+ {
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = DefaultColormap (gdk_display, gdk_screen);
+ private->visual = gdk_visual_get_system ();
+ private->private_val = FALSE;
+ private->next_color = 0;
+ private->ref_count = 1;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+ }
+
+ return colormap;
+}
+
+gint
+gdk_colormap_get_system_size (void)
+{
+ return DisplayCells (gdk_display, gdk_screen);
+}
+
+void
+gdk_colormap_change (GdkColormap *colormap,
+ gint ncolors)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor palette[256];
+ gint shift;
+ int max_colors;
+ int size;
+ int i;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ for (i = 0; i < ncolors; i++)
+ {
+ palette[i].pixel = colormap->colors[i].pixel;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoRed | DoGreen | DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors);
+ private->next_color = MAX (private->next_color, ncolors);
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+
+ shift = visual->red_shift;
+ max_colors = 1 << visual->red_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].red = colormap->colors[i].red;
+ palette[i].flags = DoRed;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->green_shift;
+ max_colors = 1 << visual->green_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].green = colormap->colors[i].green;
+ palette[i].flags = DoGreen;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+
+ shift = visual->blue_shift;
+ max_colors = 1 << visual->blue_prec;
+ size = (ncolors < max_colors) ? (ncolors) : (max_colors);
+
+ for (i = 0; i < size; i++)
+ {
+ palette[i].pixel = i << shift;
+ palette[i].blue = colormap->colors[i].blue;
+ palette[i].flags = DoBlue;
+ }
+
+ XStoreColors (private->xdisplay, private->xcolormap, palette, size);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+gdk_colors_store (GdkColormap *colormap,
+ GdkColor *colors,
+ gint ncolors)
+{
+ gint i;
+
+ for (i = 0; i < ncolors; i++)
+ {
+ colormap->colors[i].pixel = colors[i].pixel;
+ colormap->colors[i].red = colors[i].red;
+ colormap->colors[i].green = colors[i].green;
+ colormap->colors[i].blue = colors[i].blue;
+ }
+
+ gdk_colormap_change (colormap, ncolors);
+}
+
+gint
+gdk_colors_alloc (GdkColormap *colormap,
+ gint contiguous,
+ gulong *planes,
+ gint nplanes,
+ gulong *pixels,
+ gint npixels)
+{
+ GdkColormapPrivate *private;
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, 0);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ return_val = XAllocColorCells (private->xdisplay, private->xcolormap,
+ contiguous, planes, nplanes, pixels, npixels);
+
+ return return_val;
+}
+
+void
+gdk_colors_free (GdkColormap *colormap,
+ gulong *pixels,
+ gint npixels,
+ gulong planes)
+{
+ GdkColormapPrivate *private;
+
+ g_return_if_fail (colormap != NULL);
+
+ private = (GdkColormapPrivate*) colormap;
+
+ XFreeColors (private->xdisplay, private->xcolormap,
+ pixels, npixels, planes);
+}
+
+gint
+gdk_color_white (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = WhitePixel (gdk_display, gdk_screen);
+ color->red = 65535;
+ color->green = 65535;
+ color->blue = 65535;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_black (GdkColormap *colormap,
+ GdkColor *color)
+{
+ gint return_val;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+
+ if (color)
+ {
+ color->pixel = BlackPixel (gdk_display, gdk_screen);
+ color->red = 0;
+ color->green = 0;
+ color->blue = 0;
+
+ return_val = gdk_color_alloc (colormap, color);
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_parse (const gchar *spec,
+ GdkColor *color)
+{
+ Colormap xcolormap;
+ XColor xcolor;
+ gint return_val;
+
+ g_return_val_if_fail (spec != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolormap = DefaultColormap (gdk_display, gdk_screen);
+
+ if (XParseColor (gdk_display, xcolormap, spec, &xcolor))
+ {
+ return_val = TRUE;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+ }
+ else
+ return_val = FALSE;
+
+ return return_val;
+}
+
+gint
+gdk_color_alloc (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ GdkVisual *visual;
+ XColor xcolor;
+ gchar available[256];
+ gint available_init;
+ gint return_val;
+ gint i, index;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.pixel = color->pixel;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ return_val = FALSE;
+ private = (GdkColormapPrivate*) colormap;
+
+ switch (private->visual->type)
+ {
+ case GDK_VISUAL_GRAYSCALE:
+ case GDK_VISUAL_PSEUDO_COLOR:
+ if (private->private_val)
+ {
+ if (private->next_color > 255)
+ {
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ *color = colormap->colors[index];
+ return_val = TRUE;
+ }
+ else
+ {
+ return_val = FALSE;
+ }
+ }
+ else
+ {
+ xcolor.pixel = 255 - private->next_color;
+ color->pixel = xcolor.pixel;
+ private->next_color += 1;
+
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+ return_val = TRUE;
+ }
+ }
+ else
+ {
+ available_init = 1;
+
+ while (1)
+ {
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ color->red = xcolor.red;
+ color->green = xcolor.green;
+ color->blue = xcolor.blue;
+
+ colormap->colors[color->pixel] = *color;
+
+ return_val = TRUE;
+ break;
+ }
+ else
+ {
+ if (available_init)
+ {
+ available_init = 0;
+ for (i = 0; i < 256; i++)
+ available[i] = TRUE;
+ }
+
+ index = gdk_colormap_match_color (colormap, color, available);
+ if (index != -1)
+ {
+ available[index] = FALSE;
+ xcolor.red = colormap->colors[index].red;
+ xcolor.green = colormap->colors[index].green;
+ xcolor.blue = colormap->colors[index].blue;
+ }
+ else
+ {
+ return_val = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case GDK_VISUAL_DIRECT_COLOR:
+ visual = private->visual;
+ xcolor.pixel = (((xcolor.red >> (16 - visual->red_prec)) << visual->red_shift) +
+ ((xcolor.green >> (16 - visual->green_prec)) << visual->green_shift) +
+ ((xcolor.blue >> (16 - visual->blue_prec)) << visual->blue_shift));
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ break;
+
+ case GDK_VISUAL_STATIC_GRAY:
+ case GDK_VISUAL_STATIC_COLOR:
+ case GDK_VISUAL_TRUE_COLOR:
+ if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor))
+ {
+ color->pixel = xcolor.pixel;
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ break;
+ }
+
+ return return_val;
+}
+
+gint
+gdk_color_change (GdkColormap *colormap,
+ GdkColor *color)
+{
+ GdkColormapPrivate *private;
+ XColor xcolor;
+
+ g_return_val_if_fail (colormap != NULL, FALSE);
+ g_return_val_if_fail (color != NULL, FALSE);
+
+ xcolor.pixel = color->pixel;
+ xcolor.red = color->red;
+ xcolor.green = color->green;
+ xcolor.blue = color->blue;
+ xcolor.flags = DoRed | DoGreen | DoBlue;
+
+ private = (GdkColormapPrivate*) colormap;
+ XStoreColor (private->xdisplay, private->xcolormap, &xcolor);
+
+ return TRUE;
+}
+
+gint
+gdk_color_equal (GdkColor *colora,
+ GdkColor *colorb)
+{
+ g_return_val_if_fail (colora != NULL, FALSE);
+ g_return_val_if_fail (colorb != NULL, FALSE);
+
+ return ((colora->red == colorb->red) &&
+ (colora->green == colorb->green) &&
+ (colora->blue == colorb->blue));
+}
+
+GdkColormap*
+gdkx_colormap_get (Colormap xcolormap)
+{
+ GdkColormap *colormap;
+ GdkColormapPrivate *private;
+ XColor xpalette[256];
+ gint i;
+
+ colormap = gdk_colormap_lookup (xcolormap);
+ if (colormap)
+ return colormap;
+
+ if (xcolormap == DefaultColormap (gdk_display, gdk_screen))
+ return gdk_colormap_get_system ();
+
+ private = g_new (GdkColormapPrivate, 1);
+ colormap = (GdkColormap*) private;
+
+ private->xdisplay = gdk_display;
+ private->xcolormap = xcolormap;
+ private->visual = NULL;
+ private->private_val = TRUE;
+ private->next_color = 0;
+
+ for (i = 0; i < 256; i++)
+ {
+ xpalette[i].pixel = i;
+ xpalette[i].red = 0;
+ xpalette[i].green = 0;
+ xpalette[i].blue = 0;
+ }
+
+ XQueryColors (gdk_display, private->xcolormap, xpalette, 256);
+
+ for (i = 0; i < 256; i++)
+ {
+ colormap->colors[i].pixel = xpalette[i].pixel;
+ colormap->colors[i].red = xpalette[i].red;
+ colormap->colors[i].green = xpalette[i].green;
+ colormap->colors[i].blue = xpalette[i].blue;
+ }
+
+ gdk_colormap_add (colormap);
+
+ return colormap;
+}
+
+
+static gint
+gdk_colormap_match_color (GdkColormap *cmap,
+ GdkColor *color,
+ const gchar *available)
+{
+ GdkColor *colors;
+ guint sum, max;
+ gint rdiff, gdiff, bdiff;
+ gint i, index;
+
+ g_return_val_if_fail (cmap != NULL, 0);
+ g_return_val_if_fail (color != NULL, 0);
+
+ colors = cmap->colors;
+ max = 3 * (65536);
+ index = -1;
+
+ for (i = 0; i < 256; i++)
+ {
+ if ((!available) || (available && available[i]))
+ {
+ rdiff = (color->red - colors[i].red);
+ gdiff = (color->green - colors[i].green);
+ bdiff = (color->blue - colors[i].blue);
+
+ sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
+
+ if (sum < max)
+ {
+ index = i;
+ max = sum;
+ }
+ }
+ }
+
+ return index;
+}
+
+
+GdkColormap*
+gdk_colormap_lookup (Colormap xcolormap)
+{
+ GdkColormap *cmap;
+
+ if (!colormap_hash)
+ return NULL;
+
+ cmap = g_hash_table_lookup (colormap_hash, &xcolormap);
+ return cmap;
+}
+
+static void
+gdk_colormap_add (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);
+}
+
+static void
+gdk_colormap_remove (GdkColormap *cmap)
+{
+ GdkColormapPrivate *private;
+
+ if (!colormap_hash)
+ colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash,
+ (GCompareFunc) gdk_colormap_cmp);
+
+ private = (GdkColormapPrivate*) cmap;
+
+ g_hash_table_remove (colormap_hash, &private->xcolormap);
+}
+
+static guint
+gdk_colormap_hash (Colormap *cmap)
+{
+ return *cmap;
+}
+
+static gint
+gdk_colormap_cmp (Colormap *a,
+ Colormap *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/x11/gdkcursor-x11.c b/gdk/x11/gdkcursor-x11.c
new file mode 100644
index 000000000..22bfd250b
--- /dev/null
+++ b/gdk/x11/gdkcursor-x11.c
@@ -0,0 +1,52 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkCursor*
+gdk_cursor_new (GdkCursorType cursor_type)
+{
+ GdkCursorPrivate *private;
+ GdkCursor *cursor;
+ Cursor xcursor;
+
+ xcursor = XCreateFontCursor (gdk_display, cursor_type);
+ private = g_new (GdkCursorPrivate, 1);
+ private->xdisplay = gdk_display;
+ private->xcursor = xcursor;
+ cursor = (GdkCursor*) private;
+ cursor->type = cursor_type;
+
+ return cursor;
+}
+
+void
+gdk_cursor_destroy (GdkCursor *cursor)
+{
+ GdkCursorPrivate *private;
+
+ g_return_if_fail (cursor != NULL);
+
+ private = (GdkCursorPrivate *) cursor;
+ XFreeCursor (private->xdisplay, private->xcursor);
+
+ g_free (private);
+}
diff --git a/gdk/x11/gdkfont-x11.c b/gdk/x11/gdkfont-x11.c
new file mode 100644
index 000000000..e1b1e7254
--- /dev/null
+++ b/gdk/x11/gdkfont-x11.c
@@ -0,0 +1,379 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+GdkFont*
+gdk_font_load (const gchar *font_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ private->xfont = XLoadQueryFont (private->xdisplay, font_name);
+ private->ref_count = 1;
+
+ if (!private->xfont)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ font->type = GDK_FONT_FONT;
+ font->ascent = ((XFontStruct *) private->xfont)->ascent;
+ font->descent = ((XFontStruct *) private->xfont)->descent;
+ }
+
+ gdk_xid_table_insert (&((XFontStruct *) private->xfont)->fid, font);
+
+ return font;
+}
+
+GdkFont*
+gdk_fontset_load(gchar *fontset_name)
+{
+ GdkFont *font;
+ GdkFontPrivate *private;
+ XFontSet fontset;
+ gint missing_charset_count;
+ gchar **missing_charset_list;
+ gchar *def_string;
+
+ private = g_new (GdkFontPrivate, 1);
+ font = (GdkFont*) private;
+
+ private->xdisplay = gdk_display;
+ fontset = XCreateFontSet (gdk_display, fontset_name,
+ &missing_charset_list, &missing_charset_count,
+ &def_string);
+
+ if (missing_charset_count)
+ {
+ g_print ("Missing charsets in FontSet creation");
+ XFreeStringList (missing_charset_list);
+ }
+
+ private->ref_count = 1;
+
+ if (!fontset)
+ {
+ g_free (font);
+ return NULL;
+ }
+ else
+ {
+ XFontSetExtents *extent = XExtentsOfFontSet(fontset);
+
+ private->xfont = fontset;
+ font->type = GDK_FONT_FONTSET;
+ /* how to define ascent and descent for fontset ??? */
+ font->ascent = extent->max_logical_extent.height;
+ font->descent = font->ascent / 4 ;
+ }
+ return font;
+}
+void
+gdk_font_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (((XFontStruct *) private->xfont)->fid);
+ XFreeFont (private->xdisplay, (XFontStruct *) private->xfont);
+ g_free (font);
+ }
+}
+
+void
+gdk_fontset_free (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_if_fail (font != NULL);
+
+ private = (GdkFontPrivate*) font;
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ {
+ XFreeFontSet (private->xdisplay, (XFontSet) private->xfont);
+ g_free (font);
+ }
+}
+
+GdkFont*
+gdk_font_ref (GdkFont *font)
+{
+ GdkFontPrivate *private;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ private = (GdkFontPrivate*) font;
+ private->ref_count += 1;
+ return font;
+}
+
+gint
+gdk_font_id (GdkFont *font)
+{
+ GdkFontPrivate *font_private;
+
+ g_return_val_if_fail (font != NULL, 0);
+
+ font_private = (GdkFontPrivate*) font;
+
+ if (font->type == GDK_FONT_FONT)
+ {
+ return ((XFontStruct *) font_private->xfont)->fid;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+gint
+gdk_font_equal (GdkFont *fonta,
+ GdkFont *fontb)
+{
+ GdkFontPrivate *privatea;
+ GdkFontPrivate *privateb;
+
+ g_return_val_if_fail (fonta != NULL, FALSE);
+ g_return_val_if_fail (fontb != NULL, FALSE);
+
+ privatea = (GdkFontPrivate*) fonta;
+ privateb = (GdkFontPrivate*) fontb;
+
+ if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
+ {
+ return (((XFontStruct *) privatea->xfont)->fid ==
+ ((XFontStruct *) privateb->xfont)->fid);
+ }
+ else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
+ {
+ /* how to compare two fontsets ?? by basename or XFontSet ?? */
+ return (((XFontSet) privatea->xfont) == ((XFontSet) privateb->xfont));
+ }
+ else
+ /* fontset != font */
+ return 0;
+}
+
+gint
+gdk_string_width (GdkFont *font,
+ const gchar *string)
+{
+ GdkFontPrivate *font_private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ font_private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) font_private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, string, strlen (string));
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) string, strlen (string) / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) font_private->xfont;
+ width = XmbTextEscapement (fontset, string, strlen(string));
+ break;
+ default:
+ width = 0;
+ }
+
+ return width;
+}
+
+gint
+gdk_text_width (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ gint width;
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ width = XTextWidth (xfont, text, text_length);
+ }
+ else
+ {
+ width = XTextWidth16 (xfont, (XChar2b *) text, text_length / 2);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, text, text_length);
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+/* Problem: What if a character is a 16 bits character ?? */
+gint
+gdk_char_width (GdkFont *font,
+ gchar character)
+{
+ GdkFontPrivate *private;
+ XCharStruct *chars;
+ gint width;
+ guint ch = character & 0xff; /* get rid of sign-extension */
+ XFontStruct *xfont;
+ XFontSet fontset;
+
+ g_return_val_if_fail (font != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ /* only 8 bits characters are considered here */
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) &&
+ (xfont->max_byte1 == 0) &&
+ (ch >= xfont->min_char_or_byte2) &&
+ (ch <= xfont->max_char_or_byte2))
+ {
+ chars = xfont->per_char;
+ if (chars)
+ width = chars[ch - xfont->min_char_or_byte2].width;
+ else
+ width = xfont->min_bounds.width;
+ }
+ else
+ {
+ width = XTextWidth (xfont, &character, 1);
+ }
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ width = XmbTextEscapement (fontset, &character, 1) ;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_string_measure (GdkFont *font,
+ const gchar *string)
+{
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (string != NULL, -1);
+
+ return gdk_text_measure (font, string, strlen (string));
+}
+
+gint
+gdk_text_measure (GdkFont *font,
+ const gchar *text,
+ gint text_length)
+{
+ GdkFontPrivate *private;
+ XCharStruct overall;
+ XFontStruct *xfont;
+ XFontSet fontset;
+ XRectangle ink, log;
+ int direction;
+ int font_ascent;
+ int font_descent;
+ gint width;
+
+ g_return_val_if_fail (font != NULL, -1);
+ g_return_val_if_fail (text != NULL, -1);
+
+ private = (GdkFontPrivate*) font;
+
+ switch (font->type)
+ {
+ case GDK_FONT_FONT:
+ xfont = (XFontStruct *) private->xfont;
+ if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+ {
+ XTextExtents (xfont, text, text_length,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ else
+ {
+ XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
+ &direction, &font_ascent, &font_descent,
+ &overall);
+ }
+ width = overall.rbearing;
+ break;
+ case GDK_FONT_FONTSET:
+ fontset = (XFontSet) private->xfont;
+ XmbTextExtents (fontset, text, text_length, &ink, &log);
+ width = log.width;
+ break;
+ default:
+ width = 0;
+ }
+ return width;
+}
+
+gint
+gdk_char_measure (GdkFont *font,
+ gchar character)
+{
+ g_return_val_if_fail (font != NULL, -1);
+
+ return gdk_text_measure (font, &character, 1);
+}
diff --git a/gdk/x11/gdkglobals-x11.c b/gdk/x11/gdkglobals-x11.c
new file mode 100644
index 000000000..58f7bf844
--- /dev/null
+++ b/gdk/x11/gdkglobals-x11.c
@@ -0,0 +1,47 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include "gdktypes.h"
+#include "gdkprivate.h"
+
+gint gdk_debug_level = 0;
+gint gdk_show_events = FALSE;
+gint gdk_use_xshm = TRUE;
+gchar *gdk_display_name = NULL;
+Display *gdk_display = NULL;
+gint gdk_screen;
+Window gdk_root_window;
+Window gdk_leader_window;
+GdkWindowPrivate gdk_root_parent;
+Atom gdk_wm_delete_window;
+Atom gdk_wm_take_focus;
+Atom gdk_wm_protocols;
+Atom gdk_wm_window_protocols[2];
+Atom gdk_selection_property;
+GdkDndGlobals gdk_dnd = {None,None,None,
+ None,None,None,
+ None,
+ None,None,
+ NULL,
+ 0, 0,
+ {0,0}};
+gchar *gdk_progname = NULL;
+gchar *gdk_progclass = NULL;
+gint gdk_error_code;
+gint gdk_error_warnings = TRUE;
diff --git a/gdk/x11/gdkimage-x11.c b/gdk/x11/gdkimage-x11.c
new file mode 100644
index 000000000..bcda3119f
--- /dev/null
+++ b/gdk/x11/gdkimage-x11.c
@@ -0,0 +1,492 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <sys/types.h>
+
+#if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
+#define USE_SHM
+#endif
+
+#ifdef USE_SHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* USE_SHM */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef USE_SHM
+#include <X11/extensions/XShm.h>
+#endif /* USE_SHM */
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+static void gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
+
+
+static GList *image_list = NULL;
+
+
+void
+gdk_image_exit ()
+{
+ GdkImage *image;
+
+ while (image_list)
+ {
+ image = image_list->data;
+ gdk_image_destroy (image);
+ }
+}
+
+GdkImage *
+gdk_image_new_bitmap(GdkVisual *visual, gpointer data, gint w, gint h)
+/*
+ * Desc: create a new bitmap image
+ */
+{
+ Visual *xvisual;
+ GdkImage *image;
+ GdkImagePrivate *private;
+ private = g_new(GdkImagePrivate, 1);
+ image = (GdkImage *) private;
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = visual;
+ image->width = w;
+ image->height = h;
+ image->depth = 1;
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+ private->ximage = XCreateImage(private->xdisplay, xvisual, 1, XYBitmap,
+ 0, 0, w ,h, 8, 0);
+ private->ximage->data = data;
+ private->ximage->bitmap_bit_order = MSBFirst;
+ private->ximage->byte_order = MSBFirst;
+ image->byte_order = MSBFirst;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+ return(image);
+} /* gdk_image_new_bitmap() */
+
+static int
+gdk_image_check_xshm(Display *display)
+/*
+ * Desc: query the server for support for the MIT_SHM extension
+ * Return: 0 = not available
+ * 1 = shared XImage support available
+ * 2 = shared Pixmap support available also
+ */
+{
+#ifdef USE_SHM
+ int major, minor, ignore;
+ Bool pixmaps;
+
+ if (XQueryExtension(display, "MIT-SHM", &ignore, &ignore, &ignore))
+ {
+ if (XShmQueryVersion(display, &major, &minor, &pixmaps )==True)
+ {
+ return (pixmaps==True) ? 2 : 1;
+ }
+ }
+#endif /* USE_SHM */
+ return 0;
+}
+
+void
+gdk_image_init ()
+{
+ if (gdk_use_xshm)
+ {
+ if (!gdk_image_check_xshm (gdk_display))
+ {
+ g_warning ("MIT-SHM Extension not availible on server");
+ gdk_use_xshm = False;
+ }
+ }
+}
+
+GdkImage*
+gdk_image_new (GdkImageType type,
+ GdkVisual *visual,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+ Visual *xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_FASTEST:
+ image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
+
+ if (!image)
+ image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
+ break;
+
+ default:
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = NULL;
+
+ image->type = type;
+ image->visual = visual;
+ image->width = width;
+ image->height = height;
+ image->depth = visual->depth;
+
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ switch (type)
+ {
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ if (gdk_use_xshm)
+ {
+ private->image_put = gdk_image_put_shared;
+
+ private->x_shm_info = g_new (XShmSegmentInfo, 1);
+ x_shm_info = private->x_shm_info;
+
+ private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, NULL, x_shm_info, width, height);
+ if (private->ximage == NULL)
+ {
+ g_warning ("XShmCreateImage failed");
+
+ g_free (image);
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->shmid = shmget (IPC_PRIVATE,
+ private->ximage->bytes_per_line * private->ximage->height,
+ IPC_CREAT | 0777);
+
+ if (x_shm_info->shmid == -1)
+ {
+ g_warning ("shmget failed!");
+
+ XDestroyImage (private->ximage);
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ x_shm_info->readOnly = False;
+ x_shm_info->shmaddr = shmat (x_shm_info->shmid, 0, 0);
+ private->ximage->data = x_shm_info->shmaddr;
+
+ if (x_shm_info->shmaddr == (char*) -1)
+ {
+ g_warning ("shmat failed!");
+
+ XDestroyImage (private->ximage);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ return NULL;
+ }
+
+#ifdef IPC_RMID_DEFERRED_RELEASE
+ if (x_shm_info->shmaddr != (char*) -1)
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+#endif
+
+ gdk_error_code = 0;
+ gdk_error_warnings = 0;
+
+ XShmAttach (private->xdisplay, x_shm_info);
+ XSync (private->xdisplay, False);
+
+ gdk_error_warnings = 1;
+ if (gdk_error_code == -1)
+ {
+ g_warning ("XShmAttach failed!");
+
+ XDestroyImage (private->ximage);
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+ g_free (image);
+
+ gdk_use_xshm = False;
+ return NULL;
+ }
+
+ if (image)
+ image_list = g_list_prepend (image_list, image);
+ }
+ else
+ {
+ g_free (image);
+ return NULL;
+ }
+ break;
+#else /* USE_SHM */
+ g_free (image);
+ return NULL;
+#endif /* USE_SHM */
+ case GDK_IMAGE_NORMAL:
+ private->image_put = gdk_image_put_normal;
+
+ private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
+ ZPixmap, 0, 0, width, height, 32, 0);
+
+ private->ximage->data = g_new (char, private->ximage->bytes_per_line *
+ private->ximage->height);
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ if (image)
+ {
+ image->byte_order = private->ximage->byte_order;
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+
+ switch (private->ximage->bits_per_pixel)
+ {
+ case 8:
+ image->bpp = 1;
+ break;
+ case 16:
+ image->bpp = 2;
+ break;
+ case 24:
+ image->bpp = 3;
+ break;
+ case 32:
+ image->bpp = 4;
+ break;
+ }
+ }
+ }
+
+ return image;
+}
+
+GdkImage*
+gdk_image_get (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkImage *image;
+ GdkImagePrivate *private;
+ GdkWindowPrivate *win_private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ win_private = (GdkWindowPrivate *) window;
+
+ private = g_new (GdkImagePrivate, 1);
+ image = (GdkImage*) private;
+
+ private->xdisplay = gdk_display;
+ private->image_put = gdk_image_put_normal;
+ private->ximage = XGetImage (private->xdisplay,
+ win_private->xwindow,
+ x, y, width, height,
+ AllPlanes, ZPixmap);
+
+ image->type = GDK_IMAGE_NORMAL;
+ image->visual = gdk_window_get_visual (window);
+ image->width = width;
+ image->height = height;
+ image->depth = private->ximage->depth;
+
+ image->mem = private->ximage->data;
+ image->bpl = private->ximage->bytes_per_line;
+ image->bpp = 1;
+
+ return image;
+}
+
+guint32
+gdk_image_get_pixel (GdkImage *image,
+ gint x,
+ gint y)
+{
+ guint32 pixel;
+ GdkImagePrivate *private;
+
+ g_return_val_if_fail (image != NULL, 0);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XGetPixel (private->ximage, x, y);
+
+ return pixel;
+}
+
+void
+gdk_image_put_pixel (GdkImage *image,
+ gint x,
+ gint y,
+ guint32 pixel)
+{
+ GdkImagePrivate *private;
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate *) image;
+
+ pixel = XPutPixel (private->ximage, x, y, pixel);
+}
+
+void
+gdk_image_destroy (GdkImage *image)
+{
+ GdkImagePrivate *private;
+#ifdef USE_SHM
+ XShmSegmentInfo *x_shm_info;
+#endif /* USE_SHM */
+
+ g_return_if_fail (image != NULL);
+
+ private = (GdkImagePrivate*) image;
+ switch (image->type)
+ {
+ case GDK_IMAGE_NORMAL:
+ XDestroyImage (private->ximage);
+ break;
+
+ case GDK_IMAGE_SHARED:
+#ifdef USE_SHM
+ XShmDetach (private->xdisplay, private->x_shm_info);
+ XDestroyImage (private->ximage);
+
+ x_shm_info = private->x_shm_info;
+ shmdt (x_shm_info->shmaddr);
+ shmctl (x_shm_info->shmid, IPC_RMID, 0);
+
+ g_free (private->x_shm_info);
+
+ image_list = g_list_remove (image_list, image);
+#else /* USE_SHM */
+ g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+ break;
+
+ case GDK_IMAGE_FASTEST:
+ g_assert_not_reached ();
+ }
+
+ g_free (image);
+}
+
+static void
+gdk_image_put_normal (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
+
+ XPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height);
+}
+
+static void
+gdk_image_put_shared (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+#ifdef USE_SHM
+ GdkWindowPrivate *drawable_private;
+ GdkImagePrivate *image_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (image != NULL);
+ g_return_if_fail (gc != NULL);
+
+ drawable_private = (GdkWindowPrivate*) drawable;
+ image_private = (GdkImagePrivate*) image;
+ gc_private = (GdkGCPrivate*) gc;
+
+ g_return_if_fail (image->type == GDK_IMAGE_SHARED);
+
+ XShmPutImage (drawable_private->xdisplay, drawable_private->xwindow,
+ gc_private->xgc, image_private->ximage,
+ xsrc, ysrc, xdest, ydest, width, height, False);
+#else /* USE_SHM */
+ g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");
+#endif /* USE_SHM */
+}
diff --git a/gdk/x11/gdkinput-gxi.c b/gdk/x11/gdkinput-gxi.c
new file mode 100644
index 000000000..a30e05f95
--- /dev/null
+++ b/gdk/x11/gdkinput-gxi.c
@@ -0,0 +1,628 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_GXI
+
+/* #define DEBUG_SWITCHING */
+
+#include <gxid_lib.h>
+
+/* Forward declarations */
+static void gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode);
+static gint gdk_input_is_extension_device (guint32 deviceid);
+static void gdk_input_gxi_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev);
+
+static gint gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent);
+static gint gdk_input_gxi_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_gxi_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static Window gdk_input_find_root_child(Display *dpy, Window w);
+static void gdk_input_compute_obscuring(GdkInputWindow *input_window);
+static gint gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x,
+ gdouble y);
+static GdkTimeCoord *gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+static gint gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_gxi_ungrab_pointer (guint32 time);
+
+/* Local variables */
+
+static GdkDevicePrivate *gdk_input_current_device;
+static GdkDevicePrivate *gdk_input_core_pointer;
+
+void
+gdk_input_init(void)
+{
+ GList *tmp_list;
+
+ gdk_input_vtable.set_mode = gdk_input_gxi_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_gxi_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_gxi_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_gxi_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_gxi_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_gxi_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_gxi_enter_event;
+ gdk_input_vtable.other_event = gdk_input_gxi_other_event;
+ gdk_input_vtable.window_none_event = gdk_input_gxi_window_none_event;
+ gdk_input_vtable.enable_window = gdk_input_gxi_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_gxi_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_core_pointer = NULL;
+
+ if (!gdk_input_gxid_host)
+ {
+ gdk_input_gxid_host = getenv("GXID_HOST");
+ }
+ if (!gdk_input_gxid_port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ gdk_input_gxid_port = atoi(t);
+ }
+
+ gdk_input_common_init(TRUE);
+
+ /* find initial core pointer */
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdk_input_is_extension_device(gdkdev->info.deviceid))
+ {
+ gdk_input_gxi_select_notify (gdkdev);
+ }
+ else
+ {
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+}
+
+static void
+gdk_input_gxi_select_notify (GdkDevicePrivate *gdkdev)
+{
+ XEventClass class;
+
+ ChangeDeviceNotify (gdkdev->xdevice, gdkdev->changenotify_type, class);
+
+ XSelectExtensionEvent (gdk_display, gdk_root_window, &class, 1);
+}
+
+/* Set the core pointer. Device should already be enabled. */
+static gint
+gdk_input_gxi_set_core_pointer(GdkDevicePrivate *gdkdev)
+{
+ int x_axis,y_axis;
+
+ g_return_val_if_fail(gdkdev->xdevice,FALSE);
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+
+ g_return_val_if_fail(x_axis != -1 && y_axis != -1,FALSE);
+
+ /* core_pointer might not be up to date so we check with the server
+ before change the pointer */
+
+ if ( !gdk_input_is_extension_device(gdkdev->info.deviceid) )
+ {
+#if 0
+ if (gdkdev != gdk_input_core_pointer)
+ g_warning("core pointer inconsistency");
+#endif
+ return TRUE;
+ }
+
+ if ( XChangePointerDevice(gdk_display,gdkdev->xdevice, x_axis, y_axis)
+ != Success )
+ {
+ return FALSE;
+ }
+ else
+ {
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ return TRUE;
+ }
+}
+
+
+/* FIXME, merge with gdk_input_xfree_set_mode */
+
+static gint
+gdk_input_gxi_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (old_mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ if (mode != GDK_MODE_DISABLED)
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ if (!gdk_input_enable_window(input_window->window, gdkdev))
+ {
+ gdk_input_set_mode(deviceid, old_mode);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+gint
+gdk_input_is_extension_device (guint32 deviceid)
+{
+ XDeviceInfo *devices;
+ int num_devices, loop;
+
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ devices = XListInputDevices(gdk_display, &num_devices);
+ for(loop=0; loop<num_devices; loop++)
+ {
+ if ((devices[loop].id == deviceid) && (devices[loop].use == IsXExtensionDevice))
+ {
+ XFreeDeviceList(devices);
+ return TRUE;
+ }
+ }
+
+ XFreeDeviceList(devices);
+ return FALSE;
+}
+
+static void
+gdk_input_gxi_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_get_root_relative_geometry(gdk_display,GDK_WINDOW_XWINDOW(window),
+ &root_x, &root_y, NULL, NULL);
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+ gdk_input_compute_obscuring(input_window);
+}
+
+static void
+gdk_input_gxi_enter_event (XCrossingEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_compute_obscuring(input_window);
+}
+
+static gint
+gdk_input_gxi_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)
+ return FALSE;
+
+ if (gdkdev != gdk_input_current_device &&
+ xevent->type != gdkdev->changenotify_type)
+ {
+ gdk_input_current_device = gdkdev;
+ }
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_MOTION_NOTIFY &&
+ (!gdkdev->button_state) && (!input_window->grabbed) &&
+ ((event->motion.x < 0) || (event->motion.y < 0) ||
+ (event->motion.x > ((GdkWindowPrivate *)window)->width) ||
+ (event->motion.y > ((GdkWindowPrivate *)window)->height) ||
+ gdk_input_is_obscured(input_window,event->motion.x,event->motion.y)))
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("gdkinput: Setting core pointer to %d on motion at (%f,%f)\n",
+ gdkdev->info.deviceid,event->motion.x,event->motion.y);
+ g_print(" window geometry is: %dx%d\n",
+ ((GdkWindowPrivate *)window)->width,
+ ((GdkWindowPrivate *)window)->height);
+#endif
+ gdk_input_gxi_set_core_pointer(gdkdev);
+ return FALSE;
+ }
+ else
+ return return_val;
+
+}
+
+static void
+gdk_input_gxi_update_device (GdkDevicePrivate *gdkdev)
+{
+ GList *t;
+
+ if (gdk_input_is_extension_device (gdkdev->info.deviceid))
+ {
+ if (!gdkdev->xdevice)
+ {
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+ gdk_input_gxi_select_notify (gdkdev);
+ gdkdev->needs_update = 1;
+ }
+ if (gdkdev->needs_update && gdkdev->xdevice)
+ {
+ for (t = gdk_input_windows; t; t = t->next)
+ gdk_input_common_select_events (((GdkInputWindow *)t->data)->window,
+ gdkdev);
+ gdkdev->needs_update = 0;
+ }
+ }
+}
+
+static gint
+gdk_input_gxi_window_none_event (GdkEvent *event, XEvent *xevent)
+{
+ GdkDevicePrivate *gdkdev =
+ gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ if (xevent->type == gdkdev->changenotify_type)
+ {
+ if (gdk_input_core_pointer != gdkdev)
+ {
+#ifdef DEBUG_SWITCHING
+ g_print("ChangeNotify from %d to %d:\n",
+ gdk_input_core_pointer->info.deviceid,
+ gdkdev->info.deviceid);
+#endif
+ gdk_input_gxi_update_device (gdk_input_core_pointer);
+ gdk_input_core_pointer = gdkdev;
+ }
+ }
+
+ return FALSE;
+}
+
+static gint
+gdk_input_gxi_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (!gdkdev->claimed)
+ {
+ if (gxid_claim_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window), FALSE) !=
+ GXID_RETURN_OK)
+ {
+ g_warning("Could not get device (is gxid running?)\n");
+ return FALSE;
+ }
+ gdkdev->claimed = TRUE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_gxi_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_val_if_fail (input_window != NULL, FALSE);
+
+ if (gdkdev->claimed)
+ {
+ gxid_release_device(gdk_input_gxid_host, gdk_input_gxid_port,
+ gdkdev->info.deviceid,
+ GDK_WINDOW_XWINDOW(window));
+
+ gdkdev->claimed = FALSE;
+ }
+
+ if (gdkdev->xdevice && gdkdev != gdk_input_core_pointer)
+ gdk_input_common_select_events(window, gdkdev);
+ else
+ gdkdev->needs_update = TRUE;
+
+ return TRUE;
+}
+
+static gint
+gdk_input_is_obscured(GdkInputWindow *input_window, gdouble x, gdouble y)
+{
+ int i;
+ for (i=0;i<input_window->num_obscuring;i++)
+ {
+ GdkRectangle *rect = &input_window->obscuring[i];
+ if ((x >= rect->x) &&
+ (y >= rect->y) &&
+ (x < rect->x + rect->width) &&
+ (y < rect->y + rect->height))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gxid.c will need it too. */
+
+static Window
+gdk_input_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+void
+gdk_input_compute_obscuring(GdkInputWindow *input_window)
+{
+ int i;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ Window w = GDK_WINDOW_XWINDOW(input_window->window);
+ Window root_child = gdk_input_find_root_child(gdk_display,w);
+ gdk_input_get_root_relative_geometry(gdk_display,w,&x,&y,&width,&height);
+
+ input_window->root_x = x;
+ input_window->root_y = y;
+
+ XQueryTree(gdk_display,GDK_ROOT_WINDOW(),
+ &root,&parent,&children,&nchildren);
+
+
+ if (input_window->obscuring)
+ g_free(input_window->obscuring);
+ input_window->obscuring = 0;
+ input_window->num_obscuring = 0;
+
+ for (i=0;i<nchildren;i++)
+ if (children[i] == root_child)
+ break;
+
+ if (i>=nchildren-1)
+ {
+ if (nchildren)
+ XFree(children);
+ return;
+ }
+
+ input_window->obscuring = g_new(GdkRectangle,(nchildren-i-1));
+
+ for (i=i+1;i<nchildren;i++)
+ {
+ int xmin, xmax, ymin, ymax;
+ XGetGeometry(gdk_display,children[i],&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc, &depthc);
+ xmin = xc>x ? xc : x;
+ xmax = (xc+widthc)<(x+width) ? xc+widthc : x+width;
+ ymin = yc>y ? yc : y;
+ ymax = (yc+heightc)<(y+height) ? yc+heightc : y+height;
+ if ((xmin < xmax) && (ymin < ymax))
+ {
+ XWindowAttributes attributes;
+ XGetWindowAttributes(gdk_display,children[i],&attributes);
+ if (attributes.map_state == IsViewable)
+ {
+ GdkRectangle *rect = &input_window->obscuring[input_window->num_obscuring];
+
+ /* we store the whole window, not just the obscuring part */
+ rect->x = xc - x;
+ rect->y = yc - y;
+ rect->width = widthc;
+ rect->height = heightc;
+ input_window->num_obscuring++;
+ }
+ }
+ }
+
+ if (nchildren)
+ XFree(children);
+}
+
+static void
+gdk_input_gxi_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ if (gdkdev == gdk_input_core_pointer)
+ gdk_input_common_get_pointer (window, GDK_CORE_POINTER, x, y,
+ pressure, xtilt, ytilt, mask);
+ else
+ gdk_input_common_get_pointer (window, deviceid, x, y,
+ pressure, xtilt, ytilt, mask);
+}
+
+static GdkTimeCoord *
+gdk_input_gxi_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkDevicePrivate *gdkdev;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+
+
+ if (gdkdev == gdk_input_core_pointer)
+ return gdk_input_motion_events (window, GDK_CORE_POINTER, start, stop,
+ nevents_return);
+ else
+ return gdk_input_common_motion_events (window, deviceid, start, stop,
+ nevents_return);
+
+}
+
+static gint
+gdk_input_gxi_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ new_window = input_window;
+
+ tmp_list = tmp_list->next;
+ }
+
+ new_window->grabbed = TRUE;
+ return Success;
+}
+
+static void
+gdk_input_gxi_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ input_window->grabbed = FALSE;
+ tmp_list = tmp_list->next;
+ }
+}
+
+#endif /* XINPUT_GXI */
diff --git a/gdk/x11/gdkinput-none.c b/gdk/x11/gdkinput-none.c
new file mode 100644
index 000000000..8ae8c4189
--- /dev/null
+++ b/gdk/x11/gdkinput-none.c
@@ -0,0 +1,72 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_NONE
+
+static void gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+void
+gdk_input_init ()
+{
+ gdk_input_vtable.set_mode = NULL;
+ gdk_input_vtable.set_axes = NULL;
+ gdk_input_vtable.motion_events = NULL;
+ gdk_input_vtable.get_pointer = gdk_input_none_get_pointer;
+ gdk_input_vtable.grab_pointer = NULL;
+ gdk_input_vtable.ungrab_pointer = NULL;
+ gdk_input_vtable.configure_event = NULL;
+ gdk_input_vtable.enter_event = NULL;
+ gdk_input_vtable.other_event = NULL;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = NULL;
+ gdk_input_vtable.disable_window = NULL;
+
+ gdk_input_devices = g_list_append (NULL, &gdk_input_core_info);
+
+ gdk_input_ignore_core = FALSE;
+}
+
+static void
+gdk_input_none_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ gint x_int, y_int;
+
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+}
+
+#endif /* XINPUT_NONE */
diff --git a/gdk/x11/gdkinput-x11.c b/gdk/x11/gdkinput-x11.c
new file mode 100644
index 000000000..5e457e0aa
--- /dev/null
+++ b/gdk/x11/gdkinput-x11.c
@@ -0,0 +1,687 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(XINPUT_GXI) || defined(XINPUT_XFREE)
+
+/* Forward declarations */
+static void gdk_input_get_root_relative_geometry (Display *dpy, Window w,
+ int *x_ret, int *y_ret,
+ int *width_ret,
+ int *height_ret);
+static GdkDevicePrivate *gdk_input_device_new(XDeviceInfo *device,
+ gint include_core);
+static void gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes);
+static void gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_translate_coordinates(GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt);
+static guint gdk_input_translate_state(guint state, guint device_state);
+static gint gdk_input_common_init(gint include_core);
+static gint gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev);
+static void gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes);
+static GdkTimeCoord * gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return);
+static void gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask);
+
+/* Global variables */
+
+static gint gdk_input_root_width;
+static gint gdk_input_root_height;
+
+static void
+gdk_input_get_root_relative_geometry(Display *dpy, Window w, int *x_ret, int *y_ret,
+ int *width_ret, int *height_ret)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+ int x,y,width,height;
+ int xc,yc,widthc,heightc,border_widthc,depthc;
+
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&x,&y,&width,&height,&border_widthc,
+ &depthc);
+ x += border_widthc;
+ y += border_widthc;
+
+ while (root != parent)
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ XGetGeometry(dpy,w,&root,&xc,&yc,&widthc,&heightc,
+ &border_widthc,&depthc);
+ x += xc + border_widthc;
+ y += yc + border_widthc;
+ }
+
+ if (x_ret)
+ *x_ret = x;
+ if (y_ret)
+ *y_ret = y;
+ if (width_ret)
+ *width_ret = width;
+ if (height_ret)
+ *height_ret = height;
+}
+
+static GdkDevicePrivate *
+gdk_input_device_new(XDeviceInfo *device, gint include_core)
+{
+ GdkDevicePrivate *gdkdev;
+ gchar *tmp_name, *p;
+ XAnyClassPtr class;
+ gint i,j;
+
+ gdkdev = g_new(GdkDevicePrivate,1);
+
+ gdkdev->info.deviceid = device->id;
+ if (device->name[0]) {
+ gdkdev->info.name = g_new(char, strlen(device->name)+1);
+ strcpy(gdkdev->info.name,device->name);
+ } else {
+ /* XFree86 3.2 gives an empty name to the default core devices,
+ (fixed in 3.2A) */
+ gdkdev->info.name = g_strdup("pointer");
+ strcpy(gdkdev->info.name,"pointer");
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ }
+
+ gdkdev->info.mode = GDK_MODE_DISABLED;
+
+ /* Try to figure out what kind of device this is by its name -
+ could invite a very, very, long list... Lowercase name
+ for comparison purposes */
+
+ tmp_name = g_strdup(gdkdev->info.name);
+ for (p = tmp_name; *p; p++)
+ {
+ if (*p >= 'A' && *p <= 'Z')
+ *p += 'a' - 'A';
+ }
+
+ if (!strcmp (tmp_name, "pointer"))
+ gdkdev->info.source = GDK_SOURCE_MOUSE;
+ else if (!strcmp (tmp_name, "wacom") ||
+ !strcmp (tmp_name, "pen"))
+ gdkdev->info.source = GDK_SOURCE_PEN;
+ else if (!strcmp (tmp_name, "eraser"))
+ gdkdev->info.source = GDK_SOURCE_ERASER;
+ else if (!strcmp (tmp_name, "cursor"))
+ gdkdev->info.source = GDK_SOURCE_CURSOR;
+ else
+ gdkdev->info.source = GDK_SOURCE_PEN;
+
+ g_free(tmp_name);
+
+ gdkdev->xdevice = NULL;
+
+ /* step through the classes */
+
+ gdkdev->info.num_axes = 0;
+ gdkdev->axes = 0;
+ gdkdev->info.has_cursor = 0;
+ gdkdev->needs_update = FALSE;
+ gdkdev->claimed = FALSE;
+ gdkdev->button_state = 0;
+
+ class = device->inputclassinfo;
+ for (i=0;i<device->num_classes;i++)
+ {
+ switch (class->class) {
+ case ButtonClass:
+ {
+ break;
+ }
+ case ValuatorClass:
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ gdkdev->info.num_axes = xvi->num_axes;
+ gdkdev->axes = g_new(GdkAxisInfo, xvi->num_axes);
+ gdkdev->info.axes = g_new(GdkAxisUse, xvi->num_axes);
+ for (j=0;j<xvi->num_axes;j++)
+ {
+ gdkdev->axes[j].resolution =
+ gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
+ gdkdev->axes[j].min_value =
+ gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
+ gdkdev->axes[j].max_value =
+ gdkdev->axes[j].xmax_value = xvi->axes[j].max_value;
+ gdkdev->info.axes[j] = GDK_AXIS_IGNORE;
+ }
+ j=0;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_X;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_Y;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_PRESSURE;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_XTILT;
+ if (j<xvi->num_axes)
+ gdkdev->info.axes[j++] = GDK_AXIS_YTILT;
+
+ /* set up reverse lookup on axis use */
+ for (j=GDK_AXIS_IGNORE;j<GDK_AXIS_LAST;j++)
+ gdkdev->axis_for_use[j] = -1;
+
+ for (j=0;j<xvi->num_axes;j++)
+ if (gdkdev->info.axes[j] != GDK_AXIS_IGNORE)
+ gdkdev->axis_for_use[gdkdev->info.axes[j]] = j;
+
+ break;
+ }
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+ /* return NULL if no axes */
+ if (!gdkdev->info.num_axes || !gdkdev->axes ||
+ (!include_core && device->use == IsXPointer))
+ {
+ g_free(gdkdev->info.name);
+ if (gdkdev->axes)
+ g_free(gdkdev->axes);
+ g_free(gdkdev);
+ return NULL;
+ }
+
+ if (device->use != IsXPointer)
+ gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
+
+ return gdkdev;
+}
+
+static void
+gdk_input_common_find_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes)
+{
+ gint i;
+ XEventClass class;
+
+ i = 0;
+ /* We have to track press and release events in pairs to keep
+ track of button state correctly and implement grabbing */
+ if (mask & GDK_BUTTON_PRESS_MASK || mask & GDK_BUTTON_RELEASE_MASK)
+ {
+ DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ DeviceButtonRelease (gdkdev->xdevice, gdkdev->buttonrelease_type,
+ class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_MASK)
+ {
+ DeviceMotionNotify (gdkdev->xdevice, gdkdev->motionnotify_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_POINTER_MOTION_HINT_MASK)
+ {
+ /* We'll get into trouble if the macros change, but at least we'll
+ know about it, and we avoid warnings now */
+ DevicePointerMotionHint (gdkdev->xdevice, 0, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_IN_MASK)
+ {
+ ProximityIn (gdkdev->xdevice, gdkdev->proximityin_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+ if (mask & GDK_PROXIMITY_OUT_MASK)
+ {
+ ProximityOut (gdkdev->xdevice, gdkdev->proximityout_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ *num_classes = i;
+}
+
+static void
+gdk_input_common_select_events(GdkWindow *window,
+ GdkDevicePrivate *gdkdev)
+{
+ XEventClass classes[6];
+ gint num_classes;
+
+ if (gdkdev->info.mode == GDK_MODE_DISABLED)
+ gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
+ else
+ gdk_input_common_find_events(window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ classes, &num_classes);
+
+ XSelectExtensionEvent (gdk_display,
+ GDK_WINDOW_XWINDOW(window),
+ classes, num_classes);
+}
+
+gint
+gdk_input_common_init(gint include_core)
+{
+ char **extensions;
+ XDeviceInfo *devices;
+ int num_devices;
+ int num_extensions, loop;
+ Display *display = gdk_display;
+
+ /* Init global vars */
+ gdk_window_get_geometry(NULL, /* use root window */
+ NULL,NULL,
+ &gdk_input_root_width,&gdk_input_root_height,
+ NULL);
+
+ /* Init XInput extension */
+
+ extensions = XListExtensions(display, &num_extensions);
+ for (loop = 0; loop < num_extensions &&
+ (strcmp(extensions[loop], "XInputExtension") != 0); loop++);
+ XFreeExtensionList(extensions);
+ if (loop == num_extensions) /* XInput extension not found */
+ return FALSE;
+
+ gdk_input_devices = 0;
+ devices = XListInputDevices(display, &num_devices);
+
+ for(loop=0; loop<num_devices; loop++)
+ {
+ GdkDevicePrivate *gdkdev = gdk_input_device_new(&devices[loop],
+ include_core);
+ if (gdkdev)
+ gdk_input_devices = g_list_append(gdk_input_devices, gdkdev);
+ }
+ XFreeDeviceList(devices);
+
+ gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
+
+ return TRUE;
+}
+
+static void
+gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
+ GdkInputWindow *input_window,
+ gint *axis_data,
+ gdouble *x, gdouble *y, gdouble *pressure,
+ gdouble *xtilt, gdouble *ytilt)
+{
+ GdkWindowPrivate *win_priv;
+
+ int x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
+
+ double device_width, device_height;
+ double x_offset, y_offset, x_scale, y_scale;
+
+ win_priv = (GdkWindowPrivate *) input_window->window;
+
+ x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
+ y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
+ pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
+ xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
+ ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
+
+ device_width = gdkdev->axes[x_axis].max_value -
+ gdkdev->axes[x_axis].min_value;
+ device_height = gdkdev->axes[y_axis].max_value -
+ gdkdev->axes[y_axis].min_value;
+
+ if (gdkdev->info.mode == GDK_MODE_SCREEN)
+ {
+ x_scale = gdk_input_root_width / device_width;
+ y_scale = gdk_input_root_height / device_height;
+
+ x_offset = - input_window->root_x;
+ y_offset = - input_window->root_y;
+ }
+ else /* GDK_MODE_WINDOW */
+ {
+ double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
+ (device_width*gdkdev->axes[x_axis].resolution);
+
+ if (device_aspect * win_priv->width >= win_priv->height)
+ {
+ /* device taller than window */
+ x_scale = win_priv->width / device_width;
+ y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
+ / gdkdev->axes[y_axis].resolution;
+
+ x_offset = 0;
+ y_offset = -(device_height * y_scale -
+ win_priv->height)/2;
+ }
+ else
+ {
+ /* window taller than device */
+ y_scale = win_priv->height / device_height;
+ x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
+ / gdkdev->axes[x_axis].resolution;
+
+ y_offset = 0;
+ x_offset = - (device_width * x_scale - win_priv->width)/2;
+ }
+ }
+
+ if (x) *x = x_offset + x_scale*axis_data[x_axis];
+ if (y) *y = y_offset + y_scale*axis_data[y_axis];
+
+ if (pressure)
+ {
+ if (pressure_axis != -1)
+ *pressure = ((double)axis_data[pressure_axis]
+ - gdkdev->axes[pressure_axis].min_value)
+ / (gdkdev->axes[pressure_axis].max_value
+ - gdkdev->axes[pressure_axis].min_value);
+ else
+ *pressure = 0.5;
+ }
+
+ if (xtilt)
+ {
+ if (xtilt_axis != -1)
+ {
+ *xtilt = 2. * (double)(axis_data[xtilt_axis] -
+ (gdkdev->axes[xtilt_axis].min_value +
+ gdkdev->axes[xtilt_axis].max_value)/2) /
+ (gdkdev->axes[xtilt_axis].max_value -
+ gdkdev->axes[xtilt_axis].min_value);
+ }
+ else *xtilt = 0;
+ }
+
+ if (ytilt)
+ {
+ if (ytilt_axis != -1)
+ {
+ *ytilt = 2. * (double)(axis_data[ytilt_axis] -
+ (gdkdev->axes[ytilt_axis].min_value +
+ gdkdev->axes[ytilt_axis].max_value)/2) /
+ (gdkdev->axes[ytilt_axis].max_value -
+ gdkdev->axes[ytilt_axis].min_value);
+ }
+ else
+ *ytilt = 0;
+ }
+}
+
+/* combine the state of the core device and the device state
+ into one - for now we do this in a simple-minded manner -
+ we just take the keyboard portion of the core device and
+ the button portion (all of?) the device state.
+ Any button remapping should go on here. */
+static guint
+gdk_input_translate_state(guint state, guint device_state)
+{
+ return device_state | (state & 0xFF);
+}
+
+static gint
+gdk_input_common_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkInputWindow *input_window,
+ GdkDevicePrivate *gdkdev)
+{
+ if ((xevent->type == gdkdev->buttonpress_type) ||
+ (xevent->type == gdkdev->buttonrelease_type))
+ {
+ XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
+
+ if (xdbe->type == gdkdev->buttonpress_type)
+ {
+ event->button.type = GDK_BUTTON_PRESS;
+ gdkdev->button_state |= 1 << xdbe->button;
+ }
+ else
+ {
+ event->button.type = GDK_BUTTON_RELEASE;
+ gdkdev->button_state &= ~(1 << xdbe->button);
+ }
+ event->button.window = input_window->window;
+ event->button.time = xdbe->time;
+ event->button.source = gdkdev->info.source;
+ event->button.deviceid = xdbe->deviceid;
+
+ gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
+ &event->button.x,&event->button.y,
+ &event->button.pressure,
+ &event->button.xtilt,
+ &event->button.ytilt);
+ event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
+ event->button.button = xdbe->button;
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->motionnotify_type)
+ {
+ XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
+
+ gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
+ &event->motion.x,&event->motion.y,
+ &event->motion.pressure,
+ &event->motion.xtilt,
+ &event->motion.ytilt);
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = input_window->window;
+ event->motion.time = xdme->time;
+ event->motion.deviceid = xdme->deviceid;
+ event->motion.state = gdk_input_translate_state(xdme->state,
+ xdme->device_state);
+ event->motion.source = gdkdev->info.source;
+ event->motion.deviceid = xdme->deviceid;
+
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld device: %ld x,y: %f %f hint: %s\n",
+ xdme->window,
+ xdme->deviceid,
+ event->motion.x, event->motion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false");
+
+
+ return TRUE;
+ }
+
+ if (xevent->type == gdkdev->proximityin_type ||
+ xevent->type == gdkdev->proximityout_type)
+ {
+ XProximityNotifyEvent *xpne = (XProximityNotifyEvent *)(xevent);
+
+ event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
+ GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
+ event->proximity.window = input_window->window;
+ event->proximity.time = xpne->time;
+ event->proximity.source = gdkdev->info.source;
+ event->proximity.deviceid = xpne->deviceid;
+
+ return TRUE;
+ }
+
+ return -1; /* wasn't one of our event types */
+}
+
+static void
+gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ int i;
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ for (i=GDK_AXIS_IGNORE;i<GDK_AXIS_LAST;i++)
+ {
+ gdkdev->axis_for_use[i] = -1;
+ }
+
+ for (i=0;i<gdkdev->info.num_axes;i++)
+ {
+ gdkdev->info.axes[i] = axes[i];
+ gdkdev->axis_for_use[axes[i]] = i;
+ }
+}
+
+static GdkTimeCoord *
+gdk_input_common_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ GdkTimeCoord *coords;
+ XDeviceTimeCoord *device_coords;
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+
+ int mode_return;
+ int axis_count_return;
+ int i;
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_val_if_fail (gdkdev != NULL, NULL);
+ g_return_val_if_fail (gdkdev->xdevice != NULL, NULL);
+ g_return_val_if_fail (input_window != NULL, NULL);
+
+ device_coords = XGetDeviceMotionEvents (gdk_display,
+ gdkdev->xdevice,
+ start, stop,
+ nevents_return, &mode_return,
+ &axis_count_return);
+
+ if (device_coords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+
+ for (i=0; i<*nevents_return; i++)
+ {
+ gdk_input_translate_coordinates (gdkdev, input_window,
+ device_coords[i].data,
+ &coords[i].x, &coords[i].y,
+ &coords[i].pressure,
+ &coords[i].xtilt, &coords[i].ytilt);
+ }
+ XFreeDeviceMotionEvents (device_coords);
+
+ return coords;
+ }
+ else
+ return NULL;
+}
+
+static void
+gdk_input_common_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ GdkDevicePrivate *gdkdev;
+ GdkInputWindow *input_window;
+ XDeviceState *state;
+ XInputClass *input_class;
+ gint x_int, y_int;
+ gint i;
+
+ /* we probably need to get the mask in any case */
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+ if (x) *x = x_int;
+ if (y) *y = y_int;
+ if (pressure) *pressure = 0.5;
+ if (xtilt) *xtilt = 0;
+ if (ytilt) *ytilt = 0;
+ }
+ else
+ {
+ if (mask)
+ gdk_window_get_pointer (window, NULL, NULL, mask);
+
+ gdkdev = gdk_input_find_device (deviceid);
+ input_window = gdk_input_window_find (window);
+
+ g_return_if_fail (gdkdev != NULL);
+ g_return_if_fail (gdkdev->xdevice != NULL);
+ g_return_if_fail (input_window != NULL);
+
+ state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
+ input_class = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ switch (input_class->class)
+ {
+ case ValuatorClass:
+ gdk_input_translate_coordinates(gdkdev, input_window,
+ ((XValuatorState *)input_class)->valuators,
+ x, y, pressure,
+ xtilt, ytilt);
+
+
+ break;
+ case ButtonClass:
+ if (mask)
+ {
+ *mask &= ~(GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK);
+ for (i=0; i < ((XButtonState *)input_class)->num_buttons; i++)
+ {
+ if (((XButtonState *)input_class)->buttons[i])
+ *mask |= GDK_BUTTON1_MASK << i;
+ }
+ }
+ break;
+ }
+ input_class = (XInputClass *)(((char *)input_class)+input_class->length);
+ }
+ }
+}
+
+#endif
diff --git a/gdk/x11/gdkinput-xfree.c b/gdk/x11/gdkinput-xfree.c
new file mode 100644
index 000000000..f74249008
--- /dev/null
+++ b/gdk/x11/gdkinput-xfree.c
@@ -0,0 +1,368 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_XFREE
+
+/* forward declarations */
+
+static gint gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode);
+static void gdk_input_check_proximity();
+static void gdk_input_xfree_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_enable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_disable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_xfree_ungrab_pointer (guint32 time);
+
+void
+gdk_input_init(void)
+{
+ gdk_input_vtable.set_mode = gdk_input_xfree_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_common_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_common_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_xfree_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_xfree_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_xfree_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_xfree_enter_event;
+ gdk_input_vtable.other_event = gdk_input_xfree_other_event;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = gdk_input_xfree_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_xfree_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_common_init(FALSE);
+}
+
+static gint
+gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (mode == GDK_MODE_WINDOW)
+ {
+ gdkdev->info.has_cursor = FALSE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_enable_window (input_window->window, gdkdev);
+ else
+ if (old_mode != GDK_MODE_DISABLED)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+ else if (mode == GDK_MODE_SCREEN)
+ {
+ gdkdev->info.has_cursor = TRUE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
+ gdkdev);
+ }
+ else /* mode == GDK_MODE_DISABLED */
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (old_mode != GDK_MODE_WINDOW ||
+ input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ return TRUE;
+
+}
+
+static void
+gdk_input_check_proximity()
+{
+ gint new_proximity = 0;
+ GList *tmp_list = gdk_input_devices;
+
+ while (tmp_list && !new_proximity)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.mode != GDK_MODE_DISABLED
+ && gdkdev->info.deviceid != GDK_CORE_POINTER
+ && gdkdev->xdevice)
+ {
+ XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
+ gdkdev->xdevice);
+ XInputClass *xic;
+ int i;
+
+ xic = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ if (xic->class == ValuatorClass)
+ {
+ XValuatorState *xvs = (XValuatorState *)xic;
+ if ((xvs->mode & ProximityState) == InProximity)
+ {
+ new_proximity = TRUE;
+ }
+ break;
+ }
+ xic = (XInputClass *)((char *)xic + xic->length);
+ }
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ gdk_input_ignore_core = new_proximity;
+}
+
+static void
+gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static void
+gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_check_proximity();
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static gint
+gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ /* FIXME: It would be nice if we could just get rid of the events
+ entirely, instead of having to ignore them */
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ (gdkdev->info.mode == GDK_MODE_WINDOW
+ && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+ return FALSE;
+
+ if (!gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
+ gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ /* Do a passive button grab. We have to be careful not to release
+ an explicit grab, if any. Doubling the grab should be harmless,
+ but we check anyways. */
+
+ /* FIXME, finding the proper events here is going to be SLOW - but
+ we might have different sets for each window/device combination */
+
+ if (return_val> 0 && !input_window->grabbed)
+ {
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, event->button.time);
+ }
+ else if (event->type == GDK_BUTTON_RELEASE)
+ XUngrabDevice( GDK_DISPLAY(), gdkdev->xdevice, event->button.time);
+ }
+
+ return return_val;
+}
+
+static gint
+gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ /* FIXME: watchout, gdkdev might be core pointer, never opened */
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ tmp_list = gdk_input_windows;
+ new_window = NULL;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ {
+ new_window = input_window;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_return_if_fail (new_window == NULL);
+
+ new_window->grabbed = TRUE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ /* FIXME: we should do something on failure */
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ return Success;
+}
+
+static void
+gdk_input_xfree_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list) /* we found a grabbed window */
+ {
+ input_window->grabbed = FALSE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ XUngrabDevice( gdk_display, gdkdev->xdevice, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+#endif /* XINPUT_XFREE */
diff --git a/gdk/x11/gdkinput.c b/gdk/x11/gdkinput.c
new file mode 100644
index 000000000..ad4b1fcc9
--- /dev/null
+++ b/gdk/x11/gdkinput.c
@@ -0,0 +1,324 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "../config.h"
+#include "gdk.h"
+#include "gdkx.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+/* Forward declarations */
+
+static gint gdk_input_enable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_disable_window (GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
+static GdkDevicePrivate *gdk_input_find_device (guint32 id);
+
+
+/* Incorporate the specific routines depending on compilation options */
+
+static GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
+
+static GdkDeviceInfo gdk_input_core_info =
+{
+ GDK_CORE_POINTER,
+ "Core Pointer",
+ GDK_SOURCE_MOUSE,
+ GDK_MODE_SCREEN,
+ TRUE,
+ 2,
+ gdk_input_core_axes
+};
+
+/* Global variables */
+
+GdkInputVTable gdk_input_vtable;
+/* information about network port and host for gxid daemon */
+gchar *gdk_input_gxid_host;
+gint gdk_input_gxid_port;
+gint gdk_input_ignore_core;
+
+/* Local variables */
+
+static GList *gdk_input_devices;
+static GList *gdk_input_windows;
+
+#include "gdkinputnone.h"
+#include "gdkinputcommon.h"
+#include "gdkinputxfree.h"
+#include "gdkinputgxi.h"
+
+GList *
+gdk_input_list_devices ()
+{
+ return gdk_input_devices;
+}
+
+void
+gdk_input_set_source (guint32 deviceid, GdkInputSource source)
+{
+ GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
+ g_return_if_fail (gdkdev != NULL);
+
+ gdkdev->info.source = source;
+}
+
+gint
+gdk_input_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ if (deviceid == GDK_CORE_POINTER)
+ return FALSE;
+
+ if (gdk_input_vtable.set_mode)
+ return gdk_input_vtable.set_mode(deviceid,mode);
+ else
+ return FALSE;
+}
+
+void
+gdk_input_set_axes (guint32 deviceid, GdkAxisUse *axes)
+{
+ if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_axes)
+ gdk_input_vtable.set_axes (deviceid, axes);
+}
+
+GdkTimeCoord *
+gdk_input_motion_events (GdkWindow *window,
+ guint32 deviceid,
+ guint32 start,
+ guint32 stop,
+ gint *nevents_return)
+{
+ XTimeCoord *xcoords;
+ GdkTimeCoord *coords;
+ int i;
+
+ if (deviceid == GDK_CORE_POINTER)
+ {
+ xcoords = XGetMotionEvents (gdk_display,
+ ((GdkWindowPrivate *)window)->xwindow,
+ start, stop, nevents_return);
+ if (xcoords)
+ {
+ coords = g_new (GdkTimeCoord, *nevents_return);
+ for (i=0; i<*nevents_return; i++)
+ {
+ coords[i].time = xcoords[i].time;
+ coords[i].x = xcoords[i].x;
+ coords[i].y = xcoords[i].y;
+ coords[i].pressure = 0.5;
+ coords[i].xtilt = 0.0;
+ coords[i].ytilt = 0.0;
+ }
+
+ XFree(xcoords);
+
+ return coords;
+ }
+ else
+ return NULL;
+ }
+ else
+ {
+ if (gdk_input_vtable.motion_events)
+ {
+ return gdk_input_vtable.motion_events(window,
+ deviceid, start, stop,
+ nevents_return);
+ }
+ else
+ {
+ *nevents_return = 0;
+ return NULL;
+ }
+ }
+}
+
+static gint
+gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.enable_window)
+ return gdk_input_vtable.enable_window (window, gdkdev);
+ else
+ return TRUE;
+}
+
+static gint
+gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ if (gdk_input_vtable.disable_window)
+ return gdk_input_vtable.disable_window(window,gdkdev);
+ else
+ return TRUE;
+}
+
+
+static GdkInputWindow *
+gdk_input_window_find(GdkWindow *window)
+{
+ GList *tmp_list;
+
+ for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
+ if (((GdkInputWindow *)(tmp_list->data))->window == window)
+ return (GdkInputWindow *)(tmp_list->data);
+
+ return NULL; /* Not found */
+}
+
+/* FIXME: this routine currently needs to be called between creation
+ and the corresponding configure event (because it doesn't get the
+ root_relative_geometry). This should work with
+ gtk_window_set_extension_events, but will likely fail in other
+ cases */
+
+void
+gdk_input_set_extension_events (GdkWindow *window, gint mask,
+ GdkExtensionMode mode)
+{
+ GList *tmp_list;
+ GdkInputWindow *iw;
+
+ g_return_if_fail (window != NULL);
+
+ if (mode == GDK_EXTENSION_EVENTS_NONE)
+ mask = 0;
+
+ if (mask != 0)
+ {
+ iw = g_new(GdkInputWindow,1);
+
+ iw->window = window;
+ iw->mode = mode;
+
+ iw->obscuring = NULL;
+ iw->num_obscuring = 0;
+ iw->grabbed = FALSE;
+
+ gdk_input_windows = g_list_append(gdk_input_windows,iw);
+ ((GdkWindowPrivate *)window)->extension_events = mask;
+
+ /* Add enter window events to the event mask */
+ /* FIXME, this is not needed for XINPUT_NONE */
+ gdk_window_set_events (window,
+ gdk_window_get_events (window) |
+ GDK_ENTER_NOTIFY_MASK);
+ }
+ else
+ {
+ iw = gdk_input_window_find (window);
+ if (iw)
+ {
+ gdk_input_windows = g_list_remove(gdk_input_windows,iw);
+ g_free(iw);
+ }
+
+ ((GdkWindowPrivate *)window)->extension_events = 0;
+ }
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
+ && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
+ gdk_input_enable_window(window,gdkdev);
+ else
+ gdk_input_disable_window(window,gdkdev);
+ }
+ }
+}
+
+void
+gdk_input_window_destroy (GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ input_window = gdk_input_window_find (window);
+ g_return_if_fail (input_window != NULL);
+
+ gdk_input_windows = g_list_remove(gdk_input_windows,input_window);
+ g_free(input_window);
+}
+
+void
+gdk_input_exit (void)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+
+ for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER)
+ {
+ gdk_input_set_mode(gdkdev->info.deviceid,GDK_MODE_DISABLED);
+
+ g_free(gdkdev->info.name);
+#ifndef XINPUT_NONE
+ g_free(gdkdev->axes);
+#endif
+ g_free(gdkdev->info.axes);
+ g_free(gdkdev);
+ }
+ }
+
+ g_list_free(gdk_input_devices);
+
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ g_free(tmp_list->data);
+ }
+ g_list_free(gdk_input_windows);
+}
+
+static GdkDevicePrivate *
+gdk_input_find_device(guint32 id)
+{
+ GList *tmp_list = gdk_input_devices;
+ GdkDevicePrivate *gdkdev;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+ if (gdkdev->info.deviceid == id)
+ return gdkdev;
+ tmp_list = tmp_list->next;
+ }
+ return NULL;
+}
+
+void
+gdk_input_window_get_pointer (GdkWindow *window,
+ guint32 deviceid,
+ gdouble *x,
+ gdouble *y,
+ gdouble *pressure,
+ gdouble *xtilt,
+ gdouble *ytilt,
+ GdkModifierType *mask)
+{
+ if (gdk_input_vtable.get_pointer)
+ gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
+ xtilt, ytilt, mask);
+}
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
new file mode 100644
index 000000000..d5f85dd1e
--- /dev/null
+++ b/gdk/x11/gdkmain-x11.c
@@ -0,0 +1,2897 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+
+#include <ctype.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H_ */
+
+#define XLIB_ILLEGAL_ACCESS
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/WinUtil.h>
+#include <X11/cursorfont.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+#include "gdkinput.h"
+
+
+#ifndef X_GETTIMEOFDAY
+#define X_GETTIMEOFDAY(tv) gettimeofday (tv, NULL)
+#endif /* X_GETTIMEOFDAY */
+
+
+#define DOUBLE_CLICK_TIME 250
+#define TRIPLE_CLICK_TIME 500
+#define DOUBLE_CLICK_DIST 5
+#define TRIPLE_CLICK_DIST 5
+
+
+#ifndef NO_FD_SET
+# define SELECT_MASK fd_set
+#else
+# ifndef _AIX
+ typedef long fd_mask;
+# endif
+# if defined(_IBMR2)
+# define SELECT_MASK void
+# else
+# define SELECT_MASK int
+# endif
+#endif
+
+
+typedef struct _GdkInput GdkInput;
+typedef struct _GdkPredicate GdkPredicate;
+
+struct _GdkInput
+{
+ gint tag;
+ gint source;
+ GdkInputCondition condition;
+ GdkInputFunction function;
+ gpointer data;
+};
+
+struct _GdkPredicate
+{
+ GdkEventFunc func;
+ gpointer data;
+};
+
+/*
+ * Private function declarations
+ */
+static gint gdk_event_wait (void);
+static gint gdk_event_translate (GdkEvent *event,
+ XEvent *xevent);
+static Bool gdk_event_get_type (Display *display,
+ XEvent *xevent,
+ XPointer arg);
+static void gdk_synthesize_click (GdkEvent *event,
+ gint nclicks);
+
+static void gdk_dnd_drag_begin (GdkWindow *initial_window);
+static void gdk_dnd_drag_enter (Window dest);
+static void gdk_dnd_drag_leave (Window dest);
+static void gdk_dnd_drag_end (Window dest,
+ GdkPoint coords);
+static GdkAtom gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent);
+static void gdk_print_atom (GdkAtom anatom);
+
+/*
+ * old junk from offix, we might use it though so leave it
+ */
+static Window gdk_drop_get_client_window (Display *dpy,
+ Window win);
+static GdkWindow * gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y);
+static void gdk_exit_func (void);
+static int gdk_x_error (Display *display,
+ XErrorEvent *error);
+static int gdk_x_io_error (Display *display);
+static RETSIGTYPE gdk_signal (int signum);
+
+
+/* Private variable declarations
+ */
+static int initialized = 0; /* 1 if the library is initialized,
+ * 0 otherwise.
+ */
+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 gint received_destroy_notify = FALSE; /* Did we just receive a destroy notify
+ * event? If so, we need to actually
+ * destroy the window which received
+ * it now.
+ */
+static GdkWindow *window_to_destroy = NULL; /* If we previously received a destroy
+ * notify event then this is the window
+ * which received that event.
+ */
+
+static struct timeval start; /* The time at which the library was
+ * last initialized.
+ */
+static struct timeval timer; /* Timeout interval to use in the call
+ * to "select". This is used in
+ * conjunction with "timerp" to create
+ * a maximum time to wait for an event
+ * to arrive.
+ */
+static struct timeval *timerp; /* The actual timer passed to "select"
+ * This may be NULL, in which case
+ * "select" will block until an event
+ * arrives.
+ */
+static guint32 timer_val; /* The timeout length as specified by
+ * the user in milliseconds.
+ */
+static GList *inputs; /* A list of the input file descriptors
+ * that we care about. Each list node
+ * contains a GdkInput struct that describes
+ * when we are interested in the specified
+ * file descriptor. That is, when it is
+ * available for read, write or has an
+ * exception pending.
+ */
+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.
+ */
+
+#define OTHER_XEVENT_BUFSIZE 4
+static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
+static int other_xevent_i = 0;
+static GList *putback_events = NULL;
+
+static gulong base_id;
+static gint autorepeat;
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_init
+ *
+ * Initialize the library for use.
+ *
+ * Arguments:
+ * "argc" is the number of arguments.
+ * "argv" is an array of strings.
+ *
+ * Results:
+ * "argc" and "argv" are modified to reflect any arguments
+ * which were not handled. (Such arguments should either
+ * be handled by the application or dismissed).
+ *
+ * Side effects:
+ * The library is initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_init (int *argc,
+ char ***argv)
+{
+ XKeyboardState keyboard_state;
+ int synchronize;
+ int i, j, k;
+ XClassHint *class_hint;
+ int argc_orig = *argc;
+ char **argv_orig;
+
+ argv_orig = malloc ((argc_orig + 1) * sizeof (char*));
+ for (i = 0; i < argc_orig; i++)
+ argv_orig[i] = g_strdup ((*argv)[i]);
+ argv_orig[argc_orig] = NULL;
+
+ X_GETTIMEOFDAY (&start);
+
+ signal (SIGHUP, gdk_signal);
+ signal (SIGINT, gdk_signal);
+ signal (SIGQUIT, gdk_signal);
+ signal (SIGBUS, gdk_signal);
+ signal (SIGSEGV, gdk_signal);
+ signal (SIGPIPE, gdk_signal);
+ signal (SIGTERM, gdk_signal);
+
+ gdk_display_name = NULL;
+
+ XSetErrorHandler (gdk_x_error);
+ XSetIOErrorHandler (gdk_x_io_error);
+
+ synchronize = FALSE;
+
+ if (argc && argv)
+ {
+ if (*argc > 0)
+ gdk_progname = (*argv)[0];
+
+ for (i = 1; i < *argc;)
+ {
+ if (strcmp ("--display", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+
+ if ((i + 1) < *argc)
+ {
+ gdk_display_name = g_strdup ((*argv)[i + 1]);
+ (*argv)[i + 1] = NULL;
+ i += 1;
+ }
+ }
+ else if (strcmp ("--sync", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ synchronize = TRUE;
+ }
+ else if (strcmp ("--show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = TRUE;
+ }
+ else if (strcmp ("--no-show-events", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_show_events = FALSE;
+ }
+ else if (strcmp ("--no-xshm", (*argv)[i]) == 0)
+ {
+ (*argv)[i] = NULL;
+ gdk_use_xshm = FALSE;
+ }
+ else if (strcmp ("--debug-level", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_debug_level = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-name", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progname = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("-class", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_progclass = (*argv)[i];
+ (*argv)[i] = NULL;
+ }
+ }
+#ifdef XINPUT_GXI
+ else if (strcmp ("--gxid_host", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_host = ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+ else if (strcmp ("--gxid_port", (*argv)[i]) == 0)
+ {
+ if ((i + 1) < *argc)
+ {
+ (*argv)[i++] = NULL;
+ gdk_input_gxid_port = atoi ((*argv)[i]);
+ (*argv)[i] = NULL;
+ }
+ }
+#endif
+ i += 1;
+ }
+
+ for (i = 1; i < *argc; i++)
+ {
+ for (k = i; k < *argc; k++)
+ if ((*argv)[k] != NULL)
+ break;
+
+ if (k > i)
+ {
+ k -= i;
+ for (j = i + k; j < *argc; j++)
+ (*argv)[j-k] = (*argv)[j];
+ *argc -= k;
+ }
+ }
+ }
+ else
+ {
+ gdk_progname = "<unknown>";
+ }
+
+ gdk_display = XOpenDisplay (gdk_display_name);
+ if (!gdk_display)
+ g_error ("cannot open display: %s", XDisplayName (gdk_display_name));
+
+ /* 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.
+ */
+ /* base_id = RESOURCE_BASE; */
+ base_id = 0;
+ if (gdk_show_events)
+ g_print ("base id: %lu\n", base_id);
+
+ connection_number = ConnectionNumber (gdk_display);
+ if (gdk_debug_level >= 1)
+ g_print ("connection number: %d\n", connection_number);
+
+ if (synchronize)
+ XSynchronize (gdk_display, True);
+
+ gdk_screen = DefaultScreen (gdk_display);
+ gdk_root_window = RootWindow (gdk_display, gdk_screen);
+
+ gdk_leader_window = XCreateSimpleWindow(gdk_display, gdk_root_window,
+ 10, 10, 10, 10, 0, 0 , 0);
+ class_hint = XAllocClassHint();
+ class_hint->res_name = gdk_progname;
+ class_hint->res_class = gdk_progclass;
+ XSetClassHint(gdk_display, gdk_leader_window, class_hint);
+ XSetCommand(gdk_display, gdk_leader_window, argv_orig, argc_orig);
+ XFree (class_hint);
+
+ gdk_wm_delete_window = XInternAtom (gdk_display, "WM_DELETE_WINDOW", True);
+ gdk_wm_take_focus = XInternAtom (gdk_display, "WM_TAKE_FOCUS", True);
+ gdk_wm_protocols = XInternAtom (gdk_display, "WM_PROTOCOLS", True);
+ gdk_wm_window_protocols[0] = gdk_wm_delete_window;
+ gdk_wm_window_protocols[1] = gdk_wm_take_focus;
+ gdk_selection_property = XInternAtom (gdk_display, "GDK_SELECTION", False);
+
+ gdk_dnd.gdk_XdeEnter = gdk_atom_intern("_XDE_ENTER", FALSE);
+ gdk_dnd.gdk_XdeLeave = gdk_atom_intern("_XDE_LEAVE", FALSE);
+ gdk_dnd.gdk_XdeRequest = gdk_atom_intern("_XDE_REQUEST", FALSE);
+ gdk_dnd.gdk_XdeDataAvailable = gdk_atom_intern("_XDE_DATA_AVAILABLE", FALSE);
+ gdk_dnd.gdk_XdeTypelist = gdk_atom_intern("_XDE_TYPELIST", FALSE);
+ gdk_dnd.gdk_cursor_dragdefault = XCreateFontCursor(gdk_display, XC_bogosity);
+ gdk_dnd.gdk_cursor_dragok = XCreateFontCursor(gdk_display, XC_heart);
+
+ XGetKeyboardControl (gdk_display, &keyboard_state);
+ autorepeat = keyboard_state.global_auto_repeat;
+
+ timer.tv_sec = 0;
+ timer.tv_usec = 0;
+ timerp = NULL;
+
+ 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;
+
+ if (ATEXIT (gdk_exit_func))
+ g_warning ("unable to register exit function");
+
+ gdk_visual_init ();
+ gdk_window_init ();
+ gdk_image_init ();
+ gdk_input_init ();
+
+ initialized = 1;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit
+ *
+ * Restores the library to an un-itialized state and exits
+ * the program using the "exit" system call.
+ *
+ * Arguments:
+ * "errorcode" is the error value to pass to "exit".
+ *
+ * Results:
+ * Allocated structures are freed and the program exits
+ * cleanly.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_exit (int errorcode)
+{
+ /* de-initialisation is done by the gdk_exit_funct(),
+ no need to do this here (Alex J.) */
+ exit (errorcode);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_locale
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gchar*
+gdk_set_locale ()
+{
+ if (!setlocale (LC_ALL,""))
+ g_print ("locale not supported by C library\n");
+
+ if (!XSupportsLocale ())
+ {
+ g_print ("locale not supported by Xlib, locale set to C\n");
+ setlocale (LC_ALL, "C");
+ }
+
+ if (!XSetLocaleModifiers (""))
+ {
+ g_print ("can not set locale modifiers\n");
+ }
+
+ return setlocale (LC_ALL,NULL);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_events_pending
+ *
+ * Returns the number of events pending on the queue.
+ * These events have already been read from the server
+ * connection.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the number of events on XLib's event queue.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_events_pending ()
+{
+ return XPending (gdk_display);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_get
+ *
+ * Gets the next event.
+ *
+ * Arguments:
+ * "event" is used to hold the received event.
+ * If "event" is NULL an event is received as normal
+ * however it is not placed in "event" (and thus no
+ * error occurs).
+ *
+ * Results:
+ * Returns TRUE if an event was received that we care about
+ * and FALSE otherwise. This function will also return
+ * before an event is received if the timeout interval
+ * runs out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_event_get (GdkEvent *event,
+ GdkEventFunc pred,
+ gpointer data)
+{
+ GdkEvent *temp_event;
+ GdkPredicate event_pred;
+ GList *temp_list;
+ XEvent xevent;
+
+ /* If the last event we received was a destroy notify
+ * event then we will actually destroy the "gdk" data
+ * structures now. We don't want to destroy them at the
+ * time of receiving the event since the main program
+ * may try to access them and may need to destroy user
+ * data that has been attached to the window
+ */
+ if (received_destroy_notify)
+ {
+ if (gdk_show_events)
+ g_print ("destroying window:\twindow: %ld\n",
+ ((GdkWindowPrivate*) window_to_destroy)->xwindow - base_id);
+
+ gdk_window_real_destroy (window_to_destroy);
+ received_destroy_notify = FALSE;
+ window_to_destroy = NULL;
+ }
+
+ /* Initially we haven't received an event and want to
+ * return FALSE. If "event" is non-NULL, then initialize
+ * it to the nothing event.
+ */
+ if (event)
+ {
+ event->any.type = GDK_NOTHING;
+ event->any.window = NULL;
+ event->any.send_event = FALSE;
+ }
+
+ if (pred)
+ {
+ temp_list = putback_events;
+ while (temp_list)
+ {
+ temp_event = temp_list->data;
+
+ if ((* pred) (temp_event, data))
+ {
+ if (event)
+ *event = *temp_event;
+ putback_events = g_list_remove_link (putback_events, temp_list);
+ g_list_free (temp_list);
+ return TRUE;
+ }
+
+ temp_list = temp_list->next;
+ }
+
+ event_pred.func = pred;
+ event_pred.data = data;
+
+ if (XCheckIfEvent (gdk_display, &xevent, gdk_event_get_type, (XPointer) &event_pred))
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ else
+ {
+ if (putback_events)
+ {
+ temp_event = putback_events->data;
+ *event = *temp_event;
+
+ temp_list = putback_events;
+ putback_events = putback_events->next;
+ if (putback_events)
+ putback_events->prev = NULL;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+ g_list_free (temp_list);
+ g_free (temp_event);
+
+ return TRUE;
+ }
+
+ /* Wait for an event to occur or the timeout to elapse.
+ * If an event occurs "gdk_event_wait" will return TRUE.
+ * If the timeout elapses "gdk_event_wait" will return
+ * FALSE.
+ */
+ if (gdk_event_wait ())
+ {
+ /* If we get here we can rest assurred that an event
+ * has occurred. Read it.
+ */
+ XNextEvent (gdk_display, &xevent);
+
+ event->any.send_event = xevent.xany.send_event;
+
+ /* If "event" non-NULL.
+ */
+ if (event)
+ return gdk_event_translate (event, &xevent);
+ }
+ }
+
+ return FALSE;
+}
+
+void
+gdk_event_put (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_if_fail (event != NULL);
+
+ new_event = g_new (GdkEvent, 1);
+ *new_event = *event;
+
+ putback_events = g_list_prepend (putback_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;
+
+GdkEvent*
+gdk_event_copy (GdkEvent *event)
+{
+ GdkEvent *new_event;
+
+ g_return_val_if_fail (event != NULL, NULL);
+
+ 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);
+ *new_event = *event;
+ gdk_window_ref (new_event->any.window);
+ 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);
+
+ gdk_window_unref (event->any.window);
+ g_mem_chunk_free (event_chunk, event);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_set_debug_level
+ *
+ * Sets the debugging level.
+ *
+ * Arguments:
+ * "level" is the new debugging level.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Other function calls to "gdk" use the debugging
+ * level to determine what kind of debugging information
+ * to print out.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_set_debug_level (int level)
+{
+ gdk_debug_level = level;
+}
+
+/*
+ *--------------------------------------------------------------
+ * 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)
+{
+ gdk_show_events = show_events;
+}
+
+void
+gdk_set_use_xshm (gint use_xshm)
+{
+ gdk_use_xshm = use_xshm;
+}
+
+gint
+gdk_get_debug_level ()
+{
+ return gdk_debug_level;
+}
+
+gint
+gdk_get_show_events ()
+{
+ return gdk_show_events;
+}
+
+gint
+gdk_get_use_xshm ()
+{
+ return gdk_use_xshm;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_time_get
+ *
+ * Get the number of milliseconds since the library was
+ * initialized.
+ *
+ * Arguments:
+ *
+ * Results:
+ * The time since the library was initialized is returned.
+ * This time value is accurate to milliseconds even though
+ * a more accurate time down to the microsecond could be
+ * returned.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_time_get ()
+{
+ struct timeval end;
+ struct timeval elapsed;
+ guint32 milliseconds;
+
+ X_GETTIMEOFDAY (&end);
+
+ if (start.tv_usec > end.tv_usec)
+ {
+ end.tv_usec += 1000000;
+ end.tv_sec--;
+ }
+ elapsed.tv_sec = end.tv_sec - start.tv_sec;
+ elapsed.tv_usec = end.tv_usec - start.tv_usec;
+
+ milliseconds = (elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000);
+
+ return milliseconds;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_get
+ *
+ * Returns the current timer.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns the current timer interval. This interval is
+ * in units of milliseconds.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32
+gdk_timer_get ()
+{
+ return timer_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_timer_set
+ *
+ * Sets the timer interval.
+ *
+ * Arguments:
+ * "milliseconds" is the new value for the timer.
+ *
+ * Results:
+ *
+ * Side effects:
+ * Calls to "gdk_event_get" will last for a maximum
+ * of time of "milliseconds". However, a value of 0
+ * milliseconds will cause "gdk_event_get" to block
+ * indefinately until an event is received.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_timer_set (guint32 milliseconds)
+{
+ timer_val = milliseconds;
+ timer.tv_sec = milliseconds / 1000;
+ timer.tv_usec = (milliseconds % 1000) * 1000;
+
+}
+
+void
+gdk_timer_enable ()
+{
+ timerp = &timer;
+}
+
+void
+gdk_timer_disable ()
+{
+ timerp = NULL;
+}
+
+gint
+gdk_input_add (gint source,
+ GdkInputCondition condition,
+ GdkInputFunction function,
+ gpointer data)
+{
+ static gint next_tag = 1;
+ GList *list;
+ GdkInput *input;
+ gint tag;
+
+ tag = 0;
+ list = inputs;
+
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if ((input->source == source) && (input->condition == condition))
+ {
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+ }
+ }
+
+ if (!tag)
+ {
+ input = g_new (GdkInput, 1);
+ input->tag = next_tag++;
+ input->source = source;
+ input->condition = condition;
+ input->function = function;
+ input->data = data;
+ tag = input->tag;
+
+ inputs = g_list_prepend (inputs, input);
+ }
+
+ return tag;
+}
+
+void
+gdk_input_remove (gint tag)
+{
+ GList *list;
+ GList *temp_list;
+ GdkInput *input;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+
+ if (input->tag == tag)
+ {
+ temp_list = list;
+
+ if (list->next)
+ list->next->prev = list->prev;
+ if (list->prev)
+ list->prev->next = list->next;
+ if (inputs == list)
+ inputs = list->next;
+
+ temp_list->next = NULL;
+ temp_list->prev = NULL;
+
+ g_free (temp_list->data);
+ g_list_free (temp_list);
+ break;
+ }
+
+ list = list->next;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
+ *
+ * Grabs the pointer to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "event_mask" masks only interesting events
+ * "confine_to" limits the cursor movement to the specified window
+ * "cursor" changes the cursor for the duration of the grab
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_pointer_grab (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ GdkCursor * cursor,
+ guint32 time)
+{
+ /* From gdkwindow.c */
+ extern int nevent_masks;
+ extern int event_mask_table[];
+
+ gint return_val;
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *confine_to_private;
+ GdkCursorPrivate *cursor_private;
+ guint xevent_mask;
+ Window xwindow;
+ Window xconfine_to;
+ Cursor xcursor;
+ int i;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ confine_to_private = (GdkWindowPrivate*) confine_to;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ xwindow = window_private->xwindow;
+
+ if (!confine_to)
+ xconfine_to = None;
+ else
+ xconfine_to = confine_to_private->xwindow;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+
+ xevent_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ if (((GdkWindowPrivate *)window)->extension_events &&
+ gdk_input_vtable.grab_pointer)
+ return_val = gdk_input_vtable.grab_pointer (window,
+ owner_events,
+ event_mask,
+ confine_to,
+ time);
+ else
+ return_val = Success;;
+
+ if (return_val == Success)
+ return_val = XGrabPointer (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ xevent_mask,
+ GrabModeAsync, GrabModeAsync,
+ xconfine_to,
+ xcursor,
+ time);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_ungrab
+ *
+ * Releases any pointer grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_pointer_ungrab (guint32 time)
+{
+ if (gdk_input_vtable.ungrab_pointer)
+ gdk_input_vtable.ungrab_pointer (time);
+
+ XUngrabPointer (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_grab
+ *
+ * Grabs the keyboard to a specific window
+ *
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ * requires a corresponding call to gdk_keyboard_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_keyboard_grab (GdkWindow * window,
+ gint owner_events,
+ guint32 time)
+{
+ GdkWindowPrivate *window_private;
+ Window xwindow;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ window_private = (GdkWindowPrivate*) window;
+ xwindow = window_private->xwindow;
+
+ return XGrabKeyboard (window_private->xdisplay,
+ xwindow,
+ owner_events,
+ GrabModeAsync, GrabModeAsync,
+ time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_keyboard_ungrab
+ *
+ * Releases any keyboard grab
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+gdk_keyboard_ungrab (guint32 time)
+{
+ XUngrabKeyboard (gdk_display, time);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_width
+ *
+ * Return the width of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_width ()
+{
+ gint return_val;
+
+ return_val = DisplayWidth (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_screen_height
+ *
+ * Return the height of the screen.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint
+gdk_screen_height ()
+{
+ gint return_val;
+
+ return_val = DisplayHeight (gdk_display, gdk_screen);
+
+ return return_val;
+}
+
+void
+gdk_key_repeat_disable ()
+{
+ XAutoRepeatOff (gdk_display);
+}
+
+void
+gdk_key_repeat_restore ()
+{
+ if (autorepeat)
+ XAutoRepeatOn (gdk_display);
+ else
+ XAutoRepeatOff (gdk_display);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * 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 ()
+{
+ XSync (gdk_display, False);
+}
+
+
+void
+gdk_beep ()
+{
+ XBell(gdk_display, 100);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * gdk_event_wait
+ *
+ * Waits until an event occurs or the timer runs out.
+ *
+ * Arguments:
+ *
+ * Results:
+ * Returns TRUE if an event is ready to be read and FALSE
+ * if the timer ran out.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static gint
+gdk_event_wait ()
+{
+ GList *list;
+ GdkInput *input;
+ GdkInputCondition condition;
+ SELECT_MASK readfds;
+ SELECT_MASK writefds;
+ SELECT_MASK exceptfds;
+ int max_input;
+ int nfd;
+
+ /* If there are no events pending we will wait for an event.
+ * The time we wait is dependant on the "timer". If no timer
+ * has been specified then we'll block until an event arrives.
+ * If a timer has been specified we'll block until an event
+ * arrives or the timer expires. (This is all done using the
+ * "select" system call).
+ */
+
+ if (XPending (gdk_display) == 0)
+ {
+ FD_ZERO (&readfds);
+ FD_ZERO (&writefds);
+ FD_ZERO (&exceptfds);
+
+ FD_SET (connection_number, &readfds);
+ max_input = connection_number;
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ if (input->condition & GDK_INPUT_READ)
+ FD_SET (input->source, &readfds);
+ if (input->condition & GDK_INPUT_WRITE)
+ FD_SET (input->source, &writefds);
+ if (input->condition & GDK_INPUT_EXCEPTION)
+ FD_SET (input->source, &exceptfds);
+
+ max_input = MAX (max_input, input->source);
+ }
+
+ nfd = select (max_input+1, &readfds, &writefds, &exceptfds, timerp);
+
+ timerp = NULL;
+ timer_val = 0;
+
+ if (nfd > 0)
+ {
+ if (FD_ISSET (connection_number, &readfds))
+ {
+ if (XPending (gdk_display) == 0)
+ {
+ if (nfd == 1)
+ {
+ XNoOp (gdk_display);
+ XFlush (gdk_display);
+ }
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+
+ list = inputs;
+ while (list)
+ {
+ input = list->data;
+ list = list->next;
+
+ condition = 0;
+ if (FD_ISSET (input->source, &readfds))
+ condition |= GDK_INPUT_READ;
+ if (FD_ISSET (input->source, &writefds))
+ condition |= GDK_INPUT_WRITE;
+ if (FD_ISSET (input->source, &exceptfds))
+ condition |= GDK_INPUT_EXCEPTION;
+
+ if (condition && input->function)
+ (* input->function) (input->data, input->source, condition);
+ }
+ }
+ }
+ else
+ return TRUE;
+
+ return FALSE;
+}
+
+static gint
+gdk_event_translate (GdkEvent *event,
+ XEvent *xevent)
+{
+
+ GdkWindow *window;
+ GdkWindowPrivate *window_private;
+ XComposeStatus compose;
+ int charcount;
+ char buf[16];
+ gint return_val;
+
+ /* Are static variables used for this purpose thread-safe? */
+ static GdkPoint dnd_drag_start = {0,0},
+ dnd_drag_oldpos = {0,0};
+ static GdkRectangle dnd_drag_dropzone = {0,0,0,0};
+ static gint dnd_drag_perhaps = 0;
+ static GdkWindowPrivate *real_sw = NULL;
+ static Window dnd_drag_curwin = None, dnd_drag_target = None;
+
+ return_val = FALSE;
+
+ /* Find the GdkWindow that this event occurred in.
+ * All events occur in some GdkWindow (otherwise, why
+ * would we be receiving them). It really is an error
+ * to receive an event for which we cannot find the
+ * corresponding GdkWindow. 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;
+
+ /* 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.
+ */
+ /* Addendum:
+ * During drag & drop you get events where the pointer is
+ * in other windows. Need to just do finer-grained checking
+ */
+ switch (xevent->type)
+ {
+ case KeyPress:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key press:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ XKeysymToString (event->key.keyval),
+ event->key.keyval);
+
+ event->key.type = GDK_KEY_PRESS;
+ event->key.window = window;
+ event->key.time = xevent->xkey.time;
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeyRelease:
+ /* Lookup the string corresponding to the given keysym.
+ */
+ charcount = XLookupString (&xevent->xkey, buf, 16,
+ (KeySym*) &event->key.keyval,
+ &compose);
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("key release:\t\twindow: %ld key: %12s %d\n",
+ xevent->xkey.window - base_id,
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ButtonPress:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button press[%d]:\t\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ 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.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;
+ }
+ if(window_private
+ && window_private->dnd_drag_enabled
+ && !dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ dnd_drag_perhaps = 1;
+ dnd_drag_start.x = xevent->xbutton.x_root;
+ dnd_drag_start.y = xevent->xbutton.y_root;
+ real_sw = window_private;
+
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+ gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
+
+ {
+ /* Set motion mask for first DnD'd window, since it
+ will be the one that is actually dragged */
+ XWindowAttributes dnd_winattr;
+ XSetWindowAttributes dnd_setwinattr;
+ Status rv;
+
+ /* We need to get motion events while the button is down, so
+ we can know whether to really start dragging or not... */
+ XGetWindowAttributes(gdk_display, (Window)window_private->xwindow,
+ &dnd_winattr);
+
+ window_private->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
+ dnd_setwinattr.event_mask =
+ window_private->dnd_drag_eventmask = ButtonMotionMask;
+ XChangeWindowAttributes(gdk_display, window_private->xwindow,
+ CWEventMask, &dnd_setwinattr);
+ }
+ }
+ return_val = window_private?(!window_private->destroyed):FALSE;
+ break;
+
+ case ButtonRelease:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("button release[%d]:\twindow: %ld x,y: %d %d button: %d\n",
+ window_private?window_private->dnd_drag_enabled:0,
+ xevent->xbutton.window - base_id,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ 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.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(dnd_drag_perhaps)
+ {
+ if(gdk_dnd.drag_really)
+ {
+ GdkPoint foo = {xevent->xbutton.x_root,
+ xevent->xbutton.y_root};
+ XUngrabPointer(gdk_display, CurrentTime);
+
+ if(dnd_drag_target != None)
+ gdk_dnd_drag_end(dnd_drag_target, foo);
+ gdk_dnd.drag_really = 0;
+
+ if(gdk_dnd.drag_numwindows)
+ {
+ XSetWindowAttributes attrs;
+ /* Reset event mask to pre-drag value, assuming event_mask
+ doesn't change during drag */
+ attrs.event_mask = real_sw->dnd_drag_savedeventmask;
+ XChangeWindowAttributes(gdk_display, real_sw->xwindow,
+ CWEventMask, &attrs);
+ }
+
+ gdk_dnd.drag_numwindows = 0;
+ if(gdk_dnd.drag_startwindows)
+ {
+ g_free(gdk_dnd.drag_startwindows);
+ gdk_dnd.drag_startwindows = NULL;
+ }
+
+ real_sw = NULL;
+ }
+
+ dnd_drag_perhaps = 0;
+ dnd_drag_start.x = dnd_drag_start.y = 0;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_curwin = None;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case MotionNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s d:%d r%d\n",
+ xevent->xmotion.window - base_id,
+ xevent->xmotion.x, xevent->xmotion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false",
+ dnd_drag_perhaps, gdk_dnd.drag_really);
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_ignore_core)
+ 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.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;
+
+#define IS_IN_ZONE(cx, cy) (cx >= dnd_drag_dropzone.x \
+ && cy >= dnd_drag_dropzone.y \
+ && cx < (dnd_drag_dropzone.x + dnd_drag_dropzone.width) \
+ && cy < (dnd_drag_dropzone.y + dnd_drag_dropzone.height))
+
+ if(dnd_drag_perhaps && gdk_dnd.drag_really)
+ {
+ /* First, we have to find what window the motion was in... */
+ /* XXX there has to be a better way to do this, perhaps with
+ XTranslateCoordinates or XQueryTree - I don't know how,
+ and this sort of works */
+ Window curwin, childwin = gdk_root_window, rootwinret;
+ int x, y;
+ unsigned int mask;
+ while(childwin != None)
+ {
+ curwin = childwin;
+ XQueryPointer(gdk_display, curwin, &rootwinret, &childwin,
+ &x, &y, &x, &y, &mask);
+ }
+ if(curwin != dnd_drag_curwin)
+ {
+ /* We have left one window and entered another
+ (do leave & enter bits) */
+ if(dnd_drag_curwin != real_sw->xwindow && dnd_drag_curwin != None)
+ gdk_dnd_drag_leave(dnd_drag_curwin);
+ dnd_drag_curwin = curwin;
+ gdk_dnd_drag_enter(dnd_drag_curwin);
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
+ dnd_drag_target = None;
+ XChangeActivePointerGrab(gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragdefault,
+ CurrentTime);
+ }
+ else if(dnd_drag_dropzone.width > 0
+ && dnd_drag_dropzone.height > 0)
+ {
+ /* Handle all that dropzone stuff - thanks John ;-) */
+ if(dnd_drag_target != None
+ && IS_IN_ZONE(dnd_drag_oldpos.x, dnd_drag_oldpos.y)
+ && !IS_IN_ZONE(xevent->xmotion.x_root,
+ xevent->xmotion.y_root))
+ {
+ /* We were in the drop zone and moved out */
+ dnd_drag_target = None;
+ gdk_dnd_drag_leave(curwin);
+ }
+ else
+ {
+ /* We were outside drop zone but in the window
+ - have to send enter events */
+ gdk_dnd_drag_enter(curwin);
+ dnd_drag_curwin = curwin;
+ dnd_drag_dropzone.x = dnd_drag_dropzone.y = 0;
+ dnd_drag_target = None;
+ }
+ } else
+ dnd_drag_curwin = None;
+ return_val = FALSE;
+ }
+ else
+ return_val = window?(!window_private->destroyed):FALSE;
+ break;
+
+ case EnterNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("enter notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail,
+ xevent->xcrossing.subwindow - base_id);
+
+ /* Tell XInput stuff about it if appropriate */
+ if (window_private &&
+ (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;
+
+ /* 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;
+ }
+
+ if(dnd_drag_perhaps
+ && gdk_dnd.drag_really
+ && xevent->xcrossing.window == real_sw->xwindow)
+ {
+ gdk_dnd.drag_really = 0;
+ XUngrabPointer(gdk_display, CurrentTime);
+ }
+
+ return_val = (window ? !window_private->destroyed : FALSE);
+ break;
+
+ case LeaveNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("leave notify:\t\twindow: %ld detail: %d subwin: %ld\n",
+ xevent->xcrossing.window - base_id,
+ xevent->xcrossing.detail, xevent->xcrossing.subwindow - base_id);
+
+ event->crossing.type = GDK_LEAVE_NOTIFY;
+ event->crossing.window = window;
+
+ /* 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;
+ }
+ if(dnd_drag_perhaps
+ && !gdk_dnd.drag_really)
+ {
+ gdk_dnd_drag_addwindow((GdkWindow *) real_sw);
+ gdk_dnd_drag_begin((GdkWindow *) real_sw);
+ XGrabPointer(gdk_display, real_sw->xwindow, False,
+ ButtonMotionMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ GrabModeAsync, GrabModeAsync, gdk_root_window,
+ gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
+ gdk_dnd.drag_really = 1;
+ }
+ return_val = window ? (!window_private->destroyed) : FALSE;
+ break;
+
+ case FocusIn:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus in:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = TRUE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case FocusOut:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("focus out:\t\twindow: %ld\n",
+ xevent->xfocus.window - base_id);
+
+ event->focus_change.type = GDK_FOCUS_CHANGE;
+ event->focus_change.window = window;
+ event->focus_change.in = FALSE;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case KeymapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("keymap notify\n");
+
+ /* Not currently handled */
+ break;
+
+ case Expose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("expose:\t\twindow: %ld %d x,y: %d %d w,h: %d %d\n",
+ xevent->xexpose.window - base_id, xevent->xexpose.count,
+ xevent->xexpose.x, xevent->xexpose.y,
+ xevent->xexpose.width, xevent->xexpose.height);
+
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case GraphicsExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("graphics expose:\tdrawable: %ld\n",
+ xevent->xgraphicsexpose.drawable - base_id);
+
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case NoExpose:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("no expose:\t\tdrawable: %ld\n",
+ xevent->xnoexpose.drawable - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case VisibilityNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ switch (xevent->xvisibility.state)
+ {
+ case VisibilityFullyObscured:
+ g_print ("visibility notify:\twindow: %ld none\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityPartiallyObscured:
+ g_print ("visibility notify:\twindow: %ld partial\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ case VisibilityUnobscured:
+ g_print ("visibility notify:\twindow: %ld full\n",
+ xevent->xvisibility.window - base_id);
+ break;
+ }
+
+ /* Not currently handled */
+ break;
+
+ case CreateNotify:
+ /* Not currently handled */
+ break;
+
+ case DestroyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("destroy notify:\twindow: %ld\n",
+ xevent->xdestroywindow.window - base_id);
+
+ event->any.type = GDK_DESTROY;
+ event->any.window = window;
+
+ /* Remeber which window received the destroy notify
+ * event so that we can destroy our associated
+ * data structures the next time the user asks
+ * us for an event.
+ */
+ received_destroy_notify = TRUE;
+ window_to_destroy = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case UnmapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("unmap notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_UNMAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case MapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("map notify:\t\twindow: %ld\n",
+ xevent->xmap.window - base_id);
+
+ event->any.type = GDK_MAP;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case ReparentNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("reparent notify:\twindow: %ld\n",
+ xevent->xreparent.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ConfigureNotify:
+ /* Print debugging info.
+ */
+ while ((XPending(gdk_display) > 0) &&
+ XCheckTypedWindowEvent(gdk_display, xevent->xany.window,
+ ConfigureNotify, xevent))
+ /*XSync(gdk_display, 0)*/;
+
+ if (gdk_show_events)
+ g_print ("configure notify:\twindow: %ld x,y: %d %d w,h: %d %d\n",
+ xevent->xconfigure.window - base_id,
+ xevent->xconfigure.x, xevent->xconfigure.y,
+ xevent->xconfigure.width, xevent->xconfigure.height);
+
+ if (window_private &&
+ (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) &&
+ ((window_private->width != xevent->xconfigure.width) ||
+ (window_private->height != xevent->xconfigure.height)))
+ {
+ event->configure.type = GDK_CONFIGURE;
+ event->configure.window = window;
+ event->configure.x = xevent->xconfigure.x;
+ event->configure.y = xevent->xconfigure.y;
+ event->configure.width = xevent->xconfigure.width;
+ event->configure.height = xevent->xconfigure.height;
+
+ window_private->x = xevent->xconfigure.x;
+ window_private->y = xevent->xconfigure.y;
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+ if (window_private->resize_count > 1)
+ window_private->resize_count -= 1;
+
+ return_val = !window_private->destroyed;
+ }
+ break;
+
+ case PropertyNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("property notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ 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;
+
+ return_val = !window_private->destroyed;
+ break;
+
+ case SelectionClear:
+ if (gdk_show_events)
+ g_print ("selection clear:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ event->selection.type = GDK_SELECTION_CLEAR;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionclear.selection;
+ event->selection.time = xevent->xselectionclear.time;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionRequest:
+ if (gdk_show_events)
+ g_print ("selection request:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+ 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;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case SelectionNotify:
+ if (gdk_show_events)
+ g_print ("selection notify:\twindow: %ld\n",
+ xevent->xproperty.window - base_id);
+
+
+ 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;
+
+ return_val = !((GdkWindowPrivate*) window)->destroyed;
+ break;
+
+ case ColormapNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("colormap notify:\twindow: %ld\n",
+ xevent->xcolormap.window - base_id);
+
+ /* Not currently handled */
+ break;
+
+ case ClientMessage:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("client message:\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ /* Client messages are the means of the window manager
+ * communicating with a program. We'll first check to
+ * see if this is really the window manager talking
+ * to us.
+ */
+ if (xevent->xclient.message_type == gdk_wm_protocols)
+ {
+ 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.
+ */
+
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("delete window:\t\twindow: %ld\n",
+ xevent->xclient.window - base_id);
+
+ event->any.type = GDK_DELETE;
+ event->any.window = window;
+
+ return_val = !window_private->destroyed;
+ }
+ else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
+ {
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter)
+ {
+ Atom reptype = 0;
+
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ if (gdk_show_events)
+ g_print ("GDK_DROP_ENTER\n");
+ return_val = FALSE;
+
+ /* Now figure out if we really want this drop...
+ * If someone is trying funky clipboard stuff, ignore
+ */
+ if (window_private
+ && window_private->dnd_drop_enabled
+ && event->dropenter.u.flags.sendreply
+ && (reptype = gdk_dnd_check_types (window, xevent)))
+ {
+ XEvent replyev;
+
+ replyev.xclient.type = ClientMessage;
+ replyev.xclient.window = xevent->xclient.data.l[0];
+ replyev.xclient.format = 32;
+ replyev.xclient.message_type = gdk_dnd.gdk_XdeRequest;
+ replyev.xclient.data.l[0] = window_private->xwindow;
+
+ event->dragrequest.u.allflags = 0;
+ event->dragrequest.u.flags.protocol_version =
+ DND_PROTOCOL_VERSION;
+ event->dragrequest.u.flags.willaccept = 1;
+ event->dragrequest.u.flags.delete_data =
+ (window_private->dnd_drop_destructive_op) ? 1 : 0;
+
+ replyev.xclient.data.l[1] = event->dragrequest.u.allflags;
+ replyev.xclient.data.l[2] = replyev.xclient.data.l[3] = 0;
+ replyev.xclient.data.l[4] = reptype;
+
+ XSendEvent (gdk_display, replyev.xclient.window,
+ False, NoEventMask, &replyev);
+
+ event->any.type = GDK_DROP_ENTER;
+ event->dropenter.requestor = replyev.xclient.window;
+ event->dropenter.u.allflags = xevent->xclient.data.l[1];
+ }
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeLeave)
+ {
+ if (gdk_show_events)
+ g_print ("GDK_DROP_LEAVE\n");
+ if (window_private && window_private->dnd_drop_enabled)
+ {
+ event->dropleave.type = GDK_DROP_LEAVE;
+ event->dropleave.window = window;
+ event->dropleave.requestor = xevent->xclient.data.l[0];
+ event->dropleave.u.allflags = xevent->xclient.data.l[1];
+ return_val = TRUE;
+ }
+ else
+ return_val = FALSE;
+ }
+ else if (xevent->xclient.message_type == gdk_dnd.gdk_XdeRequest)
+ {
+ /*
+ * make sure to only handle requests from the window the cursor is
+ * over
+ */
+ if (gdk_show_events)
+ g_print ("GDK_DRAG_REQUEST\n");
+ event->dragrequest.u.allflags = xevent->xclient.data.l[1];
+ return_val = FALSE;
+
+ if (window && gdk_dnd.drag_really &&
+ xevent->xclient.data.l[0] == dnd_drag_curwin &&
+ event->dragrequest.u.flags.sendreply == 0)
+ {
+ /* Got request - do we need to ask user? */
+ if (!event->dragrequest.u.flags.willaccept
+ && event->dragrequest.u.flags.senddata)
+ {
+ /* Yes we do :) */
+ event->dragrequest.type = GDK_DRAG_REQUEST;
+ event->dragrequest.window = window;
+ event->dragrequest.requestor = xevent->xclient.data.l[0];
+ event->dragrequest.isdrop = 0;
+ event->dragrequest.drop_coords.x =
+ event->dragrequest.drop_coords.y = 0;
+ return_val = TRUE;
+ }
+ else if (event->dragrequest.u.flags.willaccept)
+ {
+ window_private->dnd_drag_destructive_op =
+ event->dragrequest.u.flags.delete_data;
+ window_private->dnd_drag_accepted = 1;
+ window_private->dnd_drag_data_type =
+ xevent->xclient.data.l[4];
+
+ dnd_drag_target = dnd_drag_curwin;
+ XChangeActivePointerGrab (gdk_display,
+ ButtonMotionMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask,
+ gdk_dnd.gdk_cursor_dragok,
+ CurrentTime);
+ }
+ dnd_drag_dropzone.x = xevent->xclient.data.l[2] & 65535;
+ dnd_drag_dropzone.y =
+ (xevent->xclient.data.l[2] >> 16) & 65535;
+ dnd_drag_dropzone.width = xevent->xclient.data.l[3] & 65535;
+ dnd_drag_dropzone.height =
+ (xevent->xclient.data.l[3] >> 16) & 65535;
+ }
+ }
+ else if(xevent->xclient.message_type == gdk_dnd.gdk_XdeDataAvailable)
+ {
+ gint tmp_int; Atom tmp_atom;
+ gulong tmp_long;
+ guchar *tmp_charptr;
+ gpointer tmp_ptr;
+
+ if(gdk_show_events)
+ g_print("GDK_DROP_DATA_AVAIL\n");
+ event->dropdataavailable.u.allflags = xevent->xclient.data.l[1];
+ if(window
+ /* No preview of data ATM */
+ && event->dropdataavailable.u.flags.isdrop)
+ {
+ event->dropdataavailable.type = GDK_DROP_DATA_AVAIL;
+ event->dropdataavailable.window = window;
+ event->dropdataavailable.requestor = xevent->xclient.data.l[0];
+ event->dropdataavailable.data_type =
+ gdk_atom_name(xevent->xclient.data.l[2]);
+ if(XGetWindowProperty (gdk_display,
+ event->dropdataavailable.requestor,
+ xevent->xclient.data.l[2],
+ 0, LONG_MAX - 1,
+ False, XA_PRIMARY, &tmp_atom,
+ &tmp_int,
+ &event->dropdataavailable.data_numbytes,
+ &tmp_long,
+ &tmp_charptr)
+ != Success)
+ {
+ g_warning("XGetWindowProperty on %#x may have failed\n",
+ event->dropdataavailable.requestor);
+ event->dropdataavailable.data = NULL;
+ }
+ else
+ {
+ g_print("XGetWindowProperty got us %d bytes\n",
+ event->dropdataavailable.data_numbytes);
+ event->dropdataavailable.data =
+ g_malloc(event->dropdataavailable.data_numbytes);
+ memcpy(event->dropdataavailable.data,
+ tmp_charptr, event->dropdataavailable.data_numbytes);
+ XFree(tmp_charptr);
+ return_val = TRUE;
+ }
+ return_val = TRUE;
+ }
+ } else {
+ /* 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));
+ return_val = TRUE;
+ }
+ return_val = return_val && !window_private->destroyed;
+ break;
+
+ case MappingNotify:
+ /* Print debugging info.
+ */
+ if (gdk_show_events)
+ g_print ("mapping notify\n");
+
+ /* Let XLib know that there is a new keyboard mapping.
+ */
+ XRefreshKeyboardMapping (&xevent->xmapping);
+ break;
+
+ default:
+ /* something else - (e.g., a Xinput event) */
+
+ if (window_private &&
+ (window_private->extension_events != 0) &&
+ gdk_input_vtable.other_event)
+ return_val = gdk_input_vtable.other_event(event, xevent, window);
+
+ if (return_val < 0) /* not an XInput event, convert */
+ {
+ event->other.type = GDK_OTHER_EVENT;
+ event->other.window = window;
+ event->other.xevent = &other_xevent[other_xevent_i];
+ memcpy (&other_xevent[other_xevent_i], xevent, sizeof (XEvent));
+ other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
+ return_val = TRUE;
+ }
+
+ return_val = return_val && !window_private->destroyed;
+ break;
+ }
+
+ return return_val;
+}
+
+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;
+}
+
+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);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_exit_func
+ *
+ * This is the "atexit" function that makes sure the
+ * library gets a chance to cleanup.
+ *
+ * Arguments:
+ *
+ * Results:
+ *
+ * Side effects:
+ * The library is un-initialized and the program exits.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+gdk_exit_func ()
+{
+ if (initialized)
+ {
+ gdk_image_exit ();
+ gdk_input_exit ();
+ gdk_key_repeat_restore ();
+
+ XCloseDisplay (gdk_display);
+ initialized = 0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_error
+ *
+ * The X error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ * "error" is the XErrorEvent that we are handling.
+ *
+ * Results:
+ * Either we were expecting some sort of error to occur,
+ * in which case we set the "gdk_error_code" flag, or this
+ * error was unexpected, in which case we will print an
+ * error message and exit. (Since trying to continue will
+ * most likely simply lead to more errors).
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_error (Display *display,
+ XErrorEvent *error)
+{
+ char buf[64];
+
+ if (gdk_error_warnings)
+ {
+ XGetErrorText (display, error->error_code, buf, 63);
+ g_error ("%s", buf);
+ }
+
+ gdk_error_code = -1;
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_x_io_error
+ *
+ * The X I/O error handling routine.
+ *
+ * Arguments:
+ * "display" is the X display the error orignated from.
+ *
+ * Results:
+ * An X I/O error basically means we lost our connection
+ * to the X server. There is not much we can do to
+ * continue, so simply print an error message and exit.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+gdk_x_io_error (Display *display)
+{
+ g_error ("an x io error occurred");
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_signal
+ *
+ * The signal handler.
+ *
+ * Arguments:
+ * "sig_num" is the number of the signal we received.
+ *
+ * Results:
+ * The signals we catch are all fatal. So we simply build
+ * up a nice little error message and print it and exit.
+ * If in the process of doing so another signal is received
+ * we notice that we are already exiting and simply kill
+ * our process.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static RETSIGTYPE
+gdk_signal (int sig_num)
+{
+ static int caught_fatal_sig = 0;
+ char *sig;
+
+ if (caught_fatal_sig)
+ kill (getpid (), sig_num);
+ caught_fatal_sig = 1;
+
+ switch (sig_num)
+ {
+ case SIGHUP:
+ sig = "sighup";
+ break;
+ case SIGINT:
+ sig = "sigint";
+ break;
+ case SIGQUIT:
+ sig = "sigquit";
+ break;
+ case SIGBUS:
+ sig = "sigbus";
+ break;
+ case SIGSEGV:
+ sig = "sigsegv";
+ break;
+ case SIGPIPE:
+ sig = "sigpipe";
+ break;
+ case SIGTERM:
+ sig = "sigterm";
+ break;
+ default:
+ sig = "unknown signal";
+ break;
+ }
+
+ g_print ("\n** ERROR **: %s caught\n", sig);
+ gdk_exit (1);
+}
+
+static void
+gdk_dnd_drag_begin (GdkWindow *initial_window)
+{
+ GdkEventDragBegin tev;
+ tev.type = GDK_DRAG_BEGIN;
+ tev.window = initial_window;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+
+ gdk_event_put ((GdkEvent *) &tev);
+}
+
+static void
+gdk_dnd_drag_enter (Window dest)
+{
+ XEvent sev;
+ GdkEventDropEnter tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeEnter;
+ sev.xclient.window = dest;
+
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.u.flags.sendreply = 1;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_data_numtypesavail)
+ {
+ sev.xclient.data.l[0] = wp->xwindow;
+ tev.u.flags.extended_typelist = (wp->dnd_drag_data_numtypesavail > 3)?1:0;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ sev.xclient.data.l[2] = wp->dnd_drag_data_typesavail[0];
+ if (wp->dnd_drag_data_numtypesavail > 1)
+ {
+ sev.xclient.data.l[3] = wp->dnd_drag_data_typesavail[1];
+ if (wp->dnd_drag_data_numtypesavail > 2)
+ {
+ sev.xclient.data.l[4] = wp->dnd_drag_data_typesavail[2];
+ }
+ else
+ sev.xclient.data.l[4] = None;
+ }
+ else
+ sev.xclient.data.l[3] = sev.xclient.data.l[4] = None;
+ XSendEvent (gdk_display, dest, False, NoEventMask, &sev);
+ }
+
+ }
+}
+
+static void
+gdk_dnd_drag_leave (Window dest)
+{
+ XEvent sev;
+ GdkEventDropLeave tev;
+ int i;
+ GdkWindowPrivate *wp;
+
+ tev.u.allflags = 0;
+
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ sev.xclient.type = ClientMessage;
+ sev.xclient.window = dest;
+ sev.xclient.format = 32;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeLeave;
+ sev.xclient.data.l[1] = tev.u.allflags;
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ sev.xclient.data.l[0] = wp->xwindow;
+ XSendEvent(gdk_display, dest, False, NoEventMask, &sev);
+ wp->dnd_drag_accepted = 0;
+ }
+}
+
+/*
+ * when a drop occurs, we go through the list of windows being dragged and
+ * tell them that it has occurred, so that they can set things up and reply
+ * to 'dest' window
+ */
+static void
+gdk_dnd_drag_end (Window dest,
+ GdkPoint coords)
+{
+ GdkWindowPrivate *wp;
+ GdkEventDragRequest tev;
+ gchar *tmp_cptr;
+ int i;
+
+ tev.type = GDK_DRAG_REQUEST;
+ tev.drop_coords = coords;
+ tev.requestor = dest;
+ tev.u.allflags = 0;
+ tev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tev.isdrop = 1;
+
+ for (i = 0; i < gdk_dnd.drag_numwindows; i++)
+ {
+ wp = (GdkWindowPrivate *) gdk_dnd.drag_startwindows[i];
+ if (wp->dnd_drag_accepted)
+ {
+ tev.window = (GdkWindow *) wp;
+ tev.u.flags.delete_data = wp->dnd_drag_destructive_op;
+ tev.data_type =
+ gdk_atom_name(wp->dnd_drag_data_type);
+
+ gdk_event_put((GdkEvent *) &tev);
+ }
+ }
+}
+
+static GdkAtom
+gdk_dnd_check_types (GdkWindow *window,
+ XEvent *xevent)
+{
+ GdkWindowPrivate *wp = (GdkWindowPrivate *) window;
+ int i, j;
+ GdkEventDropEnter event;
+
+ g_return_val_if_fail(window != NULL, 0);
+ g_return_val_if_fail(xevent != NULL, 0);
+ g_return_val_if_fail(xevent->type == ClientMessage, 0);
+ g_return_val_if_fail(xevent->xclient.message_type == gdk_dnd.gdk_XdeEnter, 0);
+
+ if(wp->dnd_drop_data_numtypesavail <= 0 ||
+ !wp->dnd_drop_data_typesavail)
+ return 0;
+
+ for (i = 2; i <= 4; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (xevent->xclient.data.l[i] == wp->dnd_drop_data_typesavail[j])
+ return xevent->xclient.data.l[i];
+ }
+ }
+
+ /* Now we get the extended type list if it's available */
+ event.u.allflags = xevent->xclient.data.l[1];
+ if (event.u.flags.extended_typelist)
+ {
+ Atom *exttypes, realtype;
+ gulong nitems, nbar;
+ gint realfmt;
+
+ if (XGetWindowProperty(gdk_display, xevent->xclient.data.l[0],
+ gdk_dnd.gdk_XdeTypelist, 0L, LONG_MAX - 1,
+ False, AnyPropertyType, &realtype, &realfmt,
+ &nitems, &nbar, (unsigned char **) &exttypes)
+ != Success)
+ return 0;
+
+ if (realfmt != (sizeof(Atom) * 8))
+ {
+ g_warning("XdeTypelist property had format of %d instead of the expected %d, on window %#lx\n",
+ realfmt, sizeof(Atom) * 8, xevent->xclient.data.l[0]);
+ return 0;
+ }
+
+ for (i = 0; i <= nitems; i++)
+ {
+ for (j = 0; j < wp->dnd_drop_data_numtypesavail; j++)
+ {
+ if (exttypes[i] == wp->dnd_drop_data_typesavail[j])
+ {
+ XFree (exttypes);
+ return exttypes[i];
+ }
+ }
+ }
+ XFree (exttypes);
+ }
+ return 0;
+}
+
+/*
+ * used for debugging only
+ */
+static void
+gdk_print_atom (GdkAtom anatom)
+{
+ gchar *tmpstr = NULL;
+ tmpstr = (anatom!=None)?gdk_atom_name(anatom):"(none)";
+ g_print("Atom %lu has name %s\n", anatom, tmpstr);
+ if(tmpstr)
+ g_free(tmpstr);
+}
+
+/*
+ * used only by below routine and itself
+ */
+static Window
+getchildren (Display *dpy,
+ Window win,
+ Atom WM_STATE)
+{
+ Window root, parent, *children, inf = 0;
+ Atom type = None;
+ unsigned int nchildren, i;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+
+ if (XQueryTree(dpy, win, &root, &parent, &children, &nchildren) == 0)
+ return 0;
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ {
+ XGetWindowProperty (dpy, children[i], WM_STATE, 0, 0, False,
+ AnyPropertyType, &type, &format, &nitems,
+ &after, &data);
+ if (type != 0)
+ inf = children[i];
+ }
+
+ for (i = 0; !inf && (i < nchildren); i++)
+ inf = getchildren (dpy, children[i], WM_STATE);
+
+ if (children != 0)
+ XFree ((char *) children);
+
+ return inf;
+}
+
+/*
+ * find a window with WM_STATE, else return win itself, as per ICCCM
+ *
+ * modification of the XmuClientWindow() routine from X11R6.3
+ */
+Window
+gdk_get_client_window (Display *dpy,
+ Window win)
+{
+ Atom WM_STATE;
+ Atom type = None;
+ int format;
+ unsigned long nitems, after;
+ unsigned char *data;
+ Window inf;
+
+ if (win == 0)
+ return DefaultRootWindow(dpy);
+
+ if ((WM_STATE = XInternAtom (dpy, "WM_STATE", True)) == 0)
+ return win;
+
+ XGetWindowProperty (dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &data);
+ if (type)
+ return win;
+
+ inf = getchildren (dpy, win, WM_STATE);
+
+ if (inf == 0)
+ return win;
+ else
+ return inf;
+}
+
+static GdkWindow *
+gdk_drop_get_real_window (GdkWindow *w,
+ guint16 *x,
+ guint16 *y)
+{
+ GdkWindow *retval = w;
+ GdkWindowPrivate *awin;
+ GList *children;
+ gint16 myx = *x, myy = *y;
+
+ g_return_val_if_fail(w != NULL && x != NULL && y != NULL, NULL);
+
+ myx = *x;
+ myy = *y;
+
+descend:
+ for (children = gdk_window_get_children(retval);
+ children && children->next;
+ children = children->next)
+ {
+ awin = (GdkWindowPrivate *) children->data;
+ if ((myx >= awin->x) && (myy >= awin->y)
+ && (myx < (awin->x + awin->width))
+ && (myy < (awin->y + awin->height)))
+ {
+ retval = (GdkWindow *) awin;
+ myx -= awin->x;
+ myy -= awin->y;
+ goto descend;
+ }
+ }
+
+ *x = myx;
+ *y = myy;
+
+ return retval;
+}
+
+/* Sends a ClientMessage to all toplevel client windows */
+void
+gdk_event_send_clientmessage_toall(GdkEvent *event)
+{
+ XEvent sev;
+ Window *ret_children, ret_root, ret_parent, curwin;
+ unsigned int ret_nchildren;
+ int i;
+
+ 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;
+ sev.xclient.serial = CurrentTime;
+ memcpy(&sev.xclient.data, &event->client.data, sizeof(sev.xclient.data));
+ sev.xclient.message_type = event->client.message_type;
+
+ /* OK, we're all set, now let's find some windows to send this to */
+ if(XQueryTree(gdk_display, gdk_root_window, &ret_root, &ret_parent,
+ &ret_children, &ret_nchildren) != True)
+ return;
+
+ /* foreach true child window of the root window, send an event to it */
+ for(i = 0; i < ret_nchildren; i++) {
+ curwin = gdk_get_client_window(gdk_display, ret_children[i]);
+ sev.xclient.window = curwin;
+ XSendEvent(gdk_display, curwin, False, NoEventMask, &sev);
+ }
+
+ XFree(ret_children);
+}
diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c
new file mode 100644
index 000000000..d2d96b6da
--- /dev/null
+++ b/gdk/x11/gdkpixmap-x11.c
@@ -0,0 +1,657 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "../config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+
+#include "gdk.h"
+#include "gdkprivate.h"
+
+typedef struct
+{
+ gchar *color_string;
+ GdkColor color;
+ gint transparent;
+} _GdkPixmapColor;
+
+GdkPixmap*
+gdk_pixmap_new (GdkWindow *window,
+ gint width,
+ gint height,
+ gint depth)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->xwindow = XCreatePixmap (private->xdisplay, window_private->xwindow,
+ width, height, depth);
+ private->parent = NULL;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = 0;
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreateBitmapFromData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkWindow *window,
+ gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ GdkColor *fg,
+ GdkColor *bg)
+{
+ GdkPixmap *pixmap;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (fg != NULL, NULL);
+ g_return_val_if_fail (bg != NULL, NULL);
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ if (depth == -1)
+ gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
+
+ private = g_new (GdkWindowPrivate, 1);
+ pixmap = (GdkPixmap*) private;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ private->parent = NULL;
+ private->xdisplay = window_private->xdisplay;
+ private->window_type = GDK_WINDOW_PIXMAP;
+ private->x = 0;
+ private->y = 0;
+ private->width = width;
+ private->height = height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ private->destroyed = FALSE;
+
+ private->xwindow = XCreatePixmapFromBitmapData (private->xdisplay,
+ window_private->xwindow,
+ data, width, height,
+ fg->pixel, bg->pixel, depth);
+
+ gdk_xid_table_insert (&private->xwindow, pixmap);
+
+ return pixmap;
+}
+
+gint
+gdk_pixmap_seek_string (FILE *infile,
+ const gchar *str,
+ gint skip_comments)
+{
+ char instr[1024];
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%s", instr);
+ if (skip_comments == TRUE && strcmp (instr, "/*") == 0)
+ {
+ fscanf (infile, "%s", instr);
+ while (!feof (infile) && strcmp (instr, "*/") != 0)
+ fscanf (infile, "%s", instr);
+ fscanf(infile, "%s", instr);
+ }
+ if (strcmp (instr, str)==0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_seek_char (FILE *infile,
+ gchar c)
+{
+ gchar b, oldb;
+
+ while (!feof (infile))
+ {
+ fscanf(infile, "%c", &b);
+ if (c != b && b == '/')
+ {
+ fscanf (infile, "%c", &b);
+ if (b == '*')
+ {
+ oldb = b;
+ while (!feof (infile) && !(oldb == '*' && b == '/'))
+ {
+ oldb = b;
+ fscanf (infile, "%c", &b);
+ }
+ fscanf (infile, "%c", &b);
+ }
+ }
+ if (c == b)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gint
+gdk_pixmap_read_string (FILE *infile,
+ gchar **buffer,
+ int *buffer_size)
+{
+ gchar c;
+ gint cnt = 0;
+
+ if ((*buffer) == NULL)
+ {
+ (*buffer_size) = 10 * sizeof (gchar);
+ (*buffer) = (gchar *) malloc (*buffer_size);
+ }
+
+ do
+ fscanf (infile, "%c", &c);
+ while (!feof (infile) && c != '"');
+
+ if (c != '"')
+ return FALSE;
+
+ while (!feof (infile))
+ {
+ fscanf (infile, "%c", &c);
+
+ if (cnt == (*buffer_size))
+ {
+ (*buffer_size) *= 2;
+ (*buffer) = (gchar *) realloc ((*buffer), *buffer_size);
+ }
+
+ if (c != '"')
+ (*buffer)[cnt++] = c;
+ else
+ {
+ (*buffer)[cnt++] = 0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+gchar*
+gdk_pixmap_skip_whitespaces (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && (buffer[index] == 0x20 || buffer[index] == 0x09))
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_skip_string (gchar *buffer)
+{
+ gint32 index = 0;
+
+ while (buffer[index] != 0 && buffer[index] != 0x20 && buffer[index] != 0x09)
+ index++;
+
+ return &buffer[index];
+}
+
+gchar*
+gdk_pixmap_extract_color (gchar *buffer)
+{
+ gint counter, finished = FALSE, numnames;
+ gchar *ptr = NULL, ch, temp[128];
+ gchar color[128], *retcol;
+
+ counter = 0;
+ while (ptr == NULL)
+ {
+ if (buffer[counter] == 'c')
+ {
+ ch = buffer[counter + 1];
+ if (ch == 0x20 || ch == 0x09)
+ ptr = &buffer[counter + 1];
+ }
+ else if (buffer[counter] == 0)
+ return NULL;
+
+ counter++;
+ }
+
+ if (ptr == NULL)
+ return NULL;
+
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+
+ if (ptr[0] == 0)
+ return NULL;
+ else if (ptr[0] == '#')
+ {
+ retcol = g_new(gchar, strlen (ptr) + 1);
+ strcpy (retcol, ptr);
+ return retcol;
+ }
+
+ color[0] = 0;
+ numnames = 0;
+
+ while (finished == FALSE)
+ {
+ sscanf (ptr, "%s", temp);
+
+ if ((gint)ptr[0] == 0 || strcmp ("s", temp) == 0 || strcmp ("m", temp) == 0 ||
+ strcmp ("g", temp) == 0 || strcmp ("g4", temp) == 0)
+ finished = TRUE;
+ else
+ {
+ if (numnames > 0)
+ strcat (color, " ");
+ strcat (color, temp);
+ ptr = gdk_pixmap_skip_string (ptr);
+ ptr = gdk_pixmap_skip_whitespaces (ptr);
+ numnames++;
+ }
+ }
+
+ retcol = g_new(gchar, strlen (color) + 1);
+ strcpy (retcol, color);
+ return retcol;
+}
+
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ const gchar *filename)
+{
+ FILE *infile = NULL;
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt;
+ gchar *buffer = NULL, *color_name = NULL, pixel_str[32];
+ guint buffer_size = 0;
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ infile = fopen (filename, "rb");
+ if (infile != NULL)
+ {
+ if (gdk_pixmap_seek_string (infile, "XPM", FALSE) == TRUE)
+ {
+ if (gdk_pixmap_seek_char (infile,'{') == TRUE)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ gdk_pixmap_seek_char (infile, '"');
+ fseek (infile, -1, SEEK_CUR);
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ gdk_pixmap_read_string (infile, &buffer, &buffer_size);
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+ }
+ }
+
+ fclose (infile);
+ free (buffer);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+ }
+
+ return pixmap;
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_xpm_d (GdkWindow *window,
+ GdkBitmap **mask,
+ GdkColor *transparent_color,
+ gchar **data)
+{
+ GdkPixmap *pixmap = NULL;
+ GdkImage *image = NULL;
+ GdkColormap *colormap;
+ GdkVisual *visual;
+ GdkGC *gc;
+ GdkColor tmp_color;
+ gint width, height, num_cols, cpp, cnt, n, ns, xcnt, ycnt, i;
+ gchar *buffer, *color_name = NULL, pixel_str[32];
+ _GdkPixmapColor *colors = NULL, *color = NULL;
+ gulong index;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ i = 0;
+ buffer = data[i++];
+ sscanf (buffer,"%d %d %d %d", &width, &height, &num_cols, &cpp);
+
+ colors = g_new(_GdkPixmapColor, num_cols);
+
+ colormap = gdk_window_get_colormap (window);
+ visual = gdk_window_get_visual (window);
+
+ if (transparent_color == NULL)
+ {
+ gdk_color_white (colormap, &tmp_color);
+ transparent_color = &tmp_color;
+ }
+
+ for (cnt = 0; cnt < num_cols; cnt++)
+ {
+ buffer = data[i++];
+
+ colors[cnt].color_string = g_new(gchar, cpp + 1);
+ for (n = 0; n < cpp; n++)
+ colors[cnt].color_string[n] = buffer[n];
+ colors[cnt].color_string[n] = 0;
+ colors[cnt].transparent = FALSE;
+
+ if (color_name != NULL)
+ g_free (color_name);
+
+ color_name = gdk_pixmap_extract_color (&buffer[cpp]);
+
+ if (color_name != NULL)
+ {
+ if (gdk_color_parse (color_name, &colors[cnt].color) == FALSE)
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+ }
+ else
+ {
+ colors[cnt].color = *transparent_color;
+ colors[cnt].transparent = TRUE;
+ }
+
+ gdk_color_alloc (colormap, &colors[cnt].color);
+ }
+
+ index = 0;
+ image = gdk_image_new (GDK_IMAGE_FASTEST, visual, width, height);
+
+ gc = NULL;
+ if (mask)
+ {
+ *mask = gdk_pixmap_new (window, width, height, 1);
+ gc = gdk_gc_new (*mask);
+
+ gdk_color_black (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ gdk_draw_rectangle (*mask, gc, TRUE, 0, 0, -1, -1);
+
+ gdk_color_white (colormap, &tmp_color);
+ gdk_gc_set_foreground (gc, &tmp_color);
+ }
+
+ for (ycnt = 0; ycnt < height; ycnt++)
+ {
+ buffer = data[i++];
+
+ for (n = 0, cnt = 0, xcnt = 0; n < (width * cpp); n += cpp, xcnt++)
+ {
+ strncpy (pixel_str, &buffer[n], cpp);
+ pixel_str[cpp] = 0;
+ color = NULL;
+ ns = 0;
+
+ while (color == NULL)
+ {
+ if (strcmp (pixel_str, colors[ns].color_string) == 0)
+ color = &colors[ns];
+ else
+ ns++;
+ }
+
+ gdk_image_put_pixel (image, xcnt, ycnt, color->color.pixel);
+
+ if (mask && color->transparent)
+ {
+ if (cnt < xcnt)
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ cnt = xcnt + 1;
+ }
+ }
+
+ if (mask && (cnt < xcnt))
+ gdk_draw_line (*mask, gc, cnt, ycnt, xcnt - 1, ycnt);
+ }
+
+ if (mask)
+ gdk_gc_destroy (gc);
+
+ pixmap = gdk_pixmap_new (window, width, height, visual->depth);
+
+ gc = gdk_gc_new (pixmap);
+ gdk_gc_set_foreground (gc, transparent_color);
+ gdk_draw_image (pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
+ gdk_gc_destroy (gc);
+ gdk_image_destroy (image);
+
+ if (colors != NULL)
+ {
+ for (cnt = 0; cnt < num_cols; cnt++)
+ g_free (colors[cnt].color_string);
+ g_free (colors);
+ }
+
+ return pixmap;
+}
+
+void
+gdk_pixmap_destroy (GdkPixmap *pixmap)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (pixmap != NULL);
+
+ private = (GdkPixmapPrivate*) pixmap;
+ if (private->ref_count <= 0)
+ {
+ XFreePixmap (private->xdisplay, private->xwindow);
+ gdk_xid_table_remove (private->xwindow);
+ g_free (pixmap);
+ }
+ else
+ {
+ private->ref_count -= 1;
+ }
+}
diff --git a/gdk/x11/gdkproperty-x11.c b/gdk/x11/gdkproperty-x11.c
new file mode 100644
index 000000000..35d8a50cf
--- /dev/null
+++ b/gdk/x11/gdkproperty-x11.c
@@ -0,0 +1,194 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+GdkAtom
+gdk_atom_intern (const gchar *atom_name,
+ gint only_if_exists)
+{
+ return XInternAtom (gdk_display, atom_name, only_if_exists);
+}
+
+gchar *
+gdk_atom_name (GdkAtom atom)
+{
+ gchar *t;
+ gchar *name;
+
+ /* If this atom doesn't exist, we'll die with an X error unless
+ we take precautions */
+
+ gdk_error_warnings = 0;
+ t = XGetAtomName (gdk_display, atom);
+ gdk_error_warnings = 1;
+
+ if (gdk_error_code == -1)
+ {
+ return NULL;
+ }
+ else
+ {
+ name = g_strdup (t);
+ XFree (t);
+
+ return name;
+ }
+}
+
+gint
+gdk_property_get (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gulong offset,
+ gulong length,
+ gint pdelete,
+ GdkAtom *actual_property_type,
+ gint *actual_format_type,
+ gint *actual_length,
+ guchar **data)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+ Atom ret_prop_type;
+ gint ret_format;
+ gulong ret_nitems;
+ gulong ret_bytes_after;
+ gulong ret_length;
+ guchar *ret_data;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XGetWindowProperty (xdisplay, xwindow, property,
+ offset, (length + 3) / 4, pdelete,
+ type, &ret_prop_type, &ret_format,
+ &ret_nitems, &ret_bytes_after,
+ &ret_data);
+
+ if ((ret_prop_type == None) && (ret_format == 0))
+ return FALSE;
+
+ if (actual_property_type)
+ *actual_property_type = ret_prop_type;
+ if (actual_format_type)
+ *actual_format_type = ret_format;
+
+ if (ret_prop_type != property)
+ {
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ /* FIXME: ignoring bytes_after could have very bad effects */
+
+ if (data)
+ {
+ switch (ret_format)
+ {
+ case 8:
+ ret_length = ret_nitems;
+ break;
+ case 16:
+ ret_length = 2 * ret_nitems;
+ break;
+ case 32:
+ ret_length = 4 * ret_nitems;
+ break;
+ default:
+ g_warning ("unknown property return format: %d", ret_format);
+ XFree (ret_data);
+ return FALSE;
+ }
+
+ *data = g_new (guchar, ret_length);
+ memcpy (*data, ret_data, ret_length);
+ if (actual_length)
+ *actual_length = ret_length;
+ }
+
+ XFree (ret_data);
+
+ return TRUE;
+}
+
+void
+gdk_property_change (GdkWindow *window,
+ GdkAtom property,
+ GdkAtom type,
+ gint format,
+ GdkPropMode mode,
+ guchar *data,
+ gint nelements)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XChangeProperty (xdisplay, xwindow, property, type,
+ format, mode, data, nelements);
+}
+
+void
+gdk_property_delete (GdkWindow *window,
+ GdkAtom property)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (window)
+ {
+ private = (GdkWindowPrivate*) window;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = gdk_root_window;
+ }
+
+ XDeleteProperty (xdisplay, xwindow, property);
+}
diff --git a/gdk/x11/gdkselection-x11.c b/gdk/x11/gdkselection-x11.c
new file mode 100644
index 000000000..6bd425110
--- /dev/null
+++ b/gdk/x11/gdkselection-x11.c
@@ -0,0 +1,168 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+gint
+gdk_selection_owner_set (GdkWindow *owner,
+ GdkAtom selection,
+ guint32 time,
+ gint send_event)
+{
+ GdkWindowPrivate *private;
+ Display *xdisplay;
+ Window xwindow;
+
+ if (owner)
+ {
+ private = (GdkWindowPrivate*) owner;
+ xdisplay = private->xdisplay;
+ xwindow = private->xwindow;
+ }
+ else
+ {
+ xdisplay = gdk_display;
+ xwindow = None;
+ }
+
+ XSetSelectionOwner (xdisplay, selection, xwindow, time);
+
+ return (XGetSelectionOwner (xdisplay, selection) == xwindow);
+}
+
+GdkWindow*
+gdk_selection_owner_get (GdkAtom selection)
+{
+ Window xwindow;
+
+ xwindow = XGetSelectionOwner (gdk_display, selection);
+ if (xwindow == None)
+ return NULL;
+
+ return gdk_window_lookup (xwindow);
+}
+
+void
+gdk_selection_convert (GdkWindow *requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (requestor != NULL);
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XConvertSelection (private->xdisplay, selection, target,
+ gdk_selection_property, private->xwindow, time);
+}
+
+gint
+gdk_selection_property_get (GdkWindow *requestor,
+ guchar **data,
+ GdkAtom *ret_type,
+ gint *ret_format)
+{
+ GdkWindowPrivate *private;
+ gulong nitems;
+ gulong nbytes;
+ gulong length;
+ GdkAtom prop_type;
+ gint prop_format;
+ guchar *t;
+
+ g_return_val_if_fail (requestor != NULL, 0);
+
+ /* If retrieved chunks are typically small, (and the ICCM says the
+ should be) it would be a win to try first with a buffer of
+ moderate length, to avoid two round trips to the server */
+
+ private = (GdkWindowPrivate*) requestor;
+
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, 0, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (ret_type)
+ *ret_type = prop_type;
+ if (ret_format)
+ *ret_format = prop_format;
+
+ if (prop_type == None)
+ {
+ *data = NULL;
+ return 0;
+ }
+
+ XFree (t);
+
+ /* Add on an extra byte to handle null termination. X guarantees
+ that t will be 1 longer than nbytes and null terminated */
+ length = nbytes + 1;
+
+ /* We can't delete the selection here, because it might be the INCR
+ protocol, in which case the client has to make sure they'll be
+ notified of PropertyChange events _before_ the property is deleted.
+ Otherwise there's no guarantee we'll win the race ... */
+ XGetWindowProperty (private->xdisplay, private->xwindow,
+ gdk_selection_property, 0, (nbytes + 3) / 4, False,
+ AnyPropertyType, &prop_type, &prop_format,
+ &nitems, &nbytes, &t);
+
+ if (prop_type != None)
+ {
+ *data = g_new (guchar, length);
+ memcpy (*data, t, length);
+ XFree (t);
+ return length-1;
+ }
+ else
+ {
+ *data = NULL;
+ return 0;
+ }
+}
+
+
+void
+gdk_selection_send_notify (guint32 requestor,
+ GdkAtom selection,
+ GdkAtom target,
+ GdkAtom property,
+ guint32 time)
+{
+ XSelectionEvent xevent;
+
+ xevent.type = SelectionNotify;
+ xevent.serial = 0;
+ xevent.send_event = True;
+ xevent.display = gdk_display;
+ xevent.requestor = requestor;
+ xevent.selection = selection;
+ xevent.target = target;
+ xevent.property = property;
+ xevent.time = time;
+
+ XSendEvent (gdk_display, requestor, False, NoEventMask, (XEvent*) &xevent);
+}
diff --git a/gdk/x11/gdkvisual-x11.c b/gdk/x11/gdkvisual-x11.c
new file mode 100644
index 000000000..22acee6f1
--- /dev/null
+++ b/gdk/x11/gdkvisual-x11.c
@@ -0,0 +1,431 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "gdk.h"
+#include "gdkprivate.h"
+
+
+static void gdk_visual_add (GdkVisual *visual);
+static void gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec);
+static guint gdk_visual_hash (Visual *key);
+static gint gdk_visual_compare (Visual *a,
+ Visual *b);
+
+
+static GdkVisualPrivate *system_visual;
+static GdkVisualPrivate *visuals;
+static gint nvisuals;
+
+static gint available_depths[4];
+static gint navailable_depths;
+
+static GdkVisualType available_types[6];
+static gint navailable_types;
+
+static char* visual_names[] =
+{
+ "static gray",
+ "grayscale",
+ "static color",
+ "pseudo color",
+ "true color",
+ "direct color",
+};
+
+static GHashTable *visual_hash = NULL;
+
+void
+gdk_visual_init ()
+{
+ static gint possible_depths[5] = { 32, 24, 16, 15, 8 };
+ static GdkVisualType possible_types[6] =
+ {
+ GDK_VISUAL_DIRECT_COLOR,
+ GDK_VISUAL_TRUE_COLOR,
+ GDK_VISUAL_PSEUDO_COLOR,
+ GDK_VISUAL_STATIC_COLOR,
+ GDK_VISUAL_GRAYSCALE,
+ GDK_VISUAL_STATIC_GRAY
+ };
+
+ static gint npossible_depths = 5;
+ static gint npossible_types = 6;
+
+ XVisualInfo *visual_list;
+ XVisualInfo visual_template;
+ GdkVisualPrivate temp_visual;
+ Visual *default_xvisual;
+ int nxvisuals;
+ int i, j;
+
+ visual_template.screen = gdk_screen;
+ visual_list = XGetVisualInfo (gdk_display, VisualScreenMask, &visual_template, &nxvisuals);
+ visuals = g_new (GdkVisualPrivate, nxvisuals);
+
+ default_xvisual = DefaultVisual (gdk_display, gdk_screen);
+
+ nvisuals = 0;
+ for (i = 0; i < nxvisuals; i++)
+ {
+ if (visual_list[i].depth >= 8)
+ {
+#ifdef __cplusplus
+ switch (visual_list[i].c_class)
+#else /* __cplusplus */
+ switch (visual_list[i].class)
+#endif /* __cplusplus */
+ {
+ case StaticGray:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_GRAY;
+ break;
+ case GrayScale:
+ visuals[nvisuals].visual.type = GDK_VISUAL_GRAYSCALE;
+ break;
+ case StaticColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_STATIC_COLOR;
+ break;
+ case PseudoColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_PSEUDO_COLOR;
+ break;
+ case TrueColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_TRUE_COLOR;
+ break;
+ case DirectColor:
+ visuals[nvisuals].visual.type = GDK_VISUAL_DIRECT_COLOR;
+ break;
+ }
+
+ visuals[nvisuals].visual.depth = visual_list[i].depth;
+ visuals[nvisuals].visual.byte_order =
+ (ImageByteOrder(gdk_display) == LSBFirst) ?
+ GDK_LSB_FIRST : GDK_MSB_FIRST;
+ visuals[nvisuals].visual.red_mask = visual_list[i].red_mask;
+ visuals[nvisuals].visual.green_mask = visual_list[i].green_mask;
+ visuals[nvisuals].visual.blue_mask = visual_list[i].blue_mask;
+ visuals[nvisuals].visual.colormap_size = visual_list[i].colormap_size;
+ visuals[nvisuals].visual.bits_per_rgb = visual_list[i].bits_per_rgb;
+ visuals[nvisuals].xvisual = visual_list[i].visual;
+
+ if ((visuals[nvisuals].visual.type == GDK_VISUAL_TRUE_COLOR) ||
+ (visuals[nvisuals].visual.type == GDK_VISUAL_DIRECT_COLOR))
+ {
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.red_mask,
+ &visuals[nvisuals].visual.red_shift,
+ &visuals[nvisuals].visual.red_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.green_mask,
+ &visuals[nvisuals].visual.green_shift,
+ &visuals[nvisuals].visual.green_prec);
+
+ gdk_visual_decompose_mask (visuals[nvisuals].visual.blue_mask,
+ &visuals[nvisuals].visual.blue_shift,
+ &visuals[nvisuals].visual.blue_prec);
+ }
+ else
+ {
+ visuals[nvisuals].visual.red_mask = 0;
+ visuals[nvisuals].visual.red_shift = 0;
+ visuals[nvisuals].visual.red_prec = 0;
+
+ visuals[nvisuals].visual.green_mask = 0;
+ visuals[nvisuals].visual.green_shift = 0;
+ visuals[nvisuals].visual.green_prec = 0;
+
+ visuals[nvisuals].visual.blue_mask = 0;
+ visuals[nvisuals].visual.blue_shift = 0;
+ visuals[nvisuals].visual.blue_prec = 0;
+ }
+
+ nvisuals += 1;
+ }
+ }
+
+ XFree (visual_list);
+
+ for (i = 0; i < nvisuals; i++)
+ {
+ for (j = i+1; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth >= visuals[i].visual.depth)
+ {
+ if ((visuals[j].visual.depth == 8) && (visuals[i].visual.depth == 8))
+ {
+ if (visuals[j].visual.type == GDK_VISUAL_PSEUDO_COLOR)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ else if ((visuals[i].visual.type != GDK_VISUAL_PSEUDO_COLOR) &&
+ visuals[j].visual.type > visuals[i].visual.type)
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ else if ((visuals[j].visual.depth > visuals[i].visual.depth) ||
+ ((visuals[j].visual.depth == visuals[i].visual.depth) &&
+ (visuals[j].visual.type > visuals[i].visual.type)))
+ {
+ temp_visual = visuals[j];
+ visuals[j] = visuals[i];
+ visuals[i] = temp_visual;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ if (default_xvisual->visualid == visuals[i].xvisual->visualid)
+ {
+ system_visual = &visuals[i];
+ break;
+ }
+
+ if (gdk_debug_level >= 1)
+ for (i = 0; i < nvisuals; i++)
+ g_print ("visual: %s: %d\n",
+ visual_names[visuals[i].visual.type],
+ visuals[i].visual.depth);
+
+ navailable_depths = 0;
+ for (i = 0; i < npossible_depths; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.depth == possible_depths[i])
+ {
+ available_depths[navailable_depths++] = visuals[j].visual.depth;
+ break;
+ }
+ }
+ }
+
+ if (navailable_depths == 0)
+ g_error ("unable to find a usable depth");
+
+ navailable_types = 0;
+ for (i = 0; i < npossible_types; i++)
+ {
+ for (j = 0; j < nvisuals; j++)
+ {
+ if (visuals[j].visual.type == possible_types[i])
+ {
+ available_types[navailable_types++] = visuals[j].visual.type;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < nvisuals; i++)
+ gdk_visual_add ((GdkVisual*) &visuals[i]);
+
+ if (npossible_types == 0)
+ g_error ("unable to find a usable visual type");
+}
+
+GdkVisual*
+gdk_visual_ref (GdkVisual *visual)
+{
+ return visual;
+}
+
+void
+gdk_visual_unref (GdkVisual *visual)
+{
+ return;
+}
+
+gint
+gdk_visual_get_best_depth ()
+{
+ return available_depths[0];
+}
+
+GdkVisualType
+gdk_visual_get_best_type ()
+{
+ return available_types[0];
+}
+
+GdkVisual*
+gdk_visual_get_system ()
+{
+ return ((GdkVisual*) system_visual);
+}
+
+GdkVisual*
+gdk_visual_get_best ()
+{
+ return ((GdkVisual*) &(visuals[0]));
+}
+
+GdkVisual*
+gdk_visual_get_best_with_depth (gint depth)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (depth == visuals[i].visual.depth)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_type (GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if (visual_type == visuals[i].visual.type)
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+GdkVisual*
+gdk_visual_get_best_with_both (gint depth,
+ GdkVisualType visual_type)
+{
+ GdkVisual *return_val;
+ int i;
+
+ return_val = NULL;
+ for (i = 0; i < nvisuals; i++)
+ if ((depth == visuals[i].visual.depth) &&
+ (visual_type == visuals[i].visual.type))
+ {
+ return_val = (GdkVisual*) &(visuals[i]);
+ break;
+ }
+
+ return return_val;
+}
+
+void
+gdk_query_depths (gint **depths,
+ gint *count)
+{
+ *count = navailable_depths;
+ *depths = available_depths;
+}
+
+void
+gdk_query_visual_types (GdkVisualType **visual_types,
+ gint *count)
+{
+ *count = navailable_types;
+ *visual_types = available_types;
+}
+
+void
+gdk_query_visuals (GdkVisual **visual_return,
+ gint *count)
+{
+ *count = nvisuals;
+ *visual_return = (GdkVisual*) visuals;
+}
+
+
+GdkVisual*
+gdk_visual_lookup (Visual *xvisual)
+{
+ GdkVisual *visual;
+
+ if (!visual_hash)
+ return NULL;
+
+ visual = g_hash_table_lookup (visual_hash, xvisual);
+ return visual;
+}
+
+GdkVisual*
+gdkx_visual_get (VisualID xvisualid)
+{
+ int i;
+
+ for (i = 0; i < nvisuals; i++)
+ if (xvisualid == visuals[i].xvisual->visualid)
+ return (GdkVisual*) &visuals[i];
+
+ return NULL;
+}
+
+
+static void
+gdk_visual_add (GdkVisual *visual)
+{
+ GdkVisualPrivate *private;
+
+ if (!visual_hash)
+ visual_hash = g_hash_table_new ((GHashFunc) gdk_visual_hash,
+ (GCompareFunc) gdk_visual_compare);
+
+ private = (GdkVisualPrivate*) visual;
+
+ g_hash_table_insert (visual_hash, private->xvisual, visual);
+}
+
+static void
+gdk_visual_decompose_mask (gulong mask,
+ gint *shift,
+ gint *prec)
+{
+ *shift = 0;
+ *prec = 0;
+
+ while (!(mask & 0x1))
+ {
+ (*shift)++;
+ mask >>= 1;
+ }
+
+ while (mask & 0x1)
+ {
+ (*prec)++;
+ mask >>= 1;
+ }
+}
+
+static guint
+gdk_visual_hash (Visual *key)
+{
+ return key->visualid;
+}
+
+static gint
+gdk_visual_compare (Visual *a,
+ Visual *b)
+{
+ return (a->visualid == b->visualid);
+}
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
new file mode 100644
index 000000000..aef1367d9
--- /dev/null
+++ b/gdk/x11/gdkwindow-x11.c
@@ -0,0 +1,1358 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+#include <netinet/in.h>
+#include "gdk.h"
+#include "gdkinput.h"
+#include "gdkprivate.h"
+#include <stdlib.h>
+
+int nevent_masks = 16;
+int event_mask_table[18] =
+{
+ ExposureMask,
+ PointerMotionMask,
+ PointerMotionHintMask,
+ ButtonMotionMask,
+ Button1MotionMask,
+ Button2MotionMask,
+ Button3MotionMask,
+ ButtonPressMask | OwnerGrabButtonMask,
+ ButtonReleaseMask | OwnerGrabButtonMask,
+ KeyPressMask,
+ KeyReleaseMask,
+ EnterWindowMask,
+ LeaveWindowMask,
+ FocusChangeMask,
+ StructureNotifyMask,
+ PropertyChangeMask,
+ 0, /* PROXIMITY_IN */
+ 0 /* PROXIMTY_OUT */
+};
+
+
+void
+gdk_window_init ()
+{
+ XWindowAttributes xattributes;
+ unsigned int width;
+ unsigned int height;
+ unsigned int border_width;
+ unsigned int depth;
+ int x, y;
+
+ XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
+ &x, &y, &width, &height, &border_width, &depth);
+ XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
+
+ gdk_root_parent.xdisplay = gdk_display;
+ gdk_root_parent.xwindow = gdk_root_window;
+ gdk_root_parent.window_type = GDK_WINDOW_ROOT;
+ gdk_root_parent.window.user_data = NULL;
+}
+
+GdkWindow*
+gdk_window_new (GdkWindow *parent,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *parent_private;
+ GdkVisual *visual;
+ GdkColormap *colormap;
+ Display *parent_display;
+ Window xparent;
+ Visual *xvisual;
+ XSetWindowAttributes xattributes;
+ long xattributes_mask;
+ XSizeHints size_hints;
+ XWMHints wm_hints;
+ XTextProperty text_property;
+ XClassHint *class_hint;
+ int x, y, depth;
+ unsigned int class;
+ char *title;
+ int i;
+
+ g_return_val_if_fail (attributes != NULL, NULL);
+
+ if (!parent)
+ parent = (GdkWindow*) &gdk_root_parent;
+
+ parent_private = (GdkWindowPrivate*) parent;
+ xparent = parent_private->xwindow;
+ parent_display = parent_private->xdisplay;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ private->parent = parent;
+ private->xdisplay = parent_display;
+ private->destroyed = FALSE;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ xattributes_mask = 0;
+
+ if (attributes_mask & GDK_WA_X)
+ x = attributes->x;
+ else
+ x = 0;
+
+ if (attributes_mask & GDK_WA_Y)
+ y = attributes->y;
+ else
+ y = 0;
+
+ private->x = x;
+ private->y = y;
+ private->width = (attributes->width > 1) ? (attributes->width) : (1);
+ private->height = (attributes->height > 1) ? (attributes->height) : (1);
+ private->window_type = attributes->window_type;
+ private->extension_events = FALSE;
+ private->dnd_drag_data_type = None;
+ private->dnd_drag_data_typesavail =
+ private->dnd_drop_data_typesavail = NULL;
+ private->dnd_drop_enabled = private->dnd_drag_enabled =
+ private->dnd_drag_accepted = private->dnd_drag_datashow =
+ private->dnd_drop_data_numtypesavail =
+ private->dnd_drag_data_numtypesavail = 0;
+ private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
+
+ window->user_data = NULL;
+
+ if (attributes_mask & GDK_WA_VISUAL)
+ visual = attributes->visual;
+ else
+ visual = gdk_visual_get_system ();
+ xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+
+ xattributes.event_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attributes->event_mask & (1 << (i + 1)))
+ xattributes.event_mask |= event_mask_table[i];
+ }
+
+ if (xattributes.event_mask)
+ xattributes_mask |= CWEventMask;
+
+ if (attributes->wclass == GDK_INPUT_OUTPUT)
+ {
+ class = InputOutput;
+ depth = visual->depth;
+
+ if (attributes_mask & GDK_WA_COLORMAP)
+ colormap = attributes->colormap;
+ else
+ colormap = gdk_colormap_get_system ();
+
+ xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
+ xattributes_mask |= CWBorderPixel | CWBackPixel;
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_CHILD:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+ break;
+
+ case GDK_WINDOW_DIALOG:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+ break;
+
+ case GDK_WINDOW_TEMP:
+ xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+ xattributes_mask |= CWColormap;
+
+ xparent = gdk_root_window;
+
+ xattributes.save_under = True;
+ xattributes.override_redirect = True;
+ xattributes.cursor = None;
+ xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+ break;
+ case GDK_WINDOW_ROOT:
+ g_error ("cannot make windows of type GDK_WINDOW_ROOT");
+ break;
+ case GDK_WINDOW_PIXMAP:
+ g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
+ break;
+ }
+ }
+ else
+ {
+ depth = 1;
+ class = InputOnly;
+ colormap = NULL;
+ }
+
+ private->xwindow = XCreateWindow (private->xdisplay, xparent,
+ x, y, private->width, private->height,
+ 0, depth, class, xvisual,
+ xattributes_mask, &xattributes);
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_DIALOG:
+ XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_TEMP:
+ XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
+ break;
+ case GDK_WINDOW_CHILD:
+ if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+ (colormap != gdk_colormap_get_system ()) &&
+ (colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
+ {
+ g_print ("adding colormap window\n");
+ gdk_window_add_colormap_windows (window);
+ }
+ break;
+ default:
+ break;
+ }
+
+ size_hints.flags = PSize | PBaseSize;
+ size_hints.width = private->width;
+ size_hints.height = private->height;
+ size_hints.base_width = private->width;
+ size_hints.base_height = private->height;
+
+ wm_hints.flags = InputHint | StateHint | WindowGroupHint;
+ wm_hints.window_group = gdk_leader_window;
+ wm_hints.input = True;
+ wm_hints.initial_state = NormalState;
+
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+ XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
+
+ if (attributes_mask & GDK_WA_TITLE)
+ title = attributes->title;
+ else
+ title = gdk_progname;
+
+ if (XStringListToTextProperty (&title, 1, &text_property))
+ {
+ XSetWMName (private->xdisplay, private->xwindow, &text_property);
+ XSetWMIconName (private->xdisplay, private->xwindow, &text_property);
+ XFree (text_property.value);
+ }
+
+ if (attributes_mask & GDK_WA_WMCLASS)
+ {
+ class_hint = XAllocClassHint ();
+ class_hint->res_name = attributes->wmclass_name;
+ class_hint->res_class = attributes->wmclass_class;
+ XSetClassHint (private->xdisplay, private->xwindow, class_hint);
+ XFree (class_hint);
+ }
+
+ gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+ (attributes->cursor) :
+ NULL));
+
+ return window;
+}
+
+GdkWindow *
+gdk_window_foreign_new (guint32 anid)
+{
+ GdkWindow *window;
+ GdkWindowPrivate *private;
+ XWindowAttributes attrs;
+
+ private = g_new (GdkWindowPrivate, 1);
+ window = (GdkWindow*) private;
+
+ XGetWindowAttributes (gdk_display, anid, &attrs);
+
+ private->parent = NULL;
+ private->xwindow = anid;
+ private->xdisplay = gdk_display;
+ private->x = attrs.x;
+ private->y = attrs.y;
+ private->width = attrs.width;
+ private->height = attrs.height;
+ private->resize_count = 0;
+ private->ref_count = 1;
+ if (anid == attrs.root)
+ private->window_type = GDK_WINDOW_ROOT;
+ else
+ private->window_type = GDK_WINDOW_TOPLEVEL;
+ /* the above is probably wrong, but it may not be worth the extra
+ X call to get it right */
+
+ private->destroyed = FALSE;
+ private->extension_events = 0;
+
+ window->user_data = NULL;
+
+ gdk_xid_table_insert (&private->xwindow, window);
+
+ return window;
+}
+
+void
+gdk_window_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindowPrivate *temp_private;
+ GdkWindow *temp_window;
+ GList *children;
+ GList *tmp;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if(private->dnd_drag_data_numtypesavail > 0)
+ {
+ free(private->dnd_drag_data_typesavail);
+ private->dnd_drag_data_typesavail = NULL;
+ }
+ if(private->dnd_drop_data_numtypesavail > 0)
+ {
+ free(private->dnd_drop_data_typesavail);
+ private->dnd_drop_data_typesavail = NULL;
+ }
+
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (private->ref_count >= 1)
+ private->ref_count -= 1;
+
+ if (!private->destroyed || (private->destroyed == 2))
+ {
+ children = gdk_window_get_children (window);
+ tmp = children;
+
+ while (tmp)
+ {
+ temp_window = tmp->data;
+ tmp = tmp->next;
+
+ temp_private = (GdkWindowPrivate*) temp_window;
+ if (temp_private && !temp_private->destroyed)
+ /* Removes some nice coredumps... /David */
+ {
+ temp_private->destroyed = 2;
+ temp_private->ref_count += 1;
+ gdk_window_destroy (temp_window);
+ }
+ }
+
+ g_list_free (children);
+
+ if (!private->destroyed)
+ XDestroyWindow (private->xdisplay, private->xwindow);
+ private->destroyed = TRUE;
+ }
+ break;
+
+ case GDK_WINDOW_ROOT:
+ g_error ("attempted to destroy root window");
+ break;
+
+ case GDK_WINDOW_PIXMAP:
+ g_warning ("called gdk_window_destroy on a pixmap (use gdk_pixmap_destroy)");
+ gdk_pixmap_destroy (window);
+ break;
+ }
+}
+
+void
+gdk_window_real_destroy (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (private->extension_events != 0)
+ gdk_input_window_destroy (window);
+
+ if (private->ref_count == 0)
+ {
+ gdk_xid_table_remove (private->xwindow);
+ g_free (window);
+ }
+}
+
+GdkWindow*
+gdk_window_ref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count += 1;
+ return window;
+}
+
+void
+gdk_window_unref (GdkWindow *window)
+{
+ GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+ g_return_if_fail (window != NULL);
+
+ private->ref_count -= 1;
+ if (private->ref_count == 0)
+ gdk_window_real_destroy (window);
+}
+
+void
+gdk_window_show (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ {
+ XRaiseWindow (private->xdisplay, private->xwindow);
+ XMapWindow (private->xdisplay, private->xwindow);
+ }
+}
+
+void
+gdk_window_hide (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ if (!private->destroyed)
+ XUnmapWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_move (GdkWindow *window,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XMoveWindow (private->xdisplay, private->xwindow, x, y);
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->x = x;
+ private->y = y;
+ }
+}
+
+void
+gdk_window_resize (GdkWindow *window,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed &&
+ ((private->resize_count > 0) ||
+ (private->width != (guint16) width) ||
+ (private->height != (guint16) height)))
+ {
+ XResizeWindow (private->xdisplay, private->xwindow, width, height);
+ private->resize_count += 1;
+
+ if (private->window_type == GDK_WINDOW_CHILD)
+ {
+ private->width = width;
+ private->height = height;
+ }
+ }
+}
+
+void
+gdk_window_move_resize (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ private = (GdkWindowPrivate*) window;
+ XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
+
+ if (!private->destroyed &&
+ (private->window_type == GDK_WINDOW_CHILD))
+ {
+ private->x = x;
+ private->y = y;
+ private->width = width;
+ private->height = height;
+ }
+}
+
+void
+gdk_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *parent_private;
+
+ g_return_if_fail (window != NULL);
+
+ if (!new_parent)
+ new_parent = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+ parent_private = (GdkWindowPrivate*) new_parent;
+
+ XReparentWindow (window_private->xdisplay,
+ window_private->xwindow,
+ parent_private->xwindow,
+ x, y);
+}
+
+void
+gdk_window_clear (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XClearWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, False);
+}
+
+void
+gdk_window_clear_area_e (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XClearArea (private->xdisplay, private->xwindow,
+ x, y, width, height, True);
+}
+
+void
+gdk_window_copy_area (GdkWindow *window,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ GdkWindow *source_window,
+ gint source_x,
+ gint source_y,
+ gint width,
+ gint height)
+{
+ GdkWindowPrivate *src_private;
+ GdkWindowPrivate *dest_private;
+ GdkGCPrivate *gc_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (gc != NULL);
+
+ if (source_window == NULL)
+ source_window = window;
+
+ src_private = (GdkWindowPrivate*) source_window;
+ dest_private = (GdkWindowPrivate*) window;
+ gc_private = (GdkGCPrivate*) gc;
+
+ if (!src_private->destroyed && !dest_private->destroyed)
+ {
+ XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
+ gc_private->xgc,
+ source_x, source_y,
+ width, height,
+ x, y);
+ }
+}
+
+void
+gdk_window_raise (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XRaiseWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_lower (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ if (!private->destroyed)
+ XLowerWindow (private->xdisplay, private->xwindow);
+}
+
+void
+gdk_window_set_user_data (GdkWindow *window,
+ gpointer user_data)
+{
+ g_return_if_fail (window != NULL);
+
+ window->user_data = user_data;
+}
+
+void
+gdk_window_set_hints (GdkWindow *window,
+ gint x,
+ gint y,
+ gint min_width,
+ gint min_height,
+ gint max_width,
+ gint max_height,
+ gint flags)
+{
+ GdkWindowPrivate *private;
+ XSizeHints size_hints;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ size_hints.flags = 0;
+
+ if (flags & GDK_HINT_POS)
+ {
+ size_hints.flags |= PPosition;
+ size_hints.x = x;
+ size_hints.y = y;
+ }
+
+ if (flags & GDK_HINT_MIN_SIZE)
+ {
+ size_hints.flags |= PMinSize;
+ size_hints.min_width = min_width;
+ size_hints.min_height = min_height;
+ }
+
+ if (flags & GDK_HINT_MAX_SIZE)
+ {
+ size_hints.flags |= PMaxSize;
+ size_hints.max_width = max_width;
+ size_hints.max_height = max_height;
+ }
+
+ if (flags)
+ XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+}
+
+void
+gdk_window_set_title (GdkWindow *window,
+ const gchar *title)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XStoreName (private->xdisplay, private->xwindow, title);
+ XSetIconName (private->xdisplay, private->xwindow, title);
+}
+
+void
+gdk_window_set_background (GdkWindow *window,
+ GdkColor *color)
+{
+ GdkWindowPrivate *private;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowPrivate*) window;
+ XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
+}
+
+void
+gdk_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap,
+ gint parent_relative)
+{
+ GdkWindowPrivate *window_private;
+ GdkPixmapPrivate *pixmap_private;
+ Pixmap xpixmap;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkPixmapPrivate*) pixmap;
+
+ if (pixmap)
+ xpixmap = pixmap_private->xwindow;
+ else
+ xpixmap = None;
+
+ if (parent_relative)
+ xpixmap = ParentRelative;
+
+ XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
+}
+
+void
+gdk_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkWindowPrivate *window_private;
+ GdkCursorPrivate *cursor_private;
+ Cursor xcursor;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+ XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
+}
+
+void
+gdk_window_set_colormap (GdkWindow *window,
+ GdkColormap *colormap)
+{
+ GdkWindowPrivate *window_private;
+ GdkColormapPrivate *colormap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (colormap != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ colormap_private = (GdkColormapPrivate*) colormap;
+
+ XSetWindowColormap (window_private->xdisplay,
+ window_private->xwindow,
+ colormap_private->xcolormap);
+
+ if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
+ gdk_window_add_colormap_windows (window);
+}
+
+void
+gdk_window_get_user_data (GdkWindow *window,
+ gpointer *data)
+{
+ g_return_if_fail (window != NULL);
+
+ *data = window->user_data;
+}
+
+void
+gdk_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth)
+{
+ GdkWindowPrivate *window_private;
+ Window root;
+ gint tx;
+ gint ty;
+ guint twidth;
+ guint theight;
+ guint tborder_width;
+ guint tdepth;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetGeometry (window_private->xdisplay, window_private->xwindow,
+ &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+ if (width)
+ *width = twidth;
+ if (height)
+ *height = theight;
+ if (depth)
+ *depth = tdepth;
+}
+
+void
+gdk_window_get_position (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (x)
+ *x = window_private->x;
+ if (y)
+ *y = window_private->y;
+}
+
+void
+gdk_window_get_size (GdkWindow *window,
+ gint *width,
+ gint *height)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ if (width)
+ *width = window_private->width;
+ if (height)
+ *height = window_private->height;
+}
+
+
+GdkVisual*
+gdk_window_get_visual (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
+ window_private = (GdkWindowPrivate*) window_private->parent;
+
+ if (window_private)
+ {
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_visual_lookup (window_attributes.visual);
+ }
+
+ return NULL;
+}
+
+GdkColormap*
+gdk_window_get_colormap (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+ XWindowAttributes window_attributes;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+
+ XGetWindowAttributes (window_private->xdisplay,
+ window_private->xwindow,
+ &window_attributes);
+
+ return gdk_colormap_lookup (window_attributes.colormap);
+}
+
+GdkWindowType
+gdk_window_get_type (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
+
+ window_private = (GdkWindowPrivate*) window;
+ return window_private->window_type;
+}
+
+gint
+gdk_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowPrivate *private;
+ gint return_val;
+ Window child;
+ gint tx, ty;
+
+ g_return_val_if_fail (window != NULL, 0);
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = XTranslateCoordinates (private->xdisplay,
+ private->xwindow,
+ gdk_root_window,
+ 0, 0, &tx, &ty,
+ &child);
+
+ if (x)
+ *x = tx;
+ if (y)
+ *y = ty;
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *return_val;
+ Window root;
+ Window child;
+ int rootx, rooty;
+ int winx, winy;
+ unsigned int xmask;
+
+ if (!window)
+ window = (GdkWindow*) &gdk_root_parent;
+
+ private = (GdkWindowPrivate*) window;
+
+ return_val = NULL;
+ if (XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
+ &rootx, &rooty, &winx, &winy, &xmask))
+ {
+ if (x) *x = winx;
+ if (y) *y = winy;
+ if (mask) *mask = xmask;
+
+ if (child)
+ return_val = gdk_window_lookup (child);
+ }
+
+ return return_val;
+}
+
+GdkWindow*
+gdk_window_get_parent (GdkWindow *window)
+{
+ g_return_val_if_fail (window != NULL, NULL);
+
+ return ((GdkWindowPrivate*) window)->parent;
+}
+
+GdkWindow*
+gdk_window_get_toplevel (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ while (private->window_type == GDK_WINDOW_CHILD)
+ {
+ window = ((GdkWindowPrivate*) window)->parent;
+ private = (GdkWindowPrivate*) window;
+ }
+
+ return window;
+}
+
+GList*
+gdk_window_get_children (GdkWindow *window)
+{
+ GdkWindowPrivate *private;
+ GdkWindow *child;
+ GList *children;
+ Window root;
+ Window parent;
+ Window *xchildren;
+ unsigned int nchildren;
+ unsigned int i;
+
+ g_return_val_if_fail (window != NULL, NULL);
+
+ private = (GdkWindowPrivate*) window;
+
+ XQueryTree (private->xdisplay, private->xwindow,
+ &root, &parent, &xchildren, &nchildren);
+
+ children = NULL;
+
+ if (nchildren > 0)
+ {
+ for (i = 0; i < nchildren; i++)
+ {
+ child = gdk_window_lookup (xchildren[i]);
+ if (child)
+ children = g_list_prepend (children, child);
+ }
+
+ XFree (xchildren);
+ }
+
+ return children;
+}
+
+GdkEventMask
+gdk_window_get_events (GdkWindow *window)
+{
+ XWindowAttributes attrs;
+ GdkEventMask event_mask;
+ int i;
+
+ XGetWindowAttributes (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ &attrs);
+
+ event_mask = 0;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (attrs.your_event_mask & event_mask_table[i])
+ event_mask |= 1 << (i + 1);
+ }
+
+ return event_mask;
+}
+
+void
+gdk_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ long xevent_mask;
+ int i;
+
+ xevent_mask = StructureNotifyMask;
+ for (i = 0; i < nevent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= event_mask_table[i];
+ }
+
+ XSelectInput (gdk_display, ((GdkWindowPrivate *)window)->xwindow,
+ xevent_mask);
+}
+
+void
+gdk_window_add_colormap_windows (GdkWindow *window)
+{
+ GdkWindow *toplevel;
+ GdkWindowPrivate *toplevel_private;
+ GdkWindowPrivate *window_private;
+ Window *old_windows;
+ Window *new_windows;
+ int i, count;
+
+ g_return_if_fail (window != NULL);
+
+ toplevel = gdk_window_get_toplevel (window);
+ toplevel_private = (GdkWindowPrivate*) toplevel;
+ window_private = (GdkWindowPrivate*) window;
+
+ if (!XGetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ &old_windows, &count))
+ {
+ old_windows = NULL;
+ count = 0;
+ }
+
+ for (i = 0; i < count; i++)
+ if (old_windows[i] == window_private->xwindow)
+ return;
+
+ new_windows = g_new (Window, count + 1);
+
+ for (i = 0; i < count; i++)
+ new_windows[i] = old_windows[i];
+ new_windows[count] = window_private->xwindow;
+
+ XSetWMColormapWindows (toplevel_private->xdisplay,
+ toplevel_private->xwindow,
+ new_windows, count + 1);
+
+ g_free (new_windows);
+ if (old_windows)
+ XFree (old_windows);
+}
+
+/*
+ * This needs the X11 shape extension.
+ * If not available, simply remove the call to
+ * XShapeCombineMask. Shaped windows will look
+ * ugly, but programs still work. Stefan Wille
+ */
+void
+gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x, gint y)
+{
+ GdkWindowPrivate *window_private;
+ GdkWindowPrivate *pixmap_private;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (mask != NULL);
+
+ window_private = (GdkWindowPrivate*) window;
+ pixmap_private = (GdkWindowPrivate*) mask;
+
+ XShapeCombineMask (window_private->xdisplay,
+ window_private->xwindow,
+ ShapeBounding,
+ x, y, /* offset */
+ (Pixmap)pixmap_private->xwindow,
+ ShapeSet);
+}
+
+void
+gdk_dnd_drag_addwindow (GdkWindow *window)
+{
+ GdkWindowPrivate *window_private;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
+ {
+ gdk_dnd.drag_numwindows++;
+ gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
+ gdk_dnd.drag_numwindows
+ * sizeof(GdkWindow *));
+ gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
+ window_private->dnd_drag_accepted = 0;
+ }
+ else
+ g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
+}
+
+void
+gdk_window_dnd_drag_set (GdkWindow *window,
+ guint8 drag_enable,
+ gchar **typelist,
+ guint numtypes)
+{
+ GdkWindowPrivate *window_private;
+ int i, wasset = 0;
+
+ g_return_if_fail (window != NULL);
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
+
+ if (drag_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ if (window_private->dnd_drag_data_numtypesavail > 3)
+ wasset = 1;
+ window_private->dnd_drag_data_numtypesavail = numtypes;
+
+ window_private->dnd_drag_data_typesavail =
+ g_realloc (window_private->dnd_drag_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ {
+ /* Allow blanket use of ALL to get anything... */
+ if (strcmp (typelist[i], "ALL"))
+ window_private->dnd_drag_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+ else
+ window_private->dnd_drag_data_typesavail[i] = None;
+ }
+
+ /*
+ * set our extended type list if we need to
+ */
+ if (numtypes > 3)
+ gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
+ XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
+ (guchar *)(window_private->dnd_drag_data_typesavail
+ + (sizeof(GdkAtom) * 3)),
+ (numtypes - 3) * sizeof(GdkAtom));
+ else if (wasset)
+ gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
+ }
+ else
+ {
+ free (window_private->dnd_drag_data_typesavail);
+ window_private->dnd_drag_data_typesavail = NULL;
+ window_private->dnd_drag_data_numtypesavail = 0;
+ }
+}
+
+void
+gdk_window_dnd_drop_set (GdkWindow *window,
+ guint8 drop_enable,
+ gchar **typelist,
+ guint numtypes,
+ guint8 destructive_op)
+{
+ GdkWindowPrivate *window_private;
+ int i;
+
+ g_return_if_fail (window != NULL);
+
+ window_private = (GdkWindowPrivate *) window;
+
+ window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
+ if (drop_enable)
+ {
+ g_return_if_fail(typelist != NULL);
+
+ window_private->dnd_drop_data_numtypesavail = numtypes;
+
+ window_private->dnd_drop_data_typesavail =
+ g_realloc (window_private->dnd_drop_data_typesavail,
+ (numtypes + 1) * sizeof (GdkAtom));
+
+ for (i = 0; i < numtypes; i++)
+ window_private->dnd_drop_data_typesavail[i] =
+ gdk_atom_intern (typelist[i], FALSE);
+
+ window_private->dnd_drop_destructive_op = destructive_op;
+ }
+}
+
+/*
+ * This is used to reply to a GDK_DRAG_REQUEST event
+ * (which may be generated by XdeRequest or a confirmed drop...
+ */
+void
+gdk_window_dnd_data_set (GdkWindow *window,
+ GdkEvent *event,
+ gpointer data,
+ gulong data_numbytes)
+{
+ GdkWindowPrivate *window_private;
+ XEvent sev;
+ GdkEventDropDataAvailable tmp_ev;
+ gchar *tmp;
+
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (event != NULL);
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (data_numbytes > 0);
+ g_return_if_fail (event->type == GDK_DRAG_REQUEST);
+
+ g_free (event->dragrequest.data_type);
+ event->dragrequest.data_type = NULL;
+
+ window_private = (GdkWindowPrivate *) window;
+ g_return_if_fail (window_private->dnd_drag_accepted != 0);
+
+ /* We set the property on our window... */
+ gdk_property_change (window, window_private->dnd_drag_data_type,
+ XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
+ data_numbytes);
+ tmp = gdk_atom_name(window_private->dnd_drag_data_type);
+ g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
+ g_free(tmp);
+
+ /*
+ * Then we send the event to tell the receiving window that the
+ * drop has happened
+ */
+ tmp_ev.u.allflags = 0;
+ tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
+ tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
+
+ sev.xclient.type = ClientMessage;
+ sev.xclient.format = 32;
+ sev.xclient.window = event->dragrequest.requestor;
+ sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
+ sev.xclient.data.l[0] = window_private->xwindow;
+ sev.xclient.data.l[1] = tmp_ev.u.allflags;
+ sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
+
+ if (event->dragrequest.isdrop)
+ sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
+ (event->dragrequest.drop_coords.y << 16);
+ else
+ sev.xclient.data.l[3] = 0;
+
+ sev.xclient.data.l[4] = 0;
+
+ XSendEvent (gdk_display, event->dragrequest.requestor, False,
+ NoEventMask, &sev);
+}
diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h
new file mode 100644
index 000000000..cb8e33b44
--- /dev/null
+++ b/gdk/x11/gdkx.h
@@ -0,0 +1,48 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GDK_X_H__
+#define __GDK_X_H__
+
+#include <gdk/gdkprivate.h>
+
+
+#define GDK_ROOT_WINDOW() gdk_root_window
+#define GDK_ROOT_PARENT() &gdk_root_parent
+#define GDK_DISPLAY() gdk_display
+#define GDK_WINDOW_XDISPLAY(win) (((GdkWindowPrivate*) win)->xdisplay)
+#define GDK_WINDOW_XWINDOW(win) (((GdkWindowPrivate*) win)->xwindow)
+#define GDK_IMAGE_XDISPLAY(image) (((GdkImagePrivate*) image)->xdisplay)
+#define GDK_IMAGE_XIMAGE(image) (((GdkImagePrivate*) image)->ximage)
+#define GDK_GC_XDISPLAY(gc) (((GdkGCPrivate*) gc)->xdisplay)
+#define GDK_GC_XGC(gc) (((GdkGCPrivate*) gc)->xgc)
+#define GDK_COLORMAP_XDISPLAY(cmap) (((GdkColormapPrivate*) cmap)->xdisplay)
+#define GDK_COLORMAP_XCOLORMAP(cmap) (((GdkColormapPrivate*) cmap)->xcolormap)
+#define GDK_VISUAL_XVISUAL(vis) (((GdkVisualPrivate*) vis)->xvisual)
+#define GDK_FONT_XDISPLAY(font) (((GdkFontPrivate*) font)->xdisplay)
+#define GDK_FONT_XFONT(font) (((GdkFontPrivate*) font)->xfont)
+
+
+GdkVisual* gdkx_visual_get (VisualID xvisualid);
+GdkColormap* gdkx_colormap_get (Colormap xcolormap);
+/* Utility function in gdk.c - not sure where it belongs, but it's
+ needed in more than one place, so make it public */
+Window gdk_get_client_window (Display *dpy,
+ Window win);
+
+
+#endif /* __GDK_X_H__ */
diff --git a/gdk/x11/gdkxid.c b/gdk/x11/gdkxid.c
new file mode 100644
index 000000000..7ee6075c5
--- /dev/null
+++ b/gdk/x11/gdkxid.c
@@ -0,0 +1,74 @@
+/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "gdkprivate.h"
+
+
+static guint gdk_xid_hash (XID *xid);
+static gint gdk_xid_compare (XID *a,
+ XID *b);
+
+
+GHashTable *xid_ht = NULL;
+
+
+void
+gdk_xid_table_insert (XID *xid,
+ gpointer data)
+{
+ g_return_if_fail (xid != NULL);
+
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_insert (xid_ht, xid, data);
+}
+
+void
+gdk_xid_table_remove (XID xid)
+{
+ if (!xid_ht)
+ xid_ht = g_hash_table_new ((GHashFunc) gdk_xid_hash,
+ (GCompareFunc) gdk_xid_compare);
+
+ g_hash_table_remove (xid_ht, &xid);
+}
+
+gpointer
+gdk_xid_table_lookup (XID xid)
+{
+ gpointer data;
+
+ data = g_hash_table_lookup (xid_ht, &xid);
+
+ return data;
+}
+
+
+static guint
+gdk_xid_hash (XID *xid)
+{
+ return *xid;
+}
+
+static gint
+gdk_xid_compare (XID *a,
+ XID *b)
+{
+ return (*a == *b);
+}
diff --git a/gdk/x11/gxid.c b/gdk/x11/gxid.c
new file mode 100644
index 000000000..219c08bfe
--- /dev/null
+++ b/gdk/x11/gxid.c
@@ -0,0 +1,844 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+
+#include "gxid_proto.h"
+
+/* #define DEBUG_CLIENTS */
+/* #define DEBUG_EVENTS */
+
+char *program_name;
+Display *dpy;
+Window root_window; /* default root window of dpy */
+int port = 0; /* port to listen on */
+int socket_fd = 0; /* file descriptor of socket */
+typedef struct GxidWindow_ GxidWindow;
+
+typedef struct GxidDevice_ GxidDevice;
+struct GxidDevice_ {
+ XID id;
+ int exclusive;
+ int ispointer;
+
+ XDevice *xdevice;
+ int motionnotify_type;
+ int changenotify_type;
+};
+
+struct GxidWindow_ {
+ Window xwindow;
+ /* Immediate child of root that is ancestor of window */
+ Window root_child;
+ int num_devices;
+ GxidDevice **devices;
+};
+
+GxidDevice **devices = NULL;
+int num_devices = 0;
+GxidWindow **windows = NULL;
+int num_windows = 0;
+
+void
+handler(int signal)
+{
+ fprintf(stderr,"%s: dying on signal %d\n",program_name,signal);
+ if (socket_fd)
+ close(socket_fd);
+ exit(1);
+}
+
+void
+init_socket()
+{
+ struct sockaddr_in sin;
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
+ if (socket_fd < 0)
+ {
+ fprintf (stderr, "%s: error getting socket\n",
+ program_name);
+ exit(1);
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(socket_fd,(struct sockaddr *)(&sin),
+ sizeof(struct sockaddr_in)) < 0)
+ {
+ fprintf (stderr,"%s: cannot bind to port %d\n",
+ program_name,port);
+ exit(1);
+ }
+
+ if (listen(socket_fd,5) < 0)
+ {
+ fprintf (stderr,"%s: error listening on socket\n",
+ program_name);
+ exit(1);
+ };
+}
+
+#define NUM_EVENTC 2
+static void
+enable_device(GxidDevice *dev)
+{
+ XEventClass xevc[NUM_EVENTC];
+ int num_eventc = NUM_EVENTC;
+ int i,j;
+
+ if (!dev->xdevice)
+ {
+ if (dev->ispointer) return;
+
+ dev->xdevice = XOpenDevice(dpy, dev->id);
+ if (!dev->xdevice) return;
+
+ DeviceMotionNotify (dev->xdevice, dev->motionnotify_type,
+ xevc[0]);
+ ChangeDeviceNotify (dev->xdevice, dev->changenotify_type,
+ xevc[1]);
+
+ /* compress out zero event classes */
+ for (i=0,j=0;i<NUM_EVENTC;i++)
+ {
+ if (xevc[i]) {
+ xevc[j] = xevc[i];
+ j++;
+ }
+ }
+ num_eventc = j;
+
+ XSelectExtensionEvent (dpy, root_window, xevc, num_eventc);
+ }
+}
+
+/* switch the core pointer from whatever it is now to something else,
+ return true on success, false otherwise */
+static int
+switch_core_pointer()
+{
+ GxidDevice *old_pointer = 0;
+ GxidDevice *new_pointer = 0;
+ int result;
+ int i;
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ old_pointer = devices[i];
+ else
+ if (!new_pointer && !devices[i]->exclusive)
+ new_pointer = devices[i];
+ }
+
+ if (!old_pointer || !new_pointer)
+ return 0;
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Switching core from %ld to %ld\n",
+ old_pointer->id,new_pointer->id);
+#endif
+ result = XChangePointerDevice(dpy,new_pointer->xdevice, 0, 1);
+ if (result != Success)
+ {
+ fprintf(stderr,"gxid: Error %d switching core from %ld to %ld\n",
+ result, old_pointer->id, new_pointer->id);
+ }
+ else
+ {
+ new_pointer->ispointer = 1;
+ old_pointer->ispointer = 0;
+ if (!old_pointer->xdevice)
+ enable_device(old_pointer);
+ }
+
+ return 1;
+}
+
+void
+disable_device(GxidDevice *dev)
+{
+ if (dev->xdevice)
+ {
+ if (dev->ispointer)
+ return;
+ XCloseDevice(dpy,dev->xdevice);
+ dev->xdevice = 0;
+ }
+}
+
+GxidDevice *
+init_device(XDeviceInfo *xdevice)
+{
+ GxidDevice *dev = (GxidDevice *)malloc(sizeof(GxidDevice));
+ XAnyClassPtr class;
+ int num_axes, i;
+
+ dev->id = xdevice->id;
+ dev->exclusive = 0;
+ dev->xdevice = NULL;
+
+ dev->ispointer = (xdevice->use == IsXPointer);
+
+ /* step through the classes */
+
+ num_axes = 0;
+ class = xdevice->inputclassinfo;
+ for (i=0;i<xdevice->num_classes;i++)
+ {
+ if (class->class == ValuatorClass)
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+ num_axes = xvi->num_axes;
+ }
+ class = (XAnyClassPtr)(((char *)class) + class->length);
+ }
+
+ /* return NULL if insufficient axes */
+ if (num_axes < 2)
+ {
+ free((void *)dev);
+ return NULL;
+ }
+
+ if (!dev->ispointer)
+ enable_device(dev);
+ return dev;
+}
+
+void
+init_xinput()
+{
+ char **extensions;
+ XDeviceInfo *xdevices;
+ int num_xdevices;
+ int num_extensions;
+ int i;
+
+ extensions = XListExtensions(dpy, &num_extensions);
+ for (i = 0; i < num_extensions &&
+ (strcmp(extensions[i], "XInputExtension") != 0); i++);
+ XFreeExtensionList(extensions);
+ if (i == num_extensions) /* XInput extension not found */
+ {
+ fprintf(stderr,"XInput extension not found\n");
+ exit(1);
+ }
+
+ xdevices = XListInputDevices(dpy, &num_xdevices);
+ devices = (GxidDevice **)malloc(num_xdevices * sizeof(GxidDevice *));
+
+ num_devices = 0;
+ for(i=0; i<num_xdevices; i++)
+ {
+ GxidDevice *dev = init_device(&xdevices[i]);
+ if (dev)
+ devices[num_devices++] = dev;
+ }
+ XFreeDeviceList(xdevices);
+}
+
+/* If this routine needs fixing, the corresponding routine
+ in gdkinputgxi.h will need it too. */
+
+Window
+gxi_find_root_child(Display *dpy, Window w)
+{
+ Window root,parent;
+ Window *children;
+ int nchildren;
+
+ parent = w;
+ do
+ {
+ w = parent;
+ XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
+ if (children) XFree(children);
+ }
+ while (parent != root);
+
+ return w;
+}
+
+int
+handle_claim_device(GxidClaimDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+ int exclusive = ntohl(msg->exclusive);
+ GxidDevice *device = NULL;
+ GxidWindow *window = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld claimed (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (device->exclusive)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Device %ld already claimed in exclusive mode\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ if (exclusive)
+ {
+ for (i=0;i<num_windows;i++)
+ {
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j]->id == devid)
+ {
+ /* already in use */
+ fprintf(stderr,
+ "%s: Can't establish exclusive use of device %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+ }
+ if (device->ispointer)
+ if (!switch_core_pointer())
+ {
+ fprintf(stderr,
+ "%s: Can't free up core pointer %ld\n",
+ program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ device->exclusive = 1;
+ disable_device(device);
+ XSelectInput(dpy,winid,StructureNotifyMask);
+ }
+ else /* !exclusive */
+ {
+ /* FIXME: this is a bit improper. We probably should do this only
+ when a window is first claimed. But we might be fooled if
+ an old client died without releasing it's windows. So until
+ we look for client-window closings, do it here
+
+ (We do look for closings now...)
+ */
+
+ XSelectInput(dpy,winid,EnterWindowMask|StructureNotifyMask);
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ if (windows[i]->xwindow == winid)
+ {
+ window = windows[i];
+ break;
+ }
+ }
+
+ /* Create window structure if no devices have been previously
+ claimed on it */
+ if (!window)
+ {
+ num_windows++;
+ windows = (GxidWindow **)realloc(windows,
+ sizeof(GxidWindow*)*num_windows);
+ window = (GxidWindow *)malloc(sizeof(GxidWindow));
+ windows[num_windows-1] = window;
+
+ window->xwindow = winid;
+ window->root_child = gxi_find_root_child(dpy,winid);
+ window->num_devices = 0;
+ window->devices = 0;
+ }
+
+
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == device)
+ return GXID_RETURN_OK;
+ }
+
+ window->num_devices++;
+ window->devices = (GxidDevice **)realloc(window->devices,
+ sizeof(GxidDevice*)*num_devices);
+ /* we need add the device to the window */
+ window->devices[i] = device;
+
+ return GXID_RETURN_OK;
+}
+
+int
+handle_release_device(GxidReleaseDevice *msg)
+{
+ int i,j;
+ XID devid = ntohl(msg->device);
+ XID winid = ntohl(msg->window);
+
+ GxidDevice *device = NULL;
+
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released (window 0x%lx)\n",devid,winid);
+#endif
+
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->id == devid)
+ {
+ device = devices[i];
+ break;
+ }
+ }
+ if (!device)
+ {
+ fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
+ return GXID_RETURN_ERROR;
+ }
+
+ for (i=0;i<num_windows;i++)
+ {
+ GxidWindow *w = windows[i];
+
+ if (w->xwindow == winid)
+ for (j=0;j<w->num_devices;j++)
+ if (w->devices[j]->id == devid)
+ {
+ if (j<w->num_devices-1)
+ w->devices[j] = w->devices[w->num_devices-1];
+ w->num_devices--;
+
+ if (w->num_devices == 0)
+ {
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+ }
+
+ if (device->exclusive)
+ {
+ device->exclusive = 0;
+ enable_device(device);
+ }
+ return GXID_RETURN_OK;
+ }
+ }
+
+ /* device/window combination not found */
+ fprintf(stderr,
+ "%s: Device %ld not claimed for window 0x%lx\n",
+ program_name,devid,winid);
+ return GXID_RETURN_ERROR;
+}
+
+void
+handle_connection()
+{
+ GxidMessage msg;
+ GxidU32 type;
+ int length;
+ GxidI32 retval;
+
+ int conn_fd;
+ struct sockaddr_in sin;
+ int sin_length;
+ int count;
+
+ sin_length = sizeof(struct sockaddr_in);
+ conn_fd = accept(socket_fd,(struct sockaddr *)&sin,&sin_length);
+ if (conn_fd < 0)
+ {
+ fprintf(stderr,"%s: Error accepting connection\n",
+ program_name);
+ exit(1);
+ }
+
+ /* read type and length of message */
+
+ count = read(conn_fd,(char *)&msg,2*sizeof(GxidU32));
+ if (count != 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message header\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+ type = ntohl(msg.any.type);
+ length = ntohl(msg.any.length);
+
+ /* read rest of message */
+
+ if (length > sizeof(GxidMessage))
+ {
+ fprintf(stderr,"%s: Bad message length\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ count = read(conn_fd,2*sizeof(GxidU32) + (char *)&msg,
+ length - 2*sizeof(GxidU32));
+ if (count != length - 2*sizeof(GxidU32))
+ {
+ fprintf(stderr,"%s: Error reading message body\n",
+ program_name);
+ close(conn_fd);
+ return;
+ }
+
+ switch (type)
+ {
+ case GXID_CLAIM_DEVICE:
+ retval = handle_claim_device((GxidClaimDevice *)&msg);
+ break;
+ case GXID_RELEASE_DEVICE:
+ retval = handle_release_device((GxidReleaseDevice *)&msg);
+ break;
+ default:
+ fprintf(stderr,"%s: Unknown message type: %ld (ignoring)\n",
+ program_name,type);
+ close(conn_fd);
+ return;
+ }
+
+ count = write(conn_fd,&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"%s: Error writing return code\n",
+ program_name);
+ }
+
+ close(conn_fd);
+}
+
+void
+handle_motion_notify(XDeviceMotionEvent *event)
+{
+ int i,j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+ Window w, root, child;
+ int root_x, root_y, x, y, mask;
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+ if (new_device && !new_device->exclusive && !new_device->ispointer)
+ {
+ /* make sure we aren't stealing the pointer back from a slow
+ client */
+ child = root_window;
+ do
+ {
+ w = child;
+ /* FIXME: this fails disasterously if child vanishes between
+ calls. (Which is prone to happening since we get events
+ on root just as the client exits) */
+
+ XQueryPointer(dpy,w,&root,&child,&root_x,&root_y,
+ &x,&y,&mask);
+ }
+ while (child != None);
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == w)
+ for (j=0;j<windows[i]->num_devices;j++)
+ if (windows[i]->devices[j] == new_device)
+ return;
+
+ /* FIXME: do something smarter with axes */
+ XChangePointerDevice(dpy,new_device->xdevice, 0, 1);
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_change_notify(XChangeDeviceNotifyEvent *event)
+{
+ int j;
+ GxidDevice *old_device = NULL;
+ GxidDevice *new_device = NULL;
+
+
+ for (j=0;j<num_devices;j++)
+ {
+ if (devices[j]->ispointer)
+ old_device = devices[j];
+ if (devices[j]->id == event->deviceid)
+ new_device = devices[j];
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: ChangeNotify event; old = %ld; new = %ld\n",
+ old_device->id, new_device->id);
+#endif
+
+ if (old_device != new_device)
+ {
+ new_device->ispointer = 1;
+
+ old_device->ispointer = 0;
+ if (!old_device->xdevice)
+ enable_device(old_device);
+ }
+}
+
+void
+handle_enter_notify(XEnterWindowEvent *event, GxidWindow *window)
+{
+ int i;
+ GxidDevice *old_pointer = NULL;
+ for (i=0;i<num_devices;i++)
+ {
+ if (devices[i]->ispointer)
+ {
+ old_pointer = devices[i];
+ break;
+ }
+ }
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"gxid: Enter event; oldpointer = %ld\n",
+ old_pointer->id);
+#endif
+
+ if (old_pointer)
+ for (i=0;i<window->num_devices;i++)
+ {
+ if (window->devices[i] == old_pointer)
+ {
+ switch_core_pointer();
+ break;
+ }
+ }
+}
+
+void
+handle_destroy_notify(XDestroyWindowEvent *event)
+{
+ int i,j;
+
+ for (i=0;i<num_windows;i++)
+ if (windows[i]->xwindow == event->window)
+ {
+ GxidWindow *w = windows[i];
+
+ for (j=0;j<w->num_devices;j++)
+ {
+#ifdef DEBUG_CLIENTS
+ fprintf(stderr,"device %ld released on destruction of window 0x%lx.\n",
+ w->devices[j]->id,w->xwindow);
+#endif
+
+ if (w->devices[j]->exclusive)
+ {
+ w->devices[j]->exclusive = 0;
+ enable_device(devices[j]);
+ }
+ }
+
+ if (i<num_windows-1)
+ windows[i] = windows[num_windows-1];
+ num_windows--;
+
+ if (w->devices)
+ free((void *)w->devices);
+ free((void *)w);
+ /* FIXME: should we deselect input? But what
+ what if window is already destroyed */
+
+ return;
+ }
+}
+
+void
+handle_xevent()
+{
+ int i;
+ XEvent event;
+
+ XNextEvent (dpy, &event);
+
+#ifdef DEBUG_EVENTS
+ fprintf(stderr,"Event - type = %d; window = 0x%lx\n",
+ event.type,event.xany.window);
+#endif
+
+ if (event.type == ConfigureNotify)
+ {
+#ifdef DEBUG_EVENTS
+ XConfigureEvent *xce = (XConfigureEvent *)&event;
+ fprintf(stderr," configureNotify: window = 0x%lx\n",xce->window);
+#endif
+ }
+ else if (event.type == EnterNotify)
+ {
+ /* pointer entered a claimed window */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_enter_notify((XEnterWindowEvent *)&event,windows[i]);
+ }
+ }
+ else if (event.type == DestroyNotify)
+ {
+ /* A claimed window was destroyed */
+ for (i=0;i<num_windows;i++)
+ {
+ if (event.xany.window == windows[i]->xwindow)
+ handle_destroy_notify((XDestroyWindowEvent *)&event);
+ }
+ }
+ else
+ for (i=0;i<num_devices;i++)
+ {
+ if (event.type == devices[i]->motionnotify_type)
+ {
+ handle_motion_notify((XDeviceMotionEvent *)&event);
+ break;
+ }
+ else if (event.type == devices[i]->changenotify_type)
+ {
+ handle_change_notify((XChangeDeviceNotifyEvent *)&event);
+ break;
+ }
+ }
+}
+
+void
+usage()
+{
+ fprintf(stderr,"Usage: %s [-d display] [-p --gxid-port port]\n",
+ program_name);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ char *display_name = NULL;
+ fd_set readfds;
+
+ program_name = argv[0];
+
+ for (i=1;i<argc;i++)
+ {
+ if (!strcmp(argv[i],"-d"))
+ {
+ if (++i >= argc) usage();
+ display_name = argv[i];
+ }
+ else if (!strcmp(argv[i],"--gxid-port") ||
+ !strcmp(argv[i],"-p"))
+ {
+ if (++i >= argc) usage();
+ port = atoi(argv[i]);
+ break;
+ }
+ else
+ usage();
+ }
+
+ if (!port)
+ {
+ char *t = getenv("GXID_PORT");
+ if (t)
+ port = atoi(t);
+ else
+ port = 6951;
+ }
+ /* set up a signal handler so we can clean up if killed */
+
+ signal(SIGTERM,handler);
+ signal(SIGINT,handler);
+
+ /* initialize the X connection */
+
+ dpy = XOpenDisplay (display_name);
+ if (!dpy)
+ {
+ fprintf (stderr, "%s: unable to open display '%s'\n",
+ program_name, XDisplayName (display_name));
+ exit (1);
+ }
+
+ root_window = DefaultRootWindow(dpy);
+
+ /* We'll want to do this in the future if we are to support
+ gxid monitoring visibility information for clients */
+#if 0
+ XSelectInput(dpy,root_window,SubstructureNotifyMask);
+#endif
+ init_xinput();
+
+ /* set up our server connection */
+
+ init_socket();
+
+ /* main loop */
+
+ if (XPending(dpy)) /* this seems necessary to get things
+ in sync */
+ handle_xevent();
+ while (1)
+ {
+
+ FD_ZERO(&readfds);
+ FD_SET(ConnectionNumber(dpy),&readfds);
+ FD_SET(socket_fd,&readfds);
+
+ if (select(8*sizeof(readfds),&readfds,
+ (fd_set *)0,(fd_set *)0, (struct timeval *)0) < 0)
+ {
+ fprintf(stderr,"Error in select\n");
+ exit(1);
+ }
+
+ if (FD_ISSET(socket_fd,&readfds))
+ handle_connection(socket_fd);
+
+ while (XPending(dpy))
+ handle_xevent();
+ }
+
+ XCloseDisplay (dpy);
+ exit (0);
+}
diff --git a/gdk/x11/gxid_lib.c b/gdk/x11/gxid_lib.c
new file mode 100644
index 000000000..357b76451
--- /dev/null
+++ b/gdk/x11/gxid_lib.c
@@ -0,0 +1,116 @@
+/*
+ * gxid version 0.3
+ *
+ * Copyright 1997 Owen Taylor <owt1@cornell.edu>
+*/
+
+#include "../config.h"
+
+#ifdef XINPUT_GXI
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "gxid_lib.h"
+
+/* handles mechanics of communicating with a client */
+static int
+gxid_send_message(char *host, int port, GxidMessage *msg)
+{
+ int socket_fd;
+ struct sockaddr_in sin;
+ int count;
+ GxidI32 retval;
+ struct hostent *he;
+
+ if (!port) port = 6951;
+
+ if (!host || strcmp(host,"localhost") )
+ {
+ /* looking it up as localhost can be _SLOW_ on ppp systems */
+ /* FIXME: Could localhost be anything other than loopback? */
+ host = "127.0.0.1";
+ }
+
+ he = gethostbyname(host);
+ if (!he)
+ {
+ fprintf(stderr,"gxid_lib: error looking up %s\n",host);
+ return GXID_RETURN_ERROR;
+ }
+
+ sin.sin_family = he->h_addrtype;
+ sin.sin_port = htons(port);
+ memcpy(&sin.sin_addr,he->h_addr_list[0],he->h_length);
+
+ socket_fd = socket(AF_INET,SOCK_STREAM,0);
+ if (socket_fd < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't get socket");
+ return GXID_RETURN_ERROR;
+ }
+
+ if (connect(socket_fd, (struct sockaddr *)&sin,
+ sizeof sin) < 0)
+ {
+ fprintf(stderr,"gxid_lib: can't connect to %s:%d\n",host,port);
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ count = write(socket_fd,(char *)msg,ntohl(msg->any.length));
+ if (count != ntohl(msg->any.length))
+ {
+ fprintf(stderr,"gxid_lib: error writing");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ /* now read the return code */
+ count = read(socket_fd,(char *)&retval,sizeof(GxidI32));
+ if (count != sizeof(GxidI32))
+ {
+ fprintf(stderr,"gxid_lib: error reading return code");
+ close(socket_fd);
+ return GXID_RETURN_ERROR;
+ }
+
+ close (socket_fd);
+ return ntohl(retval);
+}
+
+/* claim a device. If exclusive, device is claimed exclusively */
+int
+gxid_claim_device(char *host, int port, GxidU32 device, GxidU32 window,
+ int exclusive)
+{
+ GxidClaimDevice msg;
+ msg.type = htonl(GXID_CLAIM_DEVICE);
+ msg.length = htonl(sizeof(GxidClaimDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+ msg.exclusive = htonl(exclusive);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+/* release a device/window pair */
+int
+gxid_release_device(char *host, int port, GxidU32 device, GxidU32 window)
+{
+ GxidReleaseDevice msg;
+ msg.type = htonl(GXID_RELEASE_DEVICE);
+ msg.length = htonl(sizeof(GxidReleaseDevice));
+ msg.device = htonl(device);
+ msg.window = htonl(window);
+
+ return gxid_send_message(host,port,(GxidMessage *)&msg);
+}
+
+#endif /* XINPUT_GXI */
+
diff --git a/gdk/x11/gxid_lib.h b/gdk/x11/gxid_lib.h
new file mode 100644
index 000000000..6a7103bbe
--- /dev/null
+++ b/gdk/x11/gxid_lib.h
@@ -0,0 +1,6 @@
+#include "gxid_proto.h"
+
+int gxid_claim_device(char *host, int port,
+ GxidU32 device, GxidU32 window, int exclusive);
+int gxid_release_device(char *host, int port, GxidU32 device,
+ GxidU32 window);
diff --git a/gdk/x11/gxid_proto.h b/gdk/x11/gxid_proto.h
new file mode 100644
index 000000000..24959b806
--- /dev/null
+++ b/gdk/x11/gxid_proto.h
@@ -0,0 +1,39 @@
+#define GXID_CLAIM_DEVICE 1
+#define GXID_RELEASE_DEVICE 2
+
+#define GXID_RETURN_OK 0
+#define GXID_RETURN_ERROR -1
+
+typedef struct GxidClaimDevice_ GxidClaimDevice;
+typedef struct GxidReleaseDevice_ GxidReleaseDevice;
+typedef struct GxidMessageAny_ GxidMessageAny;
+typedef union GxidMessage_ GxidMessage;
+
+typedef unsigned long GxidU32;
+typedef long GxidI32;
+
+struct GxidClaimDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+ GxidU32 exclusive;
+};
+
+struct GxidReleaseDevice_ {
+ GxidU32 type;
+ GxidU32 length;
+ GxidU32 device;
+ GxidU32 window;
+};
+
+struct GxidMessageAny_ {
+ GxidU32 type;
+ GxidU32 length;
+};
+
+union GxidMessage_ {
+ GxidMessageAny any;
+ GxidClaimDevice claim;
+ GxidReleaseDevice release;
+};