Compare commits

...

59 Commits

Author SHA1 Message Date
Carlos Garnacho
d8b6c8b70b Remove GdkDevicePrivate usage. 2009-09-26 14:07:36 +02:00
Carlos Garnacho
347065e57f Add initial GdkDeviceManagerXI implementation
GdkDeviceManagerXI and GdkDeviceXI were added to deal with XInput 1, They're
pretty barebones, but already handle event translation.
2009-09-26 13:45:47 +02:00
Carlos Garnacho
4756f42fc0 GdkEventSource: Pass an allocated event to filters. 2009-09-25 10:17:32 +02:00
Carlos Garnacho
32ee1fa82f Compile again with xinput support enabled.
The events refactor broke build when xinput is enabled, actual XInput support
is still broken.
2009-09-25 01:15:07 +02:00
Carlos Garnacho
48c9d7c722 Remove gdk/x11/gdkevents-x11.c
All remaining relevant code has been moved to wherever it made most sense.
2009-09-24 19:28:18 +02:00
Carlos Garnacho
b35bdaa81b Merge branch 'master' into events-refactor
New code from gdkevents-x11.c was moved to GdkDisplayX11, the rest of the
code is unaffected.
2009-09-22 00:36:09 +02:00
Carlos Garnacho
e1d99c07b9 GdkDeviceManager: Remove gdk_device_manager_set_window_events().
It was replaced by gdk_event_translator_select_window_events().
2009-09-04 01:50:26 +02:00
Carlos Garnacho
d0097e6b87 Merge branch 'master' into events-refactor 2009-08-26 19:23:23 +02:00
Carlos Garnacho
cf8501fa93 GdkDeviceManagerCore: Add keyboard device. use it for keyboard events.
Now there is a keyboard device, used for key and focus events.
2009-08-25 22:51:10 +02:00
Carlos Garnacho
e2c41c3cfb Add a GdkDevice parameter to GdkEventKey and GdkEventFocus. 2009-08-25 22:50:24 +02:00
Carlos Garnacho
5515288fed GdkDisplayX11: Make core pointer detection a bit more robust.
Now it tries to detect the first device whose source is a mouse. Bear in
mind that this is still quite weak and is just provided for backwards
compatibility.
2009-08-25 22:46:56 +02:00
Carlos Garnacho
1c7c015a86 GdkDeviceManagerCore: Set input-mode in core pointer. 2009-08-25 01:56:54 +02:00
Carlos Garnacho
ebb9e41a45 GdkDisplayX11: Fix critical warning. 2009-08-25 01:54:45 +02:00
Carlos Garnacho
6b7ac422fb Remove senseless code path.
This code in master doesn't seem to do anything relevant actually, since
neither xwindow nor xevent->xany.window are used in any meaningful way
after this happens. Doing a lookup on toplevel->focus_window already seems
to return the correct GdkWindow.
2009-08-23 18:39:05 +02:00
Carlos Garnacho
32838cc12c GdkEventTranslator: Remove gdk_event_translator_get_event_window(). 2009-08-23 18:38:12 +02:00
Carlos Garnacho
8f1b078d64 GdkDisplayX11: Add internal version of get_event_window(). 2009-08-23 18:35:33 +02:00
Carlos Garnacho
d2bc526bd6 GdkDeviceManagerCore: Remove get_event_window() implementation.
This is now used internally. Also some extra checks have been added.
2009-08-23 18:21:43 +02:00
Carlos Garnacho
b32c34bfec GdkWindowX11: Replace XSelectInput with gdk_event_source_select_events(). 2009-08-23 01:26:43 +02:00
Carlos Garnacho
be711dcaf0 GdkWindowImplX11: use gdk_event_source_select_events(). 2009-08-23 00:46:54 +02:00
Carlos Garnacho
8c18a08caf GdkEventSource: Add gdk_event_source_select_events(). 2009-08-23 00:45:22 +02:00
Carlos Garnacho
aef890e113 GdkEventTranslator: add methods for selecting events on a window. 2009-08-23 00:35:59 +02:00
Carlos Garnacho
fbd21b482c GdkEventTranslator: remove get_filter_window(), it's unused. 2009-08-22 19:18:30 +02:00
Carlos Garnacho
5899f40aea GdkEventSource: Enable window filters.
commented out code has been removed in the event translators.
2009-08-18 02:11:31 +02:00
Carlos Garnacho
1c842fca52 Add back WM_* and _NET_WM_* client messages filter. 2009-08-18 02:11:18 +02:00
Carlos Garnacho
df12a54536 Also copy number of axes to device->axes_len. 2009-08-15 18:39:17 +02:00
Carlos Garnacho
0ad80b6b50 Add new API declarations to gdkdevice.h 2009-08-15 18:13:19 +02:00
Carlos Garnacho
c5fbe7d828 Fix guint underflow. 2009-08-15 18:12:35 +02:00
Carlos Garnacho
be3721119f Add/Improve API for handling devices' axes. 2009-08-15 17:13:44 +02:00
Carlos Garnacho
920b369d7e Implement gdk_device_set_mode(). 2009-08-14 23:14:17 +02:00
Carlos Garnacho
68b3974a3f Fix indentation of gdk_device_get_display(). 2009-08-14 13:48:41 +02:00
Carlos Garnacho
75011a56e4 Make GdkDeviceClass private. 2009-08-14 01:22:33 +02:00
Carlos Garnacho
5896aa3f2e gdk_display_warp_pointer(): Use GdkDevice::warp. 2009-08-12 19:48:35 +02:00
Carlos Garnacho
b36afe82df GdkDeviceCore: Implement warp(). 2009-08-12 19:47:26 +02:00
Carlos Garnacho
12794ee48c GdkDevice: Add warp() vmethod. 2009-08-12 19:46:48 +02:00
Carlos Garnacho
3c3efee0fa Delay core pointer creation until the display is available. 2009-08-12 19:43:08 +02:00
Carlos Garnacho
c225c84fde Add public gdk_device_get_display(). 2009-08-01 18:11:19 +02:00
Carlos Garnacho
6d0b51c10c Implement set_window_cursor() for GdkDeviceCore. 2009-07-10 20:28:01 +01:00
Carlos Garnacho
e61672d603 Fix prototype for gdk_device_core_get_state(). 2009-07-10 20:14:07 +01:00
Carlos Garnacho
386b9d6524 Add set_window_cursor() vmethod to GdkDeviceClass. 2009-07-10 20:08:02 +01:00
Carlos Garnacho
37c3ec1dab Merge branch 'master' into events-refactor
Conflicts:
	gdk/x11/gdkdisplay-x11.c
	gdk/x11/gdkevents-x11.c
	gdk/x11/gdkmain-x11.c
	gdk/x11/gdkwindow-x11.c
2009-07-10 18:46:00 +01:00
Carlos Garnacho
aaf92a2128 Include gdkwindow.h in gdkdevice-core.c 2009-07-03 11:21:12 +01:00
Carlos Garnacho
456d028b4f Replace GdkInput with GdkDevice.
* This "new" object now lives in its own files, allowing different
  implementations.
* There's also a GdkDeviceCore implementation, representing the core pointer.
* All of gdk/x11/gdkinput* is now removed from autofoo, will be completely
  removed in a close future.
  * There are some features left to implement, mostly related to GdkInputWindow
    and extended devices grabs.
  * gdk_input_set_extension_events() is now an empty stub, will be reimplemented
    on top of the newer API, when it's done.
* gdk/gdkinput.c was added to contain the to-be-deprecated functions.
* GdkDeviceManagerCore now creates a GdkDeviceCore
2009-07-02 22:46:24 +02:00
Carlos Garnacho
5434c8c3b8 Backport commit 375d19aa92 to events-refactor branch. 2009-06-14 19:43:36 +02:00
Carlos Garnacho
c951dc0255 Make the device manager select for events on GdkWindow initialization. 2009-06-14 19:37:21 +02:00
Carlos Garnacho
fb2ca79edf Fix compile warning. 2009-06-14 19:37:21 +02:00
Carlos Garnacho
f96f96b651 add gdk_device_manager_set_window_events() method.
Implementations will do the necessary initialization in order to get the
X events they're interested in.
2009-06-14 19:37:21 +02:00
Carlos Garnacho
0f527d4856 Add GdkEventSource.
This object is a GSource that generates GdkEvents from XEvents. Several
GdkEventTranslators can be attached.

This GSource is now hooked to GdkDisplayX11, and conflicting code in
gdkevents-x11.c is ifdef'ed out.
2009-06-14 19:37:21 +02:00
Carlos Garnacho
988bb1bba0 Compile fix. 2009-06-14 19:37:20 +02:00
Carlos Garnacho
eec943cb85 Hook up GdkDisplayX11 to current events translation. 2009-06-14 19:37:20 +02:00
Carlos Garnacho
e897167a86 Make GdkDisplayX11 implement GdkEventTranslator.
* Code was ripped out from gdkevents-x11.c to handle events related to
displays/screens/windows.
2009-06-14 19:37:19 +02:00
Carlos Garnacho
de04fed8eb Refactor out some code from GdkDeviceManagerCore.
* Code unrelated to input devices' event translation was removed.
* It now uses methods from GdkEventTranslator to get the Xevent related windows.
2009-06-14 19:37:19 +02:00
Carlos Garnacho
1fa2f018ef Add methods for getting event/filter window from the event, with default impl. 2009-06-14 19:37:19 +02:00
Carlos Garnacho
a18600e21f Put some duplicated code into functions in GdkDeviceManagerCore event handling. 2009-06-14 19:37:19 +02:00
Carlos Garnacho
c09ea067fe Hook up GdkDeviceManager into current event translation. 2009-06-14 19:37:19 +02:00
Carlos Garnacho
7dfbe5cc85 Rip out some gdkevents-x11 code into GdkDeviceManagerCore.
GdkDeviceManagerCore now implements the GdkEventTranslator interface, code was
taken from gdkevents-x11.c so it translates XEvents related to input devices
into GdkEvents.
2009-06-14 19:37:18 +02:00
Carlos Garnacho
563675f62b Add gdk_event_translator_get_type() prototype. 2009-06-14 19:37:18 +02:00
Carlos Garnacho
8e721ff894 Added the GdkEventTranslator interface. 2009-06-14 19:37:17 +02:00
Carlos Garnacho
6abf0134be Hook up GdkDeviceManager to build. 2009-06-14 19:37:17 +02:00
Carlos Garnacho
c1a48f4e58 Add GdkDeviceManager and skeleton for the default X11 implementation. 2009-06-14 19:37:16 +02:00
36 changed files with 6113 additions and 3533 deletions

View File

@@ -67,6 +67,9 @@ gdk_public_h_sources = \
gdkcairo.h \
gdkcolor.h \
gdkcursor.h \
gdkdevice.h \
gdkdevicemanager.h \
gdkdeviceprivate.h \
gdkdisplay.h \
gdkdisplaymanager.h \
gdkdnd.h \
@@ -107,6 +110,8 @@ gdk_c_sources = \
gdkcairo.c \
gdkcolor.c \
gdkcursor.c \
gdkdevice.c \
gdkdevicemanager.c \
gdkdisplay.c \
gdkdisplaymanager.c \
gdkdnd.c \
@@ -116,6 +121,7 @@ gdk_c_sources = \
gdkgc.c \
gdkglobals.c \
gdkimage.c \
gdkinput.c \
gdkinternals.h \
gdkintl.h \
gdkkeys.c \

View File

@@ -33,6 +33,8 @@
#include <gdk/gdkcairo.h>
#include <gdk/gdkcolor.h>
#include <gdk/gdkcursor.h>
#include <gdk/gdkdevice.h>
#include <gdk/gdkdevicemanager.h>
#include <gdk/gdkdisplay.h>
#include <gdk/gdkdisplaymanager.h>
#include <gdk/gdkdnd.h>

View File

@@ -19,16 +19,6 @@
#define IN_HEADER(x) 1
#endif
#if IN_HEADER(__GDK_EVENTS_H__)
#if IN_FILE(__GDK_EVENTS_X11_C__)
gdk_add_client_message_filter
#ifndef GDK_DISABLE_DEPRECATED
gdk_event_get_graphics_expose
#endif
gdk_events_pending
#endif
#endif
#if IN_HEADER(__GDK_TEST_UTILS_H__)
#if IN_FILE(__GDK_TEST_UTILS_X11_C__)
gdk_test_simulate_button
@@ -61,6 +51,19 @@ gdk_setting_get
#endif
#endif
#if IN_HEADER(__GDK_EVENTS_H__)
#if IN_FILE(__GDK_DISPLAY_X11_C__)
gdk_add_client_message_filter
gdk_event_get_graphics_expose
#endif
#endif
#if IN_HEADER(__GDK_EVENTS_H__)
#if IN_FILE(__GDK_EVENT_SOURCE_C__)
gdk_events_pending
#endif
#endif
#if IN_HEADER(__GDK_H__)
#if IN_FILE(__GDK_MAIN_X11_C__)
gdk_error_trap_pop
@@ -78,6 +81,8 @@ gdk_keyboard_grab
#if IN_HEADER(__GDK_H__)
#if IN_FILE(__GDK_DISPLAY_C__)
gdk_beep
gdk_device_get_core_pointer
gdk_display_get_core_pointer
gdk_set_pointer_hooks
gdk_keyboard_ungrab
gdk_pointer_is_grabbed
@@ -101,14 +106,10 @@ gdk_set_locale
#endif
#if IN_HEADER(__GDK_H__)
#if IN_FILE(__GDK_EVENTS_X11_C__)
#if IN_FILE(__GDK_DISPLAY_X11_C__)
gdk_display_list_devices
gdk_event_send_client_message_for_display
gdk_flush
#endif
#endif
#if IN_HEADER(__GDK_H__)
#if IN_FILE(__GDK_DISPLAY_X11_C__)
gdk_notify_startup_complete
gdk_notify_startup_complete_with_id
#endif
@@ -373,8 +374,16 @@ gdk_cursor_get_image
#endif
#endif
#if IN_HEADER(__GDK_INPUT_H__)
#if IN_FILE(__GDK_INPUT_C__)
#if IN_HEADER(__GDK_DEVICE_MANAGER_H__)
#if IN_FILE(__GDK_DEVICE_MANAGER_C__)
gdk_device_manager_get_display
gdk_device_manager_get_for_display
gdk_device_manager_get_type G_GNUC_CONST
#endif
#endif
#if IN_HEADER(__GDK_DEVICE_H__)
#if IN_FILE(__GDK_DEVICE_C__)
gdk_device_free_history
gdk_device_get_axis
gdk_device_get_history
@@ -382,46 +391,32 @@ gdk_device_get_type G_GNUC_CONST
gdk_device_set_axis_use
gdk_device_set_key
gdk_device_set_source
gdk_devices_list
gdk_input_set_extension_events
#endif
#endif
#if IN_HEADER(__GDK_INPUT_H__)
#if IN_FILE(__GDK_DISPLAY_C__)
gdk_device_get_core_pointer
#endif
#if IN_FILE(__GDK_INPUT_NONE_C__)
gdk_device_get_state
gdk_device_set_mode
#endif
#if IN_FILE(__GDK_INPUT_XFREE_C__)
gdk_device_set_mode
#endif
#if IN_HEADER(__GDK_INPUT_H__)
#if IN_FILE(__GDK_INPUT_X11_C__)
gdk_device_get_state
#endif
#endif
#if IN_HEADER(__GDK_INPUT_H__)
#if IN_FILE(__GDK_INPUT_XFREE_C__)
gdk_device_set_mode
#endif
#endif
#if IN_HEADER(__GDK_INPUT_H__)
#if IN_FILE(__GDK_INPUT_NONE_C__)
gdk_device_get_state
gdk_device_set_mode
#endif
#endif
#if IN_HEADER(__GDK_DISPLAY_H__)
#if IN_FILE(__GDK_EVENTS_X11_C__)
gdk_display_add_client_message_filter
#if IN_FILE(__GDK_INPUT_C__)
gdk_devices_list
gdk_input_set_extension_events
#endif
#endif
#if IN_HEADER(__GDK_DISPLAY_H__)
#if IN_FILE(__GDK_DISPLAY_C__)
gdk_display_close
gdk_display_get_core_pointer
gdk_display_get_event
gdk_display_get_pointer
gdk_display_get_type G_GNUC_CONST
@@ -455,6 +450,7 @@ gdk_display_supports_cursor_color
#if IN_HEADER(__GDK_DISPLAY_H__)
#if IN_FILE(__GDK_DISPLAY_X11_C__)
gdk_display_add_client_message_filter
gdk_display_beep
gdk_display_sync
gdk_display_flush
@@ -476,12 +472,6 @@ gdk_display_supports_composite
#endif
#endif
#if IN_HEADER(__GDK_DISPLAY_H__)
#if IN_FILE(__GDK_INPUT_C__)
gdk_display_list_devices
#endif
#endif
#if IN_HEADER(__GDK_DISPLAY_H__)
#if IN_FILE(__GDK_C__)
gdk_display_open_default_libgtk_only
@@ -894,12 +884,6 @@ gdk_visual_get_type G_GNUC_CONST
#endif
#endif
#if IN_HEADER(__GDK_X_H__)
#if IN_FILE(__GDK_EVENTS_X11_C__)
gdk_net_wm_supports
#endif
#endif
#if IN_HEADER(__GDK_PANGO_H__)
#if IN_FILE(__GDK_PANGO_C__)
gdk_pango_attr_emboss_color_new
@@ -1046,13 +1030,6 @@ gdk_screen_get_rgb_visual
#endif
#endif
#if IN_HEADER(__GDK_SCREEN_H__)
#if IN_FILE(__GDK_EVENTS_X11_C__)
gdk_screen_get_setting
gdk_screen_broadcast_client_message
#endif
#endif
#if IN_HEADER(__GDK_SCREEN_H__)
#if IN_FILE(__GDK_VISUAL_X11_C__)
gdk_screen_get_system_visual
@@ -1068,6 +1045,7 @@ gdk_screen_get_toplevel_windows
#if IN_HEADER(__GDK_SCREEN_H__)
#if IN_FILE(__GDK_SCREEN_X11_C__)
gdk_screen_broadcast_client_message
gdk_screen_get_display
gdk_screen_get_width
gdk_screen_get_width_mm
@@ -1075,6 +1053,7 @@ gdk_screen_get_height
gdk_screen_get_height_mm
gdk_screen_get_number
gdk_screen_get_root_window
gdk_screen_get_setting
gdk_screen_get_default_colormap
gdk_screen_set_default_colormap
gdk_screen_get_n_monitors
@@ -1217,6 +1196,7 @@ gdk_x11_display_ungrab
gdk_x11_lookup_xdisplay
gdk_x11_display_broadcast_startup_message
gdk_x11_display_get_startup_notification_id
gdk_x11_register_standard_event_type
#endif
#if IN_FILE(__GDK_DRAWABLE_X11_C__)
@@ -1247,22 +1227,18 @@ gdk_x11_grab_server
gdk_x11_ungrab_server
#endif
#if IN_FILE(__GDK_EVENTS_X11_C__)
gdk_x11_get_server_time
gdk_x11_register_standard_event_type
gdk_x11_screen_get_window_manager_name
gdk_x11_screen_supports_net_wm_hint
#endif
#if IN_FILE(__GDK_IMAGE_X11_C__)
gdk_x11_image_get_xdisplay
gdk_x11_image_get_ximage
#endif
#if IN_FILE(__GDK_SCREEN_X11_C__)
gdk_net_wm_supports
gdk_x11_screen_get_screen_number
gdk_x11_screen_get_window_manager_name
gdk_x11_screen_get_xscreen
gdk_x11_screen_get_monitor_output
gdk_x11_screen_supports_net_wm_hint
#endif
#if IN_FILE(__GDK_VISUAL_X11_C__)
@@ -1272,6 +1248,7 @@ gdkx_visual_get
#endif
#if IN_FILE(__GDK_WINDOW_X11_C__)
gdk_x11_get_server_time
gdk_x11_window_set_user_time
gdk_x11_window_move_to_current_desktop
#endif

585
gdk/gdkdevice.c Normal file
View File

@@ -0,0 +1,585 @@
/* 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
{
GdkDisplay *display;
GArray *axes;
};
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_NAME,
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->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_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_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_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_NAME:
if (device->name)
g_free (device->name);
device->name = g_value_dup_string (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_NAME:
g_value_set_string (value,
device->name);
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;
}
}
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);
}
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;
}
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)
{
g_return_if_fail (GDK_IS_DEVICE (device));
g_return_if_fail (index < device->num_axes);
device->axes[index].use = use;
switch (use)
{
case GDK_AXIS_X:
case GDK_AXIS_Y:
device->axes[index].min = 0.;
device->axes[index].max = 0.;
break;
case GDK_AXIS_XTILT:
case GDK_AXIS_YTILT:
device->axes[index].min = -1.;
device->axes[index].max = 1;
break;
default:
device->axes[index].min = 0.;
device->axes[index].max = 1;
break;
}
}
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;
}
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;
}
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;
}
/* 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);
}
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;
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;
return priv->axes->len - 1;
}
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;
}
gboolean
_gdk_device_translate_axis (GdkDevice *device,
gdouble window_width,
gdouble window_height,
gdouble window_x,
gdouble window_y,
guint index,
gdouble value,
gdouble *axis_value)
{
GdkDevicePrivate *priv;
GdkAxisInfo axis_info;
gdouble out = 0;
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)
{
GdkAxisInfo *axis_info_x, *axis_info_y;
gdouble device_width, device_height;
gdouble x_offset, y_offset;
gdouble x_scale, y_scale;
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->mode == GDK_MODE_SCREEN)
{
if (axis_info.use == GDK_AXIS_X)
out = window_x;
else
out = window_y;
}
else /* GDK_MODE_WINDOW */
{
gdouble x_resolution, y_resolution, device_aspect;
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_info.use == GDK_AXIS_X)
out = x_offset + x_scale * (value - axis_info.min_value);
else
out = y_offset + y_scale * (value - axis_info.min_value);
}
}
else
{
gdouble axis_width;
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"

163
gdk/gdkdevice.h Normal file
View File

@@ -0,0 +1,163 @@
/* 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_H__
#define __GDK_DEVICE_H__
#include <gdk/gdktypes.h>
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE (gdk_device_get_type ())
#define GDK_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE, GdkDevice))
#define GDK_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE))
typedef struct _GdkDevice GdkDevice;
typedef struct _GdkDeviceKey GdkDeviceKey;
typedef struct _GdkDeviceAxis GdkDeviceAxis;
typedef struct _GdkTimeCoord GdkTimeCoord;
typedef enum
{
GDK_EXTENSION_EVENTS_NONE,
GDK_EXTENSION_EVENTS_ALL,
GDK_EXTENSION_EVENTS_CURSOR
} GdkExtensionMode;
typedef enum
{
GDK_SOURCE_MOUSE,
GDK_SOURCE_PEN,
GDK_SOURCE_ERASER,
GDK_SOURCE_CURSOR,
GDK_SOURCE_KEYBOARD
} GdkInputSource;
typedef enum
{
GDK_MODE_DISABLED,
GDK_MODE_SCREEN,
GDK_MODE_WINDOW
} GdkInputMode;
typedef enum
{
GDK_AXIS_IGNORE,
GDK_AXIS_X,
GDK_AXIS_Y,
GDK_AXIS_PRESSURE,
GDK_AXIS_XTILT,
GDK_AXIS_YTILT,
GDK_AXIS_WHEEL,
GDK_AXIS_LAST
} GdkAxisUse;
struct _GdkDeviceKey
{
guint keyval;
GdkModifierType modifiers;
};
struct _GdkDeviceAxis
{
GdkAxisUse use;
gdouble min;
gdouble max;
};
/* We don't allocate each coordinate this big, but we use it to
* be ANSI compliant and avoid accessing past the defined limits.
*/
#define GDK_MAX_TIMECOORD_AXES 128
struct _GdkTimeCoord
{
guint32 time;
gdouble axes[GDK_MAX_TIMECOORD_AXES];
};
struct _GdkDevice
{
GObject parent_instance;
/* All fields are read-only */
gchar *name;
GdkInputSource source;
GdkInputMode mode;
gboolean has_cursor; /* TRUE if the X pointer follows device motion */
gint num_axes;
GdkDeviceAxis *axes;
gint num_keys;
GdkDeviceKey *keys;
};
GType gdk_device_get_type (void) G_GNUC_CONST;
/* Functions to configure a device */
void gdk_device_set_source (GdkDevice *device,
GdkInputSource source);
gboolean gdk_device_set_mode (GdkDevice *device,
GdkInputMode mode);
void gdk_device_set_key (GdkDevice *device,
guint index_,
guint keyval,
GdkModifierType modifiers);
void gdk_device_set_axis_use (GdkDevice *device,
guint index_,
GdkAxisUse use);
void gdk_device_get_state (GdkDevice *device,
GdkWindow *window,
gdouble *axes,
GdkModifierType *mask);
gboolean gdk_device_get_history (GdkDevice *device,
GdkWindow *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
guint *n_events);
void gdk_device_free_history (GdkTimeCoord **events,
gint n_events);
GList * gdk_device_list_axes (GdkDevice *device);
gboolean gdk_device_get_axis_value (GdkDevice *device,
gdouble *axes,
GdkAtom axis_label,
gdouble *value);
gboolean gdk_device_get_axis (GdkDevice *device,
gdouble *axes,
GdkAxisUse use,
gdouble *value);
GdkDisplay * gdk_device_get_display (GdkDevice *device);
G_END_DECLS
#endif /* __GDK_DEVICE_H__ */

230
gdk/gdkdevicemanager.c Normal file
View File

@@ -0,0 +1,230 @@
/* 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.h"
#include "gdkintl.h"
#include "gdkinternals.h"
#include "gdkalias.h"
static void gdk_device_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gdk_device_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_ABSTRACT_TYPE (GdkDeviceManager, gdk_device_manager, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_DISPLAY
};
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
DEVICE_CHANGED,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0 };
static GHashTable *device_managers = NULL;
typedef struct GdkDeviceManagerPrivate GdkDeviceManagerPrivate;
struct GdkDeviceManagerPrivate
{
GdkDisplay *display;
};
#define GDK_DEVICE_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDK_TYPE_DEVICE_MANAGER, GdkDeviceManagerPrivate))
static void
gdk_device_manager_class_init (GdkDeviceManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = gdk_device_manager_set_property;
object_class->get_property = gdk_device_manager_get_property;
g_object_class_install_property (object_class,
PROP_DISPLAY,
g_param_spec_object ("display",
P_("Display"),
P_("Display for the device manager"),
GDK_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
signals [DEVICE_ADDED] =
g_signal_new (g_intern_static_string ("device-added"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GdkDeviceManagerClass, device_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GDK_TYPE_DEVICE);
signals [DEVICE_REMOVED] =
g_signal_new (g_intern_static_string ("device-removed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GdkDeviceManagerClass, device_removed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GDK_TYPE_DEVICE);
signals [DEVICE_CHANGED] =
g_signal_new (g_intern_static_string ("device-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GdkDeviceManagerClass, device_changed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GDK_TYPE_DEVICE);
g_type_class_add_private (object_class, sizeof (GdkDeviceManagerPrivate));
}
static void
gdk_device_manager_init (GdkDeviceManager *manager)
{
}
static void
gdk_device_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkDeviceManagerPrivate *priv;
priv = GDK_DEVICE_MANAGER_GET_PRIVATE (object);
switch (prop_id)
{
case PROP_DISPLAY:
priv->display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_device_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkDeviceManagerPrivate *priv;
priv = GDK_DEVICE_MANAGER_GET_PRIVATE (object);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, priv->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* gdk_device_manager_get_for_display:
* @display: A #GdkDisplay
*
* Returns the #GdkDeviceManager attached to @display.
*
* Returns: the #GdkDeviceManager attached to @display. This memory
* is owned by GTK+, and must not be freed or unreffed.
**/
GdkDeviceManager *
gdk_device_manager_get_for_display (GdkDisplay *display)
{
GdkDeviceManager *device_manager;
if (G_UNLIKELY (!device_managers))
device_managers = g_hash_table_new (g_direct_hash,
g_direct_equal);
device_manager = g_hash_table_lookup (device_managers, display);
if (G_UNLIKELY (!device_manager))
{
device_manager = _gdk_device_manager_new (display);
g_hash_table_insert (device_managers, display, device_manager);
}
return device_manager;
}
/**
* gdk_device_manager_get_display:
* @device_manager: a #GdkDeviceManager
*
* Gets the #GdkDisplay associated to @device_manager.
*
* Returns: the #GdkDisplay to which @device_manager is
* associated to, or #NULL.
**/
GdkDisplay *
gdk_device_manager_get_display (GdkDeviceManager *device_manager)
{
GdkDeviceManagerPrivate *priv;
g_return_val_if_fail (GDK_IS_DEVICE_MANAGER (device_manager), NULL);
priv = GDK_DEVICE_MANAGER_GET_PRIVATE (device_manager);
return priv->display;
}
/**
* gdk_device_manager_get_devices:
* @device_manager: a #GdkDeviceManager
* @type: device type to get.
*
* Returns the list of devices of type @type currently attached to
* @device_manager.
*
* Returns: a list of #GdkDevice<!-- -->s. The returned list must be
* freed with g_list_free ().
**/
GList *
gdk_device_manager_get_devices (GdkDeviceManager *device_manager,
GdkDeviceType type)
{
g_return_val_if_fail (GDK_IS_DEVICE_MANAGER (device_manager), NULL);
return GDK_DEVICE_MANAGER_GET_CLASS (device_manager)->get_devices (device_manager, type);
}
#define __GDK_DEVICE_MANAGER_C__
#include "gdkaliasdef.c"

81
gdk/gdkdevicemanager.h Normal file
View File

@@ -0,0 +1,81 @@
/* 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_MANAGER_H__
#define __GDK_DEVICE_MANAGER_H__
#include <gdk/gdktypes.h>
#include <gdk/gdkdevice.h>
#include <gdk/gdkdisplay.h>
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE_MANAGER (gdk_device_manager_get_type ())
#define GDK_DEVICE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_MANAGER, GdkDeviceManager))
#define GDK_DEVICE_MANAGER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_MANAGER, GdkDeviceManagerClass))
#define GDK_IS_DEVICE_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_MANAGER))
#define GDK_IS_DEVICE_MANAGER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_MANAGER))
#define GDK_DEVICE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_MANAGER, GdkDeviceManagerClass))
typedef struct _GdkDeviceManager GdkDeviceManager;
typedef struct _GdkDeviceManagerClass GdkDeviceManagerClass;
typedef enum {
GDK_DEVICE_TYPE_MASTER,
GDK_DEVICE_TYPE_SLAVE,
GDK_DEVICE_TYPE_FLOATING
} GdkDeviceType;
struct _GdkDeviceManager
{
GObject parent_instance;
};
struct _GdkDeviceManagerClass
{
GObjectClass parent_class;
/* Signals */
void (* device_added) (GdkDeviceManager *device_manager,
GdkDevice *device);
void (* device_removed) (GdkDeviceManager *device_manager,
GdkDevice *device);
void (* device_changed) (GdkDeviceManager *device_manager,
GdkDevice *device);
/* VMethods */
GList * (* get_devices) (GdkDeviceManager *device_manager,
GdkDeviceType type);
};
GType gdk_device_manager_get_type (void) G_GNUC_CONST;
GdkDeviceManager * gdk_device_manager_get_for_display (GdkDisplay *display);
GdkDisplay * gdk_device_manager_get_display (GdkDeviceManager *device_manager);
GList * gdk_device_manager_get_devices (GdkDeviceManager *device_manager,
GdkDeviceType type);
G_END_DECLS
#endif /* __GDK_DEVICE_MANAGER_H__ */

83
gdk/gdkdeviceprivate.h Normal file
View File

@@ -0,0 +1,83 @@
/* 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>
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);
};
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);
gboolean _gdk_device_translate_axis (GdkDevice *device,
gdouble window_width,
gdouble window_height,
gdouble window_x,
gdouble window_y,
guint index,
gdouble value,
gdouble *axis_value);
G_END_DECLS
#endif /* __GDK_DEVICE_PRIVATE_H__ */

View File

@@ -34,7 +34,7 @@
#include <gdk/gdkcolor.h>
#include <gdk/gdktypes.h>
#include <gdk/gdkdnd.h>
#include <gdk/gdkinput.h>
#include <gdk/gdkdevice.h>
G_BEGIN_DECLS
@@ -352,6 +352,7 @@ struct _GdkEventKey
guint16 hardware_keycode;
guint8 group;
guint is_modifier : 1;
GdkDevice *device;
};
struct _GdkEventCrossing
@@ -377,6 +378,7 @@ struct _GdkEventFocus
GdkWindow *window;
gint8 send_event;
gint16 in;
GdkDevice *device;
};
struct _GdkEventConfigure

40
gdk/gdkinput.c Normal file
View File

@@ -0,0 +1,40 @@
/* 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 "gdkinput.h"
#include "gdkdevicemanager.h"
#include "gdkdisplay.h"
#include "gdkalias.h"
GList *
gdk_devices_list (void)
{
return gdk_display_list_devices (gdk_display_get_default ());
}
void
gdk_input_set_extension_events (GdkWindow *window,
gint mask,
GdkExtensionMode mode)
{
/* FIXME: Not implemented */
}
#define __GDK_INPUT_C__
#include "gdkaliasdef.c"

View File

@@ -32,144 +32,25 @@
#define __GDK_INPUT_H__
#include <gdk/gdktypes.h>
#include <gdk/gdkdevice.h>
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE (gdk_device_get_type ())
#define GDK_DEVICE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DEVICE, GdkDevice))
#define GDK_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DEVICE, GdkDeviceClass))
#define GDK_IS_DEVICE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DEVICE))
#define GDK_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DEVICE))
#define GDK_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DEVICE, GdkDeviceClass))
typedef struct _GdkDeviceKey GdkDeviceKey;
typedef struct _GdkDeviceAxis GdkDeviceAxis;
typedef struct _GdkDevice GdkDevice;
typedef struct _GdkDeviceClass GdkDeviceClass;
typedef struct _GdkTimeCoord GdkTimeCoord;
typedef enum
{
GDK_EXTENSION_EVENTS_NONE,
GDK_EXTENSION_EVENTS_ALL,
GDK_EXTENSION_EVENTS_CURSOR
} GdkExtensionMode;
typedef enum
{
GDK_SOURCE_MOUSE,
GDK_SOURCE_PEN,
GDK_SOURCE_ERASER,
GDK_SOURCE_CURSOR
} GdkInputSource;
typedef enum
{
GDK_MODE_DISABLED,
GDK_MODE_SCREEN,
GDK_MODE_WINDOW
} GdkInputMode;
typedef enum
{
GDK_AXIS_IGNORE,
GDK_AXIS_X,
GDK_AXIS_Y,
GDK_AXIS_PRESSURE,
GDK_AXIS_XTILT,
GDK_AXIS_YTILT,
GDK_AXIS_WHEEL,
GDK_AXIS_LAST
} GdkAxisUse;
struct _GdkDeviceKey
{
guint keyval;
GdkModifierType modifiers;
};
struct _GdkDeviceAxis
{
GdkAxisUse use;
gdouble min;
gdouble max;
};
struct _GdkDevice
{
GObject parent_instance;
/* All fields are read-only */
gchar *name;
GdkInputSource source;
GdkInputMode mode;
gboolean has_cursor; /* TRUE if the X pointer follows device motion */
gint num_axes;
GdkDeviceAxis *axes;
gint num_keys;
GdkDeviceKey *keys;
};
/* We don't allocate each coordinate this big, but we use it to
* be ANSI compliant and avoid accessing past the defined limits.
*/
#define GDK_MAX_TIMECOORD_AXES 128
struct _GdkTimeCoord
{
guint32 time;
gdouble axes[GDK_MAX_TIMECOORD_AXES];
};
GType gdk_device_get_type (void) G_GNUC_CONST;
#ifndef GDK_MULTIHEAD_SAFE
/* Returns a list of GdkDevice * */
GList * gdk_devices_list (void);
/* Returns a list of GdkDevice * */
GList * gdk_devices_list (void);
GdkDevice *gdk_device_get_core_pointer (void);
#endif /* GDK_MULTIHEAD_SAFE */
/* Functions to configure a device */
void gdk_device_set_source (GdkDevice *device,
GdkInputSource source);
gboolean gdk_device_set_mode (GdkDevice *device,
GdkInputMode mode);
void gdk_device_set_key (GdkDevice *device,
guint index_,
guint keyval,
GdkModifierType modifiers);
void gdk_device_set_axis_use (GdkDevice *device,
guint index_,
GdkAxisUse use);
void gdk_device_get_state (GdkDevice *device,
GdkWindow *window,
gdouble *axes,
GdkModifierType *mask);
gboolean gdk_device_get_history (GdkDevice *device,
GdkWindow *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events);
void gdk_device_free_history (GdkTimeCoord **events,
gint n_events);
gboolean gdk_device_get_axis (GdkDevice *device,
gdouble *axes,
GdkAxisUse use,
gdouble *value);
GdkDevice *gdk_display_get_core_pointer (GdkDisplay *display);
void gdk_input_set_extension_events (GdkWindow *window,
gint mask,
GdkExtensionMode mode);
#ifndef GDK_MULTIHEAD_SAFE
GdkDevice *gdk_device_get_core_pointer (void);
#endif
G_END_DECLS
#endif /* __GDK_INPUT_H__ */

View File

@@ -315,6 +315,9 @@ void gdk_synthesize_window_state (GdkWindow *window,
GdkWindowState unset_flags,
GdkWindowState set_flags);
GdkDeviceManager * _gdk_device_manager_new (GdkDisplay *display);
#define GDK_SCRATCH_IMAGE_WIDTH 256
#define GDK_SCRATCH_IMAGE_HEIGHT 64

View File

@@ -23,19 +23,24 @@ libgdk_x11_la_SOURCES = \
gdkasync.h \
gdkcolor-x11.c \
gdkcursor-x11.c \
gdkdevice-core.c \
gdkdevicemanager-core.c \
gdkdevicemanager-x11.c \
gdkdisplay-x11.c \
gdkdisplay-x11.h \
gdkdnd-x11.c \
gdkdrawable-x11.c \
gdkdrawable-x11.h \
gdkevents-x11.c \
gdkeventsource.c \
gdkeventsource.h \
gdkeventtranslator.c \
gdkeventtranslator.h \
gdkfont-x11.c \
gdkgc-x11.c \
gdkgeometry-x11.c \
gdkglobals-x11.c \
gdkim-x11.c \
gdkimage-x11.c \
gdkinput.c \
gdkkeys-x11.c \
gdkmain-x11.c \
gdkpixmap-x11.c \
@@ -53,14 +58,13 @@ libgdk_x11_la_SOURCES = \
gdkxid.c \
gdkx.h \
gdkprivate-x11.h \
gdkinputprivate.h \
xsettings-client.h \
xsettings-client.c \
xsettings-common.h \
xsettings-common.c
if XINPUT_XFREE
libgdk_x11_la_SOURCES += gdkinput-x11.c gdkinput-xfree.c
libgdk_x11_la_SOURCES += gdkdevicemanager-xi.c gdkdevice-xi.c gdkinput-x11.c gdkinput-xfree.c
else
libgdk_x11_la_SOURCES += gdkinput-none.c
endif

119
gdk/x11/gdkdevice-core.c Normal file
View File

@@ -0,0 +1,119 @@
/* 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 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);
G_DEFINE_TYPE (GdkDeviceCore, gdk_device_core, GDK_TYPE_DEVICE)
static GdkDeviceAxis gdk_device_core_axes[] = {
{ GDK_AXIS_X, 0, 0 },
{ GDK_AXIS_Y, 0, 0 }
};
static void
gdk_device_core_class_init (GdkDeviceCoreClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
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;
}
static void
gdk_device_core_init (GdkDeviceCore *device_core)
{
GdkDevice *device;
device = GDK_DEVICE (device_core);
device->num_axes = G_N_ELEMENTS (gdk_device_core_axes);
device->axes = gdk_device_core_axes;
device->num_keys = 0;
device->keys = NULL;
}
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);
}

51
gdk/x11/gdkdevice-core.h Normal file
View File

@@ -0,0 +1,51 @@
/* 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_CORE_H__
#define __GDK_DEVICE_CORE_H__
#include <gdk/gdkdeviceprivate.h>
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE_CORE (gdk_device_core_get_type ())
#define GDK_DEVICE_CORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_CORE, GdkDeviceCore))
#define GDK_DEVICE_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_CORE, GdkDeviceCoreClass))
#define GDK_IS_DEVICE_CORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_CORE))
#define GDK_IS_DEVICE_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_CORE))
#define GDK_DEVICE_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_CORE, GdkDeviceCoreClass))
typedef struct _GdkDeviceCore GdkDeviceCore;
typedef struct _GdkDeviceCoreClass GdkDeviceCoreClass;
struct _GdkDeviceCore
{
GdkDevice parent_instance;
};
struct _GdkDeviceCoreClass
{
GdkDeviceClass parent_class;
};
GType gdk_device_core_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_DEVICE_CORE_H__ */

123
gdk/x11/gdkdevice-xi.c Normal file
View File

@@ -0,0 +1,123 @@
/* 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-xi.h"
#include "gdkprivate-x11.h"
#include "gdkintl.h"
#include "gdkx.h"
static void gdk_device_xi_constructed (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);
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);
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;
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;
}
}

69
gdk/x11/gdkdevice-xi.h Normal file
View File

@@ -0,0 +1,69 @@
/* 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;
/* minimum key code for device */
gint min_keycode;
/* Mask of buttons (used for button grabs) */
gint button_state;
};
struct _GdkDeviceXIClass
{
GdkDeviceClass parent_class;
};
GType gdk_device_xi_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_DEVICE_XI_H__ */

View File

@@ -0,0 +1,914 @@
/* 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/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_constructed (GObject *object);
static GList * gdk_device_manager_core_get_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->constructed = gdk_device_manager_core_constructed;
device_manager_class->get_devices = gdk_device_manager_core_get_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 (GdkDisplay *display)
{
return g_object_new (GDK_TYPE_DEVICE_CORE,
"name", "Core Pointer",
"input-source", GDK_SOURCE_MOUSE,
"input-mode", GDK_MODE_SCREEN,
"has-cursor", TRUE,
"display", display,
NULL);
}
static GdkDevice *
create_core_keyboard (GdkDisplay *display)
{
return g_object_new (GDK_TYPE_DEVICE_CORE,
"name", "Core Keyboard",
"input-source", GDK_SOURCE_KEYBOARD,
"has-cursor", TRUE,
"display", display,
NULL);
}
static void
gdk_device_manager_core_init (GdkDeviceManagerCore *device_manager)
{
}
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 (display);
device_manager->core_keyboard = create_core_keyboard (display);
}
static void
translate_key_event (GdkDisplay *display,
GdkDeviceManagerCore *device_manager,
GdkEvent *event,
XEvent *xevent)
{
GdkKeymap *keymap = gdk_keymap_get_for_display (display);
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;
event->key.device = 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, NULL);
_gdk_keymap_add_virtual_modifiers (keymap, &event->key.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.type = GDK_FOCUS_CHANGE;
event.focus_change.window = window;
event.focus_change.send_event = FALSE;
event.focus_change.in = in;
event.focus_change.device = device_manager->core_keyboard;
gdk_event_put (&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)
{
GdkDisplay *display;
GdkWindow *window;
display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (translator));
window = gdk_window_lookup_for_display (display, xevent->xany.window);
/* Apply keyboard grabs to non-native windows */
if (/* Is key event */
(xevent->type == KeyPress || xevent->type == KeyRelease) &&
/* And we have a grab */
display->keyboard_grab.window != NULL &&
(
/* The window is not a descendant of the grabbed window */
!is_parent_of ((GdkWindow *)display->keyboard_grab.window, window) ||
/* Or owner event is false */
!display->keyboard_grab.owner_events
)
)
{
/* Report key event against grab window */
return display->keyboard_grab.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 = xevent->xbutton.x;
event->scroll.y = xevent->xbutton.y;
event->scroll.x_root = (gfloat) xevent->xbutton.x_root;
event->scroll.y_root = (gfloat) 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 = xevent->xbutton.x;
event->button.y = xevent->xbutton.y;
event->button.x_root = (gfloat) xevent->xbutton.x_root;
event->button.y_root = (gfloat) xevent->xbutton.y_root;
event->button.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 = xevent->xbutton.x;
event->button.y = xevent->xbutton.y;
event->button.x_root = (gfloat) xevent->xbutton.x_root;
event->button.y_root = (gfloat) xevent->xbutton.y_root;
event->button.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 = xevent->xmotion.x;
event->motion.y = xevent->xmotion.y;
event->motion.x_root = (gfloat) xevent->xmotion.x_root;
event->motion.y_root = (gfloat) xevent->xmotion.y_root;
event->motion.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;
}
/* Handle focusing (in the case where no window manager is running */
if (toplevel && xevent->xcrossing.detail != NotifyInferior)
{
toplevel->has_pointer = TRUE;
if (xevent->xcrossing.focus && !toplevel->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (toplevel);
toplevel->has_pointer_focus = TRUE;
if (HAS_FOCUS (toplevel) != had_focus)
generate_focus_event (device_manager, window, TRUE);
}
}
event->crossing.type = GDK_ENTER_NOTIFY;
event->crossing.window = window;
/* If the subwindow field of the XEvent is non-NULL, then
* lookup the corresponding GdkWindow.
*/
if (xevent->xcrossing.subwindow != None)
event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
else
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
event->crossing.x = xevent->xcrossing.x;
event->crossing.y = xevent->xcrossing.y;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
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;
}
/* Handle focusing (in the case where no window manager is running */
if (toplevel && xevent->xcrossing.detail != NotifyInferior)
{
toplevel->has_pointer = FALSE;
if (xevent->xcrossing.focus && !toplevel->has_focus_window)
{
gboolean had_focus = HAS_FOCUS (toplevel);
toplevel->has_pointer_focus = FALSE;
if (HAS_FOCUS (toplevel) != had_focus)
generate_focus_event (device_manager, window, FALSE);
}
}
event->crossing.type = GDK_LEAVE_NOTIFY;
event->crossing.window = window;
/* If the subwindow field of the XEvent is non-NULL, then
* lookup the corresponding GdkWindow.
*/
if (xevent->xcrossing.subwindow != None)
event->crossing.subwindow = gdk_window_lookup_for_display (display, xevent->xcrossing.subwindow);
else
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
event->crossing.x = xevent->xcrossing.x;
event->crossing.y = xevent->xcrossing.y;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
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:
#ifdef HAVE_XKB
if (xevent->type == display_x11->xkb_event_type)
{
XkbEvent *xkb_event = (XkbEvent *)xevent;
switch (xkb_event->any.xkb_type)
{
case XkbNewKeyboardNotify:
case XkbMapNotify:
_gdk_keymap_keys_changed (display);
return_val = FALSE;
break;
case XkbStateNotify:
_gdk_keymap_state_changed (display, xevent);
break;
}
}
else
#endif
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_get_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;
}

View File

@@ -0,0 +1,54 @@
/* 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_MANAGER_CORE_H__
#define __GDK_DEVICE_MANAGER_CORE_H__
#include <gdk/gdkdevicemanager.h>
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE_MANAGER_CORE (gdk_device_manager_core_get_type ())
#define GDK_DEVICE_MANAGER_CORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_MANAGER_CORE, GdkDeviceManagerCore))
#define GDK_DEVICE_MANAGER_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_MANAGER_CORE, GdkDeviceManagerCoreClass))
#define GDK_IS_DEVICE_MANAGER_CORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_MANAGER_CORE))
#define GDK_IS_DEVICE_MANAGER_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_MANAGER_CORE))
#define GDK_DEVICE_MANAGER_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_MANAGER_CORE, GdkDeviceManagerCoreClass))
typedef struct _GdkDeviceManagerCore GdkDeviceManagerCore;
typedef struct _GdkDeviceManagerCoreClass GdkDeviceManagerCoreClass;
struct _GdkDeviceManagerCore
{
GdkDeviceManager parent_object;
GdkDevice *core_pointer;
GdkDevice *core_keyboard;
};
struct _GdkDeviceManagerCoreClass
{
GdkDeviceManagerClass parent_class;
};
GType gdk_device_manager_core_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_DEVICE_MANAGER_CORE_H__ */

View File

@@ -0,0 +1,55 @@
/* 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 "gdkx.h"
#include "gdkdevicemanager-core.h"
#ifdef XINPUT_XFREE
#include "gdkdevicemanager-xi.h"
#endif
GdkDeviceManager *
_gdk_device_manager_new (GdkDisplay *display)
{
GdkDeviceManager *device_manager;
int opcode, firstevent, firsterror;
int major, minor;
Display *xdisplay;
if (G_UNLIKELY (!g_getenv ("GDK_CORE_DEVICE_EVENTS")))
{
#ifdef XINPUT_XFREE
xdisplay = GDK_DISPLAY_XDISPLAY (display);
if (XQueryExtension (xdisplay, "XInputExtension",
&opcode, &firstevent, &firsterror))
{
return g_object_new (GDK_TYPE_DEVICE_MANAGER_XI,
"display", display,
"event-base", firstevent,
NULL);
}
#endif /* XINPUT_XFREE */
}
return g_object_new (GDK_TYPE_DEVICE_MANAGER_CORE,
"display", display,
NULL);
}

View File

@@ -0,0 +1,684 @@
/* 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;
};
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 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);
}
static void
translate_class_info (GdkDevice *device,
XDeviceInfo *info)
{
XAnyClassPtr class;
gint i, j;
class = info->inputclassinfo;
for (i = 0; i < info->num_classes; i++)
{
switch (class->class) {
case ButtonClass:
break;
case KeyClass:
{
#if 0
XKeyInfo *xki = (XKeyInfo *)class;
/* Hack to catch XFree86 3.3.1 bug. Other devices better
* not have exactly 25 keys...
*/
if ((xki->min_keycode == 8) && (xki->max_keycode == 32))
{
gdkdev->info.num_keys = 32;
gdkdev->min_keycode = 1;
}
else
{
gdkdev->info.num_keys = xki->max_keycode - xki->min_keycode + 1;
gdkdev->min_keycode = xki->min_keycode;
}
gdkdev->info.keys = g_new (GdkDeviceKey, gdkdev->info.num_keys);
for (j=0; j<gdkdev->info.num_keys; j++)
{
gdkdev->info.keys[j].keyval = 0;
gdkdev->info.keys[j].modifiers = 0;
}
#endif
break;
}
case ValuatorClass:
{
XValuatorInfo *xvi = (XValuatorInfo *)class;
device->num_axes = xvi->num_axes;
device->axes = g_new0 (GdkDeviceAxis, xvi->num_axes);
#if 0
gdkdev->axes = g_new (GdkAxisInfo, xvi->num_axes);
for (j = 0; j < xvi->num_axes; j++)
{
gdkdev->axes[j].resolution =
gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
gdkdev->axes[j].min_value =
gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
gdkdev->axes[j].max_value =
gdkdev->axes[j].xmax_value = xvi->axes[j].max_value;
gdkdev->info.axes[j].use = GDK_AXIS_IGNORE;
}
#endif
j=0;
if (j < xvi->num_axes)
gdk_device_set_axis_use (device, j++, GDK_AXIS_X);
if (j < xvi->num_axes)
gdk_device_set_axis_use (device, j++, GDK_AXIS_Y);
if (j < xvi->num_axes)
gdk_device_set_axis_use (device, j++, GDK_AXIS_PRESSURE);
if (j < xvi->num_axes)
gdk_device_set_axis_use (device, j++, GDK_AXIS_XTILT);
if (j < xvi->num_axes)
gdk_device_set_axis_use (device, j++, GDK_AXIS_YTILT);
if (j < xvi->num_axes)
gdk_device_set_axis_use (device, j++, GDK_AXIS_WHEEL);
break;
}
}
class = (XAnyClassPtr) (((char *) class) + class->length);
}
}
static GdkDevice *
create_device (GdkDisplay *display,
XDeviceInfo *info)
{
GdkDevice *device;
device = g_object_new (GDK_TYPE_DEVICE_XI,
"name", info->name,
"input-source", GDK_SOURCE_MOUSE,
"input-mode", GDK_MODE_DISABLED,
"has-cursor", FALSE,
"display", display,
"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 (display, &devices[i]);
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_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;
}
static void
gdk_input_translate_coordinates (GdkDevice *device,
GdkWindow *window,
gint *axis_data,
gdouble *axis_out,
gdouble *x_out,
gdouble *y_out)
{
#if 0
GdkWindowObject *priv, *impl_window;
int i;
int x_axis = 0;
int y_axis = 0;
double device_width, device_height;
double x_offset, y_offset, x_scale, y_scale;
priv = (GdkWindowObject *) window;
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
for (i = 0; i < device->num_axes; i++)
{
switch (device->axes[i].use)
{
case GDK_AXIS_X:
x_axis = i;
break;
case GDK_AXIS_Y:
y_axis = i;
break;
default:
break;
}
}
device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
if (device->mode == GDK_MODE_SCREEN)
{
x_scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / device_width;
y_scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / device_height;
x_offset = - impl_window->input_window->root_x - priv->abs_x;
y_offset = - impl_window->input_window->root_y - priv->abs_y;
}
else /* GDK_MODE_WINDOW */
{
double x_resolution = gdkdev->axes[x_axis].resolution;
double y_resolution = gdkdev->axes[y_axis].resolution;
double device_aspect;
/*
* 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 * priv->width >= priv->height)
{
/* device taller than window */
x_scale = priv->width / device_width;
y_scale = (x_scale * x_resolution) / y_resolution;
x_offset = 0;
y_offset = - (device_height * y_scale - priv->height) / 2;
}
else
{
/* window taller than device */
y_scale = priv->height / device_height;
x_scale = (y_scale * y_resolution) / x_resolution;
y_offset = 0;
x_offset = - (device_width * x_scale - priv->width) / 2;
}
}
for (i=0; i<gdkdev->info.num_axes; i++)
{
switch (gdkdev->info.axes[i].use)
{
case GDK_AXIS_X:
axis_out[i] = x_offset + x_scale * (axis_data[x_axis] -
gdkdev->axes[x_axis].min_value);
if (x_out)
*x_out = axis_out[i];
break;
case GDK_AXIS_Y:
axis_out[i] = y_offset + y_scale * (axis_data[y_axis] -
gdkdev->axes[y_axis].min_value);
if (y_out)
*y_out = axis_out[i];
break;
default:
axis_out[i] =
(device->axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
device->axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
(gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
break;
}
}
#endif
}
/* combine the state of the core device and the device state
* into one - for now we do this in a simple-minded manner -
* we just take the keyboard portion of the core device and
* the button portion (all of?) the device state.
* Any button remapping should go on here.
*/
static guint
gdk_input_translate_state (guint state, guint device_state)
{
return device_state | (state & 0xFF);
}
static 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)
{
GdkEventTranslatorIface *parent_iface;
GdkWindowObject *priv, *impl_window;
GdkInputWindow *input_window;
GdkDeviceXI *device_xi;
GdkDevice *device;
GdkWindow *window;
parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
if (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);
priv = (GdkWindowObject *) window;
if (!window)
return FALSE;
impl_window = (GdkWindowObject *) _gdk_window_get_impl_window (window);
input_window = impl_window->input_window;
if ((xevent->type == device_xi->button_press_type) ||
(xevent->type == device_xi->button_release_type))
{
XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *) xevent;
if (xdbe->type == device_xi->button_press_type)
{
event->button.type = GDK_BUTTON_PRESS;
#if 0
gdkdev->button_state |= 1 << xdbe->button;
#endif
}
else
{
event->button.type = GDK_BUTTON_RELEASE;
#if 0
gdkdev->button_state &= ~(1 << xdbe->button);
#endif
}
event->button.device = device;
event->button.window = window;
event->button.time = xdbe->time;
event->button.axes = g_new (gdouble, device->num_axes);
gdk_input_translate_coordinates (device, window, xdbe->axis_data,
event->button.axes,
&event->button.x, &event->button.y);
#if 0
event->button.x_root = event->button.x + priv->abs_x + input_window->root_x;
event->button.y_root = event->button.y + priv->abs_y + input_window->root_y;
#endif
event->button.state = gdk_input_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 0
if (xdke->keycode < gdkdev->min_keycode ||
xdke->keycode >= gdkdev->min_keycode + gdkdev->info.num_keys)
{
g_warning ("Invalid device key code received");
return FALSE;
}
event->key.keyval = device->keys[xdke->keycode - gdkdev->min_keycode].keyval;
#endif
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 = window;
event->key.time = xdke->time;
#if 0
event->key.state = gdk_input_translate_state (xdke->state, xdke->device_state)
| device->keys[xdke->keycode - device_xi->min_keycode].modifiers;
#endif
/* 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;
event->motion.axes = g_new (gdouble, device->num_axes);
gdk_input_translate_coordinates (device, window, xdme->axis_data,
event->motion.axes,
&event->motion.x, &event->motion.y);
#if 0
event->motion.x_root = event->motion.x + priv->abs_x + input_window->root_x;
event->motion.y_root = event->motion.y + priv->abs_y + input_window->root_y;
#endif
event->motion.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = xdme->time;
event->motion.state = gdk_input_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;
event->proximity.device = device;
event->proximity.type = (xevent->type == device_xi->proximity_in_type) ?
GDK_PROXIMITY_IN : GDK_PROXIMITY_OUT;
event->proximity.window = 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;
}
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;
}

View File

@@ -0,0 +1,53 @@
/* 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_MANAGER_XI_H__
#define __GDK_DEVICE_MANAGER_XI_H__
#include "gdkdevicemanager-core.h"
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE_MANAGER_XI (gdk_device_manager_xi_get_type ())
#define GDK_DEVICE_MANAGER_XI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_MANAGER_XI, GdkDeviceManagerXI))
#define GDK_DEVICE_MANAGER_XI_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_MANAGER_XI, GdkDeviceManagerXIClass))
#define GDK_IS_DEVICE_MANAGER_XI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_MANAGER_XI))
#define GDK_IS_DEVICE_MANAGER_XI_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_MANAGER_XI))
#define GDK_DEVICE_MANAGER_XI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_MANAGER_XI, GdkDeviceManagerXIClass))
typedef struct _GdkDeviceManagerXI GdkDeviceManagerXI;
typedef struct _GdkDeviceManagerXIClass GdkDeviceManagerXIClass;
struct _GdkDeviceManagerXI
{
GdkDeviceManagerCore parent_object;
GdkDevice *core_pointer;
GdkDevice *core_keyboard;
};
struct _GdkDeviceManagerXIClass
{
GdkDeviceManagerCoreClass parent_class;
};
GType gdk_device_manager_xi_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_DEVICE_MANAGER_XI_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

380
gdk/x11/gdkeventsource.c Normal file
View File

@@ -0,0 +1,380 @@
/* 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 "gdkeventsource.h"
#include "gdkinternals.h"
#include "gdkx.h"
#include "gdkalias.h"
static gboolean gdk_event_source_prepare (GSource *source,
gint *timeout);
static gboolean gdk_event_source_check (GSource *source);
static gboolean gdk_event_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data);
static void gdk_event_source_finalize (GSource *source);
struct _GdkEventSource
{
GSource source;
GdkDisplay *display;
GPollFD event_poll_fd;
GList *translators;
};
static GSourceFuncs event_funcs = {
gdk_event_source_prepare,
gdk_event_source_check,
gdk_event_source_dispatch,
gdk_event_source_finalize
};
static GList *event_sources = NULL;
static gint
gdk_event_apply_filters (XEvent *xevent,
GdkEvent *event,
GList *filters)
{
GList *tmp_list;
GdkFilterReturn result;
tmp_list = filters;
while (tmp_list)
{
GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
tmp_list = tmp_list->next;
result = filter->function (xevent, event, filter->data);
if (result != GDK_FILTER_CONTINUE)
return result;
}
return GDK_FILTER_CONTINUE;
}
static GdkWindow *
gdk_event_source_get_filter_window (GdkEventSource *event_source,
XEvent *xevent)
{
GdkWindow *window;
window = gdk_window_lookup_for_display (event_source->display,
xevent->xany.window);
if (window && !GDK_IS_WINDOW (window))
window = NULL;
return window;
}
static GdkEvent *
gdk_event_source_translate_event (GdkEventSource *event_source,
XEvent *xevent)
{
GdkEvent *event = gdk_event_new (GDK_NOTHING);
GList *list = event_source->translators;
GdkFilterReturn result;
GdkWindow *filter_window;
/* Run default filters */
if (_gdk_default_filters)
{
/* Apply global filters */
result = gdk_event_apply_filters (xevent, event,
_gdk_default_filters);
if (result == GDK_FILTER_REMOVE)
{
gdk_event_free (event);
return NULL;
}
else if (result == GDK_FILTER_TRANSLATE)
return event;
}
filter_window = gdk_event_source_get_filter_window (event_source, xevent);
if (filter_window)
{
/* Apply per-window filters */
GdkWindowObject *filter_private = (GdkWindowObject *) filter_window;
GdkFilterReturn result;
if (filter_private->filters)
{
g_object_ref (filter_window);
result = gdk_event_apply_filters (xevent, event,
filter_private->filters);
g_object_unref (filter_window);
if (result == GDK_FILTER_REMOVE)
{
gdk_event_free (event);
return NULL;
}
else if (result == GDK_FILTER_TRANSLATE)
return event;
}
}
gdk_event_free (event);
event = NULL;
while (list && !event)
{
GdkEventTranslator *translator = list->data;
list = list->next;
event = gdk_event_translator_translate (translator,
event_source->display,
xevent);
}
return event;
}
static gboolean
gdk_check_xpending (GdkDisplay *display)
{
return XPending (GDK_DISPLAY_XDISPLAY (display));
}
static gboolean
gdk_event_source_prepare (GSource *source,
gint *timeout)
{
GdkDisplay *display = ((GdkEventSource*) source)->display;
gboolean retval;
GDK_THREADS_ENTER ();
*timeout = -1;
retval = (_gdk_event_queue_find_first (display) != NULL ||
gdk_check_xpending (display));
GDK_THREADS_LEAVE ();
return retval;
}
static gboolean
gdk_event_source_check (GSource *source)
{
GdkEventSource *event_source = (GdkEventSource*) source;
gboolean retval;
GDK_THREADS_ENTER ();
if (event_source->event_poll_fd.revents & G_IO_IN)
retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
gdk_check_xpending (event_source->display));
else
retval = FALSE;
GDK_THREADS_LEAVE ();
return retval;
}
void
_gdk_events_queue (GdkDisplay *display)
{
GdkEvent *event;
XEvent xevent;
Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
GdkEventSource *event_source;
GdkDisplayX11 *display_x11;
display_x11 = GDK_DISPLAY_X11 (display);
event_source = (GdkEventSource *) display_x11->event_source;
while (!_gdk_event_queue_find_first(display) && XPending (xdisplay))
{
XNextEvent (xdisplay, &xevent);
switch (xevent.type)
{
case KeyPress:
case KeyRelease:
break;
default:
if (XFilterEvent (&xevent, None))
continue;
}
event = gdk_event_source_translate_event (event_source, &xevent);
if (event)
{
GList *node;
node = _gdk_event_queue_append (display, event);
_gdk_windowing_got_event (display, node, event, xevent.xany.serial);
}
}
}
static gboolean
gdk_event_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GdkDisplay *display = ((GdkEventSource*) source)->display;
GdkEvent *event;
GDK_THREADS_ENTER ();
event = gdk_display_get_event (display);
if (event)
{
if (_gdk_event_func)
(*_gdk_event_func) (event, _gdk_event_data);
gdk_event_free (event);
}
GDK_THREADS_LEAVE ();
return TRUE;
}
static void
gdk_event_source_finalize (GSource *source)
{
event_sources = g_list_remove (event_sources, source);
}
GSource *
gdk_event_source_new (GdkDisplay *display)
{
GSource *source;
GdkEventSource *event_source;
GdkDisplayX11 *display_x11;
int connection_number;
source = g_source_new (&event_funcs, sizeof (GdkEventSource));
event_source = (GdkEventSource *) source;
event_source->display = display;
display_x11 = GDK_DISPLAY_X11 (display);
connection_number = ConnectionNumber (display_x11->xdisplay);
event_source->event_poll_fd.fd = connection_number;
event_source->event_poll_fd.events = G_IO_IN;
g_source_add_poll (source, &event_source->event_poll_fd);
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
g_source_set_can_recurse (source, TRUE);
g_source_attach (source, NULL);
event_sources = g_list_prepend (event_sources, source);
return source;
}
void
gdk_event_source_add_translator (GdkEventSource *source,
GdkEventTranslator *translator)
{
g_return_if_fail (GDK_IS_EVENT_TRANSLATOR (translator));
source->translators = g_list_prepend (source->translators, translator);
}
void
gdk_event_source_select_events (GdkEventSource *source,
Window window,
GdkEventMask event_mask,
unsigned int extra_x_mask)
{
unsigned int xmask = extra_x_mask;
GList *list;
gint i;
list = source->translators;
while (list)
{
GdkEventTranslator *translator = list->data;
GdkEventMask translator_mask, mask;
translator_mask = gdk_event_translator_get_handled_events (translator);
mask = event_mask & translator_mask;
if (mask != 0)
{
gdk_event_translator_select_window_events (translator, window, mask);
event_mask &= ~(mask);
}
list = list->next;
}
for (i = 0; i < _gdk_nenvent_masks; i++)
{
if (event_mask & (1 << (i + 1)))
xmask |= _gdk_event_mask_table[i];
}
XSelectInput (GDK_DISPLAY_XDISPLAY (source->display), window, xmask);
}
/**
* gdk_events_pending:
*
* Checks if any events are ready to be processed for any display.
*
* Return value: %TRUE if any events are pending.
**/
gboolean
gdk_events_pending (void)
{
GList *tmp_list;
for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
{
GdkEventSource *tmp_source = tmp_list->data;
GdkDisplay *display = tmp_source->display;
if (_gdk_event_queue_find_first (display))
return TRUE;
}
for (tmp_list = event_sources; tmp_list; tmp_list = tmp_list->next)
{
GdkEventSource *tmp_source = tmp_list->data;
GdkDisplay *display = tmp_source->display;
if (gdk_check_xpending (display))
return TRUE;
}
return FALSE;
}
#define __GDK_EVENT_SOURCE_C__
#include "gdkaliasdef.c"

43
gdk/x11/gdkeventsource.h Normal file
View File

@@ -0,0 +1,43 @@
/* 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_EVENT_SOURCE_H__
#define __GDK_EVENT_SOURCE_H__
#include "gdkeventtranslator.h"
#include "gdkprivate-x11.h"
G_BEGIN_DECLS
typedef struct _GdkEventSource GdkEventSource;
GSource * gdk_event_source_new (GdkDisplay *display);
void gdk_event_source_add_translator (GdkEventSource *source,
GdkEventTranslator *translator);
void gdk_event_source_select_events (GdkEventSource *source,
Window window,
GdkEventMask event_mask,
unsigned int extra_x_mask);
G_END_DECLS
#endif /* __GDK_EVENT_SOURCE_H__ */

View File

@@ -0,0 +1,94 @@
/* 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 "gdkeventtranslator.h"
GType
gdk_event_translator_get_type (void)
{
static GType translator_type = 0;
if (G_UNLIKELY (!translator_type))
{
translator_type = g_type_register_static_simple (G_TYPE_INTERFACE,
g_intern_static_string ("GdkEventTranslator"),
sizeof (GdkEventTranslatorIface),
NULL, 0, NULL, 0);
g_type_interface_add_prerequisite (translator_type, G_TYPE_OBJECT);
}
return translator_type;
}
GdkEvent *
gdk_event_translator_translate (GdkEventTranslator *translator,
GdkDisplay *display,
XEvent *xevent)
{
GdkEventTranslatorIface *iface;
GdkEvent *event;
g_return_val_if_fail (GDK_IS_EVENT_TRANSLATOR (translator), NULL);
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
iface = GDK_EVENT_TRANSLATOR_GET_IFACE (translator);
if (!iface->translate_event)
return NULL;
event = gdk_event_new (GDK_NOTHING);
if ((iface->translate_event) (translator, display, event, xevent))
return event;
gdk_event_free (event);
return NULL;
}
GdkEventMask
gdk_event_translator_get_handled_events (GdkEventTranslator *translator)
{
GdkEventTranslatorIface *iface;
g_return_val_if_fail (GDK_IS_EVENT_TRANSLATOR (translator), 0);
iface = GDK_EVENT_TRANSLATOR_GET_IFACE (translator);
if (iface->get_handled_events)
return iface->get_handled_events (translator);
return 0;
}
void
gdk_event_translator_select_window_events (GdkEventTranslator *translator,
Window window,
GdkEventMask event_mask)
{
GdkEventTranslatorIface *iface;
g_return_if_fail (GDK_IS_EVENT_TRANSLATOR (translator));
iface = GDK_EVENT_TRANSLATOR_GET_IFACE (translator);
if (iface->select_window_events)
iface->select_window_events (translator, window, event_mask);
}

View File

@@ -0,0 +1,66 @@
/* 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_EVENT_TRANSLATOR_H__
#define __GDK_EVENT_TRANSLATOR_H__
#include <gdk/gdktypes.h>
#include <gdk/gdkdisplay.h>
#include "gdkprivate-x11.h"
G_BEGIN_DECLS
#define GDK_TYPE_EVENT_TRANSLATOR (gdk_event_translator_get_type ())
#define GDK_EVENT_TRANSLATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_EVENT_TRANSLATOR, GdkEventTranslator))
#define GDK_IS_EVENT_TRANSLATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_EVENT_TRANSLATOR))
#define GDK_EVENT_TRANSLATOR_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GDK_TYPE_EVENT_TRANSLATOR, GdkEventTranslatorIface))
typedef struct _GdkEventTranslatorIface GdkEventTranslatorIface;
typedef struct _GdkEventTranslator GdkEventTranslator; /* Dummy typedef */
struct _GdkEventTranslatorIface
{
GTypeInterface iface;
/* VMethods */
gboolean (* translate_event) (GdkEventTranslator *translator,
GdkDisplay *display,
GdkEvent *event,
XEvent *xevent);
GdkEventMask (* get_handled_events) (GdkEventTranslator *translator);
void (* select_window_events) (GdkEventTranslator *translator,
Window window,
GdkEventMask event_mask);
};
GType gdk_event_translator_get_type (void) G_GNUC_CONST;
GdkEvent * gdk_event_translator_translate (GdkEventTranslator *translator,
GdkDisplay *display,
XEvent *xevent);
GdkEventMask gdk_event_translator_get_handled_events (GdkEventTranslator *translator);
void gdk_event_translator_select_window_events (GdkEventTranslator *translator,
Window window,
GdkEventMask event_mask);
G_END_DECLS
#endif /* __GDK_EVENT_TRANSLATOR_H__ */

View File

@@ -29,17 +29,6 @@
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
void
_gdk_input_init (GdkDisplay *display)
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
_gdk_init_input_core (display);
display_x11->input_devices = g_list_append (NULL, display->core_pointer);
display->ignore_core_events = FALSE;
}
void
gdk_device_get_state (GdkDevice *device,
GdkWindow *window,
@@ -74,7 +63,7 @@ _gdk_device_get_history (GdkDevice *device,
void
_gdk_input_select_events (GdkWindow *impl_window,
GdkDevicePrivate *gdkdev)
GdkDevice *device)
{
}

View File

@@ -31,14 +31,17 @@
#include "gdk.h" /* For gdk_error_trap_push()/pop() */
#include "gdkdisplay-x11.h"
#include "gdkalias.h"
#include "gdkdevice-xi.h"
#include <string.h>
/* Forward declarations */
#if 0
static GdkDevicePrivate *gdk_input_device_new (GdkDisplay *display,
XDeviceInfo *device,
gint include_core);
static void gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
#endif
static void gdk_input_translate_coordinates (GdkDevice *device,
GdkWindow *window,
gint *axis_data,
gdouble *axis_out,
@@ -47,19 +50,22 @@ static void gdk_input_translate_coordinates (GdkDevicePrivate *gdkd
static guint gdk_input_translate_state (guint state,
guint device_state);
GdkDevicePrivate *
GdkDevice *
_gdk_input_find_device (GdkDisplay *display,
guint32 id)
{
GList *tmp_list = GDK_DISPLAY_X11 (display)->input_devices;
GdkDevicePrivate *gdkdev;
GdkDevice *device;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)(tmp_list->data);
if (gdkdev->deviceid == id)
return gdkdev;
device = tmp_list->data;
tmp_list = tmp_list->next;
if (GDK_DEVICE_XI (device)->device_id == id)
return device;
}
return NULL;
}
@@ -81,6 +87,7 @@ _gdk_input_get_root_relative_geometry (GdkWindow *window,
*y_ret = y;
}
#if 0
static GdkDevicePrivate *
gdk_input_device_new (GdkDisplay *display,
XDeviceInfo *device,
@@ -239,37 +246,40 @@ gdk_input_device_new (GdkDisplay *display,
return NULL;
}
#endif
void
_gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
_gdk_input_common_find_events (GdkDevice *device,
gint mask,
XEventClass *classes,
int *num_classes)
{
GdkDeviceXI *device_xi;
gint i;
XEventClass class;
device_xi = GDK_DEVICE_XI (device);
i = 0;
if (mask & GDK_BUTTON_PRESS_MASK)
{
DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
DeviceButtonPress (device_xi->xdevice, device_xi->button_press_type,
class);
if (class != 0)
classes[i++] = class;
DeviceButtonPressGrab (gdkdev->xdevice, 0, class);
DeviceButtonPressGrab (device_xi->xdevice, 0, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_BUTTON_RELEASE_MASK)
{
DeviceButtonRelease (gdkdev->xdevice, gdkdev->buttonrelease_type,
DeviceButtonRelease (device_xi->xdevice, device_xi->button_release_type,
class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_POINTER_MOTION_MASK)
{
DeviceMotionNotify (gdkdev->xdevice, gdkdev->motionnotify_type, class);
DeviceMotionNotify (device_xi->xdevice, device_xi->motion_notify_type, class);
if (class != 0)
classes[i++] = class;
}
@@ -279,29 +289,29 @@ _gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
GDK_POINTER_MOTION_HINT_MASK))
{
/* Make sure gdkdev->motionnotify_type is set */
DeviceMotionNotify (gdkdev->xdevice, gdkdev->motionnotify_type, class);
DeviceMotionNotify (device_xi->xdevice, device_xi->motion_notify_type, class);
}
if (mask & GDK_BUTTON1_MOTION_MASK)
{
DeviceButton1Motion (gdkdev->xdevice, 0, class);
DeviceButton1Motion (device_xi->xdevice, 0, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_BUTTON2_MOTION_MASK)
{
DeviceButton2Motion (gdkdev->xdevice, 0, class);
DeviceButton2Motion (device_xi->xdevice, 0, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_BUTTON3_MOTION_MASK)
{
DeviceButton3Motion (gdkdev->xdevice, 0, class);
DeviceButton3Motion (device_xi->xdevice, 0, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_BUTTON_MOTION_MASK)
{
DeviceButtonMotion (gdkdev->xdevice, 0, class);
DeviceButtonMotion (device_xi->xdevice, 0, class);
if (class != 0)
classes[i++] = class;
}
@@ -309,31 +319,31 @@ _gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
{
/* We'll get into trouble if the macros change, but at least we'll
know about it, and we avoid warnings now */
DevicePointerMotionHint (gdkdev->xdevice, 0, class);
DevicePointerMotionHint (device_xi->xdevice, 0, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_KEY_PRESS_MASK)
{
DeviceKeyPress (gdkdev->xdevice, gdkdev->keypress_type, class);
DeviceKeyPress (device_xi->xdevice, device_xi->key_press_type, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_KEY_RELEASE_MASK)
{
DeviceKeyRelease (gdkdev->xdevice, gdkdev->keyrelease_type, class);
DeviceKeyRelease (device_xi->xdevice, device_xi->key_release_type, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_PROXIMITY_IN_MASK)
{
ProximityIn (gdkdev->xdevice, gdkdev->proximityin_type, class);
ProximityIn (device_xi->xdevice, device_xi->proximity_in_type, class);
if (class != 0)
classes[i++] = class;
}
if (mask & GDK_PROXIMITY_OUT_MASK)
{
ProximityOut (gdkdev->xdevice, gdkdev->proximityout_type, class);
ProximityOut (device_xi->xdevice, device_xi->proximity_out_type, class);
if (class != 0)
classes[i++] = class;
}
@@ -343,7 +353,7 @@ _gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
void
_gdk_input_select_events (GdkWindow *impl_window,
GdkDevicePrivate *gdkdev)
GdkDevice *device)
{
XEventClass classes[GDK_MAX_DEVICE_CLASSES];
gint num_classes;
@@ -355,13 +365,13 @@ _gdk_input_select_events (GdkWindow *impl_window,
event_mask = 0;
iw = ((GdkWindowObject *)impl_window)->input_window;
if (gdkdev->info.mode != GDK_MODE_DISABLED &&
if (device->mode != GDK_MODE_DISABLED &&
iw != NULL)
{
for (l = iw->windows; l != NULL; l = l->next)
{
w = l->data;
if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK))
if (device->has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK))
event_mask |= w->extension_events;
}
}
@@ -370,7 +380,7 @@ _gdk_input_select_events (GdkWindow *impl_window,
if (event_mask)
event_mask |= GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
_gdk_input_common_find_events (gdkdev, event_mask,
_gdk_input_common_find_events (device, event_mask,
classes, &num_classes);
XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (impl_window),
GDK_WINDOW_XWINDOW (impl_window),
@@ -381,6 +391,7 @@ gint
_gdk_input_common_init (GdkDisplay *display,
gint include_core)
{
#if 0
XDeviceInfo *devices;
int num_devices, loop;
int ignore, event_base;
@@ -409,12 +420,13 @@ _gdk_input_common_init (GdkDisplay *display,
}
display_x11->input_devices = g_list_append (display_x11->input_devices, display->core_pointer);
#endif
return TRUE;
}
static void
gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
gdk_input_translate_coordinates (GdkDevice *device,
GdkWindow *window,
gint *axis_data,
gdouble *axis_out,
@@ -433,9 +445,9 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
priv = (GdkWindowObject *) window;
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
for (i=0; i<gdkdev->info.num_axes; i++)
for (i=0; i< device->num_axes; i++)
{
switch (gdkdev->info.axes[i].use)
switch (device->axes[i].use)
{
case GDK_AXIS_X:
x_axis = i;
@@ -448,6 +460,7 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
}
}
#if 0
device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
@@ -525,8 +538,11 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
break;
}
}
#endif
}
#if 0
/* combine the state of the core device and the device state
* into one - for now we do this in a simple-minded manner -
* we just take the keyboard portion of the core device and
@@ -544,21 +560,23 @@ gboolean
_gdk_input_common_other_event (GdkEvent *event,
XEvent *xevent,
GdkWindow *window,
GdkDevicePrivate *gdkdev)
GdkDevice *device)
{
GdkWindowObject *priv, *impl_window;
GdkInputWindow *input_window;
GdkDeviceXI *device_xi;
device_xi = GDK_DEVICE_XI (device);
priv = (GdkWindowObject *) window;
impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
input_window = impl_window->input_window;
if ((xevent->type == gdkdev->buttonpress_type) ||
(xevent->type == gdkdev->buttonrelease_type))
if ((xevent->type == device_xi->button_press_type) ||
(xevent->type == device_xi->button_release_type))
{
XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
if (xdbe->type == gdkdev->buttonpress_type)
if (xdbe->type == device_xi->button_press_type)
{
event->button.type = GDK_BUTTON_PRESS;
gdkdev->button_state |= 1 << xdbe->button;
@@ -728,6 +746,21 @@ _gdk_input_common_other_event (GdkEvent *event,
return FALSE; /* wasn't one of our event types */
}
#endif
static GdkTimeCoord **
_gdk_device_allocate_history (GdkDevice *device,
gint 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;
}
gboolean
_gdk_device_get_history (GdkDevice *device,
@@ -740,17 +773,17 @@ _gdk_device_get_history (GdkDevice *device,
GdkTimeCoord **coords;
XDeviceTimeCoord *device_coords;
GdkWindow *impl_window;
GdkDevicePrivate *gdkdev;
GdkDeviceXI *device_xi;
gint mode_return;
gint axis_count_return;
gint i;
gdkdev = (GdkDevicePrivate *)device;
device_xi = (GdkDeviceXI *) device;
impl_window = _gdk_window_get_impl_window (window);
device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window),
gdkdev->xdevice,
device_xi->xdevice,
start, stop,
n_events, &mode_return,
&axis_count_return);
@@ -763,7 +796,7 @@ _gdk_device_get_history (GdkDevice *device,
{
coords[i]->time = device_coords[i].time;
gdk_input_translate_coordinates (gdkdev, window,
gdk_input_translate_coordinates (device, window,
device_coords[i].data,
coords[i]->axes, NULL, NULL);
}
@@ -803,17 +836,17 @@ gdk_device_get_state (GdkDevice *device,
}
else
{
GdkDevicePrivate *gdkdev;
GdkDeviceXI *device_xi;
XDeviceState *state;
XInputClass *input_class;
if (mask)
gdk_window_get_pointer (window, NULL, NULL, mask);
gdkdev = (GdkDevicePrivate *)device;
device_xi = (GdkDeviceXI *) device;
state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window),
gdkdev->xdevice);
device_xi->xdevice);
input_class = state->data;
for (i=0; i<state->num_classes; i++)
{
@@ -821,7 +854,7 @@ gdk_device_get_state (GdkDevice *device,
{
case ValuatorClass:
if (axes)
gdk_input_translate_coordinates (gdkdev, window,
gdk_input_translate_coordinates (device, window,
((XValuatorState *)input_class)->valuators,
axes, NULL, NULL);
break;

View File

@@ -21,6 +21,7 @@
#include "gdkinputprivate.h"
#include "gdkdisplay-x11.h"
#include "gdkalias.h"
#include "gdkdevice-xi.h"
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
@@ -33,28 +34,17 @@
static void gdk_input_check_proximity (GdkDisplay *display);
void
_gdk_input_init(GdkDisplay *display)
{
_gdk_init_input_core (display);
display->ignore_core_events = FALSE;
_gdk_input_common_init (display, FALSE);
}
gboolean
gdk_device_set_mode (GdkDevice *device,
GdkInputMode mode)
{
GList *tmp_list;
GdkDevicePrivate *gdkdev;
GdkInputWindow *input_window;
GdkDisplayX11 *display_impl;
if (GDK_IS_CORE (device))
return FALSE;
gdkdev = (GdkDevicePrivate *)device;
if (device->mode == mode)
return TRUE;
@@ -65,11 +55,11 @@ gdk_device_set_mode (GdkDevice *device,
else if (mode == GDK_MODE_SCREEN)
device->has_cursor = TRUE;
display_impl = GDK_DISPLAY_X11 (gdkdev->display);
display_impl = GDK_DISPLAY_X11 (gdk_device_get_display (device));
for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
{
input_window = (GdkInputWindow *)tmp_list->data;
_gdk_input_select_events (input_window->impl_window, gdkdev);
_gdk_input_select_events (input_window->impl_window, device);
}
return TRUE;
@@ -84,34 +74,40 @@ gdk_input_check_proximity (GdkDisplay *display)
while (tmp_list && !new_proximity)
{
GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
GdkDevice *device = tmp_list->data;
if (gdkdev->info.mode != GDK_MODE_DISABLED
&& !GDK_IS_CORE (gdkdev)
&& gdkdev->xdevice)
if (device->mode != GDK_MODE_DISABLED &&
!GDK_IS_CORE (device) &&
GDK_IS_DEVICE_XI (device))
{
XDeviceState *state = XQueryDeviceState(display_impl->xdisplay,
gdkdev->xdevice);
XInputClass *xic;
int i;
GdkDeviceXI *device_xi = GDK_DEVICE_XI (device);
xic = state->data;
for (i=0; i<state->num_classes; i++)
{
if (xic->class == ValuatorClass)
{
XValuatorState *xvs = (XValuatorState *)xic;
if ((xvs->mode & ProximityState) == InProximity)
{
new_proximity = TRUE;
}
break;
}
xic = (XInputClass *)((char *)xic + xic->length);
}
if (device_xi->xdevice)
{
XDeviceState *state = XQueryDeviceState(display_impl->xdisplay,
device_xi->xdevice);
XInputClass *xic;
int i;
XFreeDeviceState (state);
xic = state->data;
for (i = 0; i < state->num_classes; i++)
{
if (xic->class == ValuatorClass)
{
XValuatorState *xvs = (XValuatorState *)xic;
if ((xvs->mode & ProximityState) == InProximity)
{
new_proximity = TRUE;
}
break;
}
xic = (XInputClass *) ((char *) xic + xic->length);
}
XFreeDeviceState (state);
}
}
tmp_list = tmp_list->next;
}
@@ -140,7 +136,6 @@ _gdk_input_crossing_event (GdkWindow *window,
gboolean enter)
{
GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
GdkWindowObject *priv = (GdkWindowObject *)window;
GdkInputWindow *input_window;
gint root_x, root_y;
@@ -161,12 +156,13 @@ _gdk_input_crossing_event (GdkWindow *window,
display->ignore_core_events = FALSE;
}
#if 0
static GdkEventType
get_input_event_type (GdkDevicePrivate *gdkdev,
XEvent *xevent,
get_input_event_type (GdkDeviceXI *device,
XEvent *xevent,
int *core_x, int *core_y)
{
if (xevent->type == gdkdev->buttonpress_type)
if (xevent->type == device->button_press_type)
{
XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
*core_x = xie->x;
@@ -174,7 +170,7 @@ get_input_event_type (GdkDevicePrivate *gdkdev,
return GDK_BUTTON_PRESS;
}
if (xevent->type == gdkdev->buttonrelease_type)
if (xevent->type == device->button_release_type)
{
XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
*core_x = xie->x;
@@ -182,7 +178,7 @@ get_input_event_type (GdkDevicePrivate *gdkdev,
return GDK_BUTTON_RELEASE;
}
if (xevent->type == gdkdev->keypress_type)
if (xevent->type == device->key_press_type)
{
XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
*core_x = xie->x;
@@ -190,7 +186,7 @@ get_input_event_type (GdkDevicePrivate *gdkdev,
return GDK_KEY_PRESS;
}
if (xevent->type == gdkdev->keyrelease_type)
if (xevent->type == device->key_release_type)
{
XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
*core_x = xie->x;
@@ -198,7 +194,7 @@ get_input_event_type (GdkDevicePrivate *gdkdev,
return GDK_KEY_RELEASE;
}
if (xevent->type == gdkdev->motionnotify_type)
if (xevent->type == device->motion_notify_type)
{
XDeviceMotionEvent *xie = (XDeviceMotionEvent *)(xevent);
*core_x = xie->x;
@@ -206,7 +202,7 @@ get_input_event_type (GdkDevicePrivate *gdkdev,
return GDK_MOTION_NOTIFY;
}
if (xevent->type == gdkdev->proximityin_type)
if (xevent->type == device->proximity_in_type)
{
XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
*core_x = xie->x;
@@ -214,7 +210,7 @@ get_input_event_type (GdkDevicePrivate *gdkdev,
return GDK_PROXIMITY_IN;
}
if (xevent->type == gdkdev->proximityout_type)
if (xevent->type == device->proximity_out_type)
{
XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
*core_x = xie->x;
@@ -227,7 +223,6 @@ get_input_event_type (GdkDevicePrivate *gdkdev,
return GDK_NOTHING;
}
gboolean
_gdk_input_other_event (GdkEvent *event,
XEvent *xevent,
@@ -252,7 +247,7 @@ _gdk_input_other_event (GdkEvent *event,
if (!gdkdev)
return FALSE; /* we don't handle it - not an XInput event */
event_type = get_input_event_type (gdkdev, xevent, &x, &y);
event_type = get_input_event_type (device, xevent, &x, &y);
if (event_type == GDK_NOTHING)
return FALSE;
@@ -294,6 +289,8 @@ _gdk_input_other_event (GdkEvent *event,
return return_val;
}
#endif
gint
_gdk_input_grab_pointer (GdkWindow *window,
GdkWindow *native_window, /* This is the toplevel */
@@ -305,7 +302,7 @@ _gdk_input_grab_pointer (GdkWindow *window,
GdkInputWindow *input_window;
GdkWindowObject *priv, *impl_window;
gboolean need_ungrab;
GdkDevicePrivate *gdkdev;
GdkDeviceXI *device;
GList *tmp_list;
XEventClass event_classes[GDK_MAX_DEVICE_CLASSES];
gint num_classes;
@@ -339,17 +336,18 @@ _gdk_input_grab_pointer (GdkWindow *window,
tmp_list = display_impl->input_devices;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)tmp_list->data;
if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
device = tmp_list->data;
if (!GDK_IS_CORE (GDK_DEVICE (device)) && device->xdevice)
{
_gdk_input_common_find_events (gdkdev, event_mask,
_gdk_input_common_find_events (GDK_DEVICE (device), event_mask,
event_classes, &num_classes);
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
result = GrabSuccess;
else
#endif
result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice,
result = XGrabDevice (display_impl->xdisplay, device->xdevice,
GDK_WINDOW_XWINDOW (native_window),
owner_events, num_classes, event_classes,
GrabModeAsync, GrabModeAsync, time);
@@ -367,12 +365,13 @@ _gdk_input_grab_pointer (GdkWindow *window,
tmp_list = display_impl->input_devices;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)tmp_list->data;
if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice &&
((gdkdev->button_state != 0) || need_ungrab))
device = tmp_list->data;
if (!GDK_IS_CORE (GDK_DEVICE (device)) && device->xdevice &&
((device->button_state != 0) || need_ungrab))
{
XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time);
gdkdev->button_state = 0;
XUngrabDevice (display_impl->xdisplay, device->xdevice, time);
device->button_state = 0;
}
tmp_list = tmp_list->next;
@@ -387,7 +386,7 @@ _gdk_input_ungrab_pointer (GdkDisplay *display,
guint32 time)
{
GdkInputWindow *input_window = NULL; /* Quiet GCC */
GdkDevicePrivate *gdkdev;
GdkDeviceXI *device;
GList *tmp_list;
GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
@@ -407,9 +406,10 @@ _gdk_input_ungrab_pointer (GdkDisplay *display,
tmp_list = display_impl->input_devices;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)tmp_list->data;
if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
XUngrabDevice( display_impl->xdisplay, gdkdev->xdevice, time);
device = tmp_list->data;
if (!GDK_IS_CORE (GDK_DEVICE (device)) && device->xdevice)
XUngrabDevice (display_impl->xdisplay, device->xdevice, time);
tmp_list = tmp_list->next;
}

View File

@@ -38,9 +38,7 @@
#include <X11/extensions/XInput.h>
#endif
typedef struct _GdkAxisInfo GdkAxisInfo;
typedef struct _GdkDevicePrivate GdkDevicePrivate;
/* information about a device axis */
struct _GdkAxisInfo
@@ -61,46 +59,6 @@ struct _GdkAxisInfo
#define GDK_INPUT_NUM_EVENTC 6
struct _GdkDevicePrivate
{
GdkDevice info;
guint32 deviceid;
GdkDisplay *display;
#ifndef XINPUT_NONE
/* information about the axes */
GdkAxisInfo *axes;
/* Information about XInput device */
XDevice *xdevice;
/* minimum key code for device */
gint min_keycode;
int buttonpress_type, buttonrelease_type, keypress_type,
keyrelease_type, motionnotify_type, proximityin_type,
proximityout_type, changenotify_type;
/* true if we need to select a different set of events, but
can't because this is the core pointer */
gint needs_update;
/* Mask of buttons (used for button grabs) */
gint button_state;
/* true if we've claimed the device as active. (used only for XINPUT_GXI) */
gint claimed;
#endif /* !XINPUT_NONE */
};
struct _GdkDeviceClass
{
GObjectClass parent_class;
};
/* Addition used for extension_events mask */
#define GDK_ALL_DEVICES_MASK (1<<30)
@@ -122,14 +80,12 @@ struct _GdkInputWindow
/* Global data */
#define GDK_IS_CORE(d) (((GdkDevice *)(d)) == ((GdkDevicePrivate *)(d))->display->core_pointer)
#define GDK_IS_CORE(d) (((GdkDevice *)(d)) == gdk_device_get_display (d)->core_pointer)
/* Function declarations */
GdkInputWindow *_gdk_input_window_find (GdkWindow *window);
void _gdk_input_window_destroy (GdkWindow *window);
GdkTimeCoord ** _gdk_device_allocate_history (GdkDevice *device,
gint n_events);
void _gdk_init_input_core (GdkDisplay *display);
/* The following functions are provided by each implementation
@@ -163,21 +119,23 @@ gboolean _gdk_device_get_history (GdkDevice *device,
gint _gdk_input_common_init (GdkDisplay *display,
gint include_core);
GdkDevicePrivate * _gdk_input_find_device (GdkDisplay *display,
GdkDevice * _gdk_input_find_device (GdkDisplay *display,
guint32 id);
void _gdk_input_get_root_relative_geometry(GdkWindow *window,
int *x_ret,
int *y_ret);
void _gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
void _gdk_input_common_find_events (GdkDevice *device,
gint mask,
XEventClass *classes,
int *num_classes);
void _gdk_input_select_events (GdkWindow *impl_window,
GdkDevicePrivate *gdkdev);
GdkDevice *device);
#if 0
gint _gdk_input_common_other_event (GdkEvent *event,
XEvent *xevent,
GdkWindow *window,
GdkDevicePrivate *gdkdev);
GdkDevice *device);
#endif
#endif /* !XINPUT_NONE */

View File

@@ -49,7 +49,6 @@
#include "gdkinternals.h"
#include "gdkintl.h"
#include "gdkregion-generic.h"
#include "gdkinputprivate.h"
#include "gdkalias.h"
typedef struct _GdkPredicate GdkPredicate;
@@ -198,12 +197,16 @@ _gdk_windowing_pointer_grab (GdkWindow *window,
*/
xevent_mask &= ~PointerMotionHintMask;
#if 0
return_val = _gdk_input_grab_pointer (window,
native,
owner_events,
event_mask,
confine_to,
time);
#else
return_val = GrabSuccess;
#endif
if (return_val == GrabSuccess ||
G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
@@ -734,5 +737,16 @@ gdk_x11_get_default_xdisplay (void)
return GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
}
void
_gdk_windowing_event_data_copy (const GdkEvent *src,
GdkEvent *dst)
{
}
void
_gdk_windowing_event_data_free (GdkEvent *event)
{
}
#define __GDK_MAIN_X11_C__
#include "gdkaliasdef.c"

View File

@@ -173,8 +173,7 @@ void _gdk_x11_precache_atoms (GdkDisplay *display,
const gchar * const *atom_names,
gint n_atoms);
void _gdk_x11_events_init_screen (GdkScreen *screen);
void _gdk_x11_events_uninit_screen (GdkScreen *screen);
void _gdk_screen_x11_events_init (GdkScreen *screen);
void _gdk_events_init (GdkDisplay *display);
void _gdk_events_uninit (GdkDisplay *display);
@@ -182,7 +181,6 @@ void _gdk_windowing_window_init (GdkScreen *screen);
void _gdk_visual_init (GdkScreen *screen);
void _gdk_dnd_init (GdkDisplay *display);
void _gdk_windowing_image_init (GdkDisplay *display);
void _gdk_input_init (GdkDisplay *display);
PangoRenderer *_gdk_x11_renderer_get (GdkDrawable *drawable,
GdkGC *gc);

View File

@@ -51,6 +51,8 @@
#include <X11/extensions/Xfixes.h>
#endif
#include "gdksettings.c"
static void gdk_screen_x11_dispose (GObject *object);
static void gdk_screen_x11_finalize (GObject *object);
static void init_randr_support (GdkScreen *screen);
@@ -66,6 +68,14 @@ static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GdkScreenX11, _gdk_screen_x11, GDK_TYPE_SCREEN)
typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
struct _NetWmSupportedAtoms
{
Atom *atoms;
gulong n_atoms;
};
struct _GdkX11Monitor
{
GdkRectangle geometry;
@@ -272,12 +282,24 @@ gdk_screen_set_default_colormap (GdkScreen *screen,
g_object_unref (old_colormap);
}
static void
_gdk_screen_x11_events_uninit (GdkScreen *screen)
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
if (screen_x11->xsettings_client)
{
xsettings_client_destroy (screen_x11->xsettings_client);
screen_x11->xsettings_client = NULL;
}
}
static void
gdk_screen_x11_dispose (GObject *object)
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
_gdk_x11_events_uninit_screen (GDK_SCREEN (object));
_gdk_screen_x11_events_uninit (GDK_SCREEN (object));
if (screen_x11->default_colormap)
{
@@ -1360,5 +1382,637 @@ gdk_screen_get_window_stack (GdkScreen *screen)
return ret;
}
/* Sends a ClientMessage to all toplevel client windows */
static gboolean
gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
XEvent *xev,
guint32 xid,
guint level)
{
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char *data;
Window *ret_children, ret_root, ret_parent;
unsigned int ret_nchildren;
gboolean send = FALSE;
gboolean found = FALSE;
gboolean result = FALSE;
int i;
gdk_error_trap_push ();
if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid,
gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
0, 0, False, AnyPropertyType,
&type, &format, &nitems, &after, &data) != Success)
goto out;
if (type)
{
send = TRUE;
XFree (data);
}
else
{
/* OK, we're all set, now let's find some windows to send this to */
if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xid,
&ret_root, &ret_parent,
&ret_children, &ret_nchildren))
goto out;
for(i = 0; i < ret_nchildren; i++)
if (gdk_event_send_client_message_to_all_recurse (display, xev, ret_children[i], level + 1))
found = TRUE;
XFree (ret_children);
}
if (send || (!found && (level == 1)))
{
xev->xclient.window = xid;
_gdk_send_xevent (display, xid, False, NoEventMask, xev);
}
result = send || found;
out:
gdk_error_trap_pop ();
return result;
}
/**
* gdk_screen_broadcast_client_message:
* @screen: the #GdkScreen where the event will be broadcasted.
* @event: the #GdkEvent.
*
* On X11, sends an X ClientMessage event to all toplevel windows on
* @screen.
*
* Toplevel windows are determined by checking for the WM_STATE property,
* as described in the Inter-Client Communication Conventions Manual (ICCCM).
* If no windows are found with the WM_STATE property set, the message is
* sent to all children of the root window.
*
* On Windows, broadcasts a message registered with the name
* GDK_WIN32_CLIENT_MESSAGE to all top-level windows. The amount of
* data is limited to one long, i.e. four bytes.
*
* Since: 2.2
*/
void
gdk_screen_broadcast_client_message (GdkScreen *screen,
GdkEvent *event)
{
XEvent sev;
GdkWindow *root_window;
g_return_if_fail (event != NULL);
root_window = gdk_screen_get_root_window (screen);
/* Set up our event to send, with the exception of its target window */
sev.xclient.type = ClientMessage;
sev.xclient.display = GDK_WINDOW_XDISPLAY (root_window);
sev.xclient.format = event->client.data_format;
memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
sev.xclient.message_type =
gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (root_window),
event->client.message_type);
gdk_event_send_client_message_to_all_recurse (gdk_screen_get_display (screen),
&sev,
GDK_WINDOW_XID (root_window),
0);
}
static gboolean
check_transform (const gchar *xsettings_name,
GType src_type,
GType dest_type)
{
if (!g_value_type_transformable (src_type, dest_type))
{
g_warning ("Cannot transform xsetting %s of type %s to type %s\n",
xsettings_name,
g_type_name (src_type),
g_type_name (dest_type));
return FALSE;
}
else
return TRUE;
}
/**
* gdk_screen_get_setting:
* @screen: the #GdkScreen where the setting is located
* @name: the name of the setting
* @value: location to store the value of the setting
*
* Retrieves a desktop-wide setting such as double-click time
* for the #GdkScreen @screen.
*
* FIXME needs a list of valid settings here, or a link to
* more information.
*
* Returns: %TRUE if the setting existed and a value was stored
* in @value, %FALSE otherwise.
*
* Since: 2.2
**/
gboolean
gdk_screen_get_setting (GdkScreen *screen,
const gchar *name,
GValue *value)
{
const char *xsettings_name = NULL;
XSettingsResult result;
XSettingsSetting *setting = NULL;
GdkScreenX11 *screen_x11;
gboolean success = FALSE;
gint i;
GValue tmp_val = { 0, };
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
screen_x11 = GDK_SCREEN_X11 (screen);
for (i = 0; i < GDK_SETTINGS_N_ELEMENTS(); i++)
if (strcmp (GDK_SETTINGS_GDK_NAME (i), name) == 0)
{
xsettings_name = GDK_SETTINGS_X_NAME (i);
break;
}
if (!xsettings_name)
goto out;
result = xsettings_client_get_setting (screen_x11->xsettings_client,
xsettings_name, &setting);
if (result != XSETTINGS_SUCCESS)
goto out;
switch (setting->type)
{
case XSETTINGS_TYPE_INT:
if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
{
g_value_init (&tmp_val, G_TYPE_INT);
g_value_set_int (&tmp_val, setting->data.v_int);
g_value_transform (&tmp_val, value);
success = TRUE;
}
break;
case XSETTINGS_TYPE_STRING:
if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
{
g_value_init (&tmp_val, G_TYPE_STRING);
g_value_set_string (&tmp_val, setting->data.v_string);
g_value_transform (&tmp_val, value);
success = TRUE;
}
break;
case XSETTINGS_TYPE_COLOR:
if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
{
GdkColor color;
g_value_init (&tmp_val, GDK_TYPE_COLOR);
color.pixel = 0;
color.red = setting->data.v_color.red;
color.green = setting->data.v_color.green;
color.blue = setting->data.v_color.blue;
g_value_set_boxed (&tmp_val, &color);
g_value_transform (&tmp_val, value);
success = TRUE;
}
break;
}
g_value_unset (&tmp_val);
out:
if (setting)
xsettings_setting_free (setting);
if (success)
return TRUE;
else
return _gdk_x11_get_xft_setting (screen, name, value);
}
static void
cleanup_atoms(gpointer data)
{
NetWmSupportedAtoms *supported_atoms = data;
if (supported_atoms->atoms)
XFree (supported_atoms->atoms);
g_free (supported_atoms);
}
static void
fetch_net_wm_check_window (GdkScreen *screen)
{
GdkScreenX11 *screen_x11;
GdkDisplay *display;
Atom type;
gint format;
gulong n_items;
gulong bytes_after;
guchar *data;
Window *xwindow;
GTimeVal tv;
gint error;
screen_x11 = GDK_SCREEN_X11 (screen);
display = screen_x11->display;
g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client);
g_get_current_time (&tv);
if (ABS (tv.tv_sec - screen_x11->last_wmspec_check_time) < 15)
return; /* we've checked recently */
screen_x11->last_wmspec_check_time = tv.tv_sec;
data = NULL;
XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
0, G_MAXLONG, False, XA_WINDOW, &type, &format,
&n_items, &bytes_after, &data);
if (type != XA_WINDOW)
{
if (data)
XFree (data);
return;
}
xwindow = (Window *)data;
if (screen_x11->wmspec_check_window == *xwindow)
{
XFree (xwindow);
return;
}
gdk_error_trap_push ();
/* Find out if this WM goes away, so we can reset everything. */
XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
gdk_display_sync (display);
error = gdk_error_trap_pop ();
if (!error)
{
screen_x11->wmspec_check_window = *xwindow;
screen_x11->need_refetch_net_supported = TRUE;
screen_x11->need_refetch_wm_name = TRUE;
/* Careful, reentrancy */
_gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
}
else if (error == BadWindow)
{
/* Leftover property, try again immediately, new wm may be starting up */
screen_x11->last_wmspec_check_time = 0;
}
XFree (xwindow);
}
/**
* gdk_x11_screen_supports_net_wm_hint:
* @screen: the relevant #GdkScreen.
* @property: a property atom.
*
* This function is specific to the X11 backend of GDK, and indicates
* whether the window manager supports a certain hint from the
* Extended Window Manager Hints Specification. You can find this
* specification on
* <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
*
* When using this function, keep in mind that the window manager
* can change over time; so you shouldn't use this function in
* a way that impacts persistent application state. A common bug
* is that your application can start up before the window manager
* does when the user logs in, and before the window manager starts
* gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
* You can monitor the window_manager_changed signal on #GdkScreen to detect
* a window manager change.
*
* Return value: %TRUE if the window manager supports @property
*
* Since: 2.2
**/
gboolean
gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
GdkAtom property)
{
gulong i;
GdkScreenX11 *screen_x11;
NetWmSupportedAtoms *supported_atoms;
GdkDisplay *display;
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
screen_x11 = GDK_SCREEN_X11 (screen);
display = screen_x11->display;
if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
return FALSE;
supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
if (!supported_atoms)
{
supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
g_object_set_data_full (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms, cleanup_atoms);
}
fetch_net_wm_check_window (screen);
if (screen_x11->wmspec_check_window == None)
return FALSE;
if (screen_x11->need_refetch_net_supported)
{
/* WM has changed since we last got the supported list,
* refetch it.
*/
Atom type;
gint format;
gulong bytes_after;
screen_x11->need_refetch_net_supported = FALSE;
if (supported_atoms->atoms)
XFree (supported_atoms->atoms);
supported_atoms->atoms = NULL;
supported_atoms->n_atoms = 0;
XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
0, G_MAXLONG, False, XA_ATOM, &type, &format,
&supported_atoms->n_atoms, &bytes_after,
(guchar **)&supported_atoms->atoms);
if (type != XA_ATOM)
return FALSE;
}
if (supported_atoms->atoms == NULL)
return FALSE;
i = 0;
while (i < supported_atoms->n_atoms)
{
if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
return TRUE;
++i;
}
return FALSE;
}
/**
* gdk_net_wm_supports:
* @property: a property atom.
*
* This function is specific to the X11 backend of GDK, and indicates
* whether the window manager for the default screen supports a certain
* hint from the Extended Window Manager Hints Specification. See
* gdk_x11_screen_supports_net_wm_hint() for complete details.
*
* Return value: %TRUE if the window manager supports @property
**/
gboolean
gdk_net_wm_supports (GdkAtom property)
{
return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
}
static void
refcounted_grab_server (Display *xdisplay)
{
GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
gdk_x11_display_grab (display);
}
static void
refcounted_ungrab_server (Display *xdisplay)
{
GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
gdk_x11_display_ungrab (display);
}
static GdkFilterReturn
gdk_xsettings_client_event_filter (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
GdkScreenX11 *screen = data;
if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
}
static Bool
gdk_xsettings_watch_cb (Window window,
Bool is_start,
long mask,
void *cb_data)
{
GdkWindow *gdkwin;
GdkScreen *screen = cb_data;
gdkwin = gdk_window_lookup_for_display (gdk_screen_get_display (screen), window);
if (is_start)
{
if (gdkwin)
g_object_ref (gdkwin);
else
{
gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
/* gdk_window_foreign_new_for_display() can fail and return NULL if the
* window has already been destroyed.
*/
if (!gdkwin)
return False;
}
gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
}
else
{
if (!gdkwin)
{
/* gdkwin should not be NULL here, since if starting the watch succeeded
* we have a reference on the window. It might mean that the caller didn't
* remove the watch when it got a DestroyNotify event. Or maybe the
* caller ignored the return value when starting the watch failed.
*/
g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch");
return False;
}
gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
g_object_unref (gdkwin);
}
return True;
}
static void
gdk_xsettings_notify_cb (const char *name,
XSettingsAction action,
XSettingsSetting *setting,
void *data)
{
GdkEvent new_event;
GdkScreen *screen = data;
GdkScreenX11 *screen_x11 = data;
int i;
if (screen_x11->xsettings_in_init)
return;
new_event.type = GDK_SETTING;
new_event.setting.window = gdk_screen_get_root_window (screen);
new_event.setting.send_event = FALSE;
new_event.setting.name = NULL;
for (i = 0; i < GDK_SETTINGS_N_ELEMENTS() ; i++)
if (strcmp (GDK_SETTINGS_X_NAME (i), name) == 0)
{
new_event.setting.name = (char*) GDK_SETTINGS_GDK_NAME (i);
break;
}
if (!new_event.setting.name)
return;
switch (action)
{
case XSETTINGS_ACTION_NEW:
new_event.setting.action = GDK_SETTING_ACTION_NEW;
break;
case XSETTINGS_ACTION_CHANGED:
new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
break;
case XSETTINGS_ACTION_DELETED:
new_event.setting.action = GDK_SETTING_ACTION_DELETED;
break;
}
gdk_event_put (&new_event);
}
void
_gdk_screen_x11_events_init (GdkScreen *screen)
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
/* Keep a flag to avoid extra notifies that we don't need
*/
screen_x11->xsettings_in_init = TRUE;
screen_x11->xsettings_client = xsettings_client_new_with_grab_funcs (screen_x11->xdisplay,
screen_x11->screen_num,
gdk_xsettings_notify_cb,
gdk_xsettings_watch_cb,
screen,
refcounted_grab_server,
refcounted_ungrab_server);
screen_x11->xsettings_in_init = FALSE;
}
/**
* gdk_x11_screen_get_window_manager_name:
* @screen: a #GdkScreen
*
* Returns the name of the window manager for @screen.
*
* Return value: the name of the window manager screen @screen, or
* "unknown" if the window manager is unknown. The string is owned by GDK
* and should not be freed.
*
* Since: 2.2
**/
const char*
gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
{
GdkScreenX11 *screen_x11;
screen_x11 = GDK_SCREEN_X11 (screen);
if (!G_LIKELY (GDK_DISPLAY_X11 (screen_x11->display)->trusted_client))
return screen_x11->window_manager_name;
fetch_net_wm_check_window (screen);
if (screen_x11->need_refetch_wm_name)
{
/* Get the name of the window manager */
screen_x11->need_refetch_wm_name = FALSE;
g_free (screen_x11->window_manager_name);
screen_x11->window_manager_name = g_strdup ("unknown");
if (screen_x11->wmspec_check_window != None)
{
Atom type;
gint format;
gulong n_items;
gulong bytes_after;
gchar *name;
name = NULL;
gdk_error_trap_push ();
XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
screen_x11->wmspec_check_window,
gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
"_NET_WM_NAME"),
0, G_MAXLONG, False,
gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
"UTF8_STRING"),
&type, &format,
&n_items, &bytes_after,
(guchar **)&name);
gdk_display_sync (screen_x11->display);
gdk_error_trap_pop ();
if (name != NULL)
{
g_free (screen_x11->window_manager_name);
screen_x11->window_manager_name = g_strdup (name);
XFree (name);
}
}
}
return GDK_SCREEN_X11 (screen)->window_manager_name;
}
#define __GDK_SCREEN_X11_C__
#include "gdkaliasdef.c"

View File

@@ -39,17 +39,19 @@
#include <unistd.h>
#include "gdk.h"
#include "gdkx.h"
#include "gdkwindow.h"
#include "gdkwindowimpl.h"
#include "gdkasync.h"
#include "gdkinputprivate.h"
#include "gdkdisplay-x11.h"
#include "gdkprivate-x11.h"
#include "gdkregion.h"
#include "gdkinternals.h"
#include "MwmUtil.h"
#include "gdkwindow-x11.h"
#include "gdkdeviceprivate.h"
#include "gdkeventsource.h"
#include "gdkalias.h"
#include <stdlib.h>
@@ -513,18 +515,31 @@ check_leader_window_title (GdkDisplay *display)
}
static Window
create_focus_window (Display *xdisplay,
XID parent)
create_focus_window (GdkDisplay *display,
XID parent)
{
Window focus_window = XCreateSimpleWindow (xdisplay, parent,
-1, -1, 1, 1, 0,
0, 0);
GdkDisplayX11 *display_x11;
GdkEventMask event_mask;
Display *xdisplay;
Window focus_window;
xdisplay = GDK_DISPLAY_XDISPLAY (display);
display_x11 = GDK_DISPLAY_X11 (display);
focus_window = XCreateSimpleWindow (xdisplay, parent,
-1, -1, 1, 1, 0,
0, 0);
/* FIXME: probably better to actually track the requested event mask for the toplevel
*/
XSelectInput (xdisplay, focus_window,
KeyPressMask | KeyReleaseMask | FocusChangeMask);
event_mask = (GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_FOCUS_CHANGE_MASK);
gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
focus_window,
event_mask, 0);
XMapWindow (xdisplay, focus_window);
return focus_window;
@@ -573,6 +588,7 @@ setup_toplevel_window (GdkWindow *window,
{
GdkWindowObject *obj = (GdkWindowObject *)window;
GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
GdkDisplay *display = gdk_drawable_get_display (window);
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
XID xid = GDK_WINDOW_XID (window);
XID xparent = GDK_WINDOW_XID (parent);
@@ -591,7 +607,7 @@ setup_toplevel_window (GdkWindow *window,
/* The focus window is off the visible area, and serves to receive key
* press events so they don't get sent to child windows.
*/
toplevel->focus_window = create_focus_window (xdisplay, xid);
toplevel->focus_window = create_focus_window (display, xid);
_gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
}
@@ -652,6 +668,7 @@ _gdk_window_impl_new (GdkWindow *window,
GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
GdkScreenX11 *screen_x11;
GdkDisplayX11 *display_x11;
Window xparent;
Visual *xvisual;
@@ -664,12 +681,12 @@ _gdk_window_impl_new (GdkWindow *window,
unsigned int class;
const char *title;
int i;
private = (GdkWindowObject *) window;
screen_x11 = GDK_SCREEN_X11 (screen);
xparent = GDK_WINDOW_XID (real_parent);
display_x11 = GDK_DISPLAY_X11 (GDK_SCREEN_DISPLAY (screen));
impl = g_object_new (_gdk_window_impl_get_type (), NULL);
private->impl = (GdkDrawable *)impl;
@@ -683,15 +700,6 @@ _gdk_window_impl_new (GdkWindow *window,
xvisual = ((GdkVisualPrivate*) visual)->xvisual;
xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
for (i = 0; i < _gdk_nenvent_masks; i++)
{
if (event_mask & (1 << (i + 1)))
xattributes.event_mask |= _gdk_event_mask_table[i];
}
if (xattributes.event_mask)
xattributes_mask |= CWEventMask;
if (attributes_mask & GDK_WA_NOREDIR)
{
xattributes.override_redirect =
@@ -837,6 +845,10 @@ _gdk_window_impl_new (GdkWindow *window,
if (attributes_mask & GDK_WA_TYPE_HINT)
gdk_window_set_type_hint (window, attributes->type_hint);
gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
GDK_WINDOW_XWINDOW (window), event_mask,
StructureNotifyMask | PropertyChangeMask);
}
static GdkEventMask
@@ -3202,13 +3214,13 @@ gdk_display_warp_pointer (GdkDisplay *display,
gint x,
gint y)
{
Display *xdisplay;
Window dest;
GdkDevice *device;
xdisplay = GDK_DISPLAY_XDISPLAY (display);
dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
g_return_if_fail (GDK_IS_DISPLAY (display));
g_return_if_fail (GDK_IS_SCREEN (screen));
XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);
device = display->core_pointer;
GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
}
GdkWindow*
@@ -3361,17 +3373,15 @@ gdk_window_x11_set_events (GdkWindow *window,
if (!GDK_WINDOW_DESTROYED (window))
{
GdkDisplayX11 *display_x11;
if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
xevent_mask = StructureNotifyMask | PropertyChangeMask;
for (i = 0; i < _gdk_nenvent_masks; i++)
{
if (event_mask & (1 << (i + 1)))
xevent_mask |= _gdk_event_mask_table[i];
}
XSelectInput (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
xevent_mask);
display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
GDK_WINDOW_XWINDOW (window), event_mask,
xevent_mask);
}
}
@@ -5592,8 +5602,65 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
iface->queue_translation = _gdk_x11_window_queue_translation;
iface->destroy = _gdk_x11_window_destroy;
#if 0
iface->input_window_destroy = _gdk_input_window_destroy;
iface->input_window_crossing = _gdk_input_crossing_event;
#endif
}
static Bool
timestamp_predicate (Display *display,
XEvent *xevent,
XPointer arg)
{
Window xwindow = GPOINTER_TO_UINT (arg);
GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
if (xevent->type == PropertyNotify &&
xevent->xproperty.window == xwindow &&
xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
"GDK_TIMESTAMP_PROP"))
return True;
return False;
}
/**
* gdk_x11_get_server_time:
* @window: a #GdkWindow, used for communication with the server.
* The window must have GDK_PROPERTY_CHANGE_MASK in its
* events mask or a hang will result.
*
* Routine to get the current X server time stamp.
*
* Return value: the time stamp.
**/
guint32
gdk_x11_get_server_time (GdkWindow *window)
{
Display *xdisplay;
Window xwindow;
guchar c = 'a';
XEvent xevent;
Atom timestamp_prop_atom;
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
xdisplay = GDK_WINDOW_XDISPLAY (window);
xwindow = GDK_WINDOW_XWINDOW (window);
timestamp_prop_atom =
gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
"GDK_TIMESTAMP_PROP");
XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
timestamp_prop_atom,
8, PropModeReplace, &c, 1);
XIfEvent (xdisplay, &xevent,
timestamp_predicate, GUINT_TO_POINTER(xwindow));
return xevent.xproperty.time;
}
#define __GDK_WINDOW_X11_C__