[gtk+/xi2: 127/127] Merge branch 'master' into xi2
- From: Carlos Garnacho <carlosg src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtk+/xi2: 127/127] Merge branch 'master' into xi2
- Date: Sat, 13 Feb 2010 12:19:59 +0000 (UTC)
commit d8702dfdbef2bd67ee501750fa7337dc16ca9b6e
Merge: 8dc97d1 c77678e
Author: Carlos Garnacho <carlosg gnome org>
Date: Sat Feb 13 12:43:00 2010 +0100
Merge branch 'master' into xi2
Conflicts:
docs/reference/gdk/tmpl/input_devices.sgml
docs/reference/gtk/gtk-sections.txt
gdk/gdkinternals.h
gdk/gdkwindow.c
gdk/x11/gdkevents-x11.c
gtk/gtk.symbols
NEWS | 134 +
configure.in | 5 +-
demos/gtk-demo/toolpalette.c | 17 +-
docs/reference/gdk-pixbuf/gdk-pixbuf.sgml | 3 +
docs/reference/gdk-pixbuf/tmpl/animation.sgml | 5 +
docs/reference/gdk/gdk-docs.sgml | 5 +-
docs/reference/gdk/gdk-sections.txt | 2 +
docs/reference/gdk/tmpl/gdkscreen.sgml | 9 +
docs/reference/gdk/tmpl/keys.sgml | 12 +-
docs/reference/gdk/tmpl/pixmaps.sgml | 30 +
docs/reference/gtk/gtk-docs.sgml | 4 +
docs/reference/gtk/gtk-sections.txt | 18 +
docs/reference/gtk/gtk.types | 1 +
docs/reference/gtk/tmpl/gtkaccellabel.sgml | 158 -
docs/reference/gtk/tmpl/gtkaction.sgml | 23 +
docs/reference/gtk/tmpl/gtkbindings.sgml | 1 +
docs/reference/gtk/tmpl/gtkentry.sgml | 27 +
docs/reference/gtk/tmpl/gtknotebook.sgml | 20 +
docs/reference/gtk/tmpl/gtkobject.sgml | 13 +
docs/reference/gtk/tmpl/gtkprintcontext.sgml | 13 +
docs/reference/gtk/tmpl/gtkprinter.sgml | 13 +
docs/reference/gtk/tmpl/gtkprogressbar.sgml | 4 +
docs/reference/gtk/tmpl/gtkradiobutton.sgml | 3 +
docs/reference/gtk/tmpl/gtkradiomenuitem.sgml | 6 +
docs/reference/gtk/tmpl/gtkrange.sgml | 55 +
docs/reference/gtk/tmpl/gtksettings.sgml | 5 +
docs/reference/gtk/tmpl/gtkspinbutton.sgml | 7 +-
docs/reference/gtk/tmpl/gtkstatusbar.sgml | 9 +
docs/reference/gtk/tmpl/gtkstatusicon.sgml | 9 +
docs/reference/gtk/tmpl/gtkstyle.sgml | 12 +
docs/reference/gtk/tmpl/gtktextview.sgml | 8 +
docs/reference/gtk/tmpl/gtktoolitem.sgml | 36 +
docs/reference/gtk/tmpl/gtktooltips.sgml | 7 +
docs/reference/gtk/tmpl/gtkwindow.sgml | 32 +
docs/tutorial/gtk_tut.sgml |18447 -------------------------
docs/tutorial/gtk_tut_12.es.sgml |17638 -----------------------
docs/tutorial/gtk_tut_fr.sgml | 8600 ------------
docs/tutorial/gtk_tut_it.sgml |10090 --------------
docs/tutorial/gtk_tut_packbox1.eps | 7262 ----------
docs/tutorial/gtk_tut_packbox1.gif | Bin 52480 -> 0 bytes
docs/tutorial/gtk_tut_packbox1.jpg | Bin 24613 -> 0 bytes
docs/tutorial/gtk_tut_packbox2.eps | 5428 --------
docs/tutorial/gtk_tut_packbox2.gif | Bin 43000 -> 0 bytes
docs/tutorial/gtk_tut_packbox2.jpg | Bin 19530 -> 0 bytes
docs/tutorial/gtk_tut_table.eps | 1262 --
docs/tutorial/gtk_tut_table.gif | Bin 10056 -> 0 bytes
docs/tutorial/gtk_tut_table.jpg | Bin 3890 -> 0 bytes
docs/tutorial/package_tutorial.sh | 99 -
gdk-pixbuf/gdk-pixbuf-io.c | 1 +
gdk-pixbuf/pixops/pixops.c | 24 +-
gdk/directfb/gdkcolor-directfb.c | 39 +-
gdk/directfb/gdkcursor-directfb.c | 12 +-
gdk/directfb/gdkdnd-directfb.c | 84 +-
gdk/directfb/gdkgc-directfb.c | 70 +-
gdk/directfb/gdkmain-directfb.c | 10 +-
gdk/directfb/gdkprivate-directfb.h | 10 +-
gdk/gdk.symbols | 1 +
gdk/gdkgc.c | 1 +
gdk/gdkinternals.h | 1 +
gdk/gdkkeys.h | 2 +
gdk/gdkrectangle.c | 12 +-
gdk/gdkwindow.c | 54 +-
gdk/quartz/GdkQuartzView.c | 9 +
gdk/quartz/gdkevents-quartz.c | 113 +-
gdk/quartz/gdkkeys-quartz.c | 7 +
gdk/quartz/gdkprivate-quartz.h | 2 +
gdk/quartz/gdkwindow-quartz.c | 63 +-
gdk/win32/gdkkeys-win32.c | 6 +
gdk/x11/gdkdevicemanager-core.c | 2 +-
gdk/x11/gdkdevicemanager-xi2.c | 9 +-
gdk/x11/gdkdisplay-x11.c | 4 +-
gdk/x11/gdkdisplay-x11.h | 1 +
gdk/x11/gdkdnd-x11.c | 148 +-
gdk/x11/gdkkeys-x11.c | 53 +-
gdk/x11/gdkprivate-x11.h | 4 +
gdk/x11/gdkwindow-x11.c | 14 +-
gtk/Makefile.am | 2 +-
gtk/gtk.symbols | 25 +-
gtk/gtkaccellabel.c | 86 +-
gtk/gtkaccellabel.h | 6 +
gtk/gtkcalendar.c | 8 +-
gtk/gtkcontainer.c | 2 +-
gtk/gtkcustompaperunixdialog.c | 1 -
gtk/gtkdnd-quartz.c | 4 +-
gtk/gtkdnd.c | 14 +
gtk/gtkentry.c | 58 +
gtk/gtkentry.h | 13 +
gtk/gtkenums.h | 2 +
gtk/gtkimmulticontext.c | 40 +-
gtk/gtkkeyhash.c | 1 +
gtk/gtklabel.c | 24 +-
gtk/gtknotebook.c | 55 +-
gtk/gtkoffscreenwindow.c | 16 +-
gtk/gtkoffscreenwindow.h | 6 +-
gtk/gtkpagesetupunixdialog.c | 1 -
gtk/gtkpaned.c | 24 +
gtk/gtkpaned.h | 2 +
gtk/gtkplug.c | 35 +-
gtk/gtkprintbackend.c | 1 -
gtk/gtkprintoperation-unix.c | 1 -
gtk/gtkrange.c | 149 +
gtk/gtkrange.h | 14 +
gtk/gtkscale.c | 89 +-
gtk/gtkstatusicon.c | 30 +
gtk/gtkstatusicon.h | 2 +
gtk/gtktexttag.h | 56 +-
gtk/gtktoolbutton.c | 6 +
gtk/gtktoolpalette.c | 57 +-
gtk/gtktoolpalette.h | 14 +-
gtk/gtktreemodel.c | 2 +-
gtk/gtktreestore.c | 2 +-
gtk/gtktreeview.c | 51 +-
gtk/gtkwidget.c | 152 +-
gtk/gtkwidget.h | 24 +-
gtk/paper_names.c | 3 +-
gtk/paper_names_offsets.c | 178 +-
modules/engines/ms-windows/msw_style.c | 4 +-
modules/other/gail/gailentry.c | 1 +
po-properties/POTFILES.in | 5 +
po-properties/af.po | 604 +-
po-properties/am.po | 587 +-
po-properties/ang.po | 584 +-
po-properties/ar.po | 603 +-
po-properties/as.po | 604 +-
po-properties/ast.po | 3956 +++---
po-properties/az.po | 603 +-
po-properties/az_IR.po | 581 +-
po-properties/be.po | 607 +-
po-properties/be latin po | 608 +-
po-properties/bg.po | 648 +-
po-properties/bn.po | 2122 ++--
po-properties/bn_IN.po | 604 +-
po-properties/br.po | 588 +-
po-properties/bs.po | 608 +-
po-properties/ca.po | 603 +-
po-properties/ca valencia po | 603 +-
po-properties/crh.po | 624 +-
po-properties/cs.po | 642 +-
po-properties/cy.po | 3637 +++---
po-properties/da.po | 616 +-
po-properties/de.po | 609 +-
po-properties/dz.po | 603 +-
po-properties/el.po | 611 +-
po-properties/en_CA.po | 603 +-
po-properties/en_GB.po | 603 +-
po-properties/eo.po | 581 +-
po-properties/es.po | 599 +-
po-properties/et.po | 617 +-
po-properties/eu.po | 641 +-
po-properties/fa.po | 595 +-
po-properties/fi.po | 604 +-
po-properties/fr.po | 636 +-
po-properties/ga.po | 587 +-
po-properties/gl.po | 605 +-
po-properties/gu.po | 603 +-
po-properties/he.po | 603 +-
po-properties/hi.po | 603 +-
po-properties/hr.po | 604 +-
po-properties/hu.po | 604 +-
po-properties/hy.po | 587 +-
po-properties/ia.po | 586 +-
po-properties/id.po | 605 +-
po-properties/io.po | 581 +-
po-properties/is.po | 593 +-
po-properties/it.po | 611 +-
po-properties/ja.po | 607 +-
po-properties/ka.po | 603 +-
po-properties/kn.po | 603 +-
po-properties/ko.po | 603 +-
po-properties/ku.po | 585 +-
po-properties/li.po | 603 +-
po-properties/lt.po | 603 +-
po-properties/lv.po | 603 +-
po-properties/mai.po | 603 +-
po-properties/mi.po | 583 +-
po-properties/mk.po | 603 +-
po-properties/ml.po | 603 +-
po-properties/mn.po | 620 +-
po-properties/mr.po | 603 +-
po-properties/ms.po | 603 +-
po-properties/my.po | 7415 ++++++++++
po-properties/nb.po | 811 +-
po-properties/nds.po | 583 +-
po-properties/ne.po | 603 +-
po-properties/nl.po | 607 +-
po-properties/nn.po | 605 +-
po-properties/nso.po | 615 +-
po-properties/oc.po | 587 +-
po-properties/or.po | 603 +-
po-properties/pa.po | 603 +-
po-properties/pl.po | 609 +-
po-properties/ps.po | 596 +-
po-properties/pt.po | 604 +-
po-properties/pt_BR.po | 622 +-
po-properties/ro.po | 607 +-
po-properties/ru.po | 605 +-
po-properties/rw.po | 603 +-
po-properties/si.po | 592 +-
po-properties/sk.po | 603 +-
po-properties/sl.po |14567 ++++++++++----------
po-properties/sq.po | 607 +-
po-properties/sr.po | 604 +-
po-properties/sr ije po | 604 +-
po-properties/sr latin po | 604 +-
po-properties/sv.po | 4981 ++++----
po-properties/ta.po | 603 +-
po-properties/te.po | 603 +-
po-properties/th.po | 589 +-
po-properties/tk.po | 588 +-
po-properties/tr.po | 622 +-
po-properties/tt.po | 591 +-
po-properties/uk.po | 3646 +++---
po-properties/ur.po | 582 +-
po-properties/uz.po | 592 +-
po-properties/uz cyrillic po | 592 +-
po-properties/vi.po | 606 +-
po-properties/wa.po | 599 +-
po-properties/xh.po | 610 +-
po-properties/yi.po | 603 +-
po-properties/zh_CN.po | 603 +-
po-properties/zh_HK.po | 603 +-
po-properties/zh_TW.po | 603 +-
po/LINGUAS | 1 +
po/POTFILES.in | 3 +
po/af.po | 661 +-
po/am.po | 658 +-
po/ang.po | 660 +-
po/ar.po | 667 +-
po/as.po | 662 +-
po/ast.po |12451 ++++++++---------
po/az.po | 661 +-
po/az_IR.po | 656 +-
po/be.po | 661 +-
po/be latin po | 662 +-
po/bg.po | 695 +-
po/bn.po | 712 +-
po/bn_IN.po | 662 +-
po/br.po | 660 +-
po/bs.po | 661 +-
po/ca.po | 662 +-
po/ca valencia po | 662 +-
po/crh.po | 669 +-
po/cs.po | 2458 ++--
po/cy.po | 2435 ++--
po/da.po | 663 +-
po/de.po | 662 +-
po/dz.po | 662 +-
po/el.po | 662 +-
po/en_CA.po | 662 +-
po/en_GB.po | 662 +-
po/eo.po | 661 +-
po/es.po | 666 +-
po/et.po | 1360 ++-
po/eu.po | 3689 ++++--
po/fa.po | 662 +-
po/fi.po | 666 +-
po/fr.po | 690 +-
po/ga.po | 662 +-
po/gl.po | 662 +-
po/gu.po | 662 +-
po/he.po | 662 +-
po/hi.po | 662 +-
po/hr.po | 661 +-
po/hu.po | 662 +-
po/hy.po | 661 +-
po/ia.po | 660 +-
po/id.po | 662 +-
po/io.po | 662 +-
po/is.po | 661 +-
po/it.po | 662 +-
po/ja.po | 662 +-
po/ka.po | 662 +-
po/kn.po | 2530 ++--
po/ko.po | 662 +-
po/ku.po | 662 +-
po/li.po | 663 +-
po/lt.po | 662 +-
po/lv.po | 662 +-
po/mai.po | 662 +-
po/mi.po | 661 +-
po/mk.po | 662 +-
po/ml.po | 662 +-
po/mn.po | 667 +-
po/mr.po | 662 +-
po/ms.po | 661 +-
po/my.po | 5486 ++++++++
po/nb.po | 651 +-
po/nds.po | 660 +-
po/ne.po | 661 +-
po/nl.po | 666 +-
po/nn.po | 663 +-
po/nso.po | 661 +-
po/oc.po | 661 +-
po/or.po | 662 +-
po/pa.po | 662 +-
po/pl.po | 662 +-
po/ps.po | 660 +-
po/pt.po | 662 +-
po/pt_BR.po | 684 +-
po/ro.po | 662 +-
po/ru.po | 662 +-
po/rw.po | 661 +-
po/si.po | 662 +-
po/sk.po | 851 +-
po/sl.po | 3033 +++--
po/sq.po | 663 +-
po/sr.po | 662 +-
po/sr ije po | 661 +-
po/sr latin po | 662 +-
po/sv.po | 3047 +++--
po/ta.po | 662 +-
po/te.po | 662 +-
po/th.po | 878 +-
po/tk.po | 661 +-
po/tr.po | 668 +-
po/tt.po | 661 +-
po/uk.po | 2429 ++--
po/ur.po | 657 +-
po/uz.po | 662 +-
po/uz cyrillic po | 662 +-
po/vi.po | 662 +-
po/wa.po | 662 +-
po/xh.po | 661 +-
po/yi.po | 661 +-
po/zh_CN.po | 662 +-
po/zh_HK.po | 662 +-
po/zh_TW.po | 662 +-
tests/Makefile.am | 4 +-
tests/prop-editor.c | 105 +-
tests/testgtk.c | 17 +-
tests/testtoolbar.c | 5 +
331 files changed, 127969 insertions(+), 143135 deletions(-)
---
diff --cc docs/reference/gtk/gtk-sections.txt
index 65b9375,d79c5a8..1c3b1e8
--- a/docs/reference/gtk/gtk-sections.txt
+++ b/docs/reference/gtk/gtk-sections.txt
@@@ -5742,10 -5749,10 +5753,14 @@@ gtk_widget_is_topleve
gtk_widget_set_window
gtk_widget_set_receives_default
gtk_widget_get_receives_default
+gtk_widget_set_support_multidevice
+gtk_widget_create_device_group
+gtk_widget_remove_device_group
+gtk_widget_get_group_for_device
+ gtk_widget_set_realized
+ gtk_widget_get_realized
+ gtk_widget_set_mapped
+ gtk_widget_set_mapped
<SUBSECTION>
gtk_requisition_copy
diff --cc gdk/gdkinternals.h
index 7afa723,822335f..07cc7d0
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@@ -282,9 -273,7 +282,10 @@@ struct _GdkWindowObjec
GdkRegion *input_shape;
cairo_surface_t *cairo_surface;
+ guint outstanding_surfaces; /* only set on impl window */
+
+ GList *devices_inside;
+ GHashTable *device_events;
};
#define GDK_WINDOW_TYPE(d) (((GdkWindowObject*)(GDK_WINDOW (d)))->window_type)
diff --cc gdk/x11/gdkdevicemanager-core.c
index 5d59522,0000000..7bd584b
mode 100644,000000..100644
--- a/gdk/x11/gdkdevicemanager-core.c
+++ b/gdk/x11/gdkdevicemanager-core.c
@@@ -1,899 -1,0 +1,899 @@@
+/* 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 "config.h"
+
+#include <gdk/gdktypes.h>
+#include <gdk/gdkdevicemanager.h>
+#include "gdkdevicemanager-core.h"
+#include "gdkeventtranslator.h"
+#include "gdkdevice-core.h"
+#include "gdkkeysyms.h"
+#include "gdkx.h"
+
+#ifdef HAVE_XKB
+#include <X11/XKBlib.h>
+#endif
+
+
+#define HAS_FOCUS(toplevel) \
+ ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
+
+static void gdk_device_manager_core_finalize (GObject *object);
+static void gdk_device_manager_core_constructed (GObject *object);
+
+static GList * gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
+ GdkDeviceType type);
+
+static void gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface);
+
+static gboolean gdk_device_manager_core_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent);
+
+
+G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerCore, gdk_device_manager_core, GDK_TYPE_DEVICE_MANAGER,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
+ gdk_device_manager_event_translator_init))
+
+static void
+gdk_device_manager_core_class_init (GdkDeviceManagerCoreClass *klass)
+{
+ GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gdk_device_manager_core_finalize;
+ object_class->constructed = gdk_device_manager_core_constructed;
+ device_manager_class->list_devices = gdk_device_manager_core_list_devices;
+}
+
+static void
+gdk_device_manager_event_translator_init (GdkEventTranslatorIface *iface)
+{
+ iface->translate_event = gdk_device_manager_core_translate_event;
+}
+
+static GdkDevice *
+create_core_pointer (GdkDeviceManager *device_manager,
+ GdkDisplay *display)
+{
+ return g_object_new (GDK_TYPE_DEVICE_CORE,
+ "name", "Core Pointer",
+ "type", GDK_DEVICE_TYPE_MASTER,
+ "input-source", GDK_SOURCE_MOUSE,
+ "input-mode", GDK_MODE_SCREEN,
+ "has-cursor", TRUE,
+ "display", display,
+ "device-manager", device_manager,
+ NULL);
+}
+
+static GdkDevice *
+create_core_keyboard (GdkDeviceManager *device_manager,
+ GdkDisplay *display)
+{
+ return g_object_new (GDK_TYPE_DEVICE_CORE,
+ "name", "Core Keyboard",
+ "type", GDK_DEVICE_TYPE_MASTER,
+ "input-source", GDK_SOURCE_KEYBOARD,
+ "input-mode", GDK_MODE_SCREEN,
+ "has-cursor", FALSE,
+ "display", display,
+ "device-manager", device_manager,
+ NULL);
+}
+
+static void
+gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager)
+{
+}
+
+static void
+gdk_device_manager_core_finalize (GObject *object)
+{
+ GdkDeviceManagerCore *device_manager_core;
+
+ device_manager_core = GDK_DEVICE_MANAGER_CORE (object);
+
+ g_object_unref (device_manager_core->core_pointer);
+ g_object_unref (device_manager_core->core_keyboard);
+
+ G_OBJECT_CLASS (gdk_device_manager_core_parent_class)->finalize (object);
+}
+
+static void
+gdk_device_manager_core_constructed (GObject *object)
+{
+ GdkDeviceManagerCore *device_manager;
+ GdkDisplay *display;
+
+ device_manager = GDK_DEVICE_MANAGER_CORE (object);
+ display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
+ device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
+ device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
+
+ _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
+ _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
+}
+
+static void
+translate_key_event (GdkDisplay *display,
+ GdkDeviceManagerCore *device_manager,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (display);
+ GdkModifierType consumed, state;
+ gunichar c = 0;
+ gchar buf[7];
+
+ event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+ event->key.time = xevent->xkey.time;
+ gdk_event_set_device (event, device_manager->core_keyboard);
+
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
+ event->key.hardware_keycode = xevent->xkey.keycode;
+
+ 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, &consumed);
+
+ state = event->key.state & ~consumed;
- _gdk_keymap_add_virtual_modifiers (keymap, &state);
++ _gdk_keymap_add_virtual_modifiers_compat (keymap, &state);
+ event->key.state |= state;
+
+ event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
+
+ /* Fill in event->string crudely, since various programs
+ * depend on it.
+ */
+ event->key.string = NULL;
+
+ if (event->key.keyval != GDK_VoidSymbol)
+ c = gdk_keyval_to_unicode (event->key.keyval);
+
+ if (c)
+ {
+ gsize bytes_written;
+ gint len;
+
+ /* Apply the control key - Taken from Xlib
+ */
+ if (event->key.state & GDK_CONTROL_MASK)
+ {
+ if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
+ else if (c == '2')
+ {
+ event->key.string = g_memdup ("\0\0", 2);
+ event->key.length = 1;
+ buf[0] = '\0';
+ goto out;
+ }
+ 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->key.string = g_locale_from_utf8 (buf, len,
+ NULL, &bytes_written,
+ NULL);
+ if (event->key.string)
+ event->key.length = bytes_written;
+ }
+ else if (event->key.keyval == GDK_Escape)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\033");
+ }
+ else if (event->key.keyval == GDK_Return ||
+ event->key.keyval == GDK_KP_Enter)
+ {
+ event->key.length = 1;
+ event->key.string = g_strdup ("\r");
+ }
+
+ if (!event->key.string)
+ {
+ event->key.length = 0;
+ event->key.string = g_strdup ("");
+ }
+
+ out:
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ g_message ("%s:\t\twindow: %ld key: %12s %d",
+ event->type == GDK_KEY_PRESS ? "key press " : "key release",
+ xevent->xkey.window,
+ event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
+ event->key.keyval);
+
+ if (event->key.length > 0)
+ g_message ("\t\tlength: %4d string: \"%s\"",
+ event->key.length, buf);
+ }
+#endif /* G_ENABLE_DEBUG */
+ return;
+}
+
+#ifdef G_ENABLE_DEBUG
+static const char notify_modes[][19] = {
+ "NotifyNormal",
+ "NotifyGrab",
+ "NotifyUngrab",
+ "NotifyWhileGrabbed"
+};
+
+static const char notify_details[][23] = {
+ "NotifyAncestor",
+ "NotifyVirtual",
+ "NotifyInferior",
+ "NotifyNonlinear",
+ "NotifyNonlinearVirtual",
+ "NotifyPointer",
+ "NotifyPointerRoot",
+ "NotifyDetailNone"
+};
+#endif
+
+static void
+set_user_time (GdkWindow *window,
+ GdkEvent *event)
+{
+ g_return_if_fail (event != NULL);
+
+ window = gdk_window_get_toplevel (event->client.window);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ /* If an event doesn't have a valid timestamp, we shouldn't use it
+ * to update the latest user interaction time.
+ */
+ 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));
+}
+
+static void
+generate_focus_event (GdkDeviceManagerCore *device_manager,
+ GdkWindow *window,
+ gboolean in)
+{
+ GdkEvent *event;
+
+ event = gdk_event_new (GDK_FOCUS_CHANGE);
+ event->focus_change.window = g_object_ref (window);
+ event->focus_change.send_event = FALSE;
+ event->focus_change.in = in;
+ gdk_event_set_device (event, device_manager->core_keyboard);
+
+ gdk_event_put (event);
+ gdk_event_free (event);
+}
+
+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 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
+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,
+ XEvent *xevent)
+{
+ GdkDeviceManager *device_manager;
+ GdkDisplay *display;
+ GdkWindow *window;
+
+ device_manager = GDK_DEVICE_MANAGER (translator);
+ display = gdk_device_manager_get_display (device_manager);
+ window = gdk_window_lookup_for_display (display, xevent->xany.window);
+
+ /* Apply keyboard grabs to non-native windows */
+ if (xevent->type == KeyPress || xevent->type == KeyRelease)
+ {
+ GdkDeviceGrabInfo *info;
+ gulong serial;
+
+ serial = _gdk_windowing_window_get_next_serial (display);
+ info = _gdk_display_has_device_grab (display,
+ GDK_DEVICE_MANAGER_CORE (device_manager)->core_keyboard,
+ serial);
+ if (info &&
+ (!is_parent_of (info->window, window) ||
+ !info->owner_events))
+ {
+ /* Report key event against grab window */
+ window = info->window;
+ }
+ }
+
+ return window;
+}
+
+static gboolean
+gdk_device_manager_core_translate_event (GdkEventTranslator *translator,
+ GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkDeviceManagerCore *device_manager;
+ GdkWindow *window;
+ GdkWindowObject *window_private;
+ GdkWindowImplX11 *window_impl = NULL;
+ gboolean return_val;
+ GdkToplevelX11 *toplevel = NULL;
+ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+
+ device_manager = GDK_DEVICE_MANAGER_CORE (translator);
+ return_val = FALSE;
+
+ window = get_event_window (translator, xevent);
+ window_private = (GdkWindowObject *) window;
+
+ if (window && GDK_WINDOW_DESTROYED (window))
+ return FALSE;
+
+ if (window)
+ {
+ toplevel = _gdk_x11_window_get_toplevel (window);
+ window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+ g_object_ref (window);
+ }
+
+ event->any.window = window;
+ event->any.send_event = xevent->xany.send_event ? TRUE : FALSE;
+
+ if (window_private && GDK_WINDOW_DESTROYED (window))
+ {
+ if (xevent->type != DestroyNotify)
+ {
+ return_val = FALSE;
+ goto done;
+ }
+ }
+
+ if (window &&
+ (xevent->type == MotionNotify ||
+ xevent->type == ButtonRelease))
+ {
+ if (_gdk_moveresize_handle_event (xevent))
+ {
+ return_val = FALSE;
+ goto done;
+ }
+ }
+
+ /* We do a "manual" conversion of the XEvent to a
+ * GdkEvent. The structures are mostly the same so
+ * the conversion is fairly straightforward. We also
+ * optionally print debugging info regarding events
+ * received.
+ */
+
+ return_val = TRUE;
+
+ switch (xevent->type)
+ {
+ case KeyPress:
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+ translate_key_event (display, device_manager, event, xevent);
+ set_user_time (window, event);
+ break;
+
+ case KeyRelease:
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* Emulate detectable auto-repeat by checking to see
+ * if the next event is a key press with the same
+ * keycode and timestamp, and if so, ignoring the event.
+ */
+
+ if (!display_x11->have_xkb_autorepeat && XPending (xevent->xkey.display))
+ {
+ XEvent next_event;
+
+ XPeekEvent (xevent->xkey.display, &next_event);
+
+ if (next_event.type == KeyPress &&
+ next_event.xkey.keycode == xevent->xkey.keycode &&
+ next_event.xkey.time == xevent->xkey.time)
+ {
+ return_val = FALSE;
+ break;
+ }
+ }
+
+ translate_key_event (display, device_manager, event, xevent);
+ break;
+
+ case ButtonPress:
+ GDK_NOTE (EVENTS,
+ g_message ("button press:\t\twindow: %ld x,y: %d %d button: %d",
+ xevent->xbutton.window,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* If we get a ButtonPress event where the button is 4 or 5,
+ it's a Scroll event */
+ switch (xevent->xbutton.button)
+ {
+ case 4: /* up */
+ case 5: /* down */
+ case 6: /* left */
+ case 7: /* right */
+ event->scroll.type = GDK_SCROLL;
+
+ if (xevent->xbutton.button == 4)
+ event->scroll.direction = GDK_SCROLL_UP;
+ else if (xevent->xbutton.button == 5)
+ event->scroll.direction = GDK_SCROLL_DOWN;
+ else if (xevent->xbutton.button == 6)
+ event->scroll.direction = GDK_SCROLL_LEFT;
+ else
+ event->scroll.direction = GDK_SCROLL_RIGHT;
+
+ event->scroll.window = window;
+ event->scroll.time = xevent->xbutton.time;
+ event->scroll.x = (gdouble) xevent->xbutton.x;
+ event->scroll.y = (gdouble) xevent->xbutton.y;
+ event->scroll.x_root = (gdouble) xevent->xbutton.x_root;
+ event->scroll.y_root = (gdouble) xevent->xbutton.y_root;
+ event->scroll.state = (GdkModifierType) xevent->xbutton.state;
+ event->scroll.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ break;
+
+ default:
+ event->button.type = GDK_BUTTON_PRESS;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = (gdouble) xevent->xbutton.x;
+ event->button.y = (gdouble) xevent->xbutton.y;
+ event->button.x_root = (gdouble) xevent->xbutton.x_root;
+ event->button.y_root = (gdouble) xevent->xbutton.y_root;
+ event->button.axes = NULL;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ return_val = FALSE;
+
+ break;
+ }
+
+ set_user_time (window, event);
+
+ break;
+
+ case ButtonRelease:
+ GDK_NOTE (EVENTS,
+ g_message ("button release:\twindow: %ld x,y: %d %d button: %d",
+ xevent->xbutton.window,
+ xevent->xbutton.x, xevent->xbutton.y,
+ xevent->xbutton.button));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ /* We treat button presses as scroll wheel events, so ignore the release */
+ if (xevent->xbutton.button == 4 || xevent->xbutton.button == 5 ||
+ xevent->xbutton.button == 6 || xevent->xbutton.button == 7)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->button.type = GDK_BUTTON_RELEASE;
+ event->button.window = window;
+ event->button.time = xevent->xbutton.time;
+ event->button.x = (gdouble) xevent->xbutton.x;
+ event->button.y = (gdouble) xevent->xbutton.y;
+ event->button.x_root = (gdouble) xevent->xbutton.x_root;
+ event->button.y_root = (gdouble) xevent->xbutton.y_root;
+ event->button.axes = NULL;
+ event->button.state = (GdkModifierType) xevent->xbutton.state;
+ event->button.button = xevent->xbutton.button;
+ event->button.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ return_val = FALSE;
+
+ break;
+
+ case MotionNotify:
+ GDK_NOTE (EVENTS,
+ g_message ("motion notify:\t\twindow: %ld x,y: %d %d hint: %s",
+ xevent->xmotion.window,
+ xevent->xmotion.x, xevent->xmotion.y,
+ (xevent->xmotion.is_hint) ? "true" : "false"));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->motion.type = GDK_MOTION_NOTIFY;
+ event->motion.window = window;
+ event->motion.time = xevent->xmotion.time;
+ event->motion.x = (gdouble) xevent->xmotion.x;
+ event->motion.y = (gdouble) xevent->xmotion.y;
+ event->motion.x_root = (gdouble) xevent->xmotion.x_root;
+ event->motion.y_root = (gdouble) xevent->xmotion.y_root;
+ event->motion.axes = NULL;
+ event->motion.state = (GdkModifierType) xevent->xmotion.state;
+ event->motion.is_hint = xevent->xmotion.is_hint;
+ event->motion.device = device_manager->core_pointer;
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ break;
+
+ case EnterNotify:
+ GDK_NOTE (EVENTS,
+ g_message ("enter notify:\t\twindow: %ld detail: %d subwin: %ld",
+ xevent->xcrossing.window,
+ xevent->xcrossing.detail,
+ xevent->xcrossing.subwindow));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->crossing.type = GDK_ENTER_NOTIFY;
+ event->crossing.window = window;
+ gdk_event_set_device (event, device_manager->core_pointer);
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = (gdouble) xevent->xcrossing.x;
+ event->crossing.y = (gdouble) xevent->xcrossing.y;
+ event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
+ event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
+
+ event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
+ event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
+
+ event->crossing.focus = xevent->xcrossing.focus;
+ event->crossing.state = xevent->xcrossing.state;
+
+ break;
+
+ case LeaveNotify:
+ GDK_NOTE (EVENTS,
+ g_message ("leave notify:\t\twindow: %ld detail: %d subwin: %ld",
+ xevent->xcrossing.window,
+ xevent->xcrossing.detail, xevent->xcrossing.subwindow));
+
+ if (window_private == NULL)
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ if (!set_screen_from_root (display, event, xevent->xbutton.root))
+ {
+ return_val = FALSE;
+ break;
+ }
+
+ event->crossing.type = GDK_LEAVE_NOTIFY;
+ event->crossing.window = window;
+ gdk_event_set_device (event, device_manager->core_pointer);
+
+ /* If the subwindow field of the XEvent is non-NULL, then
+ * lookup the corresponding GdkWindow.
+ */
+ if (xevent->xcrossing.subwindow != None)
+ event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
+ else
+ event->crossing.subwindow = NULL;
+
+ event->crossing.time = xevent->xcrossing.time;
+ event->crossing.x = (gdouble) xevent->xcrossing.x;
+ event->crossing.y = (gdouble) xevent->xcrossing.y;
+ event->crossing.x_root = (gdouble) xevent->xcrossing.x_root;
+ event->crossing.y_root = (gdouble) xevent->xcrossing.y_root;
+
+ event->crossing.mode = translate_crossing_mode (xevent->xcrossing.mode);
+ event->crossing.detail = translate_notify_type (xevent->xcrossing.detail);
+
+ event->crossing.focus = xevent->xcrossing.focus;
+ event->crossing.state = xevent->xcrossing.state;
+
+ break;
+
+ /* We only care about focus events that indicate that _this_
+ * window (not a ancestor or child) got or lost the focus
+ */
+ case FocusIn:
+ GDK_NOTE (EVENTS,
+ g_message ("focus in:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
+
+ if (toplevel)
+ {
+ gboolean had_focus = HAS_FOCUS (toplevel);
+
+ switch (xevent->xfocus.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 &&
+ xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = FALSE;
+
+ /* fall through */
+ case NotifyNonlinear:
+ case NotifyNonlinearVirtual:
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_focus_window = TRUE;
+ /* We pretend that the focus moves to the grab
+ * window, so we pay attention to NotifyGrab
+ * NotifyUngrab, and ignore NotifyWhileGrabbed
+ */
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ toplevel->has_focus = TRUE;
+ break;
+ case NotifyPointer:
+ /* The X server sends NotifyPointer/NotifyGrab,
+ * but the pointer focus is ignored while a
+ * grab is in effect
+ */
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = TRUE;
+ break;
+ case NotifyInferior:
+ case NotifyPointerRoot:
+ case NotifyDetailNone:
+ break;
+ }
+
+ if (HAS_FOCUS (toplevel) != had_focus)
+ generate_focus_event (device_manager, window, TRUE);
+ }
+ break;
+ case FocusOut:
+ GDK_NOTE (EVENTS,
+ g_message ("focus out:\t\twindow: %ld, detail: %s, mode: %s",
+ xevent->xfocus.window,
+ notify_details[xevent->xfocus.detail],
+ notify_modes[xevent->xfocus.mode]));
+
+ if (toplevel)
+ {
+ gboolean had_focus = HAS_FOCUS (toplevel);
+
+ switch (xevent->xfocus.detail)
+ {
+ case NotifyAncestor:
+ case NotifyVirtual:
+ /* When the focus moves from the window or a descendent
+ * of the window to an ancestor of the window, *and* the
+ * pointer is inside the window, then we were previously
+ * receiving keystroke events in the has_focus_window
+ * case and are now receiving them in the
+ * has_pointer_focus case.
+ */
+ if (toplevel->has_pointer &&
+ xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = TRUE;
+
+ /* fall through */
+ case NotifyNonlinear:
+ case NotifyNonlinearVirtual:
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_focus_window = FALSE;
+ if (xevent->xfocus.mode != NotifyWhileGrabbed)
+ toplevel->has_focus = FALSE;
+ break;
+ case NotifyPointer:
+ if (xevent->xfocus.mode != NotifyGrab &&
+ xevent->xfocus.mode != NotifyUngrab)
+ toplevel->has_pointer_focus = FALSE;
+ break;
+ case NotifyInferior:
+ case NotifyPointerRoot:
+ case NotifyDetailNone:
+ break;
+ }
+
+ if (HAS_FOCUS (toplevel) != had_focus)
+ generate_focus_event (device_manager, window, FALSE);
+ }
+ break;
+
+ default:
+ return_val = FALSE;
+ }
+
+ done:
+ 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;
+ }
+
+ if (window)
+ g_object_unref (window);
+
+ return return_val;
+}
+
+static GList *
+gdk_device_manager_core_list_devices (GdkDeviceManager *device_manager,
+ GdkDeviceType type)
+{
+ GdkDeviceManagerCore *device_manager_core;
+ GList *devices = NULL;
+
+ if (type == GDK_DEVICE_TYPE_MASTER)
+ {
+ device_manager_core = (GdkDeviceManagerCore *) device_manager;
+ devices = g_list_prepend (devices, device_manager_core->core_keyboard);
+ devices = g_list_prepend (devices, device_manager_core->core_pointer);
+ }
+
+ return devices;
+}
diff --cc gdk/x11/gdkdevicemanager-xi2.c
index ee1e025,0000000..c5a2e8e
mode 100644,000000..100644
--- a/gdk/x11/gdkdevicemanager-xi2.c
+++ b/gdk/x11/gdkdevicemanager-xi2.c
@@@ -1,1138 -1,0 +1,1141 @@@
+/* 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 "config.h"
+
+#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_list_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->list_devices = gdk_device_manager_xi2_list_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 (strstr (tmp_name, "eraser"))
+ input_source = GDK_SOURCE_ERASER;
+ else if (strstr (tmp_name, "cursor"))
+ input_source = GDK_SOURCE_CURSOR;
+ 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_associated_device (device, relative);
+ _gdk_device_set_associated_device (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_list_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);
++ GdkModifierType consumed, state;
+ GdkDevice *device;
+
+ 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);
+
+ device = g_hash_table_lookup (device_manager->id_table,
+ GUINT_TO_POINTER (xev->deviceid));
+ gdk_event_set_device (event, device);
+
- _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);
++ NULL, NULL, &consumed);
++
++ state = event->key.state & ~consumed;
++ _gdk_keymap_add_virtual_modifiers_compat (keymap, &state);
++ event->key.state |= state;
+
+ 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;
+ GdkDevice *device;
+
+ 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);
+
+ device = g_hash_table_lookup (device_manager->id_table,
+ GINT_TO_POINTER (xev->deviceid));
+ gdk_event_set_device (event, device);
+
+ 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 gtk/gtk.symbols
index b2e954c,d6aa089..1c9937d
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@@ -5229,20 -5247,10 +5248,24 @@@ gtk_widget_set_can_defaul
gtk_widget_get_can_default
gtk_widget_set_can_focus
gtk_widget_get_can_focus
+ gtk_widget_set_realized
+ gtk_widget_get_realized
+ gtk_widget_set_mapped
+ gtk_widget_get_mapped
+gtk_widget_get_support_multidevice
+gtk_widget_set_support_multidevice
+gtk_widget_create_device_group
+gtk_widget_remove_device_group
+gtk_widget_get_group_for_device
+#endif
+#endif
+
+#if IN_HEADER(__GTK_DEVICE_GROUP_H__)
+#if IN_FILE(__GTK_DEVICE_GROUP_C__)
+gtk_device_group_get_type G_GNUC_CONST
+gtk_device_group_add_device
+gtk_device_group_remove_device
+gtk_device_group_get_devices
#endif
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]