[gtk+/xi2: 214/215] Merge branch 'master' into xi2
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+/xi2: 214/215] Merge branch 'master' into xi2
- Date: Tue, 20 Oct 2009 12:04:16 +0000 (UTC)
commit 3863cdd6984cb465885fbd457536fb65192d4b34
Merge: 44f11d7... cf8c4a6...
Author: Carlos Garnacho <carlos gnome org>
Date: Tue Oct 20 12:33:34 2009 +0200
Merge branch 'master' into xi2
Conflicts:
gdk/gdkdisplay.c
gdk/gdkinternals.h
gdk/gdkwindow.c
gdk/x11/gdkinput-x11.c
gdk/x11/gdkinput-xfree.c
gdk/x11/gdkinput.c
gdk/x11/gdkinputprivate.h
gdk/x11/gdkwindow-x11.c
XInput changes in master that made sense yet have been merged to gdkdevice-xi.c
and gdkdevicemanager-xi.c. The rest is mostly an adaption as-is to the xi2
branch.
NEWS | 130 +
README.in | 5 +
configure.in | 4 +-
demos/gtk-demo/Makefile.am | 1 +
demos/gtk-demo/list_store.c | 146 +-
demos/gtk-demo/spinner.c | 94 +
docs/developers.txt | 9 -
docs/dnd_internals.txt | 2 -
docs/faq/gtk-faq.sgml | 8 +-
docs/refcounting.txt | 8 +-
docs/reference/gdk/tmpl/cairo_interaction.sgml | 2 +-
docs/reference/gdk/tmpl/input_devices.sgml | 7 +-
docs/reference/gdk/tmpl/windows.sgml | 8 +
docs/reference/gtk/Makefile.am | 1 +
docs/reference/gtk/gtk-docs.sgml | 6 +
docs/reference/gtk/gtk-sections.txt | 37 +
docs/reference/gtk/gtk.types | 2 +
docs/reference/gtk/images/spinner.png | Bin 0 -> 3531 bytes
docs/reference/gtk/tmpl/gtkaboutdialog.sgml | 475 --
docs/reference/gtk/tmpl/gtkaccelgroup.sgml | 327 --
docs/reference/gtk/tmpl/gtkaccessible.sgml | 33 -
docs/reference/gtk/tmpl/gtkactivatable.sgml | 98 -
docs/reference/gtk/tmpl/gtkimage.sgml | 2 +-
docs/reference/gtk/tmpl/gtkinputdialog.sgml | 17 +-
docs/reference/gtk/tmpl/gtkprintunixdialog.sgml | 2 +-
docs/reference/gtk/tmpl/gtktoolshell.sgml | 80 -
docs/reference/gtk/visual_index.xml | 3 +
docs/tools/widgets.c | 21 +
docs/tutorial/gtk_tut.sgml | 14 +-
docs/tutorial/gtk_tut_12.es.sgml | 10 +-
docs/widget_system.txt | 2 +-
gdk-pixbuf/io-gdip-utils.c | 68 +-
gdk/directfb/gdkdnd-directfb.c | 4 +-
gdk/directfb/gdkwindow-directfb.c | 26 +-
gdk/gdkdevice.c | 23 +-
gdk/gdkdeviceprivate.h | 3 +-
gdk/gdkdisplay.c | 26 +-
gdk/gdkgc.h | 2 +-
gdk/gdkimage.h | 2 +-
gdk/gdkinternals.h | 4 +-
gdk/gdkpixmap.h | 8 +-
gdk/gdkwindow.c | 107 +-
gdk/gdkwindow.h | 4 +-
gdk/quartz/GdkQuartzView.c | 7 +
gdk/quartz/GdkQuartzWindow.c | 30 +
gdk/quartz/gdkcursor-quartz.c | 21 +-
gdk/quartz/gdkdnd-quartz.c | 6 +
gdk/quartz/gdkevents-quartz.c | 36 +-
gdk/quartz/gdkgeometry-quartz.c | 26 +
gdk/quartz/gdkprivate-quartz.h | 3 +
gdk/quartz/gdkscreen-quartz.c | 32 +-
gdk/quartz/gdkwindow-quartz.c | 134 +-
gdk/quartz/gdkwindow-quartz.h | 2 +
gdk/testgdk.c | 2 +-
gdk/win32/gdkmain-win32.c | 2 -
gdk/win32/gdkwindow-win32.c | 176 +-
gdk/x11/gdkcursor-x11.c | 4 +-
gdk/x11/gdkdevice-core.c | 11 +-
gdk/x11/gdkdevice-xi.c | 86 +-
gdk/x11/gdkdevice-xi.h | 8 +-
gdk/x11/gdkdevice-xi2.c | 11 +-
gdk/x11/gdkdevicemanager-xi.c | 47 +-
gdk/x11/gdkdevicemanager-xi2.c | 14 +-
gdk/x11/gdkwindow-x11.c | 11 +-
gtk/Makefile.am | 42 +-
gtk/gtk.h | 4 +-
gtk/gtk.symbols | 21 +
gtk/gtkaboutdialog.c | 61 +
gtk/gtkaboutdialog.h | 17 +
gtk/gtkaccelgroup.c | 25 +
gtk/gtkaccelgroup.h | 26 +
gtk/gtkaccessible.c | 7 +
gtk/gtkactivatable.c | 1 +
gtk/gtkcellrendererspinner.c | 388 ++
gtk/gtkcellrendererspinner.h | 64 +
gtk/gtkdialog.c | 43 +
gtk/gtkdialog.h | 2 +
gtk/gtkdnd-quartz.c | 134 +-
gtk/gtkentry.c | 10 +-
gtk/gtkfilechooserdefault.c | 2962 +++----------
gtk/gtkfilechooserprivate.h | 68 +-
gtk/gtkfilesystemmodel.c | 2998 +++++++-------
gtk/gtkfilesystemmodel.h | 71 +-
gtk/gtkiconview.c | 20 +-
gtk/gtkimage.c | 21 +-
gtk/gtkinputdialog.h | 8 +-
gtk/gtklabel.c | 28 +-
gtk/gtkmain.c | 13 +
gtk/gtkmarshalers.list | 1 +
gtk/gtkprintbackend.c | 164 +-
gtk/gtkprintbackend.h | 16 +-
gtk/gtkprintcontext.c | 16 +-
gtk/gtkprintoperation-unix.c | 21 +-
gtk/gtkprintunixdialog.c | 28 +-
gtk/gtksearchenginetracker.c | 95 +-
gtk/gtkspinner.c | 627 +++
gtk/gtkspinner.h | 65 +
gtk/gtkstatusicon.c | 2 +-
gtk/gtkstyle.c | 118 +-
gtk/gtkstyle.h | 18 +-
gtk/gtktextlayout.c | 65 +-
gtk/gtktoolbutton.c | 7 +
gtk/gtktoolshell.c | 1 +
gtk/gtktooltip.c | 37 +-
gtk/gtktooltip.h | 3 +
gtk/gtktreemodelfilter.c | 55 +-
gtk/gtkwidget.c | 3 +
gtk/gtkwidget.h | 4 +-
gtk/gtkwindow.c | 7 +
gtk/tests/defaultvalue.c | 9 +-
gtk/tests/filtermodel.c | 291 ++-
modules/engines/ms-windows/xp_theme.c | 3 +
modules/printbackends/cups/gtkcupsutils.c | 5 +
modules/printbackends/cups/gtkcupsutils.h | 3 +
modules/printbackends/cups/gtkprintbackendcups.c | 360 ++-
modules/printbackends/cups/gtkprintercups.c | 12 +
modules/printbackends/cups/gtkprintercups.h | 7 +
modules/printbackends/lpr/gtkprintbackendlpr.c | 2 -
po-properties/af.po | 76 +-
po-properties/am.po | 76 +-
po-properties/ang.po | 76 +-
po-properties/ar.po | 76 +-
po-properties/as.po | 265 +-
po-properties/ast.po | 76 +-
po-properties/az.po | 76 +-
po-properties/az_IR.po | 76 +-
po-properties/be.po | 76 +-
po-properties/be latin po | 76 +-
po-properties/bg.po | 76 +-
po-properties/bn.po | 76 +-
po-properties/bn_IN.po | 3712 ++++++++--------
po-properties/br.po | 76 +-
po-properties/bs.po | 76 +-
po-properties/ca.po | 3586 ++++++++--------
po-properties/ca valencia po | 76 +-
po-properties/crh.po | 76 +-
po-properties/cs.po | 76 +-
po-properties/cy.po | 76 +-
po-properties/da.po | 3474 ++++++++--------
po-properties/de.po | 3474 ++++++++--------
po-properties/dz.po | 76 +-
po-properties/el.po | 76 +-
po-properties/en_CA.po | 76 +-
po-properties/en_GB.po | 3490 ++++++++--------
po-properties/eo.po | 76 +-
po-properties/es.po | 76 +-
po-properties/et.po | 76 +-
po-properties/eu.po | 76 +-
po-properties/fa.po | 76 +-
po-properties/fi.po | 76 +-
po-properties/fr.po | 76 +-
po-properties/ga.po | 76 +-
po-properties/gl.po | 76 +-
po-properties/gu.po | 3646 ++++++++--------
po-properties/he.po | 76 +-
po-properties/hi.po | 76 +-
po-properties/hr.po | 76 +-
po-properties/hu.po | 76 +-
po-properties/hy.po | 76 +-
po-properties/ia.po | 76 +-
po-properties/id.po | 76 +-
po-properties/io.po | 76 +-
po-properties/is.po | 76 +-
po-properties/it.po | 258 +-
po-properties/ja.po | 78 +-
po-properties/ka.po | 76 +-
po-properties/kn.po | 76 +-
po-properties/ko.po | 76 +-
po-properties/ku.po | 76 +-
po-properties/li.po | 76 +-
po-properties/lt.po | 3474 ++++++++--------
po-properties/lv.po | 76 +-
po-properties/mai.po | 3642 ++++++++--------
po-properties/mi.po | 76 +-
po-properties/mk.po | 76 +-
po-properties/ml.po | 3663 ++++++++--------
po-properties/mn.po | 76 +-
po-properties/mr.po | 3664 ++++++++--------
po-properties/ms.po | 76 +-
po-properties/nb.po | 3476 ++++++++--------
po-properties/ne.po | 76 +-
po-properties/nl.po | 76 +-
po-properties/nn.po | 76 +-
po-properties/nso.po | 76 +-
po-properties/oc.po | 76 +-
po-properties/or.po | 3757 ++++++++--------
po-properties/pa.po | 3654 ++++++++--------
po-properties/pl.po | 76 +-
po-properties/ps.po | 76 +-
po-properties/pt.po | 76 +-
po-properties/pt_BR.po | 76 +-
po-properties/ro.po | 95 +-
po-properties/ru.po | 3596 ++++++++--------
po-properties/rw.po | 76 +-
po-properties/si.po | 76 +-
po-properties/sk.po | 76 +-
po-properties/sl.po | 4733 +++++++++++----------
po-properties/sq.po | 76 +-
po-properties/sr.po | 5074 ++++++++++------------
po-properties/sr ije po | 76 +-
po-properties/sr latin po | 5131 ++++++++++------------
po-properties/sv.po | 76 +-
po-properties/ta.po | 76 +-
po-properties/te.po | 76 +-
po-properties/th.po | 76 +-
po-properties/tk.po | 76 +-
po-properties/tr.po | 76 +-
po-properties/tt.po | 76 +-
po-properties/uk.po | 3474 ++++++++--------
po-properties/ur.po | 76 +-
po-properties/uz.po | 76 +-
po-properties/uz cyrillic po | 76 +-
po-properties/vi.po | 76 +-
po-properties/wa.po | 76 +-
po-properties/xh.po | 76 +-
po-properties/yi.po | 76 +-
po-properties/zh_CN.po | 3477 ++++++++--------
po-properties/zh_HK.po | 3571 ++++++++--------
po-properties/zh_TW.po | 3474 ++++++++--------
po/POTFILES.in | 2 +
po/af.po | 435 +-
po/am.po | 410 +-
po/ang.po | 408 +-
po/ar.po | 408 +-
po/as.po | 457 ++-
po/ast.po | 409 +-
po/az.po | 410 +-
po/az_IR.po | 405 +-
po/be.po | 410 +-
po/be latin po | 410 +-
po/bg.po | 2226 +++++-----
po/bn.po | 407 +-
po/bn_IN.po | 408 +-
po/br.po | 406 +-
po/bs.po | 410 +-
po/ca.po | 2319 +++++-----
po/ca valencia po | 410 +-
po/crh.po | 415 +-
po/cs.po | 410 +-
po/cy.po | 410 +-
po/da.po | 2235 +++++-----
po/de.po | 2236 +++++-----
po/dz.po | 410 +-
po/el.po | 1177 +++---
po/en_CA.po | 410 +-
po/en_GB.po | 2239 +++++-----
po/eo.po | 410 +-
po/es.po | 2283 +++++-----
po/et.po | 446 +-
po/eu.po | 409 +-
po/fa.po | 410 +-
po/fi.po | 2256 +++++-----
po/fr.po | 410 +-
po/ga.po | 408 +-
po/gl.po | 422 +-
po/gu.po | 2269 +++++-----
po/he.po | 410 +-
po/hi.po | 412 +-
po/hr.po | 410 +-
po/hu.po | 408 +-
po/hy.po | 410 +-
po/ia.po | 410 +-
po/id.po | 410 +-
po/io.po | 410 +-
po/is.po | 410 +-
po/it.po | 2229 +++++-----
po/ja.po | 409 +-
po/ka.po | 410 +-
po/kn.po | 408 +-
po/ko.po | 408 +-
po/ku.po | 410 +-
po/li.po | 410 +-
po/lt.po | 2240 +++++-----
po/lv.po | 410 +-
po/mai.po | 2272 +++++-----
po/mi.po | 410 +-
po/mk.po | 410 +-
po/ml.po | 2269 +++++-----
po/mn.po | 415 +-
po/mr.po | 2275 +++++-----
po/ms.po | 410 +-
po/nb.po | 393 +-
po/ne.po | 410 +-
po/nl.po | 2630 ++++++------
po/nn.po | 410 +-
po/nso.po | 410 +-
po/oc.po | 408 +-
po/or.po | 364 +-
po/pa.po | 2270 +++++-----
po/pl.po | 2593 ++++++------
po/ps.po | 410 +-
po/pt.po | 409 +-
po/pt_BR.po | 372 +-
po/ro.po | 2252 +++++-----
po/ru.po | 2390 +++++-----
po/rw.po | 415 +-
po/si.po | 410 +-
po/sk.po | 410 +-
po/sl.po | 630 ++--
po/sq.po | 410 +-
po/sr.po | 417 +-
po/sr ije po | 410 +-
po/sr latin po | 417 +-
po/sv.po | 2834 ++++++-------
po/ta.po | 408 +-
po/te.po | 408 +-
po/th.po | 408 +-
po/tk.po | 410 +-
po/tr.po | 415 +-
po/tt.po | 410 +-
po/uk.po | 2214 +++++-----
po/ur.po | 406 +-
po/uz.po | 410 +-
po/uz cyrillic po | 410 +-
po/vi.po | 413 +-
po/wa.po | 410 +-
po/xh.po | 410 +-
po/yi.po | 410 +-
po/zh_CN.po | 2233 +++++-----
po/zh_HK.po | 2240 +++++-----
po/zh_TW.po | 2230 +++++-----
tests/autotestkeywords.cc | 2 +
tests/testinput.c | 2 +
323 files changed, 92976 insertions(+), 90540 deletions(-)
---
diff --cc gdk/gdkdevice.c
index 67321e1,0000000..2fa58ab
mode 100644,000000..100644
--- a/gdk/gdkdevice.c
+++ b/gdk/gdkdevice.c
@@@ -1,1035 -1,0 +1,1052 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gdkdevice.h"
+#include "gdkdeviceprivate.h"
+#include "gdkintl.h"
+#include "gdkinternals.h"
+#include "gdkalias.h"
+
+#define GDK_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_DEVICE, GdkDevicePrivate))
+
+typedef struct _GdkDevicePrivate GdkDevicePrivate;
+typedef struct _GdkAxisInfo GdkAxisInfo;
+
+struct _GdkAxisInfo
+{
+ GdkAtom label;
+ GdkAxisUse use;
+
+ gdouble min_axis;
+ gdouble max_axis;
+
+ gdouble min_value;
+ gdouble max_value;
+ gdouble resolution;
+};
+
+struct _GdkDevicePrivate
+{
+ GdkDeviceManager *device_manager;
+ GdkDisplay *display;
+ GdkDevice *relative;
+ GdkDeviceType type;
+ GArray *axes;
+};
+
+static void gdk_device_dispose (GObject *object);
+static void gdk_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gdk_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+
+G_DEFINE_ABSTRACT_TYPE (GdkDevice, gdk_device, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_DISPLAY,
+ PROP_DEVICE_MANAGER,
+ PROP_NAME,
+ PROP_RELATIVE,
+ PROP_TYPE,
+ PROP_INPUT_SOURCE,
+ PROP_INPUT_MODE,
+ PROP_HAS_CURSOR,
+ PROP_N_AXES
+};
+
+
+static void
+gdk_device_class_init (GdkDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gdk_device_dispose;
+ object_class->set_property = gdk_device_set_property;
+ object_class->get_property = gdk_device_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_DISPLAY,
+ g_param_spec_object ("display",
+ P_("Device Display"),
+ P_("Display to which the device belongs to"),
+ GDK_TYPE_DISPLAY,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_MANAGER,
+ g_param_spec_object ("device-manager",
+ P_("Device manager"),
+ P_("Device manager to which the device belongs to"),
+ GDK_TYPE_DEVICE_MANAGER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ P_("Device name"),
+ P_("Device name"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_TYPE,
+ g_param_spec_enum ("type",
+ P_("Device type"),
+ P_("Device role in the device manager"),
+ GDK_TYPE_DEVICE_TYPE,
+ GDK_DEVICE_TYPE_MASTER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_RELATIVE,
+ g_param_spec_object ("relative",
+ P_("Relative device"),
+ P_("Corresponding pointer or keyboard to this device"),
+ GDK_TYPE_DEVICE,
+ G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_INPUT_SOURCE,
+ g_param_spec_enum ("input-source",
+ P_("Input source"),
+ P_("Source type for the device"),
+ GDK_TYPE_INPUT_SOURCE,
+ GDK_SOURCE_MOUSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_INPUT_MODE,
+ g_param_spec_enum ("input-mode",
+ P_("Input mode for the device"),
+ P_("Input mode for the device"),
+ GDK_TYPE_INPUT_MODE,
+ GDK_MODE_DISABLED,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_HAS_CURSOR,
+ g_param_spec_boolean ("has-cursor",
+ P_("Whether the device has cursor"),
+ P_("Whether there is a visible cursor following device motion"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_N_AXES,
+ g_param_spec_uint ("n-axes",
+ P_("Number of axes in the device"),
+ P_("Number of axes in the device"),
+ 0, G_MAXUINT, 0,
+ G_PARAM_READABLE));
+
+ g_type_class_add_private (object_class, sizeof (GdkDevicePrivate));
+}
+
+static void
+gdk_device_init (GdkDevice *device)
+{
+ GdkDevicePrivate *priv;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+ priv->axes = g_array_new (FALSE, TRUE, sizeof (GdkAxisInfo));
+}
+
+static void
+gdk_device_dispose (GObject *object)
+{
+ GdkDevicePrivate *priv;
+ GdkDevice *device;
+
+ device = GDK_DEVICE (object);
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ if (priv->relative)
+ {
+ _gdk_device_set_relative (priv->relative, NULL);
+ g_object_unref (priv->relative);
+ priv->relative = NULL;
+ }
+
+ if (priv->axes)
+ {
+ g_array_free (priv->axes, TRUE);
+ priv->axes = NULL;
+ }
+
+ g_free (device->name);
+ g_free (device->keys);
+ g_free (device->axes);
+
+ device->name = NULL;
+ device->keys = NULL;
+ device->axes = NULL;
+
+ G_OBJECT_CLASS (gdk_device_parent_class)->dispose (object);
+}
+
+static void
+gdk_device_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDevice *device = GDK_DEVICE (object);
+ GdkDevicePrivate *priv = GDK_DEVICE_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DISPLAY:
+ priv->display = g_value_get_object (value);
+ break;
+ case PROP_DEVICE_MANAGER:
+ priv->device_manager = g_value_get_object (value);
+ break;
+ case PROP_NAME:
+ if (device->name)
+ g_free (device->name);
+
+ device->name = g_value_dup_string (value);
+ break;
+ case PROP_TYPE:
+ priv->type = g_value_get_enum (value);
+ break;
+ case PROP_INPUT_SOURCE:
+ device->source = g_value_get_enum (value);
+ break;
+ case PROP_INPUT_MODE:
+ gdk_device_set_mode (device, g_value_get_enum (value));
+ break;
+ case PROP_HAS_CURSOR:
+ device->has_cursor = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdk_device_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDevice *device = GDK_DEVICE (object);
+ GdkDevicePrivate *priv = GDK_DEVICE_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DISPLAY:
+ g_value_set_object (value, priv->display);
+ break;
+ case PROP_DEVICE_MANAGER:
+ g_value_set_object (value, priv->device_manager);
+ break;
+ case PROP_RELATIVE:
+ g_value_set_object (value, priv->relative);
+ break;
+ case PROP_NAME:
+ g_value_set_string (value,
+ device->name);
+ break;
+ case PROP_TYPE:
+ g_value_set_enum (value, priv->type);
+ break;
+ case PROP_INPUT_SOURCE:
+ g_value_set_enum (value, device->source);
+ break;
+ case PROP_INPUT_MODE:
+ g_value_set_enum (value, device->mode);
+ break;
+ case PROP_HAS_CURSOR:
+ g_value_set_boolean (value,
+ device->has_cursor);
+ break;
+ case PROP_N_AXES:
+ g_value_set_uint (value, priv->axes->len);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+void
+gdk_device_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask)
+{
+ g_return_if_fail (GDK_IS_DEVICE (device));
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_DEVICE_GET_CLASS (device)->get_state)
+ GDK_DEVICE_GET_CLASS (device)->get_state (device, window, axes, mask);
+}
+
+/**
+ * gdk_device_get_history:
+ * @device: a #GdkDevice
+ * @window: the window with respect to which which the event coordinates will be reported
+ * @start: starting timestamp for range of events to return
+ * @stop: ending timestamp for the range of events to return
+ * @events: location to store a newly-allocated array of #GdkTimeCoord, or %NULL
+ * @n_events: location to store the length of @events, or %NULL
+ *
+ * Obtains the motion history for a device; given a starting and
+ * ending timestamp, return all events in the motion history for
+ * the device in the given range of time. Some windowing systems
+ * do not support motion history, in which case, %FALSE will
+ * be returned. (This is not distinguishable from the case where
+ * motion history is supported and no events were found.)
+ *
+ * Return value: %TRUE if the windowing system supports motion history and
+ * at least one event was found.
+ **/
+gboolean
+gdk_device_get_history (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events)
+{
+ g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ if (!GDK_DEVICE_GET_CLASS (device)->get_history)
+ return FALSE;
+
+ return GDK_DEVICE_GET_CLASS (device)->get_history (device, window,
+ start, stop,
+ events, n_events);
+}
+
+GdkTimeCoord **
+_gdk_device_allocate_history (GdkDevice *device,
+ guint n_events)
+{
+ GdkTimeCoord **result = g_new (GdkTimeCoord *, n_events);
+ gint i;
+
+ for (i = 0; i < n_events; i++)
+ result[i] = g_malloc (sizeof (GdkTimeCoord) -
+ sizeof (double) * (GDK_MAX_TIMECOORD_AXES - device->num_axes));
+ return result;
+}
+
+void
+gdk_device_free_history (GdkTimeCoord **events,
+ gint n_events)
+{
+ gint i;
+
+ for (i = 0; i < n_events; i++)
+ g_free (events[i]);
+
+ g_free (events);
+}
+
+void
+gdk_device_set_source (GdkDevice *device,
+ GdkInputSource source)
+{
+ g_return_if_fail (GDK_IS_DEVICE (device));
+
+ device->source = source;
+}
+
+gboolean
+gdk_device_set_mode (GdkDevice *device,
+ GdkInputMode mode)
+{
+ g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
+
+ if (device->mode == mode)
+ return TRUE;
+
+ if (mode == GDK_MODE_DISABLED &&
+ gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER)
+ return FALSE;
+
+ /* FIXME: setting has_cursor when mode is window? */
+
+ device->mode = mode;
+ g_object_notify (G_OBJECT (device), "input-mode");
+
+ if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
+ _gdk_input_check_extension_events (device);
+
+ return TRUE;
+}
+
+void
+gdk_device_set_key (GdkDevice *device,
+ guint index,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ g_return_if_fail (GDK_IS_DEVICE (device));
+ g_return_if_fail (index < device->num_keys);
+
+ device->keys[index].keyval = keyval;
+ device->keys[index].modifiers = modifiers;
+}
+
+void
+gdk_device_set_axis_use (GdkDevice *device,
+ guint index,
+ GdkAxisUse use)
+{
+ GdkDevicePrivate *priv;
+ GdkAxisInfo *info;
+
+ g_return_if_fail (GDK_IS_DEVICE (device));
+ g_return_if_fail (index < device->num_axes);
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+ info = &g_array_index (priv->axes, GdkAxisInfo, index);
+ info->use = use;
+
+ device->axes[index].use = use;
+
+ switch (use)
+ {
+ case GDK_AXIS_X:
+ case GDK_AXIS_Y:
+ device->axes[index].min = info->min_value = 0;
+ device->axes[index].max = info->max_value = 0;
+ break;
+ case GDK_AXIS_XTILT:
+ case GDK_AXIS_YTILT:
+ device->axes[index].min = info->min_value = -1;
+ device->axes[index].max = info->max_value = 1;
+ break;
+ default:
+ device->axes[index].min = info->min_value = 0;
+ device->axes[index].max = info->max_value = 1;
+ break;
+ }
+}
+
+/**
+ * gdk_device_get_display:
+ * @device: a #GdkDevice
+ *
+ * Returns the #GdkDisplay to which @device pertains.
+ *
+ * Returns: a #GdkDisplay. This memory is owned by GTK+,
+ * and must not be freed or unreffed.
+ **/
+GdkDisplay *
+gdk_device_get_display (GdkDevice *device)
+{
+ GdkDevicePrivate *priv;
+
+ g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ return priv->display;
+}
+
+GdkDevice *
+gdk_device_get_relative (GdkDevice *device)
+{
+ GdkDevicePrivate *priv;
+
+ g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ return priv->relative;
+}
+
+void
+_gdk_device_set_relative (GdkDevice *device,
+ GdkDevice *relative)
+{
+ GdkDevicePrivate *priv;
+
+ g_return_if_fail (GDK_IS_DEVICE (device));
+ g_return_if_fail (GDK_IS_DEVICE (relative));
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ if (priv->relative == relative)
+ return;
+
+ if (priv->relative)
+ {
+ g_object_unref (priv->relative);
+ priv->relative = NULL;
+ }
+
+ if (relative)
+ priv->relative = g_object_ref (relative);
+}
+
+/**
+ * gdk_device_get_device_type:
+ * @device: a #GdkDevice
+ *
+ * Returns the device type for @device.
+ *
+ * Returns: the #GdkDeviceType for @device.
+ **/
+GdkDeviceType
+gdk_device_get_device_type (GdkDevice *device)
+{
+ GdkDevicePrivate *priv;
+
+ g_return_val_if_fail (GDK_IS_DEVICE (device), GDK_DEVICE_TYPE_MASTER);
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ return priv->type;
+}
+
+/**
+ * gdk_device_list_axes:
+ * @device: a #GdkDevice
+ *
+ * Returns a #GList of #GdkAtom<!-- -->s, containing the labels for
+ * the axes that @device currently has.
+ *
+ * Returns: A #GList of #GdkAtom<!-- -->s, free with g_list_free().
+ **/
+GList *
+gdk_device_list_axes (GdkDevice *device)
+{
+ GdkDevicePrivate *priv;
+ GList *axes = NULL;
+ gint i;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ for (i = 0; i < priv->axes->len; i++)
+ {
+ GdkAxisInfo axis_info;
+
+ axis_info = g_array_index (priv->axes, GdkAxisInfo, i);
+ axes = g_list_prepend (axes, GDK_ATOM_TO_POINTER (axis_info.label));
+ }
+
+ return g_list_reverse (axes);
+}
+
+gboolean
+gdk_device_get_axis_value (GdkDevice *device,
+ gdouble *axes,
+ GdkAtom axis_label,
+ gdouble *value)
+{
+ GdkDevicePrivate *priv;
+ gint i;
+
+ g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
+
+ if (axes == NULL)
+ return FALSE;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ for (i = 0; i < priv->axes->len; i++)
+ {
+ GdkAxisInfo axis_info;
+
+ axis_info = g_array_index (priv->axes, GdkAxisInfo, i);
+
+ if (axis_info.label != axis_label)
+ continue;
+
+ if (value)
+ *value = axes[i];
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * gdk_device_get_axis:
+ * @device: a #GdkDevice
+ * @axes: pointer to an array of axes
+ * @use: the use to look for
+ * @value: location to store the found value.
+ *
+ * Interprets an array of double as axis values for a given device,
+ * and locates the value in the array for a given axis use.
+ *
+ * Return value: %TRUE if the given axis use was found, otherwise %FALSE
+ **/
+gboolean
+gdk_device_get_axis (GdkDevice *device,
+ gdouble *axes,
+ GdkAxisUse use,
+ gdouble *value)
+{
+ GdkDevicePrivate *priv;
+ gint i;
+
+ g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
+
+ if (axes == NULL)
+ return FALSE;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ g_return_val_if_fail (priv->axes != NULL, FALSE);
+
+ for (i = 0; i < priv->axes->len; i++)
+ {
+ GdkAxisInfo axis_info;
+
+ axis_info = g_array_index (priv->axes, GdkAxisInfo, i);
+
+ if (axis_info.use != use)
+ continue;
+
+ if (value)
+ *value = axes[i];
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * gdk_device_grab:
+ * @device: a #GdkDevice
+ * @window: the #GdkWindow which will own the grab (the grab window)
+ * @grab_ownership:
+ * @owner_events: if %FALSE then all device events are reported with respect to
+ * @window and are only reported if selected by @event_mask. If
+ * %TRUE then pointer events for this application are reported
+ * as normal, but pointer events outside this application are
+ * reported with respect to @window and only if selected by
+ * @event_mask. In either mode, unreported events are discarded.
+ * @event_mask: specifies the event mask, which is used in accordance with
+ * @owner_events.
+ * @cursor: the cursor to display while the grab is active if the device is
+ * a pointer. If this is %NULL then the normal cursors are used for
+ * @window and its descendants, and the cursor for @window is used
+ * elsewhere.
+ * @time_: the timestamp of the event which led to this pointer grab. This
+ * usually comes from the #GdkEvent struct, though %GDK_CURRENT_TIME
+ * can be used if the time isn't known.
+ *
+ * Grabs the device so that all events coming from this device are passed to
- * this application until the device is ungrabbed with gdk_display_device_ungrab(),
++ * this application until the device is ungrabbed with gdk_device_ungrab(),
+ * or the window becomes unviewable. This overrides any previous grab on the device
+ * by this client.
+ *
+ * Device grabs are used for operations which need complete control over the
+ * given device events (either pointer or keyboard). For example in GTK+ this
+ * is used for Drag and Drop operations, popup menus and such.
+ *
+ * Note that if the event mask of an X window has selected both button press
+ * and button release events, then a button press event will cause an automatic
+ * pointer grab until the button is released. X does this automatically since
+ * most applications expect to receive button press and release events in pairs.
+ * It is equivalent to a pointer grab on the window with @owner_events set to
+ * %TRUE.
+ *
+ * If you set up anything at the time you take the grab that needs to be
+ * cleaned up when the grab ends, you should handle the #GdkEventGrabBroken
+ * events that are emitted when the grab ends unvoluntarily.
+ *
+ * Returns: %GDK_GRAB_SUCCESS if the grab was successful.
+ **/
+GdkGrabStatus
+gdk_device_grab (GdkDevice *device,
+ GdkWindow *window,
+ GdkGrabOwnership grab_ownership,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkCursor *cursor,
+ guint32 time_)
+{
+ GdkGrabStatus res;
+ GdkWindow *native;
+
+ g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+
+ if (_gdk_native_windows)
+ native = window;
+ else
+ native = gdk_window_get_toplevel (window);
+
+ while (((GdkWindowObject *) native)->window_type == GDK_WINDOW_OFFSCREEN)
+ {
+ native = gdk_offscreen_window_get_embedder (native);
+
+ if (native == NULL ||
+ (!_gdk_window_has_impl (native) &&
+ !gdk_window_is_viewable (native)))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ native = gdk_window_get_toplevel (native);
+ }
+
+ res = _gdk_windowing_device_grab (device,
+ window,
+ native,
+ owner_events,
+ event_mask,
+ NULL,
+ cursor,
+ time_);
+
+ if (res == GDK_GRAB_SUCCESS)
+ {
+ GdkDisplay *display;
+ gulong serial;
+
+ display = gdk_drawable_get_display (window);
+ serial = _gdk_windowing_window_get_next_serial (display);
+
+ _gdk_display_add_device_grab (display,
+ device,
+ window,
+ native,
+ GDK_OWNERSHIP_NONE,
+ owner_events,
+ event_mask,
+ serial,
+ time_,
+ FALSE);
+ }
+
+ return res;
+}
+
+/* Private API */
+void
+_gdk_device_reset_axes (GdkDevice *device)
+{
+ GdkDevicePrivate *priv;
+ gint i;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ for (i = priv->axes->len - 1; i >= 0; i--)
+ g_array_remove_index (priv->axes, i);
+
+ g_object_notify (G_OBJECT (device), "n-axes");
+
+ /* This is done for backwards compatibility */
+ g_free (device->axes);
+ device->axes = NULL;
+}
+
+guint
+_gdk_device_add_axis (GdkDevice *device,
+ GdkAtom label_atom,
+ GdkAxisUse use,
+ gdouble min_value,
+ gdouble max_value,
+ gdouble resolution)
+{
+ GdkDevicePrivate *priv;
+ GdkAxisInfo axis_info;
+ guint pos;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ axis_info.use = use;
+ axis_info.label = label_atom;
+ axis_info.min_value = min_value;
+ axis_info.max_value = max_value;
+ axis_info.resolution = resolution;
+
+ switch (use)
+ {
+ case GDK_AXIS_X:
+ case GDK_AXIS_Y:
+ axis_info.min_axis = 0.;
+ axis_info.max_axis = 0.;
+ break;
+ case GDK_AXIS_XTILT:
+ case GDK_AXIS_YTILT:
+ axis_info.min_axis = -1.;
+ axis_info.max_axis = 1.;
+ break;
+ default:
+ axis_info.min_axis = 0.;
+ axis_info.max_axis = 1.;
+ break;
+ }
+
+ priv->axes = g_array_append_val (priv->axes, axis_info);
+ device->num_axes = priv->axes->len;
+ pos = device->num_axes - 1;
+
+ /* This is done for backwards compatibility, since the public
+ * struct doesn't actually store the device data.
+ */
+ device->axes = g_realloc (device->axes, sizeof (GdkDeviceAxis) * priv->axes->len);
+ device->axes[pos].use = axis_info.use;
+ device->axes[pos].min = axis_info.min_axis;
+ device->axes[pos].max = axis_info.max_axis;
+
+ g_object_notify (G_OBJECT (device), "n-axes");
+
+ return pos;
+}
+
+void
+_gdk_device_set_keys (GdkDevice *device,
+ guint num_keys)
+{
+ if (device->keys)
+ g_free (device->keys);
+
+ device->num_keys = num_keys;
+ device->keys = g_new0 (GdkDeviceKey, num_keys);
+}
+
+GdkAxisInfo *
+find_axis_info (GArray *array,
+ GdkAxisUse use)
+{
+ GdkAxisInfo *info;
+ gint i;
+
+ for (i = 0; i < GDK_AXIS_LAST; i++)
+ {
+ info = &g_array_index (array, GdkAxisInfo, i);
+
+ if (info->use == use)
+ return info;
+ }
+
+ return NULL;
+}
+
+GdkAxisUse
+_gdk_device_get_axis_use (GdkDevice *device,
+ guint index)
+{
+ GdkDevicePrivate *priv;
+ GdkAxisInfo info;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ info = g_array_index (priv->axes, GdkAxisInfo, index);
+ return info.use;
+}
+
+gboolean
+_gdk_device_translate_window_coord (GdkDevice *device,
+ GdkWindow *window,
+ guint index,
+ gdouble value,
+ gdouble *axis_value)
+{
+ GdkDevicePrivate *priv;
+ GdkAxisInfo axis_info;
+ GdkAxisInfo *axis_info_x, *axis_info_y;
+ gdouble device_width, device_height;
+ gdouble x_offset, y_offset;
+ gdouble x_scale, y_scale;
++ gdouble x_min, y_min;
+ gdouble x_resolution, y_resolution;
+ gdouble device_aspect;
+ gint window_width, window_height;
+ GdkWindowObject *window_private;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ if (index >= priv->axes->len)
+ return FALSE;
+
+ axis_info = g_array_index (priv->axes, GdkAxisInfo, index);
+
+ if (axis_info.use != GDK_AXIS_X &&
+ axis_info.use != GDK_AXIS_Y)
+ return FALSE;
+
+ if (axis_info.use == GDK_AXIS_X)
+ {
+ axis_info_x = &axis_info;
+ axis_info_y = find_axis_info (priv->axes, GDK_AXIS_Y);
+ }
+ else
+ {
+ axis_info_x = find_axis_info (priv->axes, GDK_AXIS_X);
+ axis_info_y = &axis_info;
+ }
+
+ device_width = axis_info_x->max_value - axis_info_x->min_value;
+ device_height = axis_info_y->max_value - axis_info_y->min_value;
+
++ if (device_width > 0)
++ x_min = axis_info_x->min_value;
++ else
++ {
++ device_width = gdk_screen_get_width (gdk_drawable_get_screen (window));
++ x_min = 0;
++ }
++
++ if (device_height > 0)
++ y_min = axis_info_y->min_value;
++ else
++ {
++ device_height = gdk_screen_get_height (gdk_drawable_get_screen (window));
++ y_min = 0;
++ }
++
+ window_private = (GdkWindowObject *) window;
+ gdk_drawable_get_size (window, &window_width, &window_height);
+
+ x_resolution = axis_info_x->resolution;
+ y_resolution = axis_info_y->resolution;
+
+ /*
+ * Some drivers incorrectly report the resolution of the device
+ * as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
+ * This causes the device_aspect to become NaN and totally
+ * breaks windowed mode. If this is the case, the best we can
+ * do is to assume the resolution is non-zero is equal in both
+ * directions (which is true for many devices). The absolute
+ * value of the resolution doesn't matter since we only use the
+ * ratio.
+ */
+ if (x_resolution == 0 || y_resolution == 0)
+ {
+ x_resolution = 1;
+ y_resolution = 1;
+ }
+
+ device_aspect = (device_height * y_resolution) /
+ (device_width * x_resolution);
+
+ if (device_aspect * window_width >= window_height)
+ {
+ /* device taller than window */
+ x_scale = window_width / device_width;
+ y_scale = (x_scale * x_resolution) / y_resolution;
+
+ x_offset = 0;
+ y_offset = - (device_height * y_scale - window_height) / 2;
+ }
+ else
+ {
+ /* window taller than device */
+ y_scale = window_height / device_height;
+ x_scale = (y_scale * y_resolution) / x_resolution;
+
+ y_offset = 0;
+ x_offset = - (device_width * x_scale - window_width) / 2;
+ }
+
+ if (axis_value)
+ {
+ if (axis_info.use == GDK_AXIS_X)
- *axis_value = x_offset + x_scale * (value - axis_info.min_value);
++ *axis_value = x_offset + x_scale * (value - x_min);
+ else
- *axis_value = y_offset + y_scale * (value - axis_info.min_value);
++ *axis_value = y_offset + y_scale * (value - y_min);
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gdk_device_translate_screen_coord (GdkDevice *device,
+ GdkWindow *window,
+ gint window_root_x,
+ gint window_root_y,
+ guint index,
+ gdouble value,
+ gdouble *axis_value)
+{
+ GdkDevicePrivate *priv;
+ GdkAxisInfo axis_info;
+ gdouble axis_width, scale, offset;
+ GdkWindowObject *window_private;
+
+ if (device->mode != GDK_MODE_SCREEN)
+ return FALSE;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ if (index >= priv->axes->len)
+ return FALSE;
+
+ axis_info = g_array_index (priv->axes, GdkAxisInfo, index);
+
+ if (axis_info.use != GDK_AXIS_X &&
+ axis_info.use != GDK_AXIS_Y)
+ return FALSE;
+
+ axis_width = axis_info.max_value - axis_info.min_value;
+ window_private = (GdkWindowObject *) window;
+
+ if (axis_info.use == GDK_AXIS_X)
+ {
+ scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / axis_width;
+ offset = - window_root_x - window_private->abs_x;
+ }
+ else
+ {
+ scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / axis_width;
+ offset = - window_root_y - window_private->abs_y;
+ }
+
+ if (axis_value)
+ *axis_value = offset + scale * (value - axis_info.min_value);
+
+ return TRUE;
+}
+
+gboolean
+_gdk_device_translate_axis (GdkDevice *device,
+ guint index,
+ gdouble value,
+ gdouble *axis_value)
+{
+ GdkDevicePrivate *priv;
+ GdkAxisInfo axis_info;
+ gdouble axis_width, out;
+
+ priv = GDK_DEVICE_GET_PRIVATE (device);
+
+ if (index >= priv->axes->len)
+ return FALSE;
+
+ axis_info = g_array_index (priv->axes, GdkAxisInfo, index);
+
+ if (axis_info.use == GDK_AXIS_X ||
+ axis_info.use == GDK_AXIS_Y)
+ return FALSE;
+
+ axis_width = axis_info.max_value - axis_info.min_value;
+ out = (axis_info.max_axis * (value - axis_info.min_value) +
+ axis_info.min_axis * (axis_info.max_value - value)) / axis_width;
+
+ if (axis_value)
+ *axis_value = out;
+
+ return TRUE;
+}
+
+#define __GDK_DEVICE_C__
+#include "gdkaliasdef.c"
diff --cc gdk/gdkdeviceprivate.h
index 507cf28,0000000..9ce5875
mode 100644,000000..100644
--- a/gdk/gdkdeviceprivate.h
+++ b/gdk/gdkdeviceprivate.h
@@@ -1,134 -1,0 +1,135 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#ifndef __GDK_DEVICE_PRIVATE_H__
+#define __GDK_DEVICE_PRIVATE_H__
+
+#include <gdk/gdkdevice.h>
+#include <gdk/gdkevents.h>
+
+G_BEGIN_DECLS
+
+#define GDK_DEVICE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE, GdkDeviceClass))
+#define GDK_IS_DEVICE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE))
+#define GDK_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE, GdkDeviceClass))
+
+typedef struct _GdkDeviceClass GdkDeviceClass;
+
+struct _GdkDeviceClass
+{
+ GObjectClass parent_class;
+
+ gboolean (* get_history) (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events);
+
+ void (* get_state) (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask);
+
+ void (* set_window_cursor) (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor);
+
+ void (* warp) (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y);
+ gboolean (* query_state) (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask);
+ GdkGrabStatus (* grab) (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_);
+ void (*ungrab) (GdkDevice *device,
+ guint32 time_);
+
+ GdkWindow * (* window_at_position) (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask);
++ GdkModifierType *mask,
++ gboolean get_toplevel);
+ void (* select_window_events) (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask);
+};
+
+void _gdk_device_set_relative (GdkDevice *device,
+ GdkDevice *relative);
+
+void _gdk_device_reset_axes (GdkDevice *device);
+guint _gdk_device_add_axis (GdkDevice *device,
+ GdkAtom label_atom,
+ GdkAxisUse use,
+ gdouble min_value,
+ gdouble max_value,
+ gdouble resolution);
+
+void _gdk_device_set_keys (GdkDevice *device,
+ guint num_keys);
+
+GdkAxisUse _gdk_device_get_axis_use (GdkDevice *device,
+ guint index);
+
+gboolean _gdk_device_translate_window_coord (GdkDevice *device,
+ GdkWindow *window,
+ guint index,
+ gdouble value,
+ gdouble *axis_value);
+
+gboolean _gdk_device_translate_screen_coord (GdkDevice *device,
+ GdkWindow *window,
+ gint window_root_x,
+ gint window_root_y,
+ guint index,
+ gdouble value,
+ gdouble *axis_value);
+
+gboolean _gdk_device_translate_axis (GdkDevice *device,
+ guint index,
+ gdouble value,
+ gdouble *axis_value);
+
+GdkTimeCoord ** _gdk_device_allocate_history (GdkDevice *device,
+ guint n_events);
+
+void _gdk_input_check_extension_events (GdkDevice *device);
+
+
+G_END_DECLS
+
+#endif /* __GDK_DEVICE_PRIVATE_H__ */
diff --cc gdk/gdkdisplay.c
index e39e10e,c2064ba..0c5dd79
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@@ -807,7 -510,7 +807,7 @@@ gdk_display_real_get_window_at_device_p
GdkWindow *window;
gint x, y;
- window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL);
- window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL, FALSE);
++ window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
/* This might need corrections, as the native window returned
may contain client side children */
@@@ -1291,9 -916,7 +1291,8 @@@ get_current_toplevel (GdkDisplay *
int x, y;
GdkModifierType state;
- pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state);
- pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state, TRUE);
++ pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
+
if (pointer_window != NULL &&
(GDK_WINDOW_DESTROYED (pointer_window) ||
GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
@@@ -1421,27 -1031,22 +1407,25 @@@ switch_to_pointer_grab (GdkDispla
}
void
-_gdk_display_pointer_grab_update (GdkDisplay *display,
- gulong current_serial)
+_gdk_display_device_grab_update (GdkDisplay *display,
+ GdkDevice *device,
+ gulong current_serial)
{
- GdkPointerGrabInfo *current_grab, *next_grab;
+ GdkDeviceGrabInfo *current_grab, *next_grab;
+ GList *grabs;
guint32 time;
-
+
time = display->last_event_time;
+ grabs = g_hash_table_lookup (display->device_grabs, device);
- while (display->pointer_grabs != NULL)
+ while (grabs != NULL)
{
- current_grab = display->pointer_grabs->data;
+ current_grab = grabs->data;
if (current_grab->serial_start > current_serial)
- return; /* Hasn't started yet */
+ return; /* Hasn't started yet */
-
+
- if (current_grab->serial_end > current_serial ||
- (current_grab->serial_end == current_serial &&
- current_grab->grab_one_pointer_release_event))
+ if (current_grab->serial_end > current_serial)
{
/* This one hasn't ended yet.
its the currently active one or scheduled to be active */
diff --cc gdk/gdkinternals.h
index 3199186,0681bdc..69e4c26
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@@ -182,12 -182,10 +182,11 @@@ typedef struc
guint event_mask;
gboolean implicit;
guint32 time;
+ GdkGrabOwnership ownership;
- gboolean activated;
- gboolean implicit_ungrab;
-} GdkPointerGrabInfo;
+ guint activated : 1;
+ guint implicit_ungrab : 1;
- guint grab_one_pointer_release_event : 1;
+} GdkDeviceGrabInfo;
typedef struct _GdkInputWindow GdkInputWindow;
@@@ -473,13 -457,12 +472,14 @@@ void _gdk_windowing_get_device_st
gint *x,
gint *y,
GdkModifierType *mask);
-GdkWindow* _gdk_windowing_window_at_pointer (GdkDisplay *display,
- gint *win_x,
- gint *win_y,
- GdkModifierType *mask,
- gboolean get_toplevel);
-GdkGrabStatus _gdk_windowing_pointer_grab (GdkWindow *window,
+GdkWindow* _gdk_windowing_window_at_device_position (GdkDisplay *display,
+ GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask);
++ GdkModifierType *mask,
++ gboolean get_toplevel);
+GdkGrabStatus _gdk_windowing_device_grab (GdkDevice *device,
+ GdkWindow *window,
GdkWindow *native,
gboolean owner_events,
GdkEventMask event_mask,
diff --cc gdk/gdkwindow.c
index 17d35a4,2bb5551..fd1bfaa
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@@ -1197,37 -1160,67 +1198,73 @@@ get_native_device_event_mask (GdkWindow
if (_gdk_native_windows ||
private->window_type == GDK_WINDOW_ROOT ||
private->window_type == GDK_WINDOW_FOREIGN)
- return private->event_mask;
+ return event_mask;
else
{
- return
- /* We need thse for all native window so we can emulate
- events on children: */
+ GdkEventMask mask;
+
+ /* Do whatever the app asks to, since the app
+ * may be asking for weird things for native windows,
+ * but filter out things that override the special
+ * requests below. */
+ mask = private->event_mask &
+ ~(GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_BUTTON1_MOTION_MASK |
+ GDK_BUTTON2_MOTION_MASK |
+ GDK_BUTTON3_MOTION_MASK);
+
+ /* We need thse for all native windows so we can
+ emulate events on children: */
+ mask |=
GDK_EXPOSURE_MASK |
GDK_VISIBILITY_NOTIFY_MASK |
- GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
- GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
- GDK_SCROLL_MASK |
- /* Then do whatever the app asks to, since the app
- * may be asking for weird things for native windows,
- * but filter out things that override the above
- * requests somehow. */
- (event_mask &
- ~(GDK_POINTER_MOTION_HINT_MASK |
- GDK_BUTTON_MOTION_MASK |
- GDK_BUTTON1_MOTION_MASK |
- GDK_BUTTON2_MOTION_MASK |
- GDK_BUTTON3_MOTION_MASK));
+ GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
+
+ /* Additionally we select for pointer and button events
+ * for toplevels as we need to get these to emulate
+ * them for non-native subwindows. Even though we don't
+ * select on them for all native windows we will get them
+ * as the events are propagated out to the first window
+ * that select for them.
+ * Not selecting for button press on all windows is an
+ * important thing, because in X only one client can do
+ * so, and we don't want to unexpectedly prevent another
+ * client from doing it.
+ */
+ if (gdk_window_is_toplevel (private))
+ mask |=
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_SCROLL_MASK;
+
+ return mask;
}
}
static GdkEventMask
+ get_native_grab_event_mask (GdkEventMask grab_mask)
+ {
+ /* Similar to the above but for pointer events only */
+ return
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+ GDK_SCROLL_MASK |
+ (grab_mask &
+ ~(GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_BUTTON1_MOTION_MASK |
+ GDK_BUTTON2_MOTION_MASK |
+ GDK_BUTTON3_MOTION_MASK));
+ }
+
++static GdkEventMask
+get_native_event_mask (GdkWindowObject *private)
+{
+ return get_native_device_event_mask (private, NULL);
+}
+
/* Puts the native window in the right order wrt the other native windows
* in the hierarchy, given the position it has in the client side data.
* This is useful if some operation changed the stacking order.
@@@ -6822,26 -6778,27 +6865,26 @@@ gdk_window_hide (GdkWindow *window
/* May need to break grabs on children */
display = gdk_drawable_get_display (window);
+ device_manager = gdk_display_get_device_manager (display);
- if (_gdk_display_end_pointer_grab (display,
- _gdk_windowing_window_get_next_serial (display),
- window,
- TRUE))
- gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+ /* Get all devices */
+ devices = gdk_device_manager_get_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+ devices = g_list_concat (devices, gdk_device_manager_get_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
+ devices = g_list_concat (devices, gdk_device_manager_get_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
- if (display->keyboard_grab.window != NULL)
- {
- if (is_parent_of (window, display->keyboard_grab.window))
- {
- /* Call this ourselves, even though gdk_display_keyboard_ungrab
- does so too, since we want to pass implicit == TRUE so the
- broken grab event is generated */
- _gdk_display_unset_has_keyboard_grab (display,
- TRUE);
- gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
- }
- }
+ for (d = devices; d; d = d->next)
+ {
+ GdkDevice *device = d->data;
+
+ if (_gdk_display_end_device_grab (display, device,
+ _gdk_windowing_window_get_next_serial (display),
+ window,
+ TRUE))
- gdk_display_device_ungrab (display, device, GDK_CURRENT_TIME);
++ gdk_device_ungrab (device, GDK_CURRENT_TIME);
+ }
private->state = GDK_WINDOW_STATE_WITHDRAWN;
+ g_list_free (devices);
}
did_hide = _gdk_window_update_viewable (window);
@@@ -9938,123 -9599,24 +9981,123 @@@ gdk_pointer_grab (GdkWindow * window
display = gdk_drawable_get_display (window);
serial = _gdk_windowing_window_get_next_serial (display);
+ device_manager = gdk_display_get_device_manager (display);
+ devices = gdk_device_manager_get_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+
+ /* FIXME: Should this be generic to all backends? */
+ /* FIXME: What happens with extended devices? */
+ for (dev = devices; dev; dev = dev->next)
+ {
+ device = dev->data;
+
+ if (device->source != GDK_SOURCE_MOUSE)
+ continue;
+
+ res = _gdk_windowing_device_grab (device,
+ window,
+ native,
+ owner_events,
- event_mask,
++ get_native_grab_event_mask (event_mask),
+ confine_to,
+ cursor,
+ time);
+
+ if (res == GDK_GRAB_SUCCESS)
+ _gdk_display_add_device_grab (display,
+ device,
+ window,
+ native,
+ GDK_OWNERSHIP_NONE,
+ owner_events,
+ event_mask,
+ serial,
+ time,
+ FALSE);
+ }
+
+ /* FIXME: handle errors when grabbing */
+
+ g_list_free (devices);
+
+ return res;
+}
+
+GdkGrabStatus
+gdk_keyboard_grab (GdkWindow *window,
+ gboolean owner_events,
+ guint32 time)
+{
+ GdkWindow *native;
+ GdkDisplay *display;
+ GdkDeviceManager *device_manager;
+ GdkDevice *device;
+ GdkGrabStatus res = 0;
+ gulong serial;
+ GList *devices, *dev;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+
+ /* Non-viewable client side window => fail */
+ if (!_gdk_window_has_impl (window) &&
+ !gdk_window_is_viewable (window))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ if (_gdk_native_windows)
+ native = window;
+ else
+ native = gdk_window_get_toplevel (window);
+
+ while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+ {
+ native = gdk_offscreen_window_get_embedder (native);
+
+ if (native == NULL ||
+ (!_gdk_window_has_impl (native) &&
+ !gdk_window_is_viewable (native)))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ native = gdk_window_get_toplevel (native);
+ }
+
+ display = gdk_drawable_get_display (window);
+
+ serial = _gdk_windowing_window_get_next_serial (display);
+ device_manager = gdk_display_get_device_manager (display);
+ devices = gdk_device_manager_get_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+
+ /* FIXME: Should this be generic to all backends? */
+ /* FIXME: What happens with extended devices? */
+ for (dev = devices; dev; dev = dev->next)
+ {
+ device = dev->data;
+
+ if (device->source != GDK_SOURCE_KEYBOARD)
+ continue;
- res = _gdk_windowing_pointer_grab (window,
- native,
- owner_events,
- get_native_grab_event_mask (event_mask),
- confine_to,
- cursor,
- time);
-
- if (res == GDK_GRAB_SUCCESS)
- _gdk_display_add_pointer_grab (display,
- window,
- native,
- owner_events,
- event_mask,
- serial,
- time,
- FALSE);
+ res = _gdk_windowing_device_grab (device,
+ window,
+ native,
+ owner_events,
+ GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
+ NULL,
+ NULL,
+ time);
+
+ if (res == GDK_GRAB_SUCCESS)
+ _gdk_display_add_device_grab (display,
+ device,
+ window,
+ native,
+ GDK_OWNERSHIP_NONE,
+ owner_events, 0,
+ serial,
+ time,
+ FALSE);
+ }
+
+ /* FIXME: handle errors when grabbing */
+
+ g_list_free (devices);
return res;
}
@@@ -10455,7 -9988,8 +10498,8 @@@ proxy_button_event (GdkEvent *source_ev
&toplevel_x, &toplevel_y);
if (type == GDK_BUTTON_PRESS &&
+ !source_event->any.send_event &&
- _gdk_display_has_pointer_grab (display, serial) == NULL)
+ _gdk_display_has_device_grab (display, device, serial) == NULL)
{
pointer_window =
_gdk_window_find_descendant_at (toplevel_window,
@@@ -10677,24 -10198,25 +10721,26 @@@ _gdk_windowing_got_event (GdkDisplay *d
if (_gdk_native_windows)
{
if (event->type == GDK_BUTTON_PRESS &&
+ !event->any.send_event &&
- _gdk_display_has_pointer_grab (display, serial) == NULL)
+ _gdk_display_has_device_grab (display, device, serial) == NULL)
{
- _gdk_display_add_pointer_grab (display,
- event_window,
- event_window,
- FALSE,
- gdk_window_get_events (event_window),
- serial,
- gdk_event_get_time (event),
- TRUE);
- _gdk_display_pointer_grab_update (display,
- serial);
+ _gdk_display_add_device_grab (display,
+ device,
+ event_window,
+ event_window,
+ GDK_OWNERSHIP_NONE,
+ FALSE,
+ gdk_window_get_events (event_window),
+ serial,
+ gdk_event_get_time (event),
+ TRUE);
+ _gdk_display_device_grab_update (display, device, serial);
}
- if (event->type == GDK_BUTTON_RELEASE)
+ if (event->type == GDK_BUTTON_RELEASE &&
+ !event->any.send_event)
{
button_release_grab =
- _gdk_display_has_pointer_grab (display, serial);
+ _gdk_display_has_device_grab (display, device, serial);
if (button_release_grab &&
button_release_grab->implicit &&
(event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
@@@ -10811,10 -10336,11 +10857,11 @@@
unlink_event = proxy_button_event (event,
serial);
- if (event->type == GDK_BUTTON_RELEASE)
+ if (event->type == GDK_BUTTON_RELEASE &&
+ !event->any.send_event)
{
button_release_grab =
- _gdk_display_has_pointer_grab (display, serial);
+ _gdk_display_has_device_grab (display, device, serial);
if (button_release_grab &&
button_release_grab->implicit &&
(event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
diff --cc gdk/x11/gdkdevice-core.c
index c2506ff,0000000..56dc148
mode 100644,000000..100644
--- a/gdk/x11/gdkdevice-core.c
+++ b/gdk/x11/gdkdevice-core.c
@@@ -1,489 -1,0 +1,496 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gdk/gdkwindow.h>
+#include "gdkdevice-core.h"
+#include "gdkprivate-x11.h"
+#include "gdkx.h"
+
+static gboolean gdk_device_core_get_history (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events);
+static void gdk_device_core_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask);
+static void gdk_device_core_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor);
+static void gdk_device_core_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y);
+static gboolean gdk_device_core_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask);
+static GdkGrabStatus gdk_device_core_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_);
+static void gdk_device_core_ungrab (GdkDevice *device,
+ guint32 time_);
+static GdkWindow * gdk_device_core_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask);
++ GdkModifierType *mask,
++ gboolean get_toplevel);
+static void gdk_device_core_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask);
+
+
+G_DEFINE_TYPE (GdkDeviceCore, gdk_device_core, GDK_TYPE_DEVICE)
+
+static void
+gdk_device_core_class_init (GdkDeviceCoreClass *klass)
+{
+ GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+
+ device_class->get_history = gdk_device_core_get_history;
+ device_class->get_state = gdk_device_core_get_state;
+ device_class->set_window_cursor = gdk_device_core_set_window_cursor;
+ device_class->warp = gdk_device_core_warp;
+ device_class->query_state = gdk_device_core_query_state;
+ device_class->grab = gdk_device_core_grab;
+ device_class->ungrab = gdk_device_core_ungrab;
+ device_class->window_at_position = gdk_device_core_window_at_position;
+ device_class->select_window_events = gdk_device_core_select_window_events;
+}
+
+static void
+gdk_device_core_init (GdkDeviceCore *device_core)
+{
+ GdkDevice *device;
+
+ device = GDK_DEVICE (device_core);
+
+ _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_X, 0, 0, 1);
+ _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_Y, 0, 0, 1);
+}
+
+static gboolean
+impl_coord_in_window (GdkWindow *window,
+ int impl_x,
+ int impl_y)
+{
+ GdkWindowObject *priv = (GdkWindowObject *) window;
+
+ if (impl_x < priv->abs_x ||
+ impl_x > priv->abs_x + priv->width)
+ return FALSE;
+
+ if (impl_y < priv->abs_y ||
+ impl_y > priv->abs_y + priv->height)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gdk_device_core_get_history (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events)
+{
+ GdkWindowObject *priv;
+ XTimeCoord *xcoords;
+ GdkTimeCoord **coords;
+ GdkWindow *impl_window;
+ int tmp_n_events;
+ int i, j;
+
+ impl_window = _gdk_window_get_impl_window (window);
+ xcoords = XGetMotionEvents (GDK_DRAWABLE_XDISPLAY (window),
+ GDK_DRAWABLE_XID (impl_window),
+ start, stop, &tmp_n_events);
+ if (!xcoords)
+ return FALSE;
+
+ priv = (GdkWindowObject *) window;
+ coords = _gdk_device_allocate_history (device, tmp_n_events);
+
+ for (i = 0, j = 0; i < tmp_n_events; i++)
+ {
+ if (impl_coord_in_window (window, xcoords[i].x, xcoords[i].y))
+ {
+ coords[j]->time = xcoords[i].time;
+ coords[j]->axes[0] = xcoords[i].x - priv->abs_x;
+ coords[j]->axes[1] = xcoords[i].y - priv->abs_y;
+ j++;
+ }
+ }
+
+ XFree (xcoords);
+
+ /* free the events we allocated too much */
+ for (i = j; i < tmp_n_events; i++)
+ {
+ g_free (coords[i]);
+ coords[i] = NULL;
+ }
+
+ tmp_n_events = j;
+
+ if (tmp_n_events == 0)
+ {
+ gdk_device_free_history (coords, tmp_n_events);
+ return FALSE;
+ }
+
+ if (n_events)
+ *n_events = tmp_n_events;
+
+ if (events)
+ *events = coords;
+ else if (coords)
+ gdk_device_free_history (coords, tmp_n_events);
+
+ return TRUE;
+}
+
+static void
+gdk_device_core_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask)
+{
+ gint x_int, y_int;
+
+ gdk_window_get_pointer (window, &x_int, &y_int, mask);
+
+ if (axes)
+ {
+ axes[0] = x_int;
+ axes[1] = y_int;
+ }
+}
+
+static void
+gdk_device_core_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkCursorPrivate *cursor_private;
+ Cursor xcursor;
+
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ if (!cursor)
+ xcursor = None;
+ else
+ xcursor = cursor_private->xcursor;
+
+ XDefineCursor (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ xcursor);
+}
+
+static void
+gdk_device_core_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y)
+{
+ Display *xdisplay;
+ Window dest;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_device_get_display (device));
+ dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+
+ XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);
+}
+
+static gboolean
+gdk_device_core_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask)
+{
+ GdkDisplay *display;
+ Window xroot_window, xchild_window;
+ int xroot_x, xroot_y, xwin_x, xwin_y;
+ unsigned int xmask;
+
+ display = gdk_drawable_get_display (window);
+
+ if (!XQueryPointer (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ &xroot_window,
+ &xchild_window,
+ &xroot_x,
+ &xroot_y,
+ &xwin_x,
+ &xwin_y,
+ &xmask))
+ {
+ return FALSE;
+ }
+
+ if (root_window)
+ *root_window = gdk_window_lookup_for_display (display, xroot_window);
+
+ if (child_window)
+ *child_window = gdk_window_lookup_for_display (display, xchild_window);
+
+ if (root_x)
+ *root_x = xroot_x;
+
+ if (root_y)
+ *root_y = xroot_y;
+
+ if (win_x)
+ *win_x = xwin_x;
+
+ if (win_y)
+ *win_y = xwin_y;
+
+ if (mask)
+ *mask = xmask;
+
+ return TRUE;
+}
+
+static GdkGrabStatus
+gdk_device_core_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_)
+{
+ GdkDisplay *display;
+ Window xwindow, xconfine_to;
+ int status;
+
+ display = gdk_device_get_display (device);
+
+ xwindow = GDK_WINDOW_XID (window);
+
+ if (confine_to)
+ confine_to = _gdk_window_get_impl_window (confine_to);
+
+ if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
+ xconfine_to = None;
+ else
+ xconfine_to = GDK_WINDOW_XID (confine_to);
+
+ if (device->source == GDK_SOURCE_KEYBOARD)
+ {
+ /* Device is a keyboard */
+ status = XGrabKeyboard (GDK_DISPLAY_XDISPLAY (display),
+ xwindow,
+ owner_events,
+ GrabModeAsync, GrabModeAsync,
+ time_);
+ }
+ else
+ {
+ Cursor xcursor;
+ guint xevent_mask;
+ gint i;
+
+ /* Device is a pointer */
+ if (!cursor)
+ xcursor = None;
+ else
+ {
+ _gdk_x11_cursor_update_theme (cursor);
+ xcursor = ((GdkCursorPrivate *) cursor)->xcursor;
+ }
+
+ xevent_mask = 0;
+
+ for (i = 0; i < _gdk_nenvent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xevent_mask |= _gdk_event_mask_table[i];
+ }
+
+ /* We don't want to set a native motion hint mask, as we're emulating motion
+ * hints. If we set a native one we just wouldn't get any events.
+ */
+ xevent_mask &= ~PointerMotionHintMask;
+
+ status = XGrabPointer (GDK_DISPLAY_XDISPLAY (display),
+ xwindow,
+ owner_events,
+ xevent_mask,
+ GrabModeAsync, GrabModeAsync,
+ xconfine_to,
+ xcursor,
+ time_);
+ }
+
+ return gdk_x11_convert_grab_status (status);
+}
+
+static void
+gdk_device_core_ungrab (GdkDevice *device,
+ guint32 time_)
+{
+ GdkDisplay *display;
+
+ display = gdk_device_get_display (device);
+
+ if (device->source == GDK_SOURCE_KEYBOARD)
+ XUngrabKeyboard (GDK_DISPLAY_XDISPLAY (display), time_);
+ else
+ XUngrabPointer (GDK_DISPLAY_XDISPLAY (display), time_);
+}
+
+static GdkWindow *
+gdk_device_core_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask)
++ GdkModifierType *mask,
++ gboolean get_toplevel)
+{
+ GdkDisplay *display;
+ GdkScreen *screen;
+ Display *xdisplay;
+ GdkWindow *window;
+ Window xwindow, root, child, last;
+ int xroot_x, xroot_y, xwin_x, xwin_y;
+ unsigned int xmask;
+
+ last = None;
+ display = gdk_device_get_display (device);
+ screen = gdk_display_get_default_screen (display);
+
+ /* This function really only works if the mouse pointer is held still
+ * during its operation. If it moves from one leaf window to another
+ * than we'll end up with inaccurate values for win_x, win_y
+ * and the result.
+ */
+ gdk_x11_display_grab (display);
+
+ xdisplay = GDK_SCREEN_XDISPLAY (screen);
+ xwindow = GDK_SCREEN_XROOTWIN (screen);
+
+ XQueryPointer (xdisplay, xwindow,
+ &root, &child,
+ &xroot_x, &xroot_y,
+ &xwin_x, &xwin_y,
+ &xmask);
+
+ if (root == xwindow)
+ xwindow = child;
+ else
+ xwindow = root;
+
+ while (xwindow)
+ {
+ last = xwindow;
+ XQueryPointer (xdisplay, xwindow,
+ &root, &xwindow,
+ &xroot_x, &xroot_y,
+ &xwin_x, &xwin_y,
+ &xmask);
++
++ if (get_toplevel &&
++ (window = gdk_window_lookup_for_display (display, last)) != NULL &&
++ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
++ break;
+ }
+
+ gdk_x11_display_ungrab (display);
+
+ window = gdk_window_lookup_for_display (display, last);
+
+ if (win_x)
+ *win_x = (window) ? xwin_x : -1;
+
+ if (win_y)
+ *win_y = (window) ? xwin_y : -1;
+
+ if (mask)
+ *mask = xmask;
+
+ return window;
+}
+
+static void
+gdk_device_core_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ GdkEventMask filter_mask, window_mask;
+ guint xmask = 0;
+ gint i;
+
+ window_mask = gdk_window_get_events (window);
+ filter_mask = (GDK_POINTER_MOTION_MASK &
+ GDK_POINTER_MOTION_HINT_MASK &
+ GDK_BUTTON_MOTION_MASK &
+ GDK_BUTTON1_MOTION_MASK &
+ GDK_BUTTON2_MOTION_MASK &
+ GDK_BUTTON3_MOTION_MASK &
+ GDK_BUTTON_PRESS_MASK &
+ GDK_BUTTON_RELEASE_MASK &
+ GDK_KEY_PRESS_MASK &
+ GDK_KEY_RELEASE_MASK &
+ GDK_ENTER_NOTIFY_MASK &
+ GDK_LEAVE_NOTIFY_MASK &
+ GDK_FOCUS_CHANGE_MASK &
+ GDK_PROXIMITY_IN_MASK &
+ GDK_PROXIMITY_OUT_MASK &
+ GDK_SCROLL_MASK);
+
+ /* Filter out non-device events */
+ event_mask &= filter_mask;
+
+ /* Unset device events on window mask */
+ window_mask &= ~(filter_mask);
+
+ /* Combine masks */
+ event_mask |= window_mask;
+
+ for (i = 0; i < _gdk_nenvent_masks; i++)
+ {
+ if (event_mask & (1 << (i + 1)))
+ xmask |= _gdk_event_mask_table[i];
+ }
+
+ if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
+ xmask |= StructureNotifyMask | PropertyChangeMask;
+
+ XSelectInput (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ xmask);
+}
diff --cc gdk/x11/gdkdevice-xi.c
index 1ecb438,0000000..ca98321
mode 100644,000000..100644
--- a/gdk/x11/gdkdevice-xi.c
+++ b/gdk/x11/gdkdevice-xi.c
@@@ -1,630 -1,0 +1,622 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gdk/gdkwindow.h>
+#include "gdkdeviceprivate.h"
+#include "gdkdevice-xi.h"
+#include "gdkprivate-x11.h"
+#include "gdkintl.h"
+#include "gdkx.h"
+
+#define MAX_DEVICE_CLASSES 13
+
+static GQuark quark_window_input_info = 0;
+
+typedef struct
+{
+ gdouble root_x;
+ gdouble root_y;
+} GdkWindowInputInfo;
+
+static void gdk_device_xi_constructed (GObject *object);
++static void gdk_device_xi_dispose (GObject *object);
++
+static void gdk_device_xi_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gdk_device_xi_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static gboolean gdk_device_xi_get_history (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events);
+
+static void gdk_device_xi_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask);
+static void gdk_device_xi_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor);
+static void gdk_device_xi_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y);
+static gboolean gdk_device_xi_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask);
+static GdkGrabStatus gdk_device_xi_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_);
+static void gdk_device_xi_ungrab (GdkDevice *device,
+ guint32 time_);
+
+static GdkWindow* gdk_device_xi_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask);
++ GdkModifierType *mask,
++ gboolean get_toplevel);
+
+static void gdk_device_xi_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask mask);
+
+
+G_DEFINE_TYPE (GdkDeviceXI, gdk_device_xi, GDK_TYPE_DEVICE)
+
+enum {
+ PROP_0,
+ PROP_DEVICE_ID
+};
+
+static void
+gdk_device_xi_class_init (GdkDeviceXIClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+
+ quark_window_input_info = g_quark_from_static_string ("gdk-window-input-info");
+
+ object_class->constructed = gdk_device_xi_constructed;
+ object_class->set_property = gdk_device_xi_set_property;
+ object_class->get_property = gdk_device_xi_get_property;
+ object_class->dispose = gdk_device_xi_dispose;
+
+ device_class->get_history = gdk_device_xi_get_history;
+ device_class->get_state = gdk_device_xi_get_state;
+ device_class->set_window_cursor = gdk_device_xi_set_window_cursor;
+ device_class->warp = gdk_device_xi_warp;
+ device_class->query_state = gdk_device_xi_query_state;
+ device_class->grab = gdk_device_xi_grab;
+ device_class->ungrab = gdk_device_xi_ungrab;
+ device_class->window_at_position = gdk_device_xi_window_at_position;
+ device_class->select_window_events = gdk_device_xi_select_window_events;
+
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_ID,
+ g_param_spec_int ("device-id",
+ P_("Device ID"),
+ P_("Device ID"),
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gdk_device_xi_init (GdkDeviceXI *device)
+{
+}
+
+static void
+gdk_device_xi_constructed (GObject *object)
+{
+ GdkDeviceXI *device;
+ GdkDisplay *display;
+
+ device = GDK_DEVICE_XI (object);
+ display = gdk_device_get_display (GDK_DEVICE (object));
+
+ gdk_error_trap_push ();
+ device->xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (display),
+ device->device_id);
+
+ if (gdk_error_trap_pop ())
+ g_warning ("Device %s can't be opened", GDK_DEVICE (device)->name);
+
+ if (G_OBJECT_CLASS (gdk_device_xi_parent_class)->constructed)
+ G_OBJECT_CLASS (gdk_device_xi_parent_class)->constructed (object);
+}
+
+static void
+gdk_device_xi_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDeviceXI *device = GDK_DEVICE_XI (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE_ID:
+ device->device_id = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdk_device_xi_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDeviceXI *device = GDK_DEVICE_XI (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE_ID:
+ g_value_set_int (value, device->device_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdk_device_xi_dispose (GObject *object)
+{
+ GdkDeviceXI *device_xi;
+ GdkDisplay *display;
+
+ device_xi = GDK_DEVICE_XI (object);
+ display = gdk_device_get_display (GDK_DEVICE (device_xi));
+
+ if (device_xi->xdevice)
+ {
+ XCloseDevice (GDK_DISPLAY_XDISPLAY (display), device_xi->xdevice);
+ device_xi->xdevice = NULL;
+ }
+
++ if (device_xi->axis_data)
++ {
++ g_free (device_xi->axis_data);
++ device_xi->axis_data = NULL;
++ }
++
+ G_OBJECT_CLASS (gdk_device_xi_parent_class)->dispose (object);
+}
+
+static gboolean
+gdk_device_xi_get_history (GdkDevice *device,
+ GdkWindow *window,
+ guint32 start,
+ guint32 stop,
+ GdkTimeCoord ***events,
+ guint *n_events)
+{
+ GdkTimeCoord **coords;
+ XDeviceTimeCoord *device_coords;
+ GdkWindow *impl_window;
+ GdkDeviceXI *device_xi;
+ gint n_events_return;
+ gint mode_return;
+ gint axis_count_return;
+ gint i;
+
+ device_xi = GDK_DEVICE_XI (device);
+ impl_window = _gdk_window_get_impl_window (window);
+
+ device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window),
+ device_xi->xdevice,
+ start, stop,
+ &n_events_return,
+ &mode_return,
+ &axis_count_return);
+
+ if (!device_coords)
+ return FALSE;
+
+ *n_events = (guint) n_events_return;
+ coords = _gdk_device_allocate_history (device, *n_events);
+
+ for (i = 0; i < *n_events; i++)
+ {
+ coords[i]->time = device_coords[i].time;
+ gdk_device_xi_translate_axes (device, window,
+ device_coords[i].data,
+ coords[i]->axes,
+ NULL, NULL);
+ }
+
+ XFreeDeviceMotionEvents (device_coords);
+
+ *events = coords;
+
+ return TRUE;
+}
+
+static void
+gdk_device_xi_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask)
+{
+ GdkDeviceXI *device_xi;
+ XDeviceState *state;
+ XInputClass *input_class;
+ gint i;
+
+ if (mask)
+ gdk_window_get_pointer (window, NULL, NULL, mask);
+
+ device_xi = GDK_DEVICE_XI (device);
+ state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window),
+ device_xi->xdevice);
+ input_class = state->data;
+
+ for (i = 0; i < state->num_classes; i++)
+ {
+ switch (input_class->class)
+ {
+ case ValuatorClass:
+ if (axes)
+ gdk_device_xi_translate_axes (device, window,
+ ((XValuatorState *) input_class)->valuators,
+ axes, NULL, NULL);
+ break;
+
+ case ButtonClass:
+ if (mask)
+ {
+ *mask &= 0xFF;
+ if (((XButtonState *)input_class)->num_buttons > 0)
+ *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
+ /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
+ * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
+ }
+ break;
+ }
+
+ input_class = (XInputClass *)(((char *)input_class)+input_class->length);
+ }
+
+ XFreeDeviceState (state);
+}
+
+static void
+gdk_device_xi_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor)
+{
+}
+
+static void
+gdk_device_xi_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y)
+{
+}
+
+static void
+find_events (GdkDevice *device,
+ GdkEventMask mask,
+ XEventClass *classes,
+ int *num_classes)
+{
+ GdkDeviceXI *device_xi;
+ XEventClass class;
+ gint i;
+
+ device_xi = GDK_DEVICE_XI (device);
+ i = 0;
+
+ if (mask & GDK_BUTTON_PRESS_MASK)
+ {
+ DeviceButtonPress (device_xi->xdevice, device_xi->button_press_type, class);
+ if (class != 0)
+ classes[i++] = class;
+
+ DeviceButtonPressGrab (device_xi->xdevice, 0, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ if (mask & GDK_BUTTON_RELEASE_MASK)
+ {
+ DeviceButtonRelease (device_xi->xdevice, device_xi->button_release_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
- if (mask & GDK_POINTER_MOTION_MASK)
- {
- DeviceMotionNotify (device_xi->xdevice, device_xi->motion_notify_type, class);
- if (class != 0)
- classes[i++] = class;
- }
- else if (mask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK |
- GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK))
++ if (mask & (GDK_POINTER_MOTION_MASK |
++ GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK |
++ GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_MOTION_MASK))
+ {
+ /* Make sure device->motionnotify_type is set */
+ DeviceMotionNotify (device_xi->xdevice, device_xi->motion_notify_type, class);
- }
-
- if (mask & GDK_BUTTON1_MOTION_MASK)
- {
- DeviceButton1Motion (device_xi->xdevice, 0, class);
+ if (class != 0)
- classes[i++] = class;
- }
-
- if (mask & GDK_BUTTON2_MOTION_MASK)
- {
- DeviceButton2Motion (device_xi->xdevice, 0, class);
++ classes[i++] = class;
++ DeviceStateNotify (device_xi->xdevice, device_xi->state_notify_type, class);
+ if (class != 0)
- classes[i++] = class;
- }
-
- if (mask & GDK_BUTTON3_MOTION_MASK)
- {
- DeviceButton3Motion (device_xi->xdevice, 0, class);
- if (class != 0)
- classes[i++] = class;
- }
-
- if (mask & GDK_BUTTON_MOTION_MASK)
- {
- DeviceButtonMotion (device_xi->xdevice, 0, 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 (device_xi->xdevice, 0, class);
- if (class != 0)
- classes[i++] = class;
++ classes[i++] = class;
+ }
+
+ if (mask & GDK_KEY_PRESS_MASK)
+ {
+ DeviceKeyPress (device_xi->xdevice, device_xi->key_press_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ if (mask & GDK_KEY_RELEASE_MASK)
+ {
+ DeviceKeyRelease (device_xi->xdevice, device_xi->key_release_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ if (mask & GDK_PROXIMITY_IN_MASK)
+ {
+ ProximityIn (device_xi->xdevice, device_xi->proximity_in_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ if (mask & GDK_PROXIMITY_OUT_MASK)
+ {
+ ProximityOut (device_xi->xdevice, device_xi->proximity_out_type, class);
+ if (class != 0)
+ classes[i++] = class;
+ }
+
+ *num_classes = i;
+}
+
+static gboolean
+gdk_device_xi_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask)
+{
+ return FALSE;
+}
+
+static GdkGrabStatus
+gdk_device_xi_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_)
+{
+ XEventClass event_classes[MAX_DEVICE_CLASSES];
+ gint status, num_classes;
+ GdkDeviceXI *device_xi;
+
+ device_xi = GDK_DEVICE_XI (device);
+ find_events (device, event_mask, event_classes, &num_classes);
+
+ status = XGrabDevice (GDK_WINDOW_XDISPLAY (window),
+ device_xi->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ owner_events,
+ num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync,
+ time_);
+
+ return gdk_x11_convert_grab_status (status);
+}
+
+static void
+gdk_device_xi_ungrab (GdkDevice *device,
+ guint32 time_)
+{
+ GdkDisplay *display;
+ GdkDeviceXI *device_xi;
+
+ device_xi = GDK_DEVICE_XI (device);
+ display = gdk_device_get_display (device);
+
+ XUngrabDevice (GDK_DISPLAY_XDISPLAY (device),
+ device_xi->xdevice,
+ time_);
+}
+
+static GdkWindow*
+gdk_device_xi_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask)
++ GdkModifierType *mask,
++ gboolean get_toplevel)
+{
+ return NULL;
+}
+static void
+gdk_device_xi_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ XEventClass event_classes[MAX_DEVICE_CLASSES];
+ GdkDeviceXI *device_xi;
+ gint num_classes;
+
+ event_mask |= (GDK_PROXIMITY_IN_MASK |
+ GDK_PROXIMITY_OUT_MASK);
+
+ device_xi = GDK_DEVICE_XI (device);
+ find_events (device, event_mask, event_classes, &num_classes);
+
+ XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ event_classes, num_classes);
+
+ if (event_mask)
+ {
+ GdkWindowInputInfo *info;
+
+ info = g_new0 (GdkWindowInputInfo, 1);
+ g_object_set_qdata_full (G_OBJECT (window),
+ quark_window_input_info,
+ info,
+ (GDestroyNotify) g_free);
+ }
+ else
+ g_object_set_qdata (G_OBJECT (window),
+ quark_window_input_info,
+ NULL);
+}
+
+void
+gdk_device_xi_update_window_info (GdkWindow *window)
+{
+ GdkWindowInputInfo *info;
+ gint root_x, root_y;
+
+ info = g_object_get_qdata (G_OBJECT (window),
+ quark_window_input_info);
+
+ if (!info)
+ return;
+
+ gdk_window_get_origin (window, &root_x, &root_y);
+ info->root_x = (gdouble) root_x;
+ info->root_y = (gdouble) root_y;
+}
+
+static gboolean
+gdk_device_xi_get_window_info (GdkWindow *window,
+ gdouble *root_x,
+ gdouble *root_y)
+{
+ GdkWindowInputInfo *info;
+
+ info = g_object_get_qdata (G_OBJECT (window),
+ quark_window_input_info);
+
+ if (!info)
+ return FALSE;
+
+ *root_x = info->root_x;
+ *root_y = info->root_y;
+
+ return TRUE;
+}
+
+void
++gdk_device_xi_update_axes (GdkDevice *device,
++ gint axes_count,
++ gint first_axis,
++ gint *axis_data)
++{
++ GdkDeviceXI *device_xi;
++ int i;
++
++ device_xi = GDK_DEVICE_XI (device);
++ g_return_if_fail (first_axis >= 0 && first_axis + axes_count <= device->num_axes);
++
++ if (!device_xi->axis_data)
++ device_xi->axis_data = g_new0 (gint, device->num_axes);
++
++ for (i = 0; i < axes_count; i++)
++ device_xi->axis_data[first_axis + i] = axis_data[i];
++}
++
++void
+gdk_device_xi_translate_axes (GdkDevice *device,
+ GdkWindow *window,
+ gint *axis_data,
+ gdouble *axes,
+ gdouble *x,
+ gdouble *y)
+{
++ GdkDeviceXI *device_xi;
+ GdkWindow *impl_window;
+ gdouble root_x, root_y;
+ gdouble temp_x, temp_y;
+ gint i;
+
++ device_xi = GDK_DEVICE_XI (device);
+ impl_window = _gdk_window_get_impl_window (window);
+ temp_x = temp_y = 0;
+
+ if (!gdk_device_xi_get_window_info (impl_window, &root_x, &root_y))
+ return;
+
+ for (i = 0; i < device->num_axes; i++)
+ {
+ GdkAxisUse use;
+
+ use = _gdk_device_get_axis_use (device, i);
+
+ switch (use)
+ {
+ case GDK_AXIS_X:
+ case GDK_AXIS_Y:
+ if (device->mode == GDK_MODE_WINDOW)
+ _gdk_device_translate_window_coord (device, window,
+ i, axis_data[i],
+ &axes[i]);
+ else
+ _gdk_device_translate_screen_coord (device, window,
+ root_x, root_y,
+ i, axis_data[i],
+ &axes[i]);
+ if (use == GDK_AXIS_X)
+ temp_x = axes[i];
+ else if (use == GDK_AXIS_Y)
+ temp_y = axes[i];
+
+ break;
+ default:
+ _gdk_device_translate_axis (device, i, axis_data[i], &axes[i]);
+ break;
+ }
+ }
+
+ if (x)
+ *x = temp_x;
+
+ if (y)
+ *y = temp_y;
+}
diff --cc gdk/x11/gdkdevice-xi.h
index 448f1fa,0000000..5f8f586
mode 100644,000000..100644
--- a/gdk/x11/gdkdevice-xi.h
+++ b/gdk/x11/gdkdevice-xi.h
@@@ -1,80 -1,0 +1,84 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GDK_DEVICE_XI_H__
+#define __GDK_DEVICE_XI_H__
+
+#include <gdk/gdkdeviceprivate.h>
+#include <X11/extensions/XInput.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_DEVICE_XI (gdk_device_xi_get_type ())
+#define GDK_DEVICE_XI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_XI, GdkDeviceXI))
+#define GDK_DEVICE_XI_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_XI, GdkDeviceXIClass))
+#define GDK_IS_DEVICE_XI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_XI))
+#define GDK_IS_DEVICE_XI_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_XI))
+#define GDK_DEVICE_XI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_XI, GdkDeviceXIClass))
+
+typedef struct _GdkDeviceXI GdkDeviceXI;
+typedef struct _GdkDeviceXIClass GdkDeviceXIClass;
+
+struct _GdkDeviceXI
+{
+ GdkDevice parent_instance;
+
+ guint32 device_id;
+ XDevice *xdevice;
+
+ gint button_press_type;
+ gint button_release_type;
+ gint key_press_type;
+ gint key_release_type;
+ gint motion_notify_type;
+ gint proximity_in_type;
+ gint proximity_out_type;
++ gint state_notify_type;
+
+ /* minimum key code for device */
+ gint min_keycode;
+
- /* Mask of buttons (used for button grabs) */
- gint button_state;
++ gint *axis_data;
+
+ guint in_proximity : 1;
+};
+
+struct _GdkDeviceXIClass
+{
+ GdkDeviceClass parent_class;
+};
+
+GType gdk_device_xi_get_type (void) G_GNUC_CONST;
+
+void gdk_device_xi_update_window_info (GdkWindow *window);
+
++void gdk_device_xi_update_axes (GdkDevice *device,
++ gint axes_count,
++ gint first_axis,
++ gint *axis_data);
+void gdk_device_xi_translate_axes (GdkDevice *device,
+ GdkWindow *window,
+ gint *axis_data,
+ gdouble *axes,
+ gdouble *x,
+ gdouble *y);
+
+G_END_DECLS
+
+#endif /* __GDK_DEVICE_XI_H__ */
diff --cc gdk/x11/gdkdevice-xi2.c
index 8565406,0000000..1d5e84e
mode 100644,000000..100644
--- a/gdk/x11/gdkdevice-xi2.c
+++ b/gdk/x11/gdkdevice-xi2.c
@@@ -1,555 -1,0 +1,562 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <X11/extensions/XInput2.h>
+#include "gdkdevice-xi2.h"
+#include "gdkintl.h"
+#include "gdkx.h"
+
+#define BIT_IS_ON(ptr, bit) (((unsigned char *) (ptr))[(bit)>>3] & (1 << ((bit) & 7)))
+#define GDK_DEVICE_XI2_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_DEVICE_XI2, GdkDeviceXI2Private))
+
+typedef struct GdkDeviceXI2Private GdkDeviceXI2Private;
+
+struct GdkDeviceXI2Private
+{
+ int device_id;
+};
+
+static void gdk_device_xi2_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gdk_device_xi2_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void gdk_device_xi2_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask);
+static void gdk_device_xi2_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor);
+static void gdk_device_xi2_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y);
+static gboolean gdk_device_xi2_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask);
+
+static GdkGrabStatus gdk_device_xi2_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_);
+static void gdk_device_xi2_ungrab (GdkDevice *device,
+ guint32 time_);
+
+static GdkWindow * gdk_device_xi2_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask);
++ GdkModifierType *mask,
++ gboolean get_toplevel);
+static void gdk_device_xi2_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask);
+
+
+G_DEFINE_TYPE (GdkDeviceXI2, gdk_device_xi2, GDK_TYPE_DEVICE)
+
+enum {
+ PROP_0,
+ PROP_DEVICE_ID
+};
+
+static void
+gdk_device_xi2_class_init (GdkDeviceXI2Class *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+
+ object_class->get_property = gdk_device_xi2_get_property;
+ object_class->set_property = gdk_device_xi2_set_property;
+
+ device_class->get_state = gdk_device_xi2_get_state;
+ device_class->set_window_cursor = gdk_device_xi2_set_window_cursor;
+ device_class->warp = gdk_device_xi2_warp;
+ device_class->query_state = gdk_device_xi2_query_state;
+ device_class->grab = gdk_device_xi2_grab;
+ device_class->ungrab = gdk_device_xi2_ungrab;
+ device_class->window_at_position = gdk_device_xi2_window_at_position;
+ device_class->select_window_events = gdk_device_xi2_select_window_events;
+
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_ID,
+ g_param_spec_int ("device-id",
+ P_("Device ID"),
+ P_("Device identifier"),
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (GdkDeviceXI2Private));
+}
+
+static void
+gdk_device_xi2_init (GdkDeviceXI2 *device)
+{
+}
+
+static void
+gdk_device_xi2_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDeviceXI2Private *priv;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE_ID:
+ g_value_set_int (value, priv->device_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdk_device_xi2_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDeviceXI2Private *priv;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DEVICE_ID:
+ priv->device_id = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdk_device_xi2_get_state (GdkDevice *device,
+ GdkWindow *window,
+ gdouble *axes,
+ GdkModifierType *mask)
+{
+ /* FIXME: Axes are not being translated, there doesn't
+ * seem to be any function to get valuators state in XI2.
+ */
+ gdk_device_xi2_query_state (device, window,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ mask);
+}
+
+static void
+gdk_device_xi2_set_window_cursor (GdkDevice *device,
+ GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkDeviceXI2Private *priv;
+ GdkCursorPrivate *cursor_private;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (device);
+
+ /* Non-master devices don't have a cursor */
+ if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
+ return;
+
+ if (cursor)
+ {
+ cursor_private = (GdkCursorPrivate*) cursor;
+
+ XIDefineCursor (GDK_WINDOW_XDISPLAY (window),
+ priv->device_id,
+ GDK_WINDOW_XWINDOW (window),
+ cursor_private->xcursor);
+ }
+ else
+ XIUndefineCursor (GDK_WINDOW_XDISPLAY (window),
+ priv->device_id,
+ GDK_WINDOW_XWINDOW (window));
+}
+
+static void
+gdk_device_xi2_warp (GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y)
+{
+ GdkDeviceXI2Private *priv;
+ Window dest;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (device);
+ dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+
+ XIWarpPointer (GDK_SCREEN_XDISPLAY (screen),
+ priv->device_id,
+ None, dest,
+ 0, 0, 0, 0, x, y);
+}
+
+static gboolean
+gdk_device_xi2_query_state (GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow **root_window,
+ GdkWindow **child_window,
+ gint *root_x,
+ gint *root_y,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask)
+{
+ GdkDisplay *display;
+ GdkDeviceXI2Private *priv;
+ Window xroot_window, xchild_window;
+ gdouble xroot_x, xroot_y, xwin_x, xwin_y;
+ XIButtonState button_state;
+ XIModifierState mod_state;
+ XIGroupState group_state;
+
+ if (!window || GDK_WINDOW_DESTROYED (window))
+ return FALSE;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (device);
+ display = gdk_drawable_get_display (window);
+
+ if (!XIQueryPointer (GDK_WINDOW_XDISPLAY (window),
+ priv->device_id,
+ GDK_WINDOW_XID (window),
+ &xroot_window,
+ &xchild_window,
+ &xroot_x,
+ &xroot_y,
+ &xwin_x,
+ &xwin_y,
+ &button_state,
+ &mod_state,
+ &group_state))
+ {
+ return FALSE;
+ }
+
+ if (root_window)
+ *root_window = gdk_window_lookup_for_display (display, xroot_window);
+
+ if (child_window)
+ *child_window = gdk_window_lookup_for_display (display, xchild_window);
+
+ if (root_x)
+ *root_x = (gint) xroot_x;
+
+ if (root_y)
+ *root_y = (gint) xroot_y;
+
+ if (win_x)
+ *win_x = (gint) xwin_x;
+
+ if (win_y)
+ *win_y = (gint) xwin_y;
+
+ if (mask)
+ *mask = gdk_device_xi2_translate_state (&mod_state, &button_state);
+
+ return TRUE;
+}
+
+static GdkGrabStatus
+gdk_device_xi2_grab (GdkDevice *device,
+ GdkWindow *window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time_)
+{
+ GdkDeviceXI2Private *priv;
+ GdkDisplay *display;
+ XIEventMask mask;
+ Window xwindow;
+ Cursor xcursor;
+ int status;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (device);
+ display = gdk_device_get_display (device);
+
+ /* FIXME: confine_to is actually unused */
+
+ xwindow = GDK_WINDOW_XID (window);
+
+ if (!cursor)
+ xcursor = None;
+ else
+ {
+ _gdk_x11_cursor_update_theme (cursor);
+ xcursor = ((GdkCursorPrivate *) cursor)->xcursor;
+ }
+
+ mask.deviceid = priv->device_id;
+ mask.mask = gdk_device_xi2_translate_event_mask (event_mask, &mask.mask_len);
+
+ status = XIGrabDevice (GDK_DISPLAY_XDISPLAY (display),
+ priv->device_id,
+ xwindow,
+ time_,
+ xcursor,
+ GrabModeAsync, GrabModeAsync,
+ owner_events,
+ &mask);
+
+ g_free (mask.mask);
+
+ return gdk_x11_convert_grab_status (status);
+}
+
+static void
+gdk_device_xi2_ungrab (GdkDevice *device,
+ guint32 time_)
+{
+ GdkDeviceXI2Private *priv;
+ GdkDisplay *display;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (device);
+ display = gdk_device_get_display (device);
+
+ XIUngrabDevice (GDK_DISPLAY_XDISPLAY (display),
+ priv->device_id,
+ time_);
+}
+
+static GdkWindow *
+gdk_device_xi2_window_at_position (GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask)
++ GdkModifierType *mask,
++ gboolean get_toplevel)
+{
+ GdkDeviceXI2Private *priv;
+ GdkDisplay *display;
+ GdkScreen *screen;
+ Display *xdisplay;
+ GdkWindow *window;
+ Window xwindow, root, child, last = None;
+ gdouble xroot_x, xroot_y, xwin_x, xwin_y;
+ XIButtonState button_state;
+ XIModifierState mod_state;
+ XIGroupState group_state;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (device);
+ display = gdk_device_get_display (device);
+ screen = gdk_display_get_default_screen (display);
+
+ /* This function really only works if the mouse pointer is held still
+ * during its operation. If it moves from one leaf window to another
+ * than we'll end up with inaccurate values for win_x, win_y
+ * and the result.
+ */
+ gdk_x11_display_grab (display);
+
+ xdisplay = GDK_SCREEN_XDISPLAY (screen);
+ xwindow = GDK_SCREEN_XROOTWIN (screen);
+
+ XIQueryPointer (xdisplay,
+ priv->device_id,
+ xwindow,
+ &root, &child,
+ &xroot_x, &xroot_y,
+ &xwin_x, &xwin_y,
+ &button_state,
+ &mod_state,
+ &group_state);
+
+ if (root == xwindow)
+ xwindow = child;
+ else
+ xwindow = root;
+
+ while (xwindow)
+ {
+ last = xwindow;
+ XIQueryPointer (xdisplay,
+ priv->device_id,
+ xwindow,
+ &root, &xwindow,
+ &xroot_x, &xroot_y,
+ &xwin_x, &xwin_y,
+ &button_state,
+ &mod_state,
+ &group_state);
++
++ if (get_toplevel &&
++ (window = gdk_window_lookup_for_display (display, last)) != NULL &&
++ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
++ break;
+ }
+
+ gdk_x11_display_ungrab (display);
+
+ window = gdk_window_lookup_for_display (display, last);
+
+ if (win_x)
+ *win_x = (window) ? (gint) xwin_x : -1;
+
+ if (win_y)
+ *win_y = (window) ? (gint) xwin_y : -1;
+
+ if (mask)
+ *mask = gdk_device_xi2_translate_state (&mod_state, &button_state);
+
+ return window;
+}
+
+static void
+gdk_device_xi2_select_window_events (GdkDevice *device,
+ GdkWindow *window,
+ GdkEventMask event_mask)
+{
+ GdkDeviceXI2Private *priv;
+ XIEventMask evmask;
+
+ priv = GDK_DEVICE_XI2_GET_PRIVATE (device);
+
+ evmask.deviceid = priv->device_id;
+ evmask.mask = gdk_device_xi2_translate_event_mask (event_mask, &evmask.mask_len);
+
+ XISelectEvents (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ &evmask, 1);
+
+ g_free (evmask.mask);
+}
+
+guchar *
+gdk_device_xi2_translate_event_mask (GdkEventMask event_mask,
+ int *len)
+{
+ guchar *mask;
+
+ *len = XIMaskLen (XI_LASTEVENT);
+ mask = g_new0 (guchar, *len);
+
+ if (event_mask & GDK_POINTER_MOTION_MASK ||
+ event_mask & GDK_POINTER_MOTION_HINT_MASK)
+ XISetMask (mask, XI_Motion);
+
+ if (event_mask & GDK_BUTTON_MOTION_MASK ||
+ event_mask & GDK_BUTTON1_MOTION_MASK ||
+ event_mask & GDK_BUTTON2_MOTION_MASK ||
+ event_mask & GDK_BUTTON3_MOTION_MASK)
+ {
+ XISetMask (mask, XI_ButtonPress);
+ XISetMask (mask, XI_ButtonRelease);
+ XISetMask (mask, XI_Motion);
+ }
+
+ if (event_mask & GDK_SCROLL_MASK)
+ {
+ XISetMask (mask, XI_ButtonPress);
+ XISetMask (mask, XI_ButtonRelease);
+ }
+
+ if (event_mask & GDK_BUTTON_PRESS_MASK)
+ XISetMask (mask, XI_ButtonPress);
+
+ if (event_mask & GDK_BUTTON_RELEASE_MASK)
+ XISetMask (mask, XI_ButtonRelease);
+
+ if (event_mask & GDK_KEY_PRESS_MASK)
+ XISetMask (mask, XI_KeyPress);
+
+ if (event_mask & GDK_KEY_RELEASE_MASK)
+ XISetMask (mask, XI_KeyRelease);
+
+ if (event_mask & GDK_ENTER_NOTIFY_MASK)
+ XISetMask (mask, XI_Enter);
+
+ if (event_mask & GDK_LEAVE_NOTIFY_MASK)
+ XISetMask (mask, XI_Leave);
+
+ if (event_mask & GDK_FOCUS_CHANGE_MASK)
+ {
+ XISetMask (mask, XI_FocusIn);
+ XISetMask (mask, XI_FocusOut);
+ }
+
+ return mask;
+}
+
+guint
+gdk_device_xi2_translate_state (XIModifierState *mods_state,
+ XIButtonState *buttons_state)
+{
+ guint state = 0;
+
+ if (mods_state)
+ state = (guint) mods_state->effective;
+
+ if (buttons_state)
+ {
+ gint len, i;
+
+ /* We're only interested in the first 5 buttons */
+ len = MIN (5, buttons_state->mask_len * 8);
+
+ for (i = 0; i < len; i++)
+ {
+ if (!BIT_IS_ON (buttons_state->mask, i))
+ continue;
+
+ switch (i)
+ {
+ case 1:
+ state |= GDK_BUTTON1_MASK;
+ break;
+ case 2:
+ state |= GDK_BUTTON2_MASK;
+ break;
+ case 3:
+ state |= GDK_BUTTON3_MASK;
+ break;
+ case 4:
+ state |= GDK_BUTTON4_MASK;
+ break;
+ case 5:
+ state |= GDK_BUTTON5_MASK;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return state;
+}
diff --cc gdk/x11/gdkdevicemanager-xi.c
index 5584fae,0000000..c857eb7
mode 100644,000000..100644
--- a/gdk/x11/gdkdevicemanager-xi.c
+++ b/gdk/x11/gdkdevicemanager-xi.c
@@@ -1,620 -1,0 +1,645 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gdkdevicemanager-xi.h"
+#include "gdkeventtranslator.h"
+#include "gdkdevice-xi.h"
+#include "gdkintl.h"
+#include "gdkx.h"
+
+#include <X11/extensions/XInput.h>
+
+#define GDK_DEVICE_MANAGER_XI_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDK_TYPE_DEVICE_MANAGER_XI, GdkDeviceManagerXIPrivate))
+
+typedef struct GdkDeviceManagerXIPrivate GdkDeviceManagerXIPrivate;
+
+struct GdkDeviceManagerXIPrivate
+{
+ GHashTable *id_table;
+ gint event_base;
+ GList *devices;
+ gboolean ignore_core_events;
+};
+
+static void gdk_device_manager_xi_constructed (GObject *object);
+static void gdk_device_manager_xi_finalize (GObject *object);
+static void gdk_device_manager_xi_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gdk_device_manager_xi_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void gdk_device_manager_xi_event_translator_init (GdkEventTranslatorIface *iface);
+static gboolean gdk_device_manager_xi_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent);
+static GList * gdk_device_manager_xi_get_devices (GdkDeviceManager *device_manager,
+ GdkDeviceType type);
+
+
+G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerXI, gdk_device_manager_xi, GDK_TYPE_DEVICE_MANAGER_CORE,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
+ gdk_device_manager_xi_event_translator_init))
+
+enum {
+ PROP_0,
+ PROP_EVENT_BASE
+};
+
+static void
+gdk_device_manager_xi_class_init (GdkDeviceManagerXIClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
+
+ object_class->constructed = gdk_device_manager_xi_constructed;
+ object_class->finalize = gdk_device_manager_xi_finalize;
+ object_class->set_property = gdk_device_manager_xi_set_property;
+ object_class->get_property = gdk_device_manager_xi_get_property;
+
+ device_manager_class->get_devices = gdk_device_manager_xi_get_devices;
+
+ g_object_class_install_property (object_class,
+ PROP_EVENT_BASE,
+ g_param_spec_int ("event-base",
+ P_("Event base"),
+ P_("Event base for XInput events"),
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (GdkDeviceManagerXIPrivate));
+}
+
+static GdkFilterReturn
+window_input_info_filter (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ GdkDeviceManager *device_manager;
+ GdkDisplay *display;
+ GdkWindow *window;
+ XEvent *xev;
+
+ device_manager = user_data;
+ xev = (XEvent *) xevent;
+
+ display = gdk_device_manager_get_display (device_manager);
+ window = gdk_window_lookup_for_display (display, xev->xany.window);
+
+ if (window && xev->type == ConfigureNotify)
+ gdk_device_xi_update_window_info (window);
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+gdk_device_manager_xi_init (GdkDeviceManagerXI *device_manager)
+{
+ GdkDeviceManagerXIPrivate *priv;
+
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (device_manager);
+ priv->id_table = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_object_unref);
+
+ gdk_window_add_filter (NULL, window_input_info_filter, device_manager);
+}
+
+static void
+translate_class_info (GdkDevice *device,
+ XDeviceInfo *info)
+{
+ GdkDeviceXI *device_xi;
+ XAnyClassPtr class;
+ gint i, j;
+
+ device_xi = GDK_DEVICE_XI (device);
+ class = info->inputclassinfo;
+
+ for (i = 0; i < info->num_classes; i++)
+ {
+ switch (class->class) {
+ case ButtonClass:
+ break;
+ case KeyClass:
+ {
+ XKeyInfo *xki = (XKeyInfo *)class;
+ guint num_keys;
+
+ num_keys = xki->max_keycode - xki->min_keycode + 1;
+ _gdk_device_set_keys (device, num_keys);
+
+ device_xi->min_keycode = xki->min_keycode;
+
+ break;
+ }
+ case ValuatorClass:
+ {
+ XValuatorInfo *xvi = (XValuatorInfo *)class;
+
+ for (j = 0; j < xvi->num_axes; j++)
+ {
+ GdkAxisUse use;
+
+ switch (j)
+ {
+ case 0:
+ use = GDK_AXIS_X;
+ break;
+ case 1:
+ use = GDK_AXIS_Y;
+ break;
+ case 2:
+ use = GDK_AXIS_PRESSURE;
+ break;
+ case 3:
+ use = GDK_AXIS_XTILT;
+ break;
+ case 4:
+ use = GDK_AXIS_YTILT;
+ break;
+ case 5:
+ use = GDK_AXIS_WHEEL;
+ break;
+ default:
+ use = GDK_AXIS_IGNORE;
+ }
+
+ _gdk_device_add_axis (device,
+ GDK_NONE,
+ use,
+ xvi->axes[j].min_value,
+ xvi->axes[j].max_value,
+ xvi->axes[j].resolution);
+ }
+
+ break;
+ }
+ }
+
+ class = (XAnyClassPtr) (((char *) class) + class->length);
+ }
+}
+
+static GdkDevice *
+create_device (GdkDeviceManager *device_manager,
+ GdkDisplay *display,
+ XDeviceInfo *info)
+{
+ GdkInputSource input_source;
+ GdkDevice *device;
+
+ if (info->use != IsXExtensionPointer &&
+ info->use != IsXExtensionKeyboard)
+ return NULL;
+
+ if (info->use == IsXExtensionKeyboard)
+ input_source = GDK_SOURCE_KEYBOARD;
+ else
+ {
+ gchar *tmp_name;
+
+ tmp_name = g_ascii_strdown (info->name, -1);
+
- if (g_str_has_suffix (tmp_name, "pointer"))
- input_source = GDK_SOURCE_MOUSE;
- else if (strcmp (tmp_name, "wacom") == 0 ||
- strcmp (tmp_name, "pen") == 0)
- input_source = GDK_SOURCE_PEN;
- else if (strcmp (tmp_name, "eraser") == 0)
++ if (strstr (tmp_name, "eraser"))
+ input_source = GDK_SOURCE_ERASER;
- else if (strcmp (tmp_name, "cursor") == 0)
++ else if (strstr (tmp_name, "cursor"))
+ input_source = GDK_SOURCE_CURSOR;
- else
++ else if (strstr (tmp_name, "wacom") ||
++ strstr (tmp_name, "pen"))
+ input_source = GDK_SOURCE_PEN;
++ else
++ input_source = GDK_SOURCE_MOUSE;
+
+ g_free (tmp_name);
+ }
+
+ device = g_object_new (GDK_TYPE_DEVICE_XI,
+ "name", info->name,
+ "type", GDK_DEVICE_TYPE_FLOATING,
+ "input-source", input_source,
+ "input-mode", GDK_MODE_DISABLED,
+ "has-cursor", FALSE,
+ "display", display,
+ "device-manager", device_manager,
+ "device-id", info->id,
+ NULL);
+ translate_class_info (device, info);
+
+ return device;
+}
+
+static void
+gdk_device_manager_xi_constructed (GObject *object)
+{
+ GdkDeviceManagerXIPrivate *priv;
+ XDeviceInfo *devices;
+ gint i, num_devices;
+ GdkDisplay *display;
+
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (object);
+ display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
+ devices = XListInputDevices(GDK_DISPLAY_XDISPLAY (display), &num_devices);
+
+ for(i = 0; i < num_devices; i++)
+ {
+ GdkDevice *device;
+
+ device = create_device (GDK_DEVICE_MANAGER (object),
+ display, &devices[i]);
+ if (device)
+ {
+ priv->devices = g_list_prepend (priv->devices, device);
+ g_hash_table_insert (priv->id_table,
+ GINT_TO_POINTER (devices[i].id),
+ device);
+ }
+ }
+
+ XFreeDeviceList(devices);
+
+ gdk_x11_register_standard_event_type (display,
+ priv->event_base,
+ 15 /* Number of events */);
+
+ if (G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->constructed)
+ G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->constructed (object);
+}
+
+static void
+gdk_device_manager_xi_finalize (GObject *object)
+{
+ GdkDeviceManagerXIPrivate *priv;
+
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (object);
+
+ g_list_foreach (priv->devices, (GFunc) g_object_unref, NULL);
+ g_list_free (priv->devices);
+
+ g_hash_table_destroy (priv->id_table);
+
+ gdk_window_remove_filter (NULL, window_input_info_filter, object);
+
+ G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->finalize (object);
+}
+
+static void
+gdk_device_manager_xi_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDeviceManagerXIPrivate *priv;
+
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_EVENT_BASE:
+ priv->event_base = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdk_device_manager_xi_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdkDeviceManagerXIPrivate *priv;
+
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_EVENT_BASE:
+ g_value_set_int (value, priv->event_base);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdk_device_manager_xi_event_translator_init (GdkEventTranslatorIface *iface)
+{
+ iface->translate_event = gdk_device_manager_xi_translate_event;
+}
+
+/* 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
+translate_state (guint state, guint device_state)
+{
+ return device_state | (state & 0xFF);
+}
+
+static GdkDevice *
+lookup_device (GdkDeviceManagerXI *device_manager,
+ XEvent *xevent)
+{
+ GdkDeviceManagerXIPrivate *priv;
+ guint32 device_id;
+
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (device_manager);
+
+ /* 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 */
+ device_id = ((XDeviceButtonEvent *)xevent)->deviceid;
+
+ return g_hash_table_lookup (priv->id_table, GINT_TO_POINTER (device_id));
+}
+
+static gboolean
+gdk_device_manager_xi_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkDeviceManagerXIPrivate *priv;
+ GdkEventTranslatorIface *parent_iface;
+ GdkDeviceXI *device_xi;
+ GdkDevice *device;
+ GdkWindow *window;
+
+ parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (translator);
+
+ if (!priv->ignore_core_events &&
+ parent_iface->translate_event (translator, display, event, xevent))
+ return TRUE;
+
+ device = lookup_device (GDK_DEVICE_MANAGER_XI (translator), xevent);
+ device_xi = GDK_DEVICE_XI (device);
+
+ if (!device)
+ return FALSE;
+
+ window = gdk_window_lookup_for_display (display, xevent->xany.window);
+
+ if (!window)
+ return FALSE;
+
+ if ((xevent->type == device_xi->button_press_type) ||
+ (xevent->type == device_xi->button_release_type))
+ {
+ XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *) xevent;
+
+ event->button.type = (xdbe->type == device_xi->button_press_type) ?
+ GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
+
+ event->button.device = device;
+ event->button.window = g_object_ref (window);
+ event->button.time = xdbe->time;
+
+ event->button.x_root = (gdouble) xdbe->x_root;
+ event->button.y_root = (gdouble) xdbe->y_root;
+
+ event->button.axes = g_new0 (gdouble, device->num_axes);
++ gdk_device_xi_update_axes (device, xdbe->axes_count,
++ xdbe->first_axis, xdbe->axis_data);
+ gdk_device_xi_translate_axes (device, window,
- xdbe->axis_data,
++ device_xi->axis_data,
+ event->button.axes,
+ &event->button.x,
+ &event->button.y);
+
+ event->button.state = translate_state (xdbe->state, xdbe->device_state);
+ event->button.button = xdbe->button;
+
+ if (event->button.type == GDK_BUTTON_PRESS)
+ _gdk_event_button_generate (gdk_drawable_get_display (event->button.window),
+ event);
+
+ GDK_NOTE (EVENTS,
+ g_print ("button %s:\t\twindow: %ld device: %ld x,y: %f %f button: %d\n",
+ (event->button.type == GDK_BUTTON_PRESS) ? "press" : "release",
+ xdbe->window,
+ xdbe->deviceid,
+ event->button.x, event->button.y,
+ xdbe->button));
+
+ /* Update the timestamp of the latest user interaction, if the event has
+ * a valid timestamp.
+ */
+ if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
+ return TRUE;
+ }
+
+ if ((xevent->type == device_xi->key_press_type) ||
+ (xevent->type == device_xi->key_release_type))
+ {
+ XDeviceKeyEvent *xdke = (XDeviceKeyEvent *) xevent;
+
+ GDK_NOTE (EVENTS,
+ g_print ("device key %s:\twindow: %ld device: %ld keycode: %d\n",
+ (event->key.type == GDK_KEY_PRESS) ? "press" : "release",
+ xdke->window,
+ xdke->deviceid,
+ xdke->keycode));
+
+ if (xdke->keycode < device_xi->min_keycode ||
+ xdke->keycode >= device_xi->min_keycode + device->num_keys)
+ {
+ g_warning ("Invalid device key code received");
+ return FALSE;
+ }
+
+ event->key.keyval = device->keys[xdke->keycode - device_xi->min_keycode].keyval;
+
+ if (event->key.keyval == 0)
+ {
+ GDK_NOTE (EVENTS,
+ g_print ("\t\ttranslation - NONE\n"));
+
+ return FALSE;
+ }
+
+ event->key.type = (xdke->type == device_xi->key_press_type) ?
+ GDK_KEY_PRESS : GDK_KEY_RELEASE;
+
+ event->key.window = g_object_ref (window);
+ event->key.time = xdke->time;
+
+ event->key.state = translate_state (xdke->state, xdke->device_state)
+ | device->keys[xdke->keycode - device_xi->min_keycode].modifiers;
+
+ /* Add a string translation for the key event */
+ if ((event->key.keyval >= 0x20) && (event->key.keyval <= 0xFF))
+ {
+ event->key.length = 1;
+ event->key.string = g_new (gchar, 2);
+ event->key.string[0] = (gchar) event->key.keyval;
+ event->key.string[1] = 0;
+ }
+ else
+ {
+ event->key.length = 0;
+ event->key.string = g_new0 (gchar, 1);
+ }
+
+ GDK_NOTE (EVENTS,
+ g_print ("\t\ttranslation - keyval: %d modifiers: %#x\n",
+ event->key.keyval,
+ event->key.state));
+
+ /* Update the timestamp of the latest user interaction, if the event has
+ * a valid timestamp.
+ */
+ if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
+ return TRUE;
+ }
+
+ if (xevent->type == device_xi->motion_notify_type)
+ {
+ XDeviceMotionEvent *xdme = (XDeviceMotionEvent *) xevent;
+
+ event->motion.device = device;
+
+ if (device_xi->in_proximity)
+ priv->ignore_core_events = TRUE;
+
+ event->motion.x_root = (gdouble) xdme->x_root;
+ event->motion.y_root = (gdouble) xdme->y_root;
+
+ event->motion.axes = g_new0 (gdouble, device->num_axes);
++ gdk_device_xi_update_axes (device, xdme->axes_count,
++ xdme->first_axis, xdme->axis_data);
+ gdk_device_xi_translate_axes (device, window,
- xdme->axis_data,
++ device_xi->axis_data,
+ event->motion.axes,
+ &event->motion.x,
+ &event->motion.y);
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = g_object_ref (window);
+ event->motion.time = xdme->time;
+ event->motion.state = translate_state (xdme->state,
+ xdme->device_state);
+ event->motion.is_hint = xdme->is_hint;
+
+ GDK_NOTE (EVENTS,
+ g_print ("motion notify:\t\twindow: %ld device: %ld x,y: %f %f state %#4x hint: %s\n",
+ xdme->window,
+ xdme->deviceid,
+ event->motion.x, event->motion.y,
+ event->motion.state,
+ (xdme->is_hint) ? "true" : "false"));
+
+
+ /* Update the timestamp of the latest user interaction, if the event has
+ * a valid timestamp.
+ */
+ if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
+ return TRUE;
+ }
+
+ if (xevent->type == device_xi->proximity_in_type ||
+ xevent->type == device_xi->proximity_out_type)
+ {
+ XProximityNotifyEvent *xpne = (XProximityNotifyEvent *) xevent;
+
+ if (xevent->type == device_xi->proximity_in_type)
+ {
+ event->proximity.type = GDK_PROXIMITY_IN;
+ device_xi->in_proximity = TRUE;
+ priv->ignore_core_events = TRUE;
+ }
+ else
+ {
+ event->proximity.type = GDK_PROXIMITY_OUT;
+ device_xi->in_proximity = FALSE;
+ priv->ignore_core_events = FALSE;
+ }
+
+ event->proximity.device = device;
+ event->proximity.window = g_object_ref (window);
+ event->proximity.time = xpne->time;
+
+ /* Update the timestamp of the latest user interaction, if the event has
+ * a valid timestamp.
+ */
+ if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
+ return TRUE;
- }
++ }
++
++ if (xevent->type == device_xi->state_notify_type)
++ {
++ XDeviceStateNotifyEvent *xdse = (XDeviceStateNotifyEvent *) xevent;
++ XInputClass *input_class = (XInputClass *) xdse->data;
++ int i;
++
++ for (i = 0; i < xdse->num_classes; i++)
++ {
++ if (input_class->class == ValuatorClass)
++ gdk_device_xi_update_axes (device, device->num_axes, 0,
++ ((XValuatorState *)input_class)->valuators);
++
++ input_class = (XInputClass *)(((char *)input_class)+input_class->length);
++ }
++
++ GDK_NOTE (EVENTS,
++ g_print ("device state notify:\t\twindow: %ld device: %ld\n",
++ xdse->window,
++ xdse->deviceid));
++
++ return FALSE;
++ }
+
+ return FALSE;
+}
+
+static GList *
+gdk_device_manager_xi_get_devices (GdkDeviceManager *device_manager,
+ GdkDeviceType type)
+{
+ GdkDeviceManagerXIPrivate *priv;
+
+ if (type == GDK_DEVICE_TYPE_MASTER)
+ return GDK_DEVICE_MANAGER_CLASS (gdk_device_manager_xi_parent_class)->get_devices (device_manager, type);
+ else if (type == GDK_DEVICE_TYPE_FLOATING)
+ {
+ priv = GDK_DEVICE_MANAGER_XI_GET_PRIVATE (device_manager);
+ return g_list_copy (priv->devices);
+ }
+ else
+ return NULL;
+}
diff --cc gdk/x11/gdkdevicemanager-xi2.c
index 926cd39,0000000..d0ccb2a
mode 100644,000000..100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@@ -1,1133 -1,0 +1,1131 @@@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2009 Carlos Garnacho <carlosg gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+
+#include <gdk/gdkdeviceprivate.h>
+#include "gdkdevicemanager-xi2.h"
+#include "gdkeventtranslator.h"
+#include "gdkdevice-xi2.h"
+#include "gdkkeysyms.h"
+#include "gdkx.h"
+
+#define HAS_FOCUS(toplevel) ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
+
+
+static void gdk_device_manager_xi2_constructed (GObject *object);
+static void gdk_device_manager_xi2_finalize (GObject *object);
+
+static GList * gdk_device_manager_xi2_get_devices (GdkDeviceManager *device_manager,
+ GdkDeviceType type);
+
+static void gdk_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface);
+
+static gboolean gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent);
+static GdkEventMask gdk_device_manager_xi2_get_handled_events (GdkEventTranslator *translator);
+static void gdk_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
+ Window window,
+ GdkEventMask event_mask);
+
+
+G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerXI2, gdk_device_manager_xi2, GDK_TYPE_DEVICE_MANAGER,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
+ gdk_device_manager_xi2_event_translator_init))
+
+
+static void
+gdk_device_manager_xi2_class_init (GdkDeviceManagerXI2Class *klass)
+{
+ GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gdk_device_manager_xi2_constructed;
+ object_class->finalize = gdk_device_manager_xi2_finalize;
+
+ device_manager_class->get_devices = gdk_device_manager_xi2_get_devices;
+}
+
+static void
+gdk_device_manager_xi2_init (GdkDeviceManagerXI2 *device_manager)
+{
+ device_manager->id_table = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ (GDestroyNotify) g_object_unref);
+}
+
+static void
+_gdk_device_manager_xi2_select_events (GdkDeviceManager *device_manager,
+ Window xwindow,
+ XIEventMask *event_mask)
+{
+ GdkDisplay *display;
+ Display *xdisplay;
+
+ display = gdk_device_manager_get_display (device_manager);
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+ XISelectEvents (xdisplay, xwindow, event_mask, 1);
+}
+
+static void
+translate_valuator_class (GdkDisplay *display,
+ GdkDevice *device,
+ XIValuatorClassInfo *info,
+ gint n_valuator)
+{
+ static gboolean initialized = FALSE;
+ static Atom label_atoms [GDK_AXIS_LAST] = { 0 };
+ GdkAxisUse use = GDK_AXIS_IGNORE;
+ GdkAtom label;
+ gint i;
+
+ if (!initialized)
+ {
+ label_atoms [GDK_AXIS_X] = gdk_x11_get_xatom_by_name_for_display (display, "Abs X");
+ label_atoms [GDK_AXIS_Y] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Y");
+ label_atoms [GDK_AXIS_PRESSURE] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Pressure");
+ label_atoms [GDK_AXIS_XTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt X");
+ label_atoms [GDK_AXIS_YTILT] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Tilt Y");
+ label_atoms [GDK_AXIS_WHEEL] = gdk_x11_get_xatom_by_name_for_display (display, "Abs Wheel");
+ initialized = TRUE;
+ }
+
+ for (i = GDK_AXIS_IGNORE; i <= GDK_AXIS_LAST; i++)
+ {
+ if (label_atoms[i] == info->label)
+ {
+ use = i;
+ break;
+ }
+ }
+
+ if (info->label != None)
+ label = gdk_x11_xatom_to_atom_for_display (display, info->label);
+ else
+ label = GDK_NONE;
+
+ _gdk_device_add_axis (device,
+ label,
+ use,
+ info->min,
+ info->max,
+ info->resolution);
+}
+
+static void
+translate_device_classes (GdkDisplay *display,
+ GdkDevice *device,
+ XIAnyClassInfo **classes,
+ guint n_classes)
+{
+ gint i, n_valuator = 0;
+
+ g_object_freeze_notify (G_OBJECT (device));
+
+ for (i = 0; i < n_classes; i++)
+ {
+ XIAnyClassInfo *class_info = classes[i];
+
+ switch (class_info->type)
+ {
+ case XIKeyClass:
+ {
+ XIKeyClassInfo *key_info = (XIKeyClassInfo *) class_info;
+ gint i;
+
+ _gdk_device_set_keys (device, key_info->num_keycodes);
+
+ for (i = 0; i < key_info->num_keycodes; i++)
+ gdk_device_set_key (device, i, key_info->keycodes[i], 0);
+ }
+ break;
+ case XIValuatorClass:
+ translate_valuator_class (display, device,
+ (XIValuatorClassInfo *) class_info,
+ n_valuator);
+ n_valuator++;
+ break;
+ default:
+ /* Ignore */
+ break;
+ }
+ }
+
+ g_object_thaw_notify (G_OBJECT (device));
+}
+
+static GdkDevice *
+create_device (GdkDeviceManager *device_manager,
+ GdkDisplay *display,
+ XIDeviceInfo *dev)
+{
+ GdkInputSource input_source;
+ GdkDeviceType type;
+ GdkDevice *device;
+ GdkInputMode mode;
+
+ if (dev->use == XIMasterKeyboard || dev->use == XISlaveKeyboard)
+ input_source = GDK_SOURCE_KEYBOARD;
+ else
+ {
+ gchar *tmp_name;
+
+ tmp_name = g_ascii_strdown (dev->name, -1);
+
- if (g_str_has_suffix (tmp_name, "pointer"))
- input_source = GDK_SOURCE_MOUSE;
- else if (strcmp (tmp_name, "wacom") == 0 ||
- strcmp (tmp_name, "pen") == 0)
- input_source = GDK_SOURCE_PEN;
- else if (strcmp (tmp_name, "eraser") == 0)
++ if (strstr (tmp_name, "eraser"))
+ input_source = GDK_SOURCE_ERASER;
- else if (strcmp (tmp_name, "cursor") == 0)
++ else if (strstr (tmp_name, "cursor"))
+ input_source = GDK_SOURCE_CURSOR;
- else
++ else if (strstr (tmp_name, "wacom") ||
++ strstr (tmp_name, "pen"))
+ input_source = GDK_SOURCE_PEN;
++ else
++ input_source = GDK_SOURCE_MOUSE;
+
+ g_free (tmp_name);
+ }
+
+ switch (dev->use)
+ {
+ case XIMasterKeyboard:
+ case XIMasterPointer:
+ type = GDK_DEVICE_TYPE_MASTER;
+ mode = GDK_MODE_SCREEN;
+ break;
+ case XISlaveKeyboard:
+ case XISlavePointer:
+ type = GDK_DEVICE_TYPE_SLAVE;
+ mode = GDK_MODE_DISABLED;
+ break;
+ case XIFloatingSlave:
+ default:
+ type = GDK_DEVICE_TYPE_FLOATING;
+ mode = GDK_MODE_DISABLED;
+ break;
+ }
+
+ device = g_object_new (GDK_TYPE_DEVICE_XI2,
+ "name", dev->name,
+ "type", type,
+ "input-source", input_source,
+ "input-mode", mode,
+ "has-cursor", (dev->use == XIMasterPointer),
+ "display", display,
+ "device-manager", device_manager,
+ "device-id", dev->deviceid,
+ NULL);
+
+ translate_device_classes (display, device, dev->classes, dev->num_classes);
+
+ return device;
+}
+
+static GdkDevice *
+add_device (GdkDeviceManagerXI2 *device_manager,
+ XIDeviceInfo *dev,
+ gboolean emit_signal)
+{
+ GdkDisplay *display;
+ GdkDevice *device;
+
+ display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
+ device = create_device (GDK_DEVICE_MANAGER (device_manager), display, dev);
+
+ g_hash_table_replace (device_manager->id_table,
+ GINT_TO_POINTER (dev->deviceid),
+ device);
+
+ if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard)
+ device_manager->master_devices = g_list_append (device_manager->master_devices, device);
+ else if (dev->use == XISlavePointer || dev->use == XISlaveKeyboard)
+ device_manager->slave_devices = g_list_append (device_manager->slave_devices, device);
+ else if (dev->use == XIFloatingSlave)
+ device_manager->floating_devices = g_list_append (device_manager->floating_devices, device);
+ else
+ g_warning ("Unhandled device: %s\n", device->name);
+
+ if (emit_signal)
+ g_signal_emit_by_name (device_manager, "device-added", device);
+
+ return device;
+}
+
+static void
+remove_device (GdkDeviceManagerXI2 *device_manager,
+ int device_id)
+{
+ GdkDevice *device;
+
+ device = g_hash_table_lookup (device_manager->id_table,
+ GINT_TO_POINTER (device_id));
+
+ if (device)
+ {
+ device_manager->master_devices = g_list_remove (device_manager->master_devices, device);
+ device_manager->slave_devices = g_list_remove (device_manager->slave_devices, device);
+ device_manager->floating_devices = g_list_remove (device_manager->floating_devices, device);
+
+ g_signal_emit_by_name (device_manager, "device-removed", device);
+
+ g_object_run_dispose (G_OBJECT (device));
+
+ g_hash_table_remove (device_manager->id_table,
+ GINT_TO_POINTER (device_id));
+ }
+}
+
+static void
+relate_devices (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GdkDeviceManagerXI2 *device_manager;
+ GdkDevice *device, *relative;
+
+ device_manager = user_data;
+ device = g_hash_table_lookup (device_manager->id_table, key);
+ relative = g_hash_table_lookup (device_manager->id_table, value);
+
+ _gdk_device_set_relative (device, relative);
+ _gdk_device_set_relative (relative, device);
+}
+
+static void
+gdk_device_manager_xi2_constructed (GObject *object)
+{
+ GdkDeviceManagerXI2 *device_manager_xi2;
+ GdkDisplay *display;
+ GdkScreen *screen;
+ GHashTable *relations;
+ Display *xdisplay;
+ XIDeviceInfo *info, *dev;
+ int ndevices, i;
+ XIEventMask event_mask;
+ unsigned char mask[2] = { 0 };
+
+ device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (object);
+ display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ relations = g_hash_table_new (NULL, NULL);
+
+ info = XIQueryDevice(xdisplay, XIAllDevices, &ndevices);
+
+ /* Initialize devices list */
+ for (i = 0; i < ndevices; i++)
+ {
+ GdkDevice *device;
+
+ dev = &info[i];
+ device = add_device (device_manager_xi2, dev, FALSE);
+
+ if (dev->use == XIMasterPointer ||
+ dev->use == XIMasterKeyboard)
+ {
+ g_hash_table_insert (relations,
+ GINT_TO_POINTER (dev->deviceid),
+ GINT_TO_POINTER (dev->attachment));
+ }
+ }
+
+ XIFreeDeviceInfo(info);
+
+ /* Stablish relationships between devices */
+ g_hash_table_foreach (relations, relate_devices, object);
+ g_hash_table_destroy (relations);
+
+ /* Connect to hierarchy change events */
+ screen = gdk_display_get_default_screen (display);
+ XISetMask (mask, XI_HierarchyChanged);
+ XISetMask (mask, XI_DeviceChanged);
+
+ event_mask.deviceid = XIAllDevices;
+ event_mask.mask_len = sizeof (mask);
+ event_mask.mask = mask;
+
+ _gdk_device_manager_xi2_select_events (GDK_DEVICE_MANAGER (object),
+ GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)),
+ &event_mask);
+}
+
+static void
+gdk_device_manager_xi2_finalize (GObject *object)
+{
+ GdkDeviceManagerXI2 *device_manager_xi2;
+
+ device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (object);
+
+ g_list_foreach (device_manager_xi2->master_devices, (GFunc) g_object_unref, NULL);
+ g_list_free (device_manager_xi2->master_devices);
+
+ g_list_foreach (device_manager_xi2->slave_devices, (GFunc) g_object_unref, NULL);
+ g_list_free (device_manager_xi2->slave_devices);
+
+ g_list_foreach (device_manager_xi2->floating_devices, (GFunc) g_object_unref, NULL);
+ g_list_free (device_manager_xi2->floating_devices);
+
+ g_hash_table_destroy (device_manager_xi2->id_table);
+
+ G_OBJECT_CLASS (gdk_device_manager_xi2_parent_class)->finalize (object);
+}
+
+static GList *
+gdk_device_manager_xi2_get_devices (GdkDeviceManager *device_manager,
+ GdkDeviceType type)
+{
+ GdkDeviceManagerXI2 *device_manager_xi2;
+ GList *list = NULL;
+
+ device_manager_xi2 = GDK_DEVICE_MANAGER_XI2 (device_manager);
+
+ switch (type)
+ {
+ case GDK_DEVICE_TYPE_MASTER:
+ list = device_manager_xi2->master_devices;
+ break;
+ case GDK_DEVICE_TYPE_SLAVE:
+ list = device_manager_xi2->slave_devices;
+ break;
+ case GDK_DEVICE_TYPE_FLOATING:
+ list = device_manager_xi2->floating_devices;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return g_list_copy (list);
+}
+
+static void
+gdk_device_manager_xi2_event_translator_init (GdkEventTranslatorIface *iface)
+{
+ iface->translate_event = gdk_device_manager_xi2_translate_event;
+ iface->get_handled_events = gdk_device_manager_xi2_get_handled_events;
+ iface->select_window_events = gdk_device_manager_xi2_select_window_events;
+}
+
+static void
+handle_hierarchy_changed (GdkDeviceManagerXI2 *device_manager,
+ XIHierarchyEvent *ev)
+{
+ GdkDevice *device;
+ gint i;
+
+ /* We only care about enabled devices */
+ if (!(ev->flags & XIDeviceEnabled) &&
+ !(ev->flags & XIDeviceDisabled))
+ return;
+
+ for (i = 0; i < ev->num_info; i++)
+ {
+ if (ev->info[i].flags & XIDeviceEnabled)
+ {
+ GdkDisplay *display;
+ Display *xdisplay;
+ XIDeviceInfo *info;
+ int ndevices;
+
+ display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+ info = XIQueryDevice(xdisplay, ev->info[i].deviceid, &ndevices);
+ device = add_device (device_manager, &info[0], TRUE);
+ XIFreeDeviceInfo(info);
+ }
+ else if (ev->info[i].flags & XIDeviceDisabled)
+ remove_device (device_manager, ev->info[i].deviceid);
+ }
+}
+
+static void
+handle_device_changed (GdkDeviceManagerXI2 *device_manager,
+ XIDeviceChangedEvent *ev)
+{
+ GdkDisplay *display;
+ GdkDevice *device;
+
+ display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
+ device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (ev->deviceid));
+
+ _gdk_device_reset_axes (device);
+ translate_device_classes (display, device, ev->classes, ev->num_classes);
+}
+
+static GdkCrossingMode
+translate_crossing_mode (int mode)
+{
+ switch (mode)
+ {
+ case NotifyNormal:
+ return GDK_CROSSING_NORMAL;
+ case NotifyGrab:
+ return GDK_CROSSING_GRAB;
+ case NotifyUngrab:
+ return GDK_CROSSING_UNGRAB;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static GdkNotifyType
+translate_notify_type (int detail)
+{
+ switch (detail)
+ {
+ case NotifyInferior:
+ return GDK_NOTIFY_INFERIOR;
+ case NotifyAncestor:
+ return GDK_NOTIFY_ANCESTOR;
+ case NotifyVirtual:
+ return GDK_NOTIFY_VIRTUAL;
+ case NotifyNonlinear:
+ return GDK_NOTIFY_NONLINEAR;
+ case NotifyNonlinearVirtual:
+ return GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gboolean
+set_screen_from_root (GdkDisplay *display,
+ GdkEvent *event,
+ Window xrootwin)
+{
+ GdkScreen *screen;
+
+ screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
+
+ if (screen)
+ {
+ gdk_event_set_screen (event, screen);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+set_user_time (GdkEvent *event)
+{
+ GdkWindow *window;
+ guint32 time;
+
+ window = gdk_window_get_toplevel (event->any.window);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ time = gdk_event_get_time (event);
+
+ /* If an event doesn't have a valid timestamp, we shouldn't use it
+ * to update the latest user interaction time.
+ */
+ if (time != GDK_CURRENT_TIME)
+ gdk_x11_window_set_user_time (window, time);
+}
+
+static void
+translate_keyboard_string (GdkEventKey *event)
+{
+ gunichar c = 0;
+ gchar buf[7];
+
+ /* Fill in event->string crudely, since various programs
+ * depend on it.
+ */
+ event->string = NULL;
+
+ if (event->keyval != GDK_VoidSymbol)
+ c = gdk_keyval_to_unicode (event->keyval);
+
+ if (c)
+ {
+ gsize bytes_written;
+ gint len;
+
+ /* Apply the control key - Taken from Xlib
+ */
+ if (event->state & GDK_CONTROL_MASK)
+ {
+ if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
+ else if (c == '2')
+ {
+ event->string = g_memdup ("\0\0", 2);
+ event->length = 1;
+ buf[0] = '\0';
+ return;
+ }
+ else if (c >= '3' && c <= '7') c -= ('3' - '\033');
+ else if (c == '8') c = '\177';
+ else if (c == '/') c = '_' & 0x1F;
+ }
+
+ len = g_unichar_to_utf8 (c, buf);
+ buf[len] = '\0';
+
+ event->string = g_locale_from_utf8 (buf, len,
+ NULL, &bytes_written,
+ NULL);
+ if (event->string)
+ event->length = bytes_written;
+ }
+ else if (event->keyval == GDK_Escape)
+ {
+ event->length = 1;
+ event->string = g_strdup ("\033");
+ }
+ else if (event->keyval == GDK_Return ||
+ event->keyval == GDK_KP_Enter)
+ {
+ event->length = 1;
+ event->string = g_strdup ("\r");
+ }
+
+ if (!event->string)
+ {
+ event->length = 0;
+ event->string = g_strdup ("");
+ }
+}
+
+static void
+generate_focus_event (GdkWindow *window,
+ gboolean in)
+{
+ GdkEvent event;
+
+ event.type = GDK_FOCUS_CHANGE;
+ event.focus_change.window = window;
+ event.focus_change.send_event = FALSE;
+ event.focus_change.in = in;
+
+ gdk_event_put (&event);
+}
+
+static void
+handle_focus_change (GdkWindow *window,
+ gint detail,
+ gint mode,
+ gboolean in)
+{
+ GdkToplevelX11 *toplevel;
+ gboolean had_focus;
+
+ toplevel = _gdk_x11_window_get_toplevel (window);
+
+ if (!toplevel)
+ return;
+
+ had_focus = HAS_FOCUS (toplevel);
+
+ switch (detail)
+ {
+ case NotifyAncestor:
+ case NotifyVirtual:
+ /* When the focus moves from an ancestor of the window to
+ * the window or a descendent of the window, *and* the
+ * pointer is inside the window, then we were previously
+ * receiving keystroke events in the has_pointer_focus
+ * case and are now receiving them in the
+ * has_focus_window case.
+ */
+ if (toplevel->has_pointer &&
+ mode != NotifyGrab &&
+ mode != NotifyUngrab)
+ toplevel->has_pointer_focus = (in) ? FALSE : TRUE;
+
+ /* fall through */
+ case NotifyNonlinear:
+ case NotifyNonlinearVirtual:
+ if (mode != NotifyGrab &&
+ mode != NotifyUngrab)
+ toplevel->has_focus_window = (in) ? TRUE : FALSE;
+ /* We pretend that the focus moves to the grab
+ * window, so we pay attention to NotifyGrab
+ * NotifyUngrab, and ignore NotifyWhileGrabbed
+ */
+ if (mode != NotifyWhileGrabbed)
+ toplevel->has_focus = (in) ? TRUE : FALSE;
+ break;
+ case NotifyPointer:
+ /* The X server sends NotifyPointer/NotifyGrab,
+ * but the pointer focus is ignored while a
+ * grab is in effect
+ */
+ if (mode != NotifyGrab &&
+ mode != NotifyUngrab)
+ toplevel->has_pointer_focus = (in) ? TRUE :FALSE;
+ break;
+ case NotifyInferior:
+ case NotifyPointerRoot:
+ case NotifyDetailNone:
+ break;
+ }
+
+ if (HAS_FOCUS (toplevel) != had_focus)
+ generate_focus_event (window, (in) ? TRUE : FALSE);
+}
+
+static gdouble *
+translate_axes (GdkDevice *device,
+ gdouble x,
+ gdouble y,
+ GdkWindow *window,
+ XIValuatorState *valuators)
+{
+ guint n_axes, i;
+ gint width, height;
+ gdouble *axes;
+ double *vals;
+
+ g_object_get (device, "n-axes", &n_axes, NULL);
+
+ axes = g_new0 (gdouble, n_axes);
+ vals = valuators->values;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
+
+ for (i = 0; i < valuators->mask_len * 8; i++)
+ {
+ GdkAxisUse use;
+ gdouble val;
+
+ if (!XIMaskIsSet (valuators->mask, i))
+ continue;
+
+ use = _gdk_device_get_axis_use (device, i);
+ val = *vals++;
+
+ switch (use)
+ {
+ case GDK_AXIS_X:
+ case GDK_AXIS_Y:
+ if (device->mode == GDK_MODE_WINDOW)
+ _gdk_device_translate_window_coord (device, window, i, val, &axes[i]);
+ else
+ {
+ if (use == GDK_AXIS_X)
+ axes[i] = x;
+ else
+ axes[i] = y;
+ }
+ break;
+ default:
+ _gdk_device_translate_axis (device, i, val, &axes[i]);
+ break;
+ }
+ }
+
+ return axes;
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
+
+ w = gdk_window_get_parent (w);
+ }
+
+ return FALSE;
+}
+
+static GdkWindow *
+get_event_window (GdkEventTranslator *translator,
+ XIEvent *ev)
+{
+ GdkDisplay *display;
+ GdkWindow *window = NULL;
+
+ display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
+
+ switch (ev->evtype)
+ {
+ case XI_KeyPress:
+ case XI_KeyRelease:
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+
+ window = gdk_window_lookup_for_display (display, xev->event);
+
+ /* Apply keyboard grabs to non-native windows */
+ if (ev->evtype == XI_KeyPress || ev->evtype == XI_KeyRelease)
+ {
+ GdkDeviceGrabInfo *info;
+ GdkDevice *device;
+ gulong serial;
+
+ device = g_hash_table_lookup (GDK_DEVICE_MANAGER_XI2 (translator)->id_table,
+ GUINT_TO_POINTER (((XIDeviceEvent *) ev)->deviceid));
+
+ serial = _gdk_windowing_window_get_next_serial (display);
+ info = _gdk_display_has_device_grab (display, device, serial);
+
+ if (info &&
+ (!is_parent_of (info->window, window) ||
+ !info->owner_events))
+ {
+ /* Report key event against grab window */
+ window = info->window;
+ }
+ }
+ }
+ break;
+ case XI_Enter:
+ case XI_Leave:
+ case XI_FocusIn:
+ case XI_FocusOut:
+ {
+ XIEnterEvent *xev = (XIEnterEvent *) ev;
+
+ window = gdk_window_lookup_for_display (display, xev->event);
+ }
+ break;
+ }
+
+ return window;
+}
+
+static gboolean
+gdk_device_manager_xi2_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkDeviceManagerXI2 *device_manager;
+ XGenericEventCookie *cookie;
+ gboolean return_val = TRUE;
+ GdkWindow *window;
+ XIEvent *ev;
+ Display *dpy;
+
+ dpy = GDK_DISPLAY_XDISPLAY (display);
+ device_manager = (GdkDeviceManagerXI2 *) translator;
+ cookie = &xevent->xcookie;
+
+ if (!XGetEventData (dpy, cookie))
+ return FALSE;
+
+ if (cookie->type != GenericEvent ||
+ cookie->extension != device_manager->opcode)
+ {
+ XFreeEventData (dpy, cookie);
+ return FALSE;
+ }
+
+ ev = (XIEvent *) cookie->data;
+
+ window = get_event_window (translator, ev);
+
+ if (window && GDK_WINDOW_DESTROYED (window))
+ {
+ XFreeEventData (dpy, cookie);
+ return FALSE;
+ }
+
+ if (ev->evtype == XI_Motion ||
+ ev->evtype == XI_ButtonRelease)
+ {
+ if (_gdk_moveresize_handle_event (xevent))
+ {
+ XFreeEventData (dpy, cookie);
+ return FALSE;
+ }
+ }
+
+ switch (ev->evtype)
+ {
+ case XI_HierarchyChanged:
+ handle_hierarchy_changed (device_manager,
+ (XIHierarchyEvent *) ev);
+ return_val = FALSE;
+ break;
+ case XI_DeviceChanged:
+ handle_device_changed (device_manager,
+ (XIDeviceChangedEvent *) ev);
+ return_val = FALSE;
+ break;
+ case XI_KeyPress:
+ case XI_KeyRelease:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+ GdkKeymap *keymap = gdk_keymap_get_for_display (display);
+
+ event->key.type = xev->evtype == XI_KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+
+ event->key.window = window;
+
+ event->key.time = xev->time;
+ event->key.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
+ event->key.group = _gdk_x11_get_group_for_state (display, event->key.state);
+
+ event->key.hardware_keycode = xev->detail;
+ event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
+
+ event->key.device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->deviceid));
+
+ _gdk_keymap_add_virtual_modifiers (keymap, &event->key.state);
+
+ event->key.keyval = GDK_VoidSymbol;
+
+ gdk_keymap_translate_keyboard_state (keymap,
+ event->key.hardware_keycode,
+ event->key.state,
+ event->key.group,
+ &event->key.keyval,
+ NULL, NULL, NULL);
+
+ translate_keyboard_string ((GdkEventKey *) event);
+
+ if (ev->evtype == XI_KeyPress)
+ set_user_time (event);
+
+ /* FIXME: emulate autorepeat on key
+ * release? XI2 seems attached to Xkb.
+ */
+ }
+
+ break;
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+
+ switch (xev->detail)
+ {
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ event->scroll.type = GDK_SCROLL;
+
+ if (xev->detail == 4)
+ event->scroll.direction = GDK_SCROLL_UP;
+ else if (xev->detail == 5)
+ event->scroll.direction = GDK_SCROLL_DOWN;
+ else if (xev->detail == 6)
+ event->scroll.direction = GDK_SCROLL_LEFT;
+ else
+ event->scroll.direction = GDK_SCROLL_RIGHT;
+
+ event->scroll.window = window;
+ event->scroll.time = xev->time;
+ event->scroll.x = (gdouble) xev->event_x;
+ event->scroll.y = (gdouble) xev->event_y;
+ event->scroll.x_root = (gdouble) xev->root_x;
+ event->scroll.y_root = (gdouble) xev->root_y;
+
+ event->scroll.device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->deviceid));
+
+ event->scroll.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
+ break;
+ default:
+ event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
+
+ event->button.window = window;
+ event->button.time = xev->time;
+ event->button.x = (gdouble) xev->event_x;
+ event->button.y = (gdouble) xev->event_y;
+ event->button.x_root = (gdouble) xev->root_x;
+ event->button.y_root = (gdouble) xev->root_y;
+
+ event->button.device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->deviceid));
+
+ event->button.axes = translate_axes (event->button.device,
+ event->button.x,
+ event->button.y,
+ event->button.window,
+ &xev->valuators);
+
+ if (event->button.device->mode == GDK_MODE_WINDOW)
+ {
+ GdkDevice *device = event->button.device;
+
+ /* Update event coordinates from axes */
+ gdk_device_get_axis (device, event->button.axes, GDK_AXIS_X, &event->button.x);
+ gdk_device_get_axis (device, event->button.axes, GDK_AXIS_Y, &event->button.y);
+ }
+
+ event->button.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
+ event->button.button = xev->detail;
+ }
+
+ if (!set_screen_from_root (display, event, xev->root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ set_user_time (event);
+
+ break;
+ }
+ case XI_Motion:
+ {
+ XIDeviceEvent *xev = (XIDeviceEvent *) ev;
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+
+ event->motion.window = window;
+
+ event->motion.time = xev->time;
+ event->motion.x = (gdouble) xev->event_x;
+ event->motion.y = (gdouble) xev->event_y;
+ event->motion.x_root = (gdouble) xev->root_x;
+ event->motion.y_root = (gdouble) xev->root_y;
+
+ event->motion.device = g_hash_table_lookup (device_manager->id_table,
+ GINT_TO_POINTER (xev->deviceid));
+
+ event->motion.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
+
+ /* There doesn't seem to be motion hints in XI */
+ event->motion.is_hint = FALSE;
+
+ event->motion.axes = translate_axes (event->motion.device,
+ event->motion.x,
+ event->motion.y,
+ event->motion.window,
+ &xev->valuators);
+
+ if (event->motion.device->mode == GDK_MODE_WINDOW)
+ {
+ GdkDevice *device = event->motion.device;
+
+ /* Update event coordinates from axes */
+ gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_X, &event->motion.x);
+ gdk_device_get_axis (device, event->motion.axes, GDK_AXIS_Y, &event->motion.y);
+ }
+ }
+ break;
+ case XI_Enter:
+ case XI_Leave:
+ {
+ XIEnterEvent *xev = (XIEnterEvent *) ev;
+
+ event->crossing.type = (ev->evtype == XI_Enter) ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY;
+
+ event->crossing.x = (gdouble) xev->event_x;
+ event->crossing.y = (gdouble) xev->event_y;
+ event->crossing.x_root = (gdouble) xev->root_x;
+ event->crossing.y_root = (gdouble) xev->root_y;
+ event->crossing.time = xev->time;
+ event->crossing.focus = xev->focus;
+
+ event->crossing.window = window;
+ event->crossing.subwindow = gdk_window_lookup_for_display (display, xev->child);
+ event->crossing.device = g_hash_table_lookup (device_manager->id_table,
+ GINT_TO_POINTER (xev->deviceid));
+
+ event->crossing.mode = translate_crossing_mode (xev->mode);
+ event->crossing.detail = translate_notify_type (xev->detail);
+ event->crossing.state = gdk_device_xi2_translate_state (&xev->mods, &xev->buttons);
+ }
+ break;
+ case XI_FocusIn:
+ case XI_FocusOut:
+ {
+ XIEnterEvent *xev = (XIEnterEvent *) ev;
+
+ handle_focus_change (window, xev->detail, xev->mode,
+ (ev->evtype == XI_FocusIn) ? TRUE : FALSE);
+
+ return_val = FALSE;
+ }
+ default:
+ return_val = FALSE;
+ break;
+ }
+
+ event->any.send_event = cookie->send_event;
+
+ if (return_val)
+ {
+ if (event->any.window)
+ g_object_ref (event->any.window);
+
+ if (((event->any.type == GDK_ENTER_NOTIFY) ||
+ (event->any.type == GDK_LEAVE_NOTIFY)) &&
+ (event->crossing.subwindow != NULL))
+ g_object_ref (event->crossing.subwindow);
+ }
+ else
+ {
+ /* Mark this event as having no resources to be freed */
+ event->any.window = NULL;
+ event->any.type = GDK_NOTHING;
+ }
+
+ XFreeEventData (dpy, cookie);
+
+ return return_val;
+}
+
+static GdkEventMask
+gdk_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
+{
+ return (GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_SCROLL_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON1_MOTION_MASK |
+ GDK_BUTTON2_MOTION_MASK |
+ GDK_BUTTON3_MOTION_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_FOCUS_CHANGE_MASK);
+}
+
+static void
+gdk_device_manager_xi2_select_window_events (GdkEventTranslator *translator,
+ Window window,
+ GdkEventMask evmask)
+{
+ GdkDeviceManager *device_manager;
+ XIEventMask event_mask;
+
+ device_manager = GDK_DEVICE_MANAGER (translator);
+
+ event_mask.deviceid = XIAllMasterDevices;
+ event_mask.mask = gdk_device_xi2_translate_event_mask (evmask, &event_mask.mask_len);
+
+ _gdk_device_manager_xi2_select_events (device_manager, window, &event_mask);
+ g_free (event_mask.mask);
+}
diff --cc gdk/x11/gdkwindow-x11.c
index 28f0589,a8dd83b..40c957b
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@@ -3258,11 -3212,11 +3258,12 @@@ gdk_display_warp_device (GdkDisplay *di
}
GdkWindow*
-_gdk_windowing_window_at_pointer (GdkDisplay *display,
- gint *win_x,
- gint *win_y,
- GdkModifierType *mask,
- gboolean get_toplevel)
+_gdk_windowing_window_at_device_position (GdkDisplay *display,
+ GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
- GdkModifierType *mask)
++ GdkModifierType *mask,
++ gboolean get_toplevel)
{
GdkWindow *window;
GdkScreen *screen;
@@@ -3275,9 -3240,30 +3276,9 @@@
* and the result.
*/
gdk_x11_display_grab (display);
- if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
- {
- XQueryPointer (xdisplay, xwindow,
- &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
- if (root == xwindow)
- xwindow = child;
- else
- xwindow = root;
-
- while (xwindow)
- {
- xwindow_last = xwindow;
- XQueryPointer (xdisplay, xwindow,
- &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
- if (get_toplevel &&
- (window = gdk_window_lookup_for_display (display, xwindow_last)) != NULL &&
- GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
- {
- xwindow = xwindow_last;
- break;
- }
- }
- }
- else
+ if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
- window = GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask);
++ window = GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel);
+ else
{
gint i, screens, width, height;
GList *toplevels, *list;
@@@ -3348,18 -3324,21 +3349,22 @@@
gdk_flush ();
if (gdk_error_trap_pop ())
break;
+ if (get_toplevel &&
+ (window = gdk_window_lookup_for_display (display, xwindow_last)) != NULL &&
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+ break;
}
+
+ window = gdk_window_lookup_for_display (display, xwindow_last);
+
+ *win_x = window ? winx : -1;
+ *win_y = window ? winy : -1;
+ if (mask)
+ *mask = xmask;
}
-
+
gdk_x11_display_ungrab (display);
- window = gdk_window_lookup_for_display (display, xwindow_last);
- *win_x = window ? winx : -1;
- *win_y = window ? winy : -1;
- if (mask)
- *mask = xmask;
-
return window;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]