diff options
author | Matthias Clasen <mclasen@redhat.com> | 2010-05-25 18:38:44 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2010-05-25 18:38:44 -0400 |
commit | bd4609b14042a91646cd9057764eecfbc6faf42b (patch) | |
tree | 8721405d2b45a998f87cccc672b4070780907fb8 /gdk/win32 | |
parent | a538f639b69a39d7bb85b39af2dfd296d28fc0aa (diff) | |
download | gtk+-bd4609b14042a91646cd9057764eecfbc6faf42b.tar.gz |
Merge the xi2-for-master branch
Diffstat (limited to 'gdk/win32')
-rw-r--r-- | gdk/win32/Makefile.am | 8 | ||||
-rw-r--r-- | gdk/win32/gdkdevice-win32.c | 396 | ||||
-rw-r--r-- | gdk/win32/gdkdevice-win32.h | 51 | ||||
-rw-r--r-- | gdk/win32/gdkdevice-wintab.c | 386 | ||||
-rw-r--r-- | gdk/win32/gdkdevice-wintab.h | 79 | ||||
-rw-r--r-- | gdk/win32/gdkdevicemanager-win32.c | 1089 | ||||
-rw-r--r-- | gdk/win32/gdkdevicemanager-win32.h | 59 | ||||
-rw-r--r-- | gdk/win32/gdkdnd-win32.c | 222 | ||||
-rw-r--r-- | gdk/win32/gdkevents-win32.c | 266 | ||||
-rw-r--r-- | gdk/win32/gdkinput-win32.c | 1392 | ||||
-rw-r--r-- | gdk/win32/gdkinput-win32.h | 147 | ||||
-rw-r--r-- | gdk/win32/gdkinput.c | 441 | ||||
-rw-r--r-- | gdk/win32/gdkmain-win32.c | 3 | ||||
-rw-r--r-- | gdk/win32/gdkwindow-win32.c | 246 |
14 files changed, 2440 insertions, 2345 deletions
diff --git a/gdk/win32/Makefile.am b/gdk/win32/Makefile.am index 17d048edde..e6c5b2deb4 100644 --- a/gdk/win32/Makefile.am +++ b/gdk/win32/Makefile.am @@ -29,6 +29,12 @@ libgdk_win32_la_SOURCES = \ gdkapplaunchcontext-win32.c \ gdkcolor-win32.c \ gdkcursor-win32.c \ + gdkdevicemanager-win32.c \ + gdkdevicemanager-win32.h \ + gdkdevice-win32.c \ + gdkdevice-win32.h \ + gdkdevice-wintab.c \ + gdkdevice-wintab.h \ gdkdisplay-win32.c \ gdkdnd-win32.c \ gdkdrawable-win32.c \ @@ -41,8 +47,6 @@ libgdk_win32_la_SOURCES = \ gdkim-win32.c \ gdkimage-win32.c \ gdkinput.c \ - gdkinput-win32.c \ - gdkinput-win32.h \ gdkkeys-win32.c \ gdkmain-win32.c \ gdkpixmap-win32.c \ diff --git a/gdk/win32/gdkdevice-win32.c b/gdk/win32/gdkdevice-win32.c new file mode 100644 index 0000000000..9e4eb81644 --- /dev/null +++ b/gdk/win32/gdkdevice-win32.c @@ -0,0 +1,396 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <gdk/gdkwindow.h> + +#include <windowsx.h> +#include <objbase.h> + +#include "gdkdevice-win32.h" +#include "gdkwin32.h" + +static gboolean gdk_device_win32_get_history (GdkDevice *device, + GdkWindow *window, + guint32 start, + guint32 stop, + GdkTimeCoord ***events, + guint *n_events); +static void gdk_device_win32_get_state (GdkDevice *device, + GdkWindow *window, + gdouble *axes, + GdkModifierType *mask); +static void gdk_device_win32_set_window_cursor (GdkDevice *device, + GdkWindow *window, + GdkCursor *cursor); +static void gdk_device_win32_warp (GdkDevice *device, + GdkScreen *screen, + gint x, + gint y); +static gboolean gdk_device_win32_query_state (GdkDevice *device, + GdkWindow *window, + GdkWindow **root_window, + GdkWindow **child_window, + gint *root_x, + gint *root_y, + gint *win_x, + gint *win_y, + GdkModifierType *mask); +static GdkGrabStatus gdk_device_win32_grab (GdkDevice *device, + GdkWindow *window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + guint32 time_); +static void gdk_device_win32_ungrab (GdkDevice *device, + guint32 time_); +static GdkWindow * gdk_device_win32_window_at_position (GdkDevice *device, + gint *win_x, + gint *win_y, + GdkModifierType *mask, + gboolean get_toplevel); +static void gdk_device_win32_select_window_events (GdkDevice *device, + GdkWindow *window, + GdkEventMask event_mask); + + +G_DEFINE_TYPE (GdkDeviceWin32, gdk_device_win32, GDK_TYPE_DEVICE) + +static void +gdk_device_win32_class_init (GdkDeviceWin32Class *klass) +{ + GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass); + + device_class->get_history = gdk_device_win32_get_history; + device_class->get_state = gdk_device_win32_get_state; + device_class->set_window_cursor = gdk_device_win32_set_window_cursor; + device_class->warp = gdk_device_win32_warp; + device_class->query_state = gdk_device_win32_query_state; + device_class->grab = gdk_device_win32_grab; + device_class->ungrab = gdk_device_win32_ungrab; + device_class->window_at_position = gdk_device_win32_window_at_position; + device_class->select_window_events = gdk_device_win32_select_window_events; +} + +static void +gdk_device_win32_init (GdkDeviceWin32 *device_win32) +{ + GdkDevice *device; + + device = GDK_DEVICE (device_win32); + + _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_X, 0, 0, 1); + _gdk_device_add_axis (device, GDK_NONE, GDK_AXIS_Y, 0, 0, 1); +} + +static gboolean +gdk_device_win32_get_history (GdkDevice *device, + GdkWindow *window, + guint32 start, + guint32 stop, + GdkTimeCoord ***events, + guint *n_events) +{ + return FALSE; +} + +static void +gdk_device_win32_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_win32_set_window_cursor (GdkDevice *device, + GdkWindow *window, + GdkCursor *cursor) +{ + GdkCursorPrivate *cursor_private; + GdkWindowObject *parent_window; + GdkWindowImplWin32 *impl; + HCURSOR hcursor; + HCURSOR hprevcursor; + + impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); + cursor_private = (GdkCursorPrivate*) cursor; + + hprevcursor = impl->hcursor; + + if (!cursor) + hcursor = NULL; + else + hcursor = cursor_private->hcursor; + + if (hcursor != NULL) + { + /* If the pointer is over our window, set new cursor */ + GdkWindow *curr_window = gdk_window_get_pointer (window, NULL, NULL, NULL); + + if (curr_window == window || + (curr_window && window == gdk_window_get_toplevel (curr_window))) + SetCursor (hcursor); + else + { + /* Climb up the tree and find whether our window is the + * first ancestor that has cursor defined, and if so, set + * new cursor. + */ + GdkWindowObject *curr_window_obj = GDK_WINDOW_OBJECT (curr_window); + + while (curr_window_obj && + !GDK_WINDOW_IMPL_WIN32 (curr_window_obj->impl)->hcursor) + { + curr_window_obj = curr_window_obj->parent; + if (curr_window_obj == GDK_WINDOW_OBJECT (window)) + { + SetCursor (hcursor); + break; + } + } + } + } + + /* Unset the previous cursor: Need to make sure it's no longer in + * use before we destroy it, in case we're not over our window but + * the cursor is still set to our old one. + */ + if (hprevcursor != NULL && + GetCursor () == hprevcursor) + { + /* Look for a suitable cursor to use instead */ + hcursor = NULL; + parent_window = GDK_WINDOW_OBJECT (window)->parent; + + while (hcursor == NULL) + { + if (parent_window) + { + impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl); + hcursor = impl->hcursor; + parent_window = parent_window->parent; + } + else + hcursor = LoadCursor (NULL, IDC_ARROW); + } + + SetCursor (hcursor); + } +} + +static void +gdk_device_win32_warp (GdkDevice *device, + GdkScreen *screen, + gint x, + gint y) +{ + SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y); +} + +static GdkModifierType +get_current_mask (void) +{ + GdkModifierType mask; + BYTE kbd[256]; + + GetKeyboardState (kbd); + mask = 0; + if (kbd[VK_SHIFT] & 0x80) + mask |= GDK_SHIFT_MASK; + if (kbd[VK_CAPITAL] & 0x80) + mask |= GDK_LOCK_MASK; + if (kbd[VK_CONTROL] & 0x80) + mask |= GDK_CONTROL_MASK; + if (kbd[VK_MENU] & 0x80) + mask |= GDK_MOD1_MASK; + if (kbd[VK_LBUTTON] & 0x80) + mask |= GDK_BUTTON1_MASK; + if (kbd[VK_MBUTTON] & 0x80) + mask |= GDK_BUTTON2_MASK; + if (kbd[VK_RBUTTON] & 0x80) + mask |= GDK_BUTTON3_MASK; + + return mask; +} + +static gboolean +gdk_device_win32_query_state (GdkDevice *device, + GdkWindow *window, + GdkWindow **root_window, + GdkWindow **child_window, + gint *root_x, + gint *root_y, + gint *win_x, + gint *win_y, + GdkModifierType *mask) +{ + gboolean return_val; + POINT point; + HWND hwnd, hwndc; + + g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE); + + return_val = TRUE; + + hwnd = GDK_WINDOW_HWND (window); + GetCursorPos (&point); + + if (root_x) + *root_x = point.x; + + if (root_y) + *root_y = point.y; + + ScreenToClient (hwnd, &point); + + if (win_x) + *win_x = point.x; + + if (win_y) + *win_y = point.y; + + if (window == _gdk_root) + { + if (win_x) + *win_x += _gdk_offset_x; + + if (win_y) + *win_y += _gdk_offset_y; + } + + if (child_window) + { + hwndc = ChildWindowFromPoint (hwnd, point); + + if (hwndc && hwndc != hwnd) + *child_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwndc); + else + *child_window = NULL; /* Direct child unknown to gdk */ + } + + if (root_window) + { + GdkScreen *screen; + + screen = gdk_drawable_get_screen (GDK_DRAWABLE (window)); + *root_window = gdk_screen_get_root_window (screen); + } + + if (mask) + *mask = get_current_mask (); + + return TRUE; +} + +static GdkGrabStatus +gdk_device_win32_grab (GdkDevice *device, + GdkWindow *window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + guint32 time_) +{ + if (device->source != GDK_SOURCE_KEYBOARD) + SetCapture (GDK_WINDOW_HWND (window)); + + return GDK_GRAB_SUCCESS; +} + +static void +gdk_device_win32_ungrab (GdkDevice *device, + guint32 time_) +{ + GdkDisplay *display; + + display = gdk_device_get_display (device); + + if (device->source != GDK_SOURCE_KEYBOARD) + ReleaseCapture (); +} + +static GdkWindow * +gdk_device_win32_window_at_position (GdkDevice *device, + gint *win_x, + gint *win_y, + GdkModifierType *mask, + gboolean get_toplevel) +{ + GdkWindow *window; + POINT point, pointc; + HWND hwnd, hwndc; + RECT rect; + + GetCursorPos (&pointc); + point = pointc; + hwnd = WindowFromPoint (point); + + if (hwnd == NULL) + { + window = _gdk_root; + *win_x = pointc.x + _gdk_offset_x; + *win_y = pointc.y + _gdk_offset_y; + return window; + } + + ScreenToClient (hwnd, &point); + + do + { + if (get_toplevel && + (window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd)) != NULL && + GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN) + break; + + hwndc = ChildWindowFromPoint (hwnd, point); + ClientToScreen (hwnd, &point); + ScreenToClient (hwndc, &point); + } + while (hwndc != hwnd && (hwnd = hwndc, 1)); + + window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); + + if (window && (win_x || win_y)) + { + GetClientRect (hwnd, &rect); + *win_x = point.x - rect.left; + *win_y = point.y - rect.top; + } + + return window; +} + +static void +gdk_device_win32_select_window_events (GdkDevice *device, + GdkWindow *window, + GdkEventMask event_mask) +{ +} diff --git a/gdk/win32/gdkdevice-win32.h b/gdk/win32/gdkdevice-win32.h new file mode 100644 index 0000000000..ef9c322b3d --- /dev/null +++ b/gdk/win32/gdkdevice-win32.h @@ -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_WIN32_H__ +#define __GDK_DEVICE_WIN32_H__ + +#include <gdk/gdkdeviceprivate.h> + +G_BEGIN_DECLS + +#define GDK_TYPE_DEVICE_WIN32 (gdk_device_win32_get_type ()) +#define GDK_DEVICE_WIN32(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_WIN32, GdkDeviceWin32)) +#define GDK_DEVICE_WIN32_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_WIN32, GdkDeviceWin32Class)) +#define GDK_IS_DEVICE_WIN32(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_WIN32)) +#define GDK_IS_DEVICE_WIN32_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_WIN32)) +#define GDK_DEVICE_WIN32_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_WIN32, GdkDeviceWin32Class)) + +typedef struct _GdkDeviceWin32 GdkDeviceWin32; +typedef struct _GdkDeviceWin32Class GdkDeviceWin32Class; + +struct _GdkDeviceWin32 +{ + GdkDevice parent_instance; +}; + +struct _GdkDeviceWin32Class +{ + GdkDeviceClass parent_class; +}; + +GType gdk_device_win32_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GDK_DEVICE_WIN32_H__ */ diff --git a/gdk/win32/gdkdevice-wintab.c b/gdk/win32/gdkdevice-wintab.c new file mode 100644 index 0000000000..392e10b2e4 --- /dev/null +++ b/gdk/win32/gdkdevice-wintab.c @@ -0,0 +1,386 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <gdk/gdkwindow.h> + +#include <windowsx.h> +#include <objbase.h> + +#include "gdkwin32.h" +#include "gdkdevice-wintab.h" + +static GQuark quark_window_input_info = 0; +static GSList *input_windows = NULL; + +typedef struct +{ + gdouble root_x; + gdouble root_y; + GHashTable *device_events; +} GdkWindowInputInfo; + +static gboolean gdk_device_wintab_get_history (GdkDevice *device, + GdkWindow *window, + guint32 start, + guint32 stop, + GdkTimeCoord ***events, + guint *n_events); +static void gdk_device_wintab_get_state (GdkDevice *device, + GdkWindow *window, + gdouble *axes, + GdkModifierType *mask); +static void gdk_device_wintab_set_window_cursor (GdkDevice *device, + GdkWindow *window, + GdkCursor *cursor); +static void gdk_device_wintab_warp (GdkDevice *device, + GdkScreen *screen, + gint x, + gint y); +static gboolean gdk_device_wintab_query_state (GdkDevice *device, + GdkWindow *window, + GdkWindow **root_window, + GdkWindow **child_window, + gint *root_x, + gint *root_y, + gint *win_x, + gint *win_y, + GdkModifierType *mask); +static GdkGrabStatus gdk_device_wintab_grab (GdkDevice *device, + GdkWindow *window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + guint32 time_); +static void gdk_device_wintab_ungrab (GdkDevice *device, + guint32 time_); +static GdkWindow * gdk_device_wintab_window_at_position (GdkDevice *device, + gint *win_x, + gint *win_y, + GdkModifierType *mask, + gboolean get_toplevel); +static void gdk_device_wintab_select_window_events (GdkDevice *device, + GdkWindow *window, + GdkEventMask event_mask); + + +G_DEFINE_TYPE (GdkDeviceWintab, gdk_device_wintab, GDK_TYPE_DEVICE) + +static void +gdk_device_wintab_class_init (GdkDeviceWintabClass *klass) +{ + GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass); + + device_class->get_history = gdk_device_wintab_get_history; + device_class->get_state = gdk_device_wintab_get_state; + device_class->set_window_cursor = gdk_device_wintab_set_window_cursor; + device_class->warp = gdk_device_wintab_warp; + device_class->query_state = gdk_device_wintab_query_state; + device_class->grab = gdk_device_wintab_grab; + device_class->ungrab = gdk_device_wintab_ungrab; + device_class->window_at_position = gdk_device_wintab_window_at_position; + device_class->select_window_events = gdk_device_wintab_select_window_events; + + quark_window_input_info = g_quark_from_static_string ("gdk-window-input-info"); +} + +static void +gdk_device_wintab_init (GdkDeviceWintab *device_wintab) +{ + GdkDevice *device; + + device = GDK_DEVICE (device_wintab); +} + +static gboolean +gdk_device_wintab_get_history (GdkDevice *device, + GdkWindow *window, + guint32 start, + guint32 stop, + GdkTimeCoord ***events, + guint *n_events) +{ + return FALSE; +} + +static void +gdk_device_wintab_get_state (GdkDevice *device, + GdkWindow *window, + gdouble *axes, + GdkModifierType *mask) +{ + GdkDeviceWintab *device_wintab; + + device_wintab = GDK_DEVICE_WINTAB (device); + + /* For now just use the last known button and axis state of the device. + * Since graphical tablets send an insane amount of motion events each + * second, the info should be fairly up to date */ + if (mask) + { + gdk_window_get_pointer (window, NULL, NULL, mask); + *mask &= 0xFF; /* Mask away core pointer buttons */ + *mask |= ((device_wintab->button_state << 8) + & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK + | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK + | GDK_BUTTON5_MASK)); + } + + if (device_wintab->last_axis_data) + _gdk_device_wintab_translate_axes (device, window, axes, NULL, NULL); +} + +static void +gdk_device_wintab_set_window_cursor (GdkDevice *device, + GdkWindow *window, + GdkCursor *cursor) +{ +} + +static void +gdk_device_wintab_warp (GdkDevice *device, + GdkScreen *screen, + gint x, + gint y) +{ +} + +static gboolean +gdk_device_wintab_query_state (GdkDevice *device, + GdkWindow *window, + GdkWindow **root_window, + GdkWindow **child_window, + gint *root_x, + gint *root_y, + gint *win_x, + gint *win_y, + GdkModifierType *mask) +{ + return FALSE; +} + +static GdkGrabStatus +gdk_device_wintab_grab (GdkDevice *device, + GdkWindow *window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + guint32 time_) +{ + return GDK_GRAB_SUCCESS; +} + +static void +gdk_device_wintab_ungrab (GdkDevice *device, + guint32 time_) +{ +} + +static GdkWindow * +gdk_device_wintab_window_at_position (GdkDevice *device, + gint *win_x, + gint *win_y, + GdkModifierType *mask, + gboolean get_toplevel) +{ + return NULL; +} + +static void +input_info_free (GdkWindowInputInfo *info) +{ + g_hash_table_destroy (info->device_events); + g_free (info); +} + +static void +gdk_device_wintab_select_window_events (GdkDevice *device, + GdkWindow *window, + GdkEventMask event_mask) +{ + GdkWindowInputInfo *info; + + info = g_object_get_qdata (G_OBJECT (window), + quark_window_input_info); + if (event_mask) + { + if (!info) + { + info = g_new0 (GdkWindowInputInfo, 1); + info->device_events = g_hash_table_new (NULL, NULL); + + g_object_set_qdata_full (G_OBJECT (window), + quark_window_input_info, + info, + (GDestroyNotify) input_info_free); + input_windows = g_slist_prepend (input_windows, window); + } + + g_hash_table_insert (info->device_events, device, + GUINT_TO_POINTER (event_mask)); + } + else if (info) + { + g_hash_table_remove (info->device_events, device); + + if (g_hash_table_size (info->device_events) == 0) + { + g_object_set_qdata (G_OBJECT (window), + quark_window_input_info, + NULL); + input_windows = g_slist_remove (input_windows, window); + } + } +} + +GdkEventMask +_gdk_device_wintab_get_events (GdkDeviceWintab *device, + GdkWindow *window) +{ + GdkWindowInputInfo *info; + + info = g_object_get_qdata (G_OBJECT (window), + quark_window_input_info); + + if (!info) + return 0; + + return GPOINTER_TO_UINT (g_hash_table_lookup (info->device_events, device)); +} + +gboolean +_gdk_device_wintab_get_window_coords (GdkWindow *window, + gdouble *root_x, + gdouble *root_y) +{ + GdkWindowInputInfo *info; + + info = g_object_get_qdata (G_OBJECT (window), + quark_window_input_info); + + if (!info) + return FALSE; + + *root_x = info->root_x; + *root_y = info->root_y; + + return TRUE; +} + +void +_gdk_device_wintab_update_window_coords (GdkWindow *window) +{ + GdkWindowInputInfo *info; + gint root_x, root_y; + + info = g_object_get_qdata (G_OBJECT (window), + quark_window_input_info); + + g_return_if_fail (info != NULL); + + gdk_window_get_origin (window, &root_x, &root_y); + info->root_x = (gdouble) root_x; + info->root_y = (gdouble) root_y; +} + +void +_gdk_device_wintab_translate_axes (GdkDeviceWintab *device_wintab, + GdkWindow *window, + gdouble *axes, + gdouble *x, + gdouble *y) +{ + GdkDevice *device; + GdkWindow *impl_window; + gdouble root_x, root_y; + gdouble temp_x, temp_y; + gint i; + + device = GDK_DEVICE (device_wintab); + impl_window = _gdk_window_get_impl_window (window); + temp_x = temp_y = 0; + + if (!_gdk_device_wintab_get_window_coords (impl_window, &root_x, &root_y)) + return; + + for (i = 0; i < device->num_axes; i++) + { + GdkAxisUse use; + + use = _gdk_device_get_axis_use (device, i); + + switch (use) + { + case GDK_AXIS_X: + case GDK_AXIS_Y: + if (gdk_device_get_mode (device) == GDK_MODE_WINDOW) + _gdk_device_translate_window_coord (device, window, i, + device_wintab->last_axis_data[i], + &axes[i]); + else + _gdk_device_translate_screen_coord (device, window, + root_x, root_y, i, + device_wintab->last_axis_data[i], + &axes[i]); + if (use == GDK_AXIS_X) + temp_x = axes[i]; + else if (use == GDK_AXIS_Y) + temp_y = axes[i]; + + break; + default: + _gdk_device_translate_axis (device, i, + device_wintab->last_axis_data[i], + &axes[i]); + break; + } + } + + if (x) + *x = temp_x; + + if (y) + *y = temp_y; +} + +void +_gdk_input_check_extension_events (GdkDevice *device) +{ + GSList *l; + + if (!GDK_IS_DEVICE_WINTAB (device)) + return; + + for (l = input_windows; l; l = l->next) + { + GdkWindowObject *window_private; + GdkEventMask event_mask = 0; + + window_private = l->data; + + if (gdk_device_get_mode (device) != GDK_MODE_DISABLED) + event_mask = window_private->extension_events; + + gdk_window_set_device_events (GDK_WINDOW (window_private), + device, event_mask); + } +} diff --git a/gdk/win32/gdkdevice-wintab.h b/gdk/win32/gdkdevice-wintab.h new file mode 100644 index 0000000000..79fae8a8e2 --- /dev/null +++ b/gdk/win32/gdkdevice-wintab.h @@ -0,0 +1,79 @@ +/* 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_WINTAB_H__ +#define __GDK_DEVICE_WINTAB_H__ + +#include <gdk/gdkdeviceprivate.h> + +#include <windows.h> +#include <wintab.h> + +G_BEGIN_DECLS + +#define GDK_TYPE_DEVICE_WINTAB (gdk_device_wintab_get_type ()) +#define GDK_DEVICE_WINTAB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_WINTAB, GdkDeviceWintab)) +#define GDK_DEVICE_WINTAB_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_WINTAB, GdkDeviceWintabClass)) +#define GDK_IS_DEVICE_WINTAB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_WINTAB)) +#define GDK_IS_DEVICE_WINTAB_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_WINTAB)) +#define GDK_DEVICE_WINTAB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_WINTAB, GdkDeviceWintabClass)) + +typedef struct _GdkDeviceWintab GdkDeviceWintab; +typedef struct _GdkDeviceWintabClass GdkDeviceWintabClass; + +struct _GdkDeviceWintab +{ + GdkDevice parent_instance; + + gint *last_axis_data; + gint button_state; + + /* WINTAB stuff: */ + HCTX hctx; + /* Cursor number */ + UINT cursor; + /* The cursor's CSR_PKTDATA */ + WTPKT pktdata; + /* Azimuth and altitude axis */ + AXIS orientation_axes[2]; +}; + +struct _GdkDeviceWintabClass +{ + GdkDeviceClass parent_class; +}; + +GType gdk_device_wintab_get_type (void) G_GNUC_CONST; + +GdkEventMask _gdk_device_wintab_get_events (GdkDeviceWintab *device, + GdkWindow *window); +gboolean _gdk_device_wintab_get_window_coords (GdkWindow *window, + gdouble *root_x, + gdouble *root_y); +void _gdk_device_wintab_update_window_coords (GdkWindow *window); + +void _gdk_device_wintab_translate_axes (GdkDeviceWintab *device, + GdkWindow *window, + gdouble *axes, + gdouble *x, + gdouble *y); + +G_END_DECLS + +#endif /* __GDK_DEVICE_WINTAB_H__ */ diff --git a/gdk/win32/gdkdevicemanager-win32.c b/gdk/win32/gdkdevicemanager-win32.c new file mode 100644 index 0000000000..eea814296b --- /dev/null +++ b/gdk/win32/gdkdevicemanager-win32.c @@ -0,0 +1,1089 @@ +/* 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 <stdlib.h> +#include <stdio.h> +#include <math.h> + +#include <gdk/gdk.h> +#include "gdkprivate-win32.h" +#include "gdkdevicemanager-win32.h" +#include "gdkdeviceprivate.h" +#include "gdkdevice-win32.h" +#include "gdkdevice-wintab.h" + +#include <windows.h> +#include <wintab.h> + +#define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION) +/* We want everything in absolute mode */ +#define PACKETMODE (0) +#include <pktdef.h> + +#define DEBUG_WINTAB 1 /* Verbose debug messages enabled */ +#define PROXIMITY_OUT_DELAY 200 /* In milliseconds, see set_ignore_core */ +#define TWOPI (2 * G_PI) + +static GList *wintab_contexts = NULL; +static GdkWindow *wintab_window = NULL; +static guint ignore_core_timer = 0; +extern gint _gdk_input_ignore_core; + +typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c); +typedef UINT (WINAPI *t_WTInfoW) (UINT a, UINT b, LPVOID c); +typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b); +typedef HCTX (WINAPI *t_WTOpenA) (HWND a, LPLOGCONTEXTA b, BOOL c); +typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b); +typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c); +typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b); + +static t_WTInfoA p_WTInfoA; +static t_WTInfoW p_WTInfoW; +static t_WTEnable p_WTEnable; +static t_WTOpenA p_WTOpenA; +static t_WTOverlap p_WTOverlap; +static t_WTPacket p_WTPacket; +static t_WTQueueSizeSet p_WTQueueSizeSet; + + +static void gdk_device_manager_win32_finalize (GObject *object); +static void gdk_device_manager_win32_constructed (GObject *object); + +static GList * gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager, + GdkDeviceType type); + + +G_DEFINE_TYPE (GdkDeviceManagerWin32, gdk_device_manager_win32, GDK_TYPE_DEVICE_MANAGER) + +static void +gdk_device_manager_win32_class_init (GdkDeviceManagerWin32Class *klass) +{ + GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gdk_device_manager_win32_finalize; + object_class->constructed = gdk_device_manager_win32_constructed; + device_manager_class->list_devices = gdk_device_manager_win32_list_devices; +} + +static GdkDevice * +create_core_pointer (GdkDeviceManager *device_manager) +{ + return g_object_new (GDK_TYPE_DEVICE_WIN32, + "name", "Core Pointer", + "type", GDK_DEVICE_TYPE_MASTER, + "input-source", GDK_SOURCE_MOUSE, + "input-mode", GDK_MODE_SCREEN, + "has-cursor", TRUE, + "display", _gdk_display, + "device-manager", device_manager, + NULL); +} + +static GdkDevice * +create_core_keyboard (GdkDeviceManager *device_manager) +{ + return g_object_new (GDK_TYPE_DEVICE_WIN32, + "name", "Core Keyboard", + "type", GDK_DEVICE_TYPE_MASTER, + "input-source", GDK_SOURCE_KEYBOARD, + "input-mode", GDK_MODE_SCREEN, + "has-cursor", FALSE, + "display", _gdk_display, + "device-manager", device_manager, + NULL); +} + +static void +gdk_device_manager_win32_init (GdkDeviceManagerWin32 *device_manager_win32) +{ +} + +static void +gdk_device_manager_win32_finalize (GObject *object) +{ + GdkDeviceManagerWin32 *device_manager_win32; + + device_manager_win32 = GDK_DEVICE_MANAGER_WIN32 (object); + + g_object_unref (device_manager_win32->core_pointer); + g_object_unref (device_manager_win32->core_keyboard); + + G_OBJECT_CLASS (gdk_device_manager_win32_parent_class)->finalize (object); +} + +#if DEBUG_WINTAB + +static void +print_lc(LOGCONTEXT *lc) +{ + g_print ("lcName = %s\n", lc->lcName); + g_print ("lcOptions ="); + if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM"); + if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN"); + if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES"); + if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN"); + if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE"); + if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES"); + g_print ("\n"); + g_print ("lcStatus ="); + if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED"); + if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED"); + if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP"); + g_print ("\n"); + g_print ("lcLocks ="); + if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE"); + if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT"); + if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY"); + if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN"); + g_print ("\n"); + g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n", + lc->lcMsgBase, lc->lcDevice, lc->lcPktRate); + g_print ("lcPktData ="); + if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT"); + if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS"); + if (lc->lcPktData & PK_TIME) g_print (" PK_TIME"); + if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED"); + if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER"); + if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR"); + if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS"); + if (lc->lcPktData & PK_X) g_print (" PK_X"); + if (lc->lcPktData & PK_Y) g_print (" PK_Y"); + if (lc->lcPktData & PK_Z) g_print (" PK_Z"); + if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE"); + if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE"); + if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION"); + if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION"); + g_print ("\n"); + g_print ("lcPktMode ="); + if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT"); + if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS"); + if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME"); + if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED"); + if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER"); + if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR"); + if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS"); + if (lc->lcPktMode & PK_X) g_print (" PK_X"); + if (lc->lcPktMode & PK_Y) g_print (" PK_Y"); + if (lc->lcPktMode & PK_Z) g_print (" PK_Z"); + if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE"); + if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE"); + if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION"); + if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION"); + g_print ("\n"); + g_print ("lcMoveMask ="); + if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT"); + if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS"); + if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME"); + if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED"); + if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER"); + if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR"); + if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS"); + if (lc->lcMoveMask & PK_X) g_print (" PK_X"); + if (lc->lcMoveMask & PK_Y) g_print (" PK_Y"); + if (lc->lcMoveMask & PK_Z) g_print (" PK_Z"); + if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE"); + if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE"); + if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION"); + if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION"); + g_print ("\n"); + g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n", + (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask); + g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n", + lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ); + g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n", + lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ); + g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n", + lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ); + g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n", + lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ); + g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n", + lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.); + g_print ("lcSysMode = %d\n", lc->lcSysMode); + g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n", + lc->lcSysOrgX, lc->lcSysOrgY); + g_print ("lcSysExtX = %d, lcSysExtY = %d\n", + lc->lcSysExtX, lc->lcSysExtY); + g_print ("lcSysSensX = %g, lcSysSensY = %g\n", + lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.); +} + +static void +print_cursor (int index) +{ + int size; + int i; + char *name; + BOOL active; + WTPKT wtpkt; + BYTE buttons; + BYTE buttonbits; + char *btnnames; + char *p; + BYTE buttonmap[32]; + BYTE sysbtnmap[32]; + BYTE npbutton; + UINT npbtnmarks[2]; + UINT *npresponse; + BYTE tpbutton; + UINT tpbtnmarks[2]; + UINT *tpresponse; + DWORD physid; + UINT mode; + UINT minpktdata; + UINT minbuttons; + UINT capabilities; + + size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, NULL); + name = g_malloc (size + 1); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, name); + g_print ("NAME: %s\n", name); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_ACTIVE, &active); + g_print ("ACTIVE: %s\n", active ? "YES" : "NO"); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_PKTDATA, &wtpkt); + g_print ("PKTDATA: %#x:", (guint) wtpkt); +#define BIT(x) if (wtpkt & PK_##x) g_print (" " #x) + BIT (CONTEXT); + BIT (STATUS); + BIT (TIME); + BIT (CHANGED); + BIT (SERIAL_NUMBER); + BIT (BUTTONS); + BIT (X); + BIT (Y); + BIT (Z); + BIT (NORMAL_PRESSURE); + BIT (TANGENT_PRESSURE); + BIT (ORIENTATION); + BIT (ROTATION); +#undef BIT + g_print ("\n"); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONS, &buttons); + g_print ("BUTTONS: %d\n", buttons); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONBITS, &buttonbits); + g_print ("BUTTONBITS: %d\n", buttonbits); + size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, NULL); + g_print ("BTNNAMES:"); + if (size > 0) + { + btnnames = g_malloc (size + 1); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, btnnames); + p = btnnames; + while (*p) + { + g_print (" %s", p); + p += strlen (p) + 1; + } + } + g_print ("\n"); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONMAP, buttonmap); + g_print ("BUTTONMAP:"); + for (i = 0; i < buttons; i++) + g_print (" %d", buttonmap[i]); + g_print ("\n"); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_SYSBTNMAP, sysbtnmap); + g_print ("SYSBTNMAP:"); + for (i = 0; i < buttons; i++) + g_print (" %d", sysbtnmap[i]); + g_print ("\n"); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBUTTON, &npbutton); + g_print ("NPBUTTON: %d\n", npbutton); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBTNMARKS, npbtnmarks); + g_print ("NPBTNMARKS: %d %d\n", npbtnmarks[0], npbtnmarks[1]); + size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, NULL); + g_print ("NPRESPONSE:"); + if (size > 0) + { + npresponse = g_malloc (size); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, npresponse); + for (i = 0; i < size / sizeof (UINT); i++) + g_print (" %d", npresponse[i]); + } + g_print ("\n"); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBUTTON, &tpbutton); + g_print ("TPBUTTON: %d\n", tpbutton); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBTNMARKS, tpbtnmarks); + g_print ("TPBTNMARKS: %d %d\n", tpbtnmarks[0], tpbtnmarks[1]); + size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, NULL); + g_print ("TPRESPONSE:"); + if (size > 0) + { + tpresponse = g_malloc (size); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, tpresponse); + for (i = 0; i < size / sizeof (UINT); i++) + g_print (" %d", tpresponse[i]); + } + g_print ("\n"); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_PHYSID, &physid); + g_print ("PHYSID: %#x\n", (guint) physid); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_CAPABILITIES, &capabilities); + g_print ("CAPABILITIES: %#x:", capabilities); +#define BIT(x) if (capabilities & CRC_##x) g_print (" " #x) + BIT (MULTIMODE); + BIT (AGGREGATE); + BIT (INVERT); +#undef BIT + g_print ("\n"); + if (capabilities & CRC_MULTIMODE) + { + (*p_WTInfoA) (WTI_CURSORS + index, CSR_MODE, &mode); + g_print ("MODE: %d\n", mode); + } + if (capabilities & CRC_AGGREGATE) + { + (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINPKTDATA, &minpktdata); + g_print ("MINPKTDATA: %d\n", minpktdata); + (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINBUTTONS, &minbuttons); + g_print ("MINBUTTONS: %d\n", minbuttons); + } +} +#endif + +static void +_gdk_input_wintab_init_check (GdkDeviceManagerWin32 *device_manager) +{ + static gboolean wintab_initialized = FALSE; + GdkDeviceWintab *device; + GdkWindowAttr wa; + WORD specversion; + HCTX *hctx; + UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware; + BOOL active; + DWORD physid; + AXIS axis_x, axis_y, axis_npressure, axis_or[3]; + int i, devix, cursorix, num_axes = 0; + wchar_t devname[100], csrname[100]; + gchar *devname_utf8, *csrname_utf8, *device_name; + BOOL defcontext_done; + HMODULE wintab32; + + if (wintab_initialized) + return; + + wintab_initialized = TRUE; + + wintab_contexts = NULL; + + if (_gdk_input_ignore_wintab) + return; + + if ((wintab32 = LoadLibrary ("wintab32.dll")) == NULL) + return; + + if ((p_WTInfoA = (t_WTInfoA) GetProcAddress (wintab32, "WTInfoA")) == NULL) + return; + if ((p_WTInfoW = (t_WTInfoW) GetProcAddress (wintab32, "WTInfoW")) == NULL) + return; + if ((p_WTEnable = (t_WTEnable) GetProcAddress (wintab32, "WTEnable")) == NULL) + return; + if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL) + return; + if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL) + return; + if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL) + return; + if ((p_WTQueueSizeSet = (t_WTQueueSizeSet) GetProcAddress (wintab32, "WTQueueSizeSet")) == NULL) + return; + + if (!(*p_WTInfoA) (0, 0, NULL)) + return; + + (*p_WTInfoA) (WTI_INTERFACE, IFC_SPECVERSION, &specversion); + GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n", + HIBYTE (specversion), LOBYTE (specversion))); + (*p_WTInfoA) (WTI_INTERFACE, IFC_NDEVICES, &ndevices); + (*p_WTInfoA) (WTI_INTERFACE, IFC_NCURSORS, &ncursors); +#if DEBUG_WINTAB + GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n", + ndevices, ncursors)); +#endif + /* Create a dummy window to receive wintab events */ + wa.wclass = GDK_INPUT_OUTPUT; + wa.event_mask = GDK_ALL_EVENTS_MASK; + wa.width = 2; + wa.height = 2; + wa.x = -100; + wa.y = -100; + wa.window_type = GDK_WINDOW_TOPLEVEL; + if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL) + { + g_warning ("gdk_input_wintab_init: gdk_window_new failed"); + return; + } + g_object_ref (wintab_window); + + for (devix = 0; devix < ndevices; devix++) + { + LOGCONTEXT lc; + + /* We open the Wintab device (hmm, what if there are several, or + * can there even be several, probably not?) as a system + * pointing device, i.e. it controls the normal Windows + * cursor. This seems much more natural. + */ + + (*p_WTInfoW) (WTI_DEVICES + devix, DVC_NAME, devname); + devname_utf8 = g_utf16_to_utf8 (devname, -1, NULL, NULL, NULL); +#ifdef DEBUG_WINTAB + GDK_NOTE (INPUT, (g_print("Device %d: %s\n", devix, devname_utf8))); +#endif + (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes); + (*p_WTInfoA) (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr); + (*p_WTInfoA) (WTI_DEVICES + devix, DVC_HARDWARE, &hardware); + (*p_WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x); + (*p_WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y); + (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure); + (*p_WTInfoA) (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or); + + defcontext_done = FALSE; + if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1) + { + /* Try to get device-specific default context */ + /* Some drivers, e.g. Aiptek, don't provide this info */ + if ((*p_WTInfoA) (WTI_DSCTXS + devix, 0, &lc) > 0) + defcontext_done = TRUE; +#if DEBUG_WINTAB + if (defcontext_done) + GDK_NOTE (INPUT, (g_print("Using device-specific default context\n"))); + else + GDK_NOTE (INPUT, (g_print("Note: Driver did not provide device specific default context info despite claiming to support version 1.1\n"))); +#endif + } + + if (!defcontext_done) + (*p_WTInfoA) (WTI_DEFSYSCTX, 0, &lc); +#if DEBUG_WINTAB + GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc))); +#endif + lc.lcOptions |= CXO_MESSAGES; + lc.lcStatus = 0; + lc.lcMsgBase = WT_DEFBASE; + lc.lcPktRate = 0; + lc.lcPktData = PACKETDATA; + lc.lcPktMode = PACKETMODE; + lc.lcMoveMask = PACKETDATA; + lc.lcBtnUpMask = lc.lcBtnDnMask = ~0; + lc.lcOutOrgX = axis_x.axMin; + lc.lcOutOrgY = axis_y.axMin; + lc.lcOutExtX = axis_x.axMax - axis_x.axMin; + lc.lcOutExtY = axis_y.axMax - axis_y.axMin; + lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */ +#if DEBUG_WINTAB + GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix), + print_lc(&lc))); +#endif + hctx = g_new (HCTX, 1); + if ((*hctx = (*p_WTOpenA) (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL) + { + g_warning ("gdk_input_wintab_init: WTOpen failed"); + return; + } + GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n", + devix, *hctx)); + + wintab_contexts = g_list_append (wintab_contexts, hctx); +#if 0 + (*p_WTEnable) (*hctx, TRUE); +#endif + (*p_WTOverlap) (*hctx, TRUE); + +#if DEBUG_WINTAB + GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix), + print_lc(&lc))); +#endif + /* Increase packet queue size to reduce the risk of lost packets. + * According to the specs, if the function fails we must try again + * with a smaller queue size. + */ + GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n")); + for (i = 32; i >= 1; i >>= 1) + { + if ((*p_WTQueueSizeSet) (*hctx, i)) + { + GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i)); + break; + } + } + if (!i) + GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n")); + for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++) + { +#ifdef DEBUG_WINTAB + GDK_NOTE (INPUT, (g_print("Cursor %d:\n", cursorix), print_cursor (cursorix))); +#endif + active = FALSE; + (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_ACTIVE, &active); + if (!active) + continue; + + /* Wacom tablets seem to report cursors corresponding to + * nonexistent pens or pucks. At least my ArtPad II reports + * six cursors: a puck, pressure stylus and eraser stylus, + * and then the same three again. I only have a + * pressure-sensitive pen. The puck instances, and the + * second instances of the styluses report physid zero. So + * at least for Wacom, skip cursors with physid zero. + */ + (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PHYSID, &physid); + if (wcscmp (devname, L"WACOM Tablet") == 0 && physid == 0) + continue; + + (*p_WTInfoW) (WTI_CURSORS + cursorix, CSR_NAME, csrname); + csrname_utf8 = g_utf16_to_utf8 (csrname, -1, NULL, NULL, NULL); + device_name = g_strconcat (devname_utf8, " ", csrname_utf8, NULL); + + device = g_object_new (GDK_TYPE_DEVICE_WINTAB, + "name", device_name, + "type", GDK_DEVICE_TYPE_SLAVE, + "source", GDK_SOURCE_PEN, + "mode", GDK_MODE_SCREEN, + "has-cursor", FALSE, + "display", _gdk_display, + "device-manager", device_manager, + NULL); + + g_free (csrname_utf8); + + device->hctx = *hctx; + device->cursor = cursorix; + (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PKTDATA, &device->pktdata); + + if (device->pktdata & PK_X) + { + _gdk_device_add_axis (GDK_DEVICE (device), + GDK_NONE, + GDK_AXIS_X, + axis_x.axMin, + axis_x.axMax, + axis_x.axResolution / 65535); + num_axes++; + } + + if (device->pktdata & PK_Y) + { + _gdk_device_add_axis (GDK_DEVICE (device), + GDK_NONE, + GDK_AXIS_Y, + axis_y.axMin, + axis_y.axMax, + axis_y.axResolution / 65535); + num_axes++; + } + + + if (device->pktdata & PK_NORMAL_PRESSURE) + { + _gdk_device_add_axis (GDK_DEVICE (device), + GDK_NONE, + GDK_AXIS_PRESSURE, + axis_npressure.axMin, + axis_npressure.axMax, + axis_npressure.axResolution / 65535); + num_axes++; + } + + /* The wintab driver for the Wacom ArtPad II reports + * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't + * actually sense tilt. Catch this by noticing that the + * orientation axis's azimuth resolution is zero. + */ + if ((device->pktdata & PK_ORIENTATION) && axis_or[0].axResolution == 0) + { + device->orientation_axes[0] = axis_or[0]; + device->orientation_axes[1] = axis_or[1]; + + /* Wintab gives us aximuth and altitude, which + * we convert to x and y tilt in the -1000..1000 range + */ + _gdk_device_add_axis (GDK_DEVICE (device), + GDK_NONE, + GDK_AXIS_XTILT, + -1000, + 1000, + 1000); + + _gdk_device_add_axis (GDK_DEVICE (device), + GDK_NONE, + GDK_AXIS_YTILT, + -1000, + 1000, + 1000); + num_axes += 2; + } + + device->last_axis_data = g_new (gint, num_axes); + + GDK_NOTE (INPUT, g_print ("device: (%d) %s axes: %d\n", + cursorix, + device_name, + num_axes)); + +#if 0 + for (i = 0; i < gdkdev->info.num_axes; i++) + GDK_NOTE (INPUT, g_print ("... axis %d: %d--%d@%d\n", + i, + gdkdev->axes[i].min_value, + gdkdev->axes[i].max_value, + gdkdev->axes[i].resolution)); +#endif + + device_manager->wintab_devices = g_list_append (device_manager->wintab_devices, + device); + + g_free (device_name); + } + + g_free (devname_utf8); + } +} + +static void +gdk_device_manager_win32_constructed (GObject *object) +{ + GdkDeviceManagerWin32 *device_manager; + + device_manager = GDK_DEVICE_MANAGER_WIN32 (object); + device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager)); + device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager)); + + _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard); + _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer); + + _gdk_input_wintab_init_check (device_manager); +} + +static GList * +gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager, + GdkDeviceType type) +{ + GdkDeviceManagerWin32 *device_manager_win32; + GList *devices = NULL; + + device_manager_win32 = (GdkDeviceManagerWin32 *) device_manager; + + if (type == GDK_DEVICE_TYPE_MASTER) + { + devices = g_list_prepend (devices, device_manager_win32->core_keyboard); + devices = g_list_prepend (devices, device_manager_win32->core_pointer); + } + else if (type == GDK_DEVICE_TYPE_FLOATING) + devices = g_list_copy (device_manager_win32->wintab_devices); + + return devices; +} + +void +_gdk_input_set_tablet_active (void) +{ + GList *tmp_list; + HCTX *hctx; + + /* Bring the contexts to the top of the overlap order when one of the + * application's windows is activated */ + + if (!wintab_contexts) + return; /* No tablet devices found, or Wintab not initialized yet */ + + GDK_NOTE (INPUT, g_print ("_gdk_input_set_tablet_active: " + "Bringing Wintab contexts to the top of the overlap order\n")); + + tmp_list = wintab_contexts; + + while (tmp_list) + { + hctx = (HCTX *) (tmp_list->data); + (*p_WTOverlap) (*hctx, TRUE); + tmp_list = tmp_list->next; + } +} + +static void +decode_tilt (gint *axis_data, + AXIS *axes, + PACKET *packet) +{ + double az, el; + + /* As I don't have a tilt-sensing tablet, + * I cannot test this code. + */ + az = TWOPI * packet->pkOrientation.orAzimuth / + (axes[0].axResolution / 65536.); + el = TWOPI * packet->pkOrientation.orAltitude / + (axes[1].axResolution / 65536.); + + /* X tilt */ + axis_data[0] = cos (az) * cos (el) * 1000; + /* Y tilt */ + axis_data[1] = sin (az) * cos (el) * 1000; +} + +/* + * Get the currently active keyboard modifiers (ignoring the mouse buttons) + * We could use gdk_window_get_pointer but that function does a lot of other + * expensive things besides getting the modifiers. This code is somewhat based + * on build_pointer_event_state from gdkevents-win32.c + */ +static guint +get_modifier_key_state (void) +{ + guint state; + + state = 0; + /* High-order bit is up/down, low order bit is toggled/untoggled */ + if (GetKeyState (VK_CONTROL) < 0) + state |= GDK_CONTROL_MASK; + if (GetKeyState (VK_SHIFT) < 0) + state |= GDK_SHIFT_MASK; + if (GetKeyState (VK_MENU) < 0) + state |= GDK_MOD1_MASK; + if (GetKeyState (VK_CAPITAL) & 0x1) + state |= GDK_LOCK_MASK; + + return state; +} + +static gboolean +ignore_core_timefunc (gpointer data) +{ + /* The delay has passed */ + _gdk_input_ignore_core = FALSE; + ignore_core_timer = 0; + + return FALSE; /* remove timeout */ +} + +/* + * Set or unset the _gdk_input_ignore_core variable that tells GDK + * to ignore events for the core pointer when the tablet is in proximity + * The unsetting is delayed slightly so that if a tablet event arrives + * just after proximity out, it does not cause a core pointer event + * which e.g. causes GIMP to switch tools. + */ +static void +set_ignore_core (gboolean ignore) +{ + if (ignore) + { + _gdk_input_ignore_core = TRUE; + /* Remove any pending clear */ + if (ignore_core_timer) + { + g_source_remove (ignore_core_timer); + ignore_core_timer = 0; + } + } + else if (!ignore_core_timer) + ignore_core_timer = gdk_threads_add_timeout (PROXIMITY_OUT_DELAY, + ignore_core_timefunc, NULL); +} + +static GdkDeviceWintab * +_gdk_device_manager_find_wintab_device (HCTX hctx, + UINT cursor) +{ + GdkDeviceManagerWin32 *device_manager; + GdkDeviceWintab *device; + GList *tmp_list; + + device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (_gdk_display)); + tmp_list = device_manager->wintab_devices; + + while (tmp_list) + { + device = tmp_list->data; + tmp_list = tmp_list->next; + + if (device->hctx == hctx && + device->cursor == cursor) + return device; + } + + return NULL; +} + +gboolean +_gdk_input_other_event (GdkEvent *event, + MSG *msg, + GdkWindow *window) +{ + GdkDisplay *display; + GdkWindowObject *obj; + GdkDeviceWintab *device = NULL; + GdkDeviceGrabInfo *last_grab; + GdkEventMask masktest; + guint key_state; + POINT pt; + + PACKET packet; + gdouble root_x, root_y; + gint num_axes; + gint x, y; + guint translated_buttons, button_diff, button_mask; + /* Translation from tablet button state to GDK button state for + * buttons 1-3 - swap button 2 and 3. + */ + static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7}; + + if (event->any.window != wintab_window) + { + g_warning ("_gdk_input_other_event: not wintab_window?"); + return FALSE; + } + + window = gdk_window_at_pointer (&x, &y); + if (window == NULL) + window = _gdk_root; + + g_object_ref (window); + display = gdk_drawable_get_display (window); + + GDK_NOTE (EVENTS_OR_INPUT, + g_print ("_gdk_input_other_event: window=%p %+d%+d\n", + GDK_WINDOW_HWND (window), x, y)); + + if (msg->message == WT_PACKET) + { + if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet)) + return FALSE; + } + + obj = GDK_WINDOW_OBJECT (window); + + switch (msg->message) + { + case WT_PACKET: + /* Don't produce any button or motion events while a window is being + * moved or resized, see bug #151090. + */ + if (_modal_operation_in_progress) + { + GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n")); + return FALSE; + } + + if ((device = _gdk_device_manager_find_wintab_device ((HCTX) msg->lParam, + packet.pkCursor)) == NULL) + return FALSE; + + if (gdk_device_get_mode (GDK_DEVICE (device)) == GDK_MODE_DISABLED) + return FALSE; + + last_grab = _gdk_display_get_last_device_grab (_gdk_display, GDK_DEVICE (device)); + + if (last_grab && last_grab->window) + { + g_object_unref (window); + + window = g_object_ref (last_grab->window); + obj = GDK_WINDOW_OBJECT (window); + } + + if (window == _gdk_root) + { + GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n")); + return FALSE; + } + + num_axes = 0; + if (device->pktdata & PK_X) + device->last_axis_data[num_axes++] = packet.pkX; + if (device->pktdata & PK_Y) + device->last_axis_data[num_axes++] = packet.pkY; + if (device->pktdata & PK_NORMAL_PRESSURE) + device->last_axis_data[num_axes++] = packet.pkNormalPressure; + if (device->pktdata & PK_ORIENTATION) + { + decode_tilt (device->last_axis_data + num_axes, + device->orientation_axes, &packet); + num_axes += 2; + } + + translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07); + + if (translated_buttons != device->button_state) + { + /* At least one button has changed state so produce a button event + * If more than one button has changed state (unlikely), + * just care about the first and act on the next the next time + * we get a packet + */ + button_diff = translated_buttons ^ device->button_state; + + /* Gdk buttons are numbered 1.. */ + event->button.button = 1; + + for (button_mask = 1; button_mask != 0x80000000; + button_mask <<= 1, event->button.button++) + { + if (button_diff & button_mask) + { + /* Found a button that has changed state */ + break; + } + } + + if (!(translated_buttons & button_mask)) + { + event->any.type = GDK_BUTTON_RELEASE; + masktest = GDK_BUTTON_RELEASE_MASK; + } + else + { + event->any.type = GDK_BUTTON_PRESS; + masktest = GDK_BUTTON_PRESS_MASK; + } + device->button_state ^= button_mask; + } + else + { + event->any.type = GDK_MOTION_NOTIFY; + masktest = GDK_POINTER_MOTION_MASK; + if (device->button_state & (1 << 0)) + masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK; + if (device->button_state & (1 << 1)) + masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK; + if (device->button_state & (1 << 2)) + masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK; + } + + /* Now we can check if the window wants the event, and + * propagate if necessary. + */ + while (gdk_window_get_device_events (window, GDK_DEVICE (device)) == 0) + { + GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n")); + + if (obj->parent == GDK_WINDOW_OBJECT (_gdk_root)) + return FALSE; + + /* It is not good to propagate the extended events up to the parent + * if this window wants normal (not extended) motion/button events */ + if (obj->event_mask & masktest) + { + GDK_NOTE (EVENTS_OR_INPUT, + g_print ("... wants ordinary event, ignoring this\n")); + return FALSE; + } + + pt.x = x; + pt.y = y; + ClientToScreen (GDK_WINDOW_HWND (window), &pt); + g_object_unref (window); + window = (GdkWindow *) obj->parent; + obj = GDK_WINDOW_OBJECT (window); + g_object_ref (window); + ScreenToClient (GDK_WINDOW_HWND (window), &pt); + x = pt.x; + y = pt.y; + GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n", + GDK_WINDOW_HWND (window), x, y)); + } + + if (gdk_window_get_device_events (window, GDK_DEVICE (device)) == 0) + return FALSE; + + event->any.window = window; + key_state = get_modifier_key_state (); + if (event->any.type == GDK_BUTTON_PRESS || + event->any.type == GDK_BUTTON_RELEASE) + { + event->button.time = _gdk_win32_get_next_tick (msg->time); + gdk_event_set_device (event, GDK_DEVICE (device)); + + event->button.axes = g_new (gdouble, num_axes); + _gdk_device_wintab_get_window_coords (window, &root_x, &root_y); + + _gdk_device_wintab_translate_axes (device, + window, + event->button.axes, + &event->button.x, + &event->button.y); + + event->button.x_root = event->button.x + root_x; + event->button.y_root = event->button.y + root_y; + + event->button.state = + key_state | ((device->button_state << 8) + & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK + | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK + | GDK_BUTTON5_MASK)); + + GDK_NOTE (EVENTS_OR_INPUT, + g_print ("WINTAB button %s:%d %g,%g\n", + (event->button.type == GDK_BUTTON_PRESS ? + "press" : "release"), + event->button.button, + event->button.x, event->button.y)); + } + else + { + event->motion.time = _gdk_win32_get_next_tick (msg->time); + event->motion.is_hint = FALSE; + gdk_event_set_device (event, GDK_DEVICE (device)); + + event->motion.axes = g_new (gdouble, num_axes); + _gdk_device_wintab_get_window_coords (window, &root_x, &root_y); + + _gdk_device_wintab_translate_axes (device, + window, + event->motion.axes, + &event->motion.x, + &event->motion.y); + + event->motion.x_root = event->motion.x + root_x; + event->motion.y_root = event->motion.y + root_y; + + event->motion.state = + key_state | ((device->button_state << 8) + & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK + | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK + | GDK_BUTTON5_MASK)); + + GDK_NOTE (EVENTS_OR_INPUT, + g_print ("WINTAB motion: %g,%g\n", + event->motion.x, event->motion.y)); + } + return TRUE; + + case WT_PROXIMITY: + if (LOWORD (msg->lParam) == 0) + { + event->proximity.type = GDK_PROXIMITY_OUT; + set_ignore_core (FALSE); + } + else + { + event->proximity.type = GDK_PROXIMITY_IN; + set_ignore_core (TRUE); + } + event->proximity.time = _gdk_win32_get_next_tick (msg->time); + gdk_event_set_device (event, GDK_DEVICE (device)); + + GDK_NOTE (EVENTS_OR_INPUT, + g_print ("WINTAB proximity %s\n", + (event->proximity.type == GDK_PROXIMITY_IN ? + "in" : "out"))); + return TRUE; + } + + return FALSE; +} diff --git a/gdk/win32/gdkdevicemanager-win32.h b/gdk/win32/gdkdevicemanager-win32.h new file mode 100644 index 0000000000..69d26b7561 --- /dev/null +++ b/gdk/win32/gdkdevicemanager-win32.h @@ -0,0 +1,59 @@ +/* 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_WIN32_H__ +#define __GDK_DEVICE_MANAGER_WIN32_H__ + +#include <gdk/gdkdevicemanager.h> + +G_BEGIN_DECLS + +#define GDK_TYPE_DEVICE_MANAGER_WIN32 (gdk_device_manager_win32_get_type ()) +#define GDK_DEVICE_MANAGER_WIN32(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_MANAGER_WIN32, GdkDeviceManagerWin32)) +#define GDK_DEVICE_MANAGER_WIN32_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_MANAGER_WIN32, GdkDeviceManagerWin32Class)) +#define GDK_IS_DEVICE_MANAGER_WIN32(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_MANAGER_WIN32)) +#define GDK_IS_DEVICE_MANAGER_WIN32_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_MANAGER_WIN32)) +#define GDK_DEVICE_MANAGER_WIN32_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_MANAGER_WIN32, GdkDeviceManagerWin32Class)) + +typedef struct _GdkDeviceManagerWin32 GdkDeviceManagerWin32; +typedef struct _GdkDeviceManagerWin32Class GdkDeviceManagerWin32Class; + +struct _GdkDeviceManagerWin32 +{ + GdkDeviceManager parent_object; + GdkDevice *core_pointer; + GdkDevice *core_keyboard; + GList *wintab_devices; +}; + +struct _GdkDeviceManagerWin32Class +{ + GdkDeviceManagerClass parent_class; +}; + +GType gdk_device_manager_win32_get_type (void) G_GNUC_CONST; + +void _gdk_input_set_tablet_active (void); +gboolean _gdk_input_other_event (GdkEvent *event, + MSG *msg, + GdkWindow *window); + +G_END_DECLS + +#endif /* __GDK_DEVICE_MANAGER_WIN32_H__ */ diff --git a/gdk/win32/gdkdnd-win32.c b/gdk/win32/gdkdnd-win32.c index f0b57a9b68..6436fb7817 100644 --- a/gdk/win32/gdkdnd-win32.c +++ b/gdk/win32/gdkdnd-win32.c @@ -98,6 +98,7 @@ typedef enum { * this is used on both source and destination sides. */ struct _GdkDragContextPrivateWin32 { + GdkDevice *device; gboolean being_finalized; gint ref_count; IUnknown *iface; @@ -203,6 +204,39 @@ gdk_drag_context_new (void) return g_object_new (GDK_TYPE_DRAG_CONTEXT, NULL); } +GdkDevice * +gdk_drag_context_get_device (GdkDragContext *context) +{ + GdkDragContextPrivateWin32 *private; + + g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL); + + private = PRIVATE_DATA (context); + + return private->device; +} + +void +gdk_drag_context_set_device (GdkDragContext *context, + GdkDevice *device) +{ + GdkDragContextPrivateWin32 *private; + + g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (GDK_IS_DEVICE (device)); + + private = PRIVATE_DATA (context); + + if (private->device) + { + g_object_unref (private->device); + private->device = NULL; + } + + if (device) + private->device = g_object_ref (device); +} + static GdkDragContext * gdk_drag_context_find (gboolean is_source, GdkWindow *source, @@ -425,24 +459,28 @@ dnd_event_put (GdkEventType type, const POINTL pt, gboolean to_dest_window) { - GdkEvent e; - e.type = type; + GdkEvent *e; + + e = gdk_event_new (type); + if (to_dest_window) - e.dnd.window = context->dest_window; + e->dnd.window = context->dest_window; else - e.dnd.window = context->source_window; - e.dnd.send_event = FALSE; - e.dnd.context = context; - e.dnd.time = GDK_CURRENT_TIME; - e.dnd.x_root = pt.x + _gdk_offset_x; - e.dnd.y_root = pt.x + _gdk_offset_y; + e->dnd.window = context->source_window; + e->dnd.send_event = FALSE; + e->dnd.context = g_object_ref (context); + e->dnd.time = GDK_CURRENT_TIME; + e->dnd.x_root = pt.x + _gdk_offset_x; + e->dnd.y_root = pt.x + _gdk_offset_y; - g_object_ref (e.dnd.context); - if (e.dnd.window != NULL) - g_object_ref (e.dnd.window); + if (e->dnd.window != NULL) + g_object_ref (e->dnd.window); - GDK_NOTE (EVENTS, _gdk_win32_print_event (&e)); - gdk_event_put (&e); + gdk_event_set_device (e, gdk_drag_context_get_device (context)); + + GDK_NOTE (EVENTS, _gdk_win32_print_event (e)); + gdk_event_put (e); + gdk_event_free (e); } static HRESULT STDMETHODCALLTYPE @@ -1173,6 +1211,7 @@ target_context_new (GdkWindow *window) { target_drag_context *result; GdkDragContextPrivateWin32 *private; + GdkDevice *device; result = g_new0 (target_drag_context, 1); @@ -1182,6 +1221,9 @@ target_context_new (GdkWindow *window) result->context->protocol = GDK_DRAG_PROTO_OLE2; result->context->is_source = FALSE; + device = gdk_display_get_core_pointer (_gdk_display); + gdk_drag_context_set_device (result->context, device); + result->context->source_window = NULL; result->context->dest_window = window; @@ -1208,6 +1250,7 @@ source_context_new (GdkWindow *window, { source_drag_context *result; GdkDragContextPrivateWin32 *private; + GdkDevice *device; result = g_new0 (source_drag_context, 1); @@ -1217,6 +1260,9 @@ source_context_new (GdkWindow *window, result->context->protocol = GDK_DRAG_PROTO_OLE2; result->context->is_source = TRUE; + device = gdk_display_get_core_pointer (_gdk_display); + gdk_drag_context_set_device (result->context, device); + result->context->source_window = window; g_object_ref (window); @@ -1428,6 +1474,7 @@ gdk_dropfiles_filter (GdkXEvent *xev, POINT pt; gint nfiles, i; gchar *fileName, *linkedFile; + GdkDevice *device; if (msg->message == WM_DROPFILES) { @@ -1437,6 +1484,9 @@ gdk_dropfiles_filter (GdkXEvent *xev, context->protocol = GDK_DRAG_PROTO_WIN32_DROPFILES; context->is_source = FALSE; + device = gdk_display_get_core_pointer (_gdk_display); + gdk_drag_context_set_device (context, device); + context->source_window = _gdk_root; g_object_ref (context->source_window); @@ -1452,6 +1502,7 @@ gdk_dropfiles_filter (GdkXEvent *xev, event->dnd.type = GDK_DROP_START; event->dnd.context = current_dest_drag; + gdk_event_set_device (event, gdk_drag_context_get_device (current_dest_drag)); hdrop = (HANDLE) msg->wParam; DragQueryPoint (hdrop, &pt); @@ -1615,7 +1666,7 @@ static void local_send_leave (GdkDragContext *context, guint32 time) { - GdkEvent tmp_event; + GdkEvent *tmp_event; GDK_NOTE (DND, g_print ("local_send_leave: context=%p current_dest_drag=%p\n", context, @@ -1625,17 +1676,20 @@ local_send_leave (GdkDragContext *context, (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) && (current_dest_drag->source_window == context->source_window)) { - tmp_event.dnd.type = GDK_DRAG_LEAVE; - tmp_event.dnd.window = context->dest_window; + tmp_event = gdk_event_new (GDK_DRAG_LEAVE); + + tmp_event->dnd.window = g_object_ref (context->dest_window); /* Pass ownership of context to the event */ - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = current_dest_drag; - tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ + tmp_event->dnd.send_event = FALSE; + tmp_event->dnd.context = g_object_ref (current_dest_drag); + tmp_event->dnd.time = GDK_CURRENT_TIME; /* FIXME? */ + gdk_event_set_device (tmp_event, gdk_drag_context_get_device (context)); current_dest_drag = NULL; - GDK_NOTE (EVENTS, _gdk_win32_print_event (&tmp_event)); - gdk_event_put (&tmp_event); + GDK_NOTE (EVENTS, _gdk_win32_print_event (tmp_event)); + gdk_event_put (tmp_event); + gdk_event_free (tmp_event); } } @@ -1643,9 +1697,10 @@ static void local_send_enter (GdkDragContext *context, guint32 time) { - GdkEvent tmp_event; + GdkEvent *tmp_event; GdkDragContextPrivateWin32 *private; GdkDragContext *new_context; + GdkDevice *device; GDK_NOTE (DND, g_print ("local_send_enter: context=%p current_dest_drag=%p\n", context, @@ -1663,6 +1718,9 @@ local_send_enter (GdkDragContext *context, new_context->protocol = GDK_DRAG_PROTO_LOCAL; new_context->is_source = FALSE; + device = gdk_display_get_core_pointer (_gdk_display); + gdk_drag_context_set_device (new_context, device); + new_context->source_window = context->source_window; g_object_ref (new_context->source_window); @@ -1676,16 +1734,18 @@ local_send_enter (GdkDragContext *context, GDK_PROPERTY_CHANGE_MASK); new_context->actions = context->actions; - tmp_event.type = GDK_DRAG_ENTER; - tmp_event.dnd.window = context->dest_window; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = new_context; - tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ + tmp_event = gdk_event_new (GDK_DRAG_ENTER); + tmp_event->dnd.window = g_object_ref (context->dest_window); + tmp_event->dnd.send_event = FALSE; + tmp_event->dnd.context = g_object_ref (new_context); + tmp_event->dnd.time = GDK_CURRENT_TIME; /* FIXME? */ + gdk_event_set_device (tmp_event, gdk_drag_context_get_device (context)); current_dest_drag = new_context; - GDK_NOTE (EVENTS, _gdk_win32_print_event (&tmp_event)); - gdk_event_put (&tmp_event); + GDK_NOTE (EVENTS, _gdk_win32_print_event (tmp_event)); + gdk_event_put (tmp_event); + gdk_event_free (tmp_event); } static void @@ -1695,7 +1755,7 @@ local_send_motion (GdkDragContext *context, GdkDragAction action, guint32 time) { - GdkEvent tmp_event; + GdkEvent *tmp_event; GDK_NOTE (DND, g_print ("local_send_motion: context=%p (%d,%d) current_dest_drag=%p\n", context, x_root, y_root, @@ -1705,24 +1765,26 @@ local_send_motion (GdkDragContext *context, (current_dest_drag->protocol == GDK_DRAG_PROTO_LOCAL) && (current_dest_drag->source_window == context->source_window)) { - tmp_event.type = GDK_DRAG_MOTION; - tmp_event.dnd.window = current_dest_drag->dest_window; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = current_dest_drag; - tmp_event.dnd.time = time; + tmp_event = gdk_event_new (GDK_DRAG_MOTION); + tmp_event->dnd.window = g_object_ref (current_dest_drag->dest_window); + tmp_event->dnd.send_event = FALSE; + tmp_event->dnd.context = g_object_ref (current_dest_drag); + tmp_event->dnd.time = time; + gdk_event_set_device (tmp_event, gdk_drag_context_get_device (current_dest_drag)); current_dest_drag->suggested_action = action; - tmp_event.dnd.x_root = x_root; - tmp_event.dnd.y_root = y_root; + tmp_event->dnd.x_root = x_root; + tmp_event->dnd.y_root = y_root; PRIVATE_DATA (current_dest_drag)->last_pt.x = x_root - _gdk_offset_x; PRIVATE_DATA (current_dest_drag)->last_pt.y = y_root - _gdk_offset_y; PRIVATE_DATA (context)->drag_status = GDK_DRAG_STATUS_MOTION_WAIT; - GDK_NOTE (EVENTS, _gdk_win32_print_event (&tmp_event)); - gdk_event_put (&tmp_event); + GDK_NOTE (EVENTS, _gdk_win32_print_event (tmp_event)); + gdk_event_put (tmp_event); + gdk_event_free (tmp_event); } } @@ -1730,7 +1792,7 @@ static void local_send_drop (GdkDragContext *context, guint32 time) { - GdkEvent tmp_event; + GdkEvent *tmp_event; GDK_NOTE (DND, g_print ("local_send_drop: context=%p current_dest_drag=%p\n", context, @@ -1744,19 +1806,21 @@ local_send_drop (GdkDragContext *context, private = PRIVATE_DATA (current_dest_drag); /* Pass ownership of context to the event */ - tmp_event.type = GDK_DROP_START; - tmp_event.dnd.window = current_dest_drag->dest_window; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = current_dest_drag; - tmp_event.dnd.time = GDK_CURRENT_TIME; + tmp_event = gdk_event_new (GDK_DROP_START); + tmp_event->dnd.window = g_object_ref (current_dest_drag->dest_window); + tmp_event->dnd.send_event = FALSE; + tmp_event->dnd.context = g_object_ref (current_dest_drag); + tmp_event->dnd.time = GDK_CURRENT_TIME; + gdk_event_set_device (tmp_event, gdk_drag_context_get_device (current_dest_drag)); - tmp_event.dnd.x_root = private->last_pt.x + _gdk_offset_x; - tmp_event.dnd.y_root = private->last_pt.y + _gdk_offset_y; + tmp_event->dnd.x_root = private->last_pt.x + _gdk_offset_x; + tmp_event->dnd.y_root = private->last_pt.y + _gdk_offset_y; current_dest_drag = NULL; - GDK_NOTE (EVENTS, _gdk_win32_print_event (&tmp_event)); - gdk_event_put (&tmp_event); + GDK_NOTE (EVENTS, _gdk_win32_print_event (tmp_event)); + gdk_event_put (tmp_event); + gdk_event_free (tmp_event); } } @@ -1787,11 +1851,15 @@ gdk_drag_begin (GdkWindow *window, if (!use_ole2_dnd) { GdkDragContext *new_context; + GdkDevice *device; g_return_val_if_fail (window != NULL, NULL); new_context = gdk_drag_context_new (); + device = gdk_display_get_core_pointer (_gdk_display); + gdk_drag_context_set_device (new_context, device); + new_context->is_source = TRUE; new_context->source_window = window; @@ -2043,7 +2111,7 @@ gdk_drag_motion (GdkDragContext *context, } else { - GdkEvent tmp_event; + GdkEvent *tmp_event; /* Send a leave to the last destination */ gdk_drag_do_leave (context, time); @@ -2076,18 +2144,20 @@ gdk_drag_motion (GdkDragContext *context, /* Push a status event, to let the client know that * the drag changed */ - tmp_event.type = GDK_DRAG_STATUS; - tmp_event.dnd.window = context->source_window; + tmp_event = gdk_event_new (GDK_DRAG_STATUS); + tmp_event->dnd.window = g_object_ref (context->source_window); /* We use this to signal a synthetic status. Perhaps * we should use an extra field... */ - tmp_event.dnd.send_event = TRUE; + tmp_event->dnd.send_event = TRUE; - tmp_event.dnd.context = context; - tmp_event.dnd.time = time; + tmp_event->dnd.context = g_object_ref (context); + tmp_event->dnd.time = time; + gdk_event_set_device (tmp_event, gdk_drag_context_get_device (context)); - GDK_NOTE (EVENTS, _gdk_win32_print_event (&tmp_event)); - gdk_event_put (&tmp_event); + GDK_NOTE (EVENTS, _gdk_win32_print_event (tmp_event)); + gdk_event_put (tmp_event); + gdk_event_free (tmp_event); } /* Send a drag-motion event */ @@ -2176,7 +2246,7 @@ gdk_drag_status (GdkDragContext *context, { GdkDragContextPrivateWin32 *private; GdkDragContext *src_context; - GdkEvent tmp_event; + GdkEvent *tmp_event; g_return_if_fail (context != NULL); @@ -2205,19 +2275,21 @@ gdk_drag_status (GdkDragContext *context, if (private->drag_status == GDK_DRAG_STATUS_MOTION_WAIT) private->drag_status = GDK_DRAG_STATUS_DRAG; - tmp_event.type = GDK_DRAG_STATUS; - tmp_event.dnd.window = context->source_window; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = src_context; - tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */ + tmp_event = gdk_event_new (GDK_DRAG_STATUS); + tmp_event->dnd.window = g_object_ref (context->source_window); + tmp_event->dnd.send_event = FALSE; + tmp_event->dnd.context = g_object_ref (src_context); + tmp_event->dnd.time = GDK_CURRENT_TIME; /* FIXME? */ + gdk_event_set_device (tmp_event, gdk_drag_context_get_device (src_context)); if (action == GDK_ACTION_DEFAULT) action = 0; src_context->action = action; - GDK_NOTE (EVENTS, _gdk_win32_print_event (&tmp_event)); - gdk_event_put (&tmp_event); + GDK_NOTE (EVENTS, _gdk_win32_print_event (tmp_event)); + gdk_event_put (tmp_event); + gdk_event_free (tmp_event); } } } @@ -2246,7 +2318,7 @@ gdk_drop_finish (GdkDragContext *context, { GdkDragContextPrivateWin32 *private; GdkDragContext *src_context; - GdkEvent tmp_event; + GdkEvent *tmp_event; g_return_if_fail (context != NULL); @@ -2261,13 +2333,15 @@ gdk_drop_finish (GdkDragContext *context, context->dest_window); if (src_context) { - tmp_event.type = GDK_DROP_FINISHED; - tmp_event.dnd.window = src_context->source_window; - tmp_event.dnd.send_event = FALSE; - tmp_event.dnd.context = src_context; - - GDK_NOTE (EVENTS, _gdk_win32_print_event (&tmp_event)); - gdk_event_put (&tmp_event); + tmp_event = gdk_event_new (GDK_DROP_FINISHED); + tmp_event->dnd.window = g_object_ref (src_context->source_window); + tmp_event->dnd.send_event = FALSE; + tmp_event->dnd.context = g_object_ref (src_context); + gdk_event_set_device (tmp_event, gdk_drag_context_get_device (src_context)); + + GDK_NOTE (EVENTS, _gdk_win32_print_event (tmp_event)); + gdk_event_put (tmp_event); + gdk_event_free (tmp_event); } } else diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 219da60b03..b5c6174473 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -47,8 +47,10 @@ #include "gdk.h" #include "gdkprivate-win32.h" -#include "gdkinput-win32.h" #include "gdkkeysyms.h" +#include "gdkdevicemanager-win32.h" +#include "gdkdeviceprivate.h" +#include "gdkdevice-wintab.h" #include <windowsx.h> @@ -101,6 +103,7 @@ static gboolean is_modally_blocked (GdkWindow *window); */ static GList *client_filters; /* Filters for client messages */ +extern gint _gdk_input_ignore_core; static HCURSOR p_grab_cursor; @@ -199,31 +202,44 @@ _gdk_win32_get_next_tick (gulong suggested_tick) } static void -generate_focus_event (GdkWindow *window, - gboolean in) +generate_focus_event (GdkDeviceManager *device_manager, + GdkWindow *window, + gboolean in) { + GdkDevice *device; GdkEvent *event; + device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard; + event = gdk_event_new (GDK_FOCUS_CHANGE); event->focus_change.window = window; event->focus_change.in = in; + gdk_event_set_device (event, device); append_event (event); } static void -generate_grab_broken_event (GdkWindow *window, - gboolean keyboard, - GdkWindow *grab_window) +generate_grab_broken_event (GdkDeviceManager *device_manager, + GdkWindow *window, + gboolean keyboard, + GdkWindow *grab_window) { GdkEvent *event = gdk_event_new (GDK_GRAB_BROKEN); + GdkDevice *device; + + if (keyboard) + device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard; + else + device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_pointer; event->grab_broken.window = window; event->grab_broken.send_event = 0; event->grab_broken.keyboard = keyboard; event->grab_broken.implicit = FALSE; event->grab_broken.grab_window = grab_window; - + gdk_event_set_device (event, device); + append_event (event); } @@ -443,17 +459,19 @@ event_mask_string (GdkEventMask mask) #endif GdkGrabStatus -_gdk_windowing_pointer_grab (GdkWindow *window, - GdkWindow *native_window, - gboolean owner_events, - GdkEventMask event_mask, - GdkWindow *confine_to, - GdkCursor *cursor, - guint32 time) +_gdk_windowing_device_grab (GdkDevice *device, + GdkWindow *window, + GdkWindow *native_window, + gboolean owner_events, + GdkEventMask event_mask, + GdkWindow *confine_to, + GdkCursor *cursor, + guint32 time) { HCURSOR hcursor; GdkCursorPrivate *cursor_private; gint return_val; + GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) native_window)->impl); g_return_val_if_fail (window != NULL, 0); g_return_val_if_fail (GDK_IS_WINDOW (window), 0); @@ -466,54 +484,53 @@ _gdk_windowing_pointer_grab (GdkWindow *window, else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL) WIN32_API_FAILED ("CopyCursor"); - return_val = _gdk_input_grab_pointer (native_window, - owner_events, - event_mask, - confine_to, - time); + return_val = GDK_DEVICE_GET_CLASS (device)->grab (device, + native_window, + owner_events, + event_mask, + confine_to, + cursor, + time); - if (return_val == GDK_GRAB_SUCCESS) + /* TODO_CSW: grab brokens, confine window, input_grab */ + if (p_grab_cursor != NULL) { - GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) native_window)->impl); - - SetCapture (GDK_WINDOW_HWND (native_window)); - /* TODO_CSW: grab brokens, confine window, input_grab */ - if (p_grab_cursor != NULL) - { - if (GetCursor () == p_grab_cursor) - SetCursor (NULL); - DestroyCursor (p_grab_cursor); - } - - p_grab_cursor = hcursor; + if (GetCursor () == p_grab_cursor) + SetCursor (NULL); + DestroyCursor (p_grab_cursor); + } - if (p_grab_cursor != NULL) - SetCursor (p_grab_cursor); - else if (impl->hcursor != NULL) - SetCursor (impl->hcursor); - else - SetCursor (LoadCursor (NULL, IDC_ARROW)); + p_grab_cursor = hcursor; - } + if (p_grab_cursor != NULL) + SetCursor (p_grab_cursor); + else if (impl->hcursor != NULL) + SetCursor (impl->hcursor); + else + SetCursor (LoadCursor (NULL, IDC_ARROW)); return return_val; } void -gdk_display_pointer_ungrab (GdkDisplay *display, - guint32 time) +gdk_device_ungrab (GdkDevice *device, + guint32 time) { - GdkPointerGrabInfo *info; + GdkDeviceGrabInfo *info; + GdkDisplay *display; + + g_return_if_fail (GDK_IS_DEVICE (device)); + + display = gdk_device_get_display (device); + info = _gdk_display_get_last_device_grab (display, device); - info = _gdk_display_get_last_pointer_grab (display); if (info) { info->serial_end = 0; - ReleaseCapture (); + GDK_DEVICE_GET_CLASS (device)->ungrab (device, time); } - /* TODO_CSW: cursor, confines, etc */ - _gdk_display_pointer_grab_update (display, 0); + _gdk_display_device_grab_update (display, device, 0); } @@ -525,8 +542,11 @@ find_window_for_mouse_event (GdkWindow* reported_window, POINTS points; POINT pt; GdkWindow* other_window = NULL; + GdkDeviceManagerWin32 *device_manager; + + device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (_gdk_display)); - if (!_gdk_display_get_last_pointer_grab (_gdk_display)) + if (!_gdk_display_get_last_device_grab (_gdk_display, device_manager->core_pointer)) return reported_window; points = MAKEPOINTS (msg->lParam); @@ -562,41 +582,6 @@ find_window_for_mouse_event (GdkWindow* reported_window, return other_window; } -GdkGrabStatus -gdk_keyboard_grab (GdkWindow *window, - gboolean owner_events, - guint32 time) -{ - GdkDisplay *display; - GdkWindow *toplevel; - - g_return_val_if_fail (window != NULL, 0); - g_return_val_if_fail (GDK_IS_WINDOW (window), 0); - - GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p%s\n", - GDK_WINDOW_HWND (window), owner_events ? " OWNER_EVENTS" : "")); - - display = gdk_drawable_get_display (window); - toplevel = gdk_window_get_toplevel (window); - - _gdk_display_set_has_keyboard_grab (display, - window, - toplevel, - owner_events, - 0, - time); - - return GDK_GRAB_SUCCESS; -} - -void -gdk_display_keyboard_ungrab (GdkDisplay *display, - guint32 time) -{ - GDK_NOTE (EVENTS, g_print ("gdk_display_keyboard_ungrab\n")); - _gdk_display_unset_has_keyboard_grab (display, FALSE); -} - void gdk_display_add_client_message_filter (GdkDisplay *display, GdkAtom message_type, @@ -1195,11 +1180,11 @@ do_show_window (GdkWindow *window, gboolean hide_window) } static void -synthesize_enter_or_leave_event (GdkWindow *window, - MSG *msg, - GdkEventType type, - GdkCrossingMode mode, - GdkNotifyType detail) +synthesize_enter_or_leave_event (GdkWindow *window, + MSG *msg, + GdkEventType type, + GdkCrossingMode mode, + GdkNotifyType detail) { GdkEvent *event; POINT pt; @@ -1219,12 +1204,13 @@ synthesize_enter_or_leave_event (GdkWindow *window, event->crossing.detail = detail; event->crossing.focus = TRUE; /* FIXME: Set correctly */ event->crossing.state = 0; /* FIXME: Set correctly */ + gdk_event_set_device (event, _gdk_display->core_pointer); append_event (event); if (type == GDK_ENTER_NOTIFY && ((GdkWindowObject *) window)->extension_events != 0) - _gdk_input_enter_event (window); + _gdk_device_wintab_update_window_coords (window); } static void @@ -1684,10 +1670,10 @@ handle_display_change (void) } static void -generate_button_event (GdkEventType type, - gint button, - GdkWindow *window, - MSG *msg) +generate_button_event (GdkEventType type, + gint button, + GdkWindow *window, + MSG *msg) { GdkEvent *event = gdk_event_new (type); @@ -1700,7 +1686,7 @@ generate_button_event (GdkEventType type, event->button.axes = NULL; event->button.state = build_pointer_event_state (msg); event->button.button = button; - event->button.device = _gdk_display->core_pointer; + gdk_event_set_device (event, _gdk_display->core_pointer); append_event (event); } @@ -1868,7 +1854,10 @@ gdk_event_translate (MSG *msg, GdkWindow *orig_window, *new_window, *toplevel; - GdkPointerGrabInfo *grab = NULL; + GdkDeviceManager *device_manager; + + GdkDeviceGrabInfo *keyboard_grab = NULL; + GdkDeviceGrabInfo *pointer_grab = NULL; GdkWindow *grab_window = NULL; static gint update_colors_counter = 0; @@ -1929,7 +1918,14 @@ gdk_event_translate (MSG *msg, } return FALSE; } - + + device_manager = gdk_display_get_device_manager (_gdk_display); + + keyboard_grab = _gdk_display_get_last_device_grab (_gdk_display, + GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard); + pointer_grab = _gdk_display_get_last_device_grab (_gdk_display, + GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_pointer); + g_object_ref (window); /* window's refcount has now been increased, so code below should @@ -2047,7 +2043,7 @@ gdk_event_translate (MSG *msg, /* Let the system handle Alt-Tab, Alt-Space and Alt-F4 unless * the keyboard is grabbed. */ - if (_gdk_display->keyboard_grab.window == NULL && + if (!keyboard_grab && (msg->wParam == VK_TAB || msg->wParam == VK_SPACE || msg->wParam == VK_F4)) @@ -2071,9 +2067,10 @@ gdk_event_translate (MSG *msg, in_ime_composition) break; - if (!propagate (&window, msg, - _gdk_display->keyboard_grab.window, - _gdk_display->keyboard_grab.owner_events, + if (keyboard_grab && + !propagate (&window, msg, + keyboard_grab->window, + keyboard_grab->owner_events, GDK_ALL_EVENTS_MASK, doesnt_want_key, FALSE)) break; @@ -2090,6 +2087,7 @@ gdk_event_translate (MSG *msg, event->key.string = NULL; event->key.length = 0; event->key.hardware_keycode = msg->wParam; + gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard); if (HIWORD (msg->lParam) & KF_EXTENDED) { switch (msg->wParam) @@ -2175,9 +2173,10 @@ gdk_event_translate (MSG *msg, if (!(msg->lParam & GCS_RESULTSTR)) break; - if (!propagate (&window, msg, - _gdk_display->keyboard_grab.window, - _gdk_display->keyboard_grab.owner_events, + if (keyboard_grab && + !propagate (&window, msg, + keyboard_grab->window, + keyboard_grab->owner_events, GDK_ALL_EVENTS_MASK, doesnt_want_char, FALSE)) break; @@ -2201,6 +2200,7 @@ gdk_event_translate (MSG *msg, /* Build a key press event */ event = gdk_event_new (GDK_KEY_PRESS); event->key.window = window; + gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard); build_wm_ime_composition_event (event, msg, wbuf[i], key_state); append_event (event); @@ -2211,6 +2211,7 @@ gdk_event_translate (MSG *msg, /* Build a key release event. */ event = gdk_event_new (GDK_KEY_RELEASE); event->key.window = window; + gdk_event_set_device (event, GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard); build_wm_ime_composition_event (event, msg, wbuf[i], key_state); append_event (event); @@ -2307,10 +2308,10 @@ gdk_event_translate (MSG *msg, current_toplevel ? GDK_WINDOW_HWND (current_toplevel) : NULL, toplevel ? GDK_WINDOW_HWND (toplevel) : NULL)); if (current_toplevel) - synthesize_enter_or_leave_event (current_toplevel, msg, - GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); - synthesize_enter_or_leave_event (toplevel, msg, - GDK_ENTER_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); + synthesize_enter_or_leave_event (current_toplevel, msg, + GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); + synthesize_enter_or_leave_event (toplevel, msg, + GDK_ENTER_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); assign_object (¤t_toplevel, toplevel); track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (toplevel)); } @@ -2336,7 +2337,7 @@ gdk_event_translate (MSG *msg, event->motion.axes = NULL; event->motion.state = build_pointer_event_state (msg); event->motion.is_hint = FALSE; - event->motion.device = _gdk_display->core_pointer; + gdk_event_set_device (event, _gdk_display->core_pointer); append_event (event); @@ -2365,8 +2366,8 @@ gdk_event_translate (MSG *msg, { /* we are only interested if we don't know the new window */ if (current_toplevel) - synthesize_enter_or_leave_event (current_toplevel, msg, - GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); + synthesize_enter_or_leave_event (current_toplevel, msg, + GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); assign_object (¤t_toplevel, NULL); } else @@ -2412,7 +2413,7 @@ gdk_event_translate (MSG *msg, event->scroll.x_root = (gint16) GET_X_LPARAM (msg->lParam) + _gdk_offset_x; event->scroll.y_root = (gint16) GET_Y_LPARAM (msg->lParam) + _gdk_offset_y; event->scroll.state = build_pointer_event_state (msg); - event->scroll.device = _gdk_display->core_pointer; + gdk_event_set_device (event, _gdk_display->core_pointer); append_event (event); @@ -2512,16 +2513,16 @@ gdk_event_translate (MSG *msg, break; case WM_KILLFOCUS: - if (_gdk_display->keyboard_grab.window != NULL && - !GDK_WINDOW_DESTROYED (_gdk_display->keyboard_grab.window)) + if (keyboard_grab != NULL && + !GDK_WINDOW_DESTROYED (keyboard_grab->window)) { - generate_grab_broken_event (_gdk_display->keyboard_grab.window, FALSE, NULL); + generate_grab_broken_event (device_manager, keyboard_grab->window, FALSE, NULL); } /* fallthrough */ case WM_SETFOCUS: - if (_gdk_display->keyboard_grab.window != NULL && - !_gdk_display->keyboard_grab.owner_events) + if (keyboard_grab != NULL && + !keyboard_grab->owner_events) break; if (!(((GdkWindowObject *) window)->event_mask & GDK_FOCUS_CHANGE_MASK)) @@ -2530,7 +2531,7 @@ gdk_event_translate (MSG *msg, if (GDK_WINDOW_DESTROYED (window)) break; - generate_focus_event (window, (msg->message == WM_SETFOCUS)); + generate_focus_event (device_manager, window, (msg->message == WM_SETFOCUS)); return_val = TRUE; break; @@ -2558,11 +2559,8 @@ gdk_event_translate (MSG *msg, GDK_NOTE (EVENTS, g_print (" %#x %#x", LOWORD (msg->lParam), HIWORD (msg->lParam))); - grab = _gdk_display_get_last_pointer_grab (_gdk_display); - if (grab != NULL) - { - grab_window = grab->window; - } + if (pointer_grab != NULL) + grab_window = pointer_grab->window; if (grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT) break; @@ -2617,14 +2615,14 @@ gdk_event_translate (MSG *msg, SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner)); } - grab = _gdk_display_get_last_pointer_grab (_gdk_display); - if (grab != NULL) + if (pointer_grab != NULL) { - if (grab->window == window) + if (pointer_grab->window == window) gdk_pointer_ungrab (msg->time); } - if (_gdk_display->keyboard_grab.window == window) + if (keyboard_grab && + keyboard_grab->window == window) gdk_keyboard_ungrab (msg->time); } @@ -2655,13 +2653,13 @@ gdk_event_translate (MSG *msg, if (msg->wParam == SIZE_MINIMIZED) { /* Don't generate any GDK event. This is *not* an UNMAP. */ - grab = _gdk_display_get_last_pointer_grab (_gdk_display); - if (grab != NULL) + if (pointer_grab != NULL) { - if (grab->window == window) + if (pointer_grab->window == window) gdk_pointer_ungrab (msg->time); } - if (_gdk_display->keyboard_grab.window == window) + if (keyboard_grab && + keyboard_grab->window == window) gdk_keyboard_ungrab (msg->time); gdk_synthesize_window_state (window, @@ -2707,7 +2705,7 @@ gdk_event_translate (MSG *msg, ((GdkWindowObject *) window)->resize_count -= 1; if (((GdkWindowObject *) window)->extension_events != 0) - _gdk_input_configure_event (window); + _gdk_device_wintab_update_window_coords (window); return_val = TRUE; } @@ -3089,14 +3087,14 @@ gdk_event_translate (MSG *msg, break; case WM_DESTROY: - grab = _gdk_display_get_last_pointer_grab (_gdk_display); - if (grab != NULL) + if (pointer_grab != NULL) { - if (grab->window == window) + if (pointer_grab->window == window) gdk_pointer_ungrab (msg->time); } - if (_gdk_display->keyboard_grab.window == window) + if (keyboard_grab && + keyboard_grab->window == window) gdk_keyboard_ungrab (msg->time); if ((window != NULL) && (msg->hwnd != GetDesktopWindow ())) diff --git a/gdk/win32/gdkinput-win32.c b/gdk/win32/gdkinput-win32.c deleted file mode 100644 index d02952dc1e..0000000000 --- a/gdk/win32/gdkinput-win32.c +++ /dev/null @@ -1,1392 +0,0 @@ -/* GDK - The GIMP Drawing Kit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * Copyright (C) 1998-2007 Tor Lillqvist - * - * 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. - */ - -/* - * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#include "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <math.h> - -#include "gdk.h" -#include "gdkinput.h" -#include "gdkinternals.h" -#include "gdkprivate-win32.h" -#include "gdkinput-win32.h" - -#define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION) -/* We want everything in absolute mode */ -#define PACKETMODE (0) -#include <pktdef.h> - -#define DEBUG_WINTAB 1 /* Verbose debug messages enabled */ - -#define PROXIMITY_OUT_DELAY 200 /* In milliseconds, see set_ignore_core */ - -#define TWOPI (2.*G_PI) - -/* Forward declarations */ - -static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx, - UINT id); -static GList *wintab_contexts = NULL; - -static GdkWindow *wintab_window = NULL; - -static GdkWindow *x_grab_window = NULL; /* Window that currently holds - * the extended inputs grab - */ -static GdkEventMask x_grab_mask; -static gboolean x_grab_owner_events; - -typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c); -typedef UINT (WINAPI *t_WTInfoW) (UINT a, UINT b, LPVOID c); -typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b); -typedef HCTX (WINAPI *t_WTOpenA) (HWND a, LPLOGCONTEXTA b, BOOL c); -typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b); -typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c); -typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b); - -static t_WTInfoA p_WTInfoA; -static t_WTInfoW p_WTInfoW; -static t_WTEnable p_WTEnable; -static t_WTOpenA p_WTOpenA; -static t_WTOverlap p_WTOverlap; -static t_WTPacket p_WTPacket; -static t_WTQueueSizeSet p_WTQueueSizeSet; - -static GdkDevicePrivate * -gdk_input_find_dev_from_ctx (HCTX hctx, - UINT cursor) -{ - GList *tmp_list = _gdk_input_devices; - GdkDevicePrivate *gdkdev; - - while (tmp_list) - { - gdkdev = (GdkDevicePrivate *) (tmp_list->data); - if (gdkdev->hctx == hctx && gdkdev->cursor == cursor) - return gdkdev; - tmp_list = tmp_list->next; - } - return NULL; -} - -#if DEBUG_WINTAB - -static void -print_lc(LOGCONTEXT *lc) -{ - g_print ("lcName = %s\n", lc->lcName); - g_print ("lcOptions ="); - if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM"); - if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN"); - if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES"); - if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN"); - if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE"); - if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES"); - g_print ("\n"); - g_print ("lcStatus ="); - if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED"); - if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED"); - if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP"); - g_print ("\n"); - g_print ("lcLocks ="); - if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE"); - if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT"); - if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY"); - if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN"); - g_print ("\n"); - g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n", - lc->lcMsgBase, lc->lcDevice, lc->lcPktRate); - g_print ("lcPktData ="); - if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT"); - if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS"); - if (lc->lcPktData & PK_TIME) g_print (" PK_TIME"); - if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED"); - if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER"); - if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR"); - if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS"); - if (lc->lcPktData & PK_X) g_print (" PK_X"); - if (lc->lcPktData & PK_Y) g_print (" PK_Y"); - if (lc->lcPktData & PK_Z) g_print (" PK_Z"); - if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE"); - if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE"); - if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION"); - if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION"); - g_print ("\n"); - g_print ("lcPktMode ="); - if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT"); - if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS"); - if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME"); - if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED"); - if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER"); - if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR"); - if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS"); - if (lc->lcPktMode & PK_X) g_print (" PK_X"); - if (lc->lcPktMode & PK_Y) g_print (" PK_Y"); - if (lc->lcPktMode & PK_Z) g_print (" PK_Z"); - if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE"); - if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE"); - if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION"); - if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION"); - g_print ("\n"); - g_print ("lcMoveMask ="); - if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT"); - if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS"); - if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME"); - if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED"); - if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER"); - if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR"); - if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS"); - if (lc->lcMoveMask & PK_X) g_print (" PK_X"); - if (lc->lcMoveMask & PK_Y) g_print (" PK_Y"); - if (lc->lcMoveMask & PK_Z) g_print (" PK_Z"); - if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE"); - if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE"); - if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION"); - if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION"); - g_print ("\n"); - g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n", - (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask); - g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n", - lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ); - g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n", - lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ); - g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n", - lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ); - g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n", - lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ); - g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n", - lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.); - g_print ("lcSysMode = %d\n", lc->lcSysMode); - g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n", - lc->lcSysOrgX, lc->lcSysOrgY); - g_print ("lcSysExtX = %d, lcSysExtY = %d\n", - lc->lcSysExtX, lc->lcSysExtY); - g_print ("lcSysSensX = %g, lcSysSensY = %g\n", - lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.); -} - -static void -print_cursor (int index) -{ - int size; - int i; - char *name; - BOOL active; - WTPKT wtpkt; - BYTE buttons; - BYTE buttonbits; - char *btnnames; - char *p; - BYTE buttonmap[32]; - BYTE sysbtnmap[32]; - BYTE npbutton; - UINT npbtnmarks[2]; - UINT *npresponse; - BYTE tpbutton; - UINT tpbtnmarks[2]; - UINT *tpresponse; - DWORD physid; - UINT mode; - UINT minpktdata; - UINT minbuttons; - UINT capabilities; - - size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, NULL); - name = g_malloc (size + 1); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, name); - g_print ("NAME: %s\n", name); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_ACTIVE, &active); - g_print ("ACTIVE: %s\n", active ? "YES" : "NO"); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_PKTDATA, &wtpkt); - g_print ("PKTDATA: %#x:", (guint) wtpkt); -#define BIT(x) if (wtpkt & PK_##x) g_print (" " #x) - BIT (CONTEXT); - BIT (STATUS); - BIT (TIME); - BIT (CHANGED); - BIT (SERIAL_NUMBER); - BIT (BUTTONS); - BIT (X); - BIT (Y); - BIT (Z); - BIT (NORMAL_PRESSURE); - BIT (TANGENT_PRESSURE); - BIT (ORIENTATION); - BIT (ROTATION); -#undef BIT - g_print ("\n"); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONS, &buttons); - g_print ("BUTTONS: %d\n", buttons); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONBITS, &buttonbits); - g_print ("BUTTONBITS: %d\n", buttonbits); - size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, NULL); - g_print ("BTNNAMES:"); - if (size > 0) - { - btnnames = g_malloc (size + 1); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, btnnames); - p = btnnames; - while (*p) - { - g_print (" %s", p); - p += strlen (p) + 1; - } - } - g_print ("\n"); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONMAP, buttonmap); - g_print ("BUTTONMAP:"); - for (i = 0; i < buttons; i++) - g_print (" %d", buttonmap[i]); - g_print ("\n"); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_SYSBTNMAP, sysbtnmap); - g_print ("SYSBTNMAP:"); - for (i = 0; i < buttons; i++) - g_print (" %d", sysbtnmap[i]); - g_print ("\n"); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBUTTON, &npbutton); - g_print ("NPBUTTON: %d\n", npbutton); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBTNMARKS, npbtnmarks); - g_print ("NPBTNMARKS: %d %d\n", npbtnmarks[0], npbtnmarks[1]); - size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, NULL); - g_print ("NPRESPONSE:"); - if (size > 0) - { - npresponse = g_malloc (size); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, npresponse); - for (i = 0; i < size / sizeof (UINT); i++) - g_print (" %d", npresponse[i]); - } - g_print ("\n"); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBUTTON, &tpbutton); - g_print ("TPBUTTON: %d\n", tpbutton); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBTNMARKS, tpbtnmarks); - g_print ("TPBTNMARKS: %d %d\n", tpbtnmarks[0], tpbtnmarks[1]); - size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, NULL); - g_print ("TPRESPONSE:"); - if (size > 0) - { - tpresponse = g_malloc (size); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, tpresponse); - for (i = 0; i < size / sizeof (UINT); i++) - g_print (" %d", tpresponse[i]); - } - g_print ("\n"); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_PHYSID, &physid); - g_print ("PHYSID: %#x\n", (guint) physid); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_CAPABILITIES, &capabilities); - g_print ("CAPABILITIES: %#x:", capabilities); -#define BIT(x) if (capabilities & CRC_##x) g_print (" " #x) - BIT (MULTIMODE); - BIT (AGGREGATE); - BIT (INVERT); -#undef BIT - g_print ("\n"); - if (capabilities & CRC_MULTIMODE) - { - (*p_WTInfoA) (WTI_CURSORS + index, CSR_MODE, &mode); - g_print ("MODE: %d\n", mode); - } - if (capabilities & CRC_AGGREGATE) - { - (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINPKTDATA, &minpktdata); - g_print ("MINPKTDATA: %d\n", minpktdata); - (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINBUTTONS, &minbuttons); - g_print ("MINBUTTONS: %d\n", minbuttons); - } -} -#endif - -void -_gdk_input_wintab_init_check (void) -{ - static gboolean wintab_initialized = FALSE; - GdkDevicePrivate *gdkdev; - GdkWindowAttr wa; - WORD specversion; - HCTX *hctx; - UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware; - BOOL active; - DWORD physid; - AXIS axis_x, axis_y, axis_npressure, axis_or[3]; - int i, k; - int devix, cursorix; - wchar_t devname[100], csrname[100]; - gchar *devname_utf8, *csrname_utf8; - BOOL defcontext_done; - HMODULE wintab32; - - if (wintab_initialized) - return; - - wintab_initialized = TRUE; - - wintab_contexts = NULL; - - if (_gdk_input_ignore_wintab) - return; - - if ((wintab32 = LoadLibrary ("wintab32.dll")) == NULL) - return; - - if ((p_WTInfoA = (t_WTInfoA) GetProcAddress (wintab32, "WTInfoA")) == NULL) - return; - if ((p_WTInfoW = (t_WTInfoW) GetProcAddress (wintab32, "WTInfoW")) == NULL) - return; - if ((p_WTEnable = (t_WTEnable) GetProcAddress (wintab32, "WTEnable")) == NULL) - return; - if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL) - return; - if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL) - return; - if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL) - return; - if ((p_WTQueueSizeSet = (t_WTQueueSizeSet) GetProcAddress (wintab32, "WTQueueSizeSet")) == NULL) - return; - - if (!(*p_WTInfoA) (0, 0, NULL)) - return; - - (*p_WTInfoA) (WTI_INTERFACE, IFC_SPECVERSION, &specversion); - GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n", - HIBYTE (specversion), LOBYTE (specversion))); - (*p_WTInfoA) (WTI_INTERFACE, IFC_NDEVICES, &ndevices); - (*p_WTInfoA) (WTI_INTERFACE, IFC_NCURSORS, &ncursors); -#if DEBUG_WINTAB - GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n", - ndevices, ncursors)); -#endif - /* Create a dummy window to receive wintab events */ - wa.wclass = GDK_INPUT_OUTPUT; - wa.event_mask = GDK_ALL_EVENTS_MASK; - wa.width = 2; - wa.height = 2; - wa.x = -100; - wa.y = -100; - wa.window_type = GDK_WINDOW_TOPLEVEL; - if ((wintab_window = gdk_window_new (NULL, &wa, GDK_WA_X|GDK_WA_Y)) == NULL) - { - g_warning ("gdk_input_wintab_init: gdk_window_new failed"); - return; - } - g_object_ref (wintab_window); - - for (devix = 0; devix < ndevices; devix++) - { - LOGCONTEXT lc; - - /* We open the Wintab device (hmm, what if there are several, or - * can there even be several, probably not?) as a system - * pointing device, i.e. it controls the normal Windows - * cursor. This seems much more natural. - */ - - (*p_WTInfoW) (WTI_DEVICES + devix, DVC_NAME, devname); - devname_utf8 = g_utf16_to_utf8 (devname, -1, NULL, NULL, NULL); -#ifdef DEBUG_WINTAB - GDK_NOTE (INPUT, (g_print("Device %d: %s\n", devix, devname_utf8))); -#endif - (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes); - (*p_WTInfoA) (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr); - (*p_WTInfoA) (WTI_DEVICES + devix, DVC_HARDWARE, &hardware); - (*p_WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x); - (*p_WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y); - (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure); - (*p_WTInfoA) (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or); - - defcontext_done = FALSE; - if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1) - { - /* Try to get device-specific default context */ - /* Some drivers, e.g. Aiptek, don't provide this info */ - if ((*p_WTInfoA) (WTI_DSCTXS + devix, 0, &lc) > 0) - defcontext_done = TRUE; -#if DEBUG_WINTAB - if (defcontext_done) - GDK_NOTE (INPUT, (g_print("Using device-specific default context\n"))); - else - GDK_NOTE (INPUT, (g_print("Note: Driver did not provide device specific default context info despite claiming to support version 1.1\n"))); -#endif - } - - if (!defcontext_done) - (*p_WTInfoA) (WTI_DEFSYSCTX, 0, &lc); -#if DEBUG_WINTAB - GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc))); -#endif - lc.lcOptions |= CXO_MESSAGES; - lc.lcStatus = 0; - lc.lcMsgBase = WT_DEFBASE; - lc.lcPktRate = 0; - lc.lcPktData = PACKETDATA; - lc.lcPktMode = PACKETMODE; - lc.lcMoveMask = PACKETDATA; - lc.lcBtnUpMask = lc.lcBtnDnMask = ~0; - lc.lcOutOrgX = axis_x.axMin; - lc.lcOutOrgY = axis_y.axMin; - lc.lcOutExtX = axis_x.axMax - axis_x.axMin; - lc.lcOutExtY = axis_y.axMax - axis_y.axMin; - lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */ -#if DEBUG_WINTAB - GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix), - print_lc(&lc))); -#endif - hctx = g_new (HCTX, 1); - if ((*hctx = (*p_WTOpenA) (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL) - { - g_warning ("gdk_input_wintab_init: WTOpen failed"); - return; - } - GDK_NOTE (INPUT, g_print ("opened Wintab device %d %p\n", - devix, *hctx)); - - wintab_contexts = g_list_append (wintab_contexts, hctx); -#if 0 - (*p_WTEnable) (*hctx, TRUE); -#endif - (*p_WTOverlap) (*hctx, TRUE); - -#if DEBUG_WINTAB - GDK_NOTE (INPUT, (g_print("context for device %d after WTOpen:\n", devix), - print_lc(&lc))); -#endif - /* Increase packet queue size to reduce the risk of lost packets. - * According to the specs, if the function fails we must try again - * with a smaller queue size. - */ - GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n")); - for (i = 32; i >= 1; i >>= 1) - { - if ((*p_WTQueueSizeSet) (*hctx, i)) - { - GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i)); - break; - } - } - if (!i) - GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n")); - for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++) - { -#ifdef DEBUG_WINTAB - GDK_NOTE (INPUT, (g_print("Cursor %d:\n", cursorix), print_cursor (cursorix))); -#endif - active = FALSE; - (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_ACTIVE, &active); - if (!active) - continue; - - /* Wacom tablets seem to report cursors corresponding to - * nonexistent pens or pucks. At least my ArtPad II reports - * six cursors: a puck, pressure stylus and eraser stylus, - * and then the same three again. I only have a - * pressure-sensitive pen. The puck instances, and the - * second instances of the styluses report physid zero. So - * at least for Wacom, skip cursors with physid zero. - */ - (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PHYSID, &physid); - if (wcscmp (devname, L"WACOM Tablet") == 0 && physid == 0) - continue; - - gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL); - (*p_WTInfoW) (WTI_CURSORS + cursorix, CSR_NAME, csrname); - csrname_utf8 = g_utf16_to_utf8 (csrname, -1, NULL, NULL, NULL); - gdkdev->info.name = g_strconcat (devname_utf8, " ", csrname_utf8, NULL); - g_free (csrname_utf8); - gdkdev->info.source = GDK_SOURCE_PEN; - gdkdev->info.mode = GDK_MODE_SCREEN; - gdkdev->info.has_cursor = TRUE; - gdkdev->hctx = *hctx; - gdkdev->cursor = cursorix; - (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata); - gdkdev->info.num_axes = 0; - if (gdkdev->pktdata & PK_X) - gdkdev->info.num_axes++; - if (gdkdev->pktdata & PK_Y) - gdkdev->info.num_axes++; - if (gdkdev->pktdata & PK_NORMAL_PRESSURE) - gdkdev->info.num_axes++; - /* The wintab driver for the Wacom ArtPad II reports - * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't - * actually sense tilt. Catch this by noticing that the - * orientation axis's azimuth resolution is zero. - */ - if ((gdkdev->pktdata & PK_ORIENTATION) - && axis_or[0].axResolution == 0) - gdkdev->pktdata &= ~PK_ORIENTATION; - - if (gdkdev->pktdata & PK_ORIENTATION) - gdkdev->info.num_axes += 2; /* x and y tilt */ - - gdkdev->info.axes = g_new (GdkDeviceAxis, gdkdev->info.num_axes); - gdkdev->axes = g_new (GdkAxisInfo, gdkdev->info.num_axes); - gdkdev->last_axis_data = g_new (gint, gdkdev->info.num_axes); - - k = 0; - if (gdkdev->pktdata & PK_X) - { - gdkdev->axes[k].resolution = axis_x.axResolution / 65535.; - gdkdev->axes[k].min_value = axis_x.axMin; - gdkdev->axes[k].max_value = axis_x.axMax; - gdkdev->info.axes[k].use = GDK_AXIS_X; - gdkdev->info.axes[k].min = axis_x.axMin; - gdkdev->info.axes[k].max = axis_x.axMax; - k++; - } - if (gdkdev->pktdata & PK_Y) - { - gdkdev->axes[k].resolution = axis_y.axResolution / 65535.; - gdkdev->axes[k].min_value = axis_y.axMin; - gdkdev->axes[k].max_value = axis_y.axMax; - gdkdev->info.axes[k].use = GDK_AXIS_Y; - gdkdev->info.axes[k].min = axis_y.axMin; - gdkdev->info.axes[k].max = axis_y.axMax; - k++; - } - if (gdkdev->pktdata & PK_NORMAL_PRESSURE) - { - gdkdev->axes[k].resolution = axis_npressure.axResolution / 65535.; - gdkdev->axes[k].min_value = axis_npressure.axMin; - gdkdev->axes[k].max_value = axis_npressure.axMax; - gdkdev->info.axes[k].use = GDK_AXIS_PRESSURE; - /* GIMP seems to expect values in the range 0-1 */ - gdkdev->info.axes[k].min = 0.0; /*axis_npressure.axMin;*/ - gdkdev->info.axes[k].max = 1.0; /*axis_npressure.axMax;*/ - k++; - } - if (gdkdev->pktdata & PK_ORIENTATION) - { - GdkAxisUse axis; - - gdkdev->orientation_axes[0] = axis_or[0]; - gdkdev->orientation_axes[1] = axis_or[1]; - for (axis = GDK_AXIS_XTILT; axis <= GDK_AXIS_YTILT; axis++) - { - /* Wintab gives us aximuth and altitude, which - * we convert to x and y tilt in the -1000..1000 range - */ - gdkdev->axes[k].resolution = 1000; - gdkdev->axes[k].min_value = -1000; - gdkdev->axes[k].max_value = 1000; - gdkdev->info.axes[k].use = axis; - gdkdev->info.axes[k].min = -1000; - gdkdev->info.axes[k].max = 1000; - k++; - } - } - gdkdev->info.num_keys = 0; - gdkdev->info.keys = NULL; - GDK_NOTE (INPUT, g_print ("device: (%d) %s axes: %d\n", - cursorix, - gdkdev->info.name, - gdkdev->info.num_axes)); - for (i = 0; i < gdkdev->info.num_axes; i++) - GDK_NOTE (INPUT, g_print ("... axis %d: %d--%d@%d\n", - i, - gdkdev->axes[i].min_value, - gdkdev->axes[i].max_value, - gdkdev->axes[i].resolution)); - _gdk_input_devices = g_list_append (_gdk_input_devices, - gdkdev); - } - g_free (devname_utf8); - } -} - -static void -decode_tilt (gint *axis_data, - AXIS *axes, - PACKET *packet) -{ - /* As I don't have a tilt-sensing tablet, - * I cannot test this code. - */ - - double az, el; - - az = TWOPI * packet->pkOrientation.orAzimuth / - (axes[0].axResolution / 65536.); - el = TWOPI * packet->pkOrientation.orAltitude / - (axes[1].axResolution / 65536.); - - /* X tilt */ - axis_data[0] = cos (az) * cos (el) * 1000; - /* Y tilt */ - axis_data[1] = sin (az) * cos (el) * 1000; -} - -static void -gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev, - GdkInputWindow *input_window, - gint *axis_data, - gdouble *axis_out, - gdouble *x_out, - gdouble *y_out) -{ - GdkWindowImplWin32 *root_impl; - GdkWindowObject *window_object; - - int i; - int x_axis = 0; - int y_axis = 0; - - double device_width, device_height; - double x_offset, y_offset, x_scale, y_scale; - - window_object = GDK_WINDOW_OBJECT (input_window); - - for (i=0; i<gdkdev->info.num_axes; i++) - { - switch (gdkdev->info.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 (gdkdev->info.mode == GDK_MODE_SCREEN) - { - root_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl); - x_scale = GDK_WINDOW_OBJECT (_gdk_root)->width / device_width; - y_scale = GDK_WINDOW_OBJECT (_gdk_root)->height / device_height; - - x_offset = - input_window->root_x; - y_offset = - input_window->root_y; - } - else /* GDK_MODE_WINDOW */ - { - double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) / - (device_width*gdkdev->axes[x_axis].resolution); - - if (device_aspect * window_object->width >= window_object->height) - { - /* device taller than window */ - x_scale = window_object->width / device_width; - y_scale = (x_scale * gdkdev->axes[x_axis].resolution) / gdkdev->axes[y_axis].resolution; - - x_offset = 0; - y_offset = -(device_height * y_scale - window_object->height) / 2; - } - else - { - /* window taller than device */ - y_scale = window_object->height / device_height; - x_scale = (y_scale * gdkdev->axes[y_axis].resolution) - / gdkdev->axes[x_axis].resolution; - - y_offset = 0; - x_offset = - (device_width * x_scale - window_object->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]; - if (x_out) - *x_out = axis_out[i]; - break; - case GDK_AXIS_Y: - axis_out[i] = y_offset + y_scale * axis_data[y_axis]; - if (y_out) - *y_out = axis_out[i]; - break; - default: - axis_out[i] = - (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) + - gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) / - (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value); - break; - } - } -} - -static void -gdk_input_get_root_relative_geometry (HWND w, - int *x_ret, - int *y_ret) -{ - RECT rect; - - GetWindowRect (w, &rect); - - if (x_ret) - *x_ret = rect.left + _gdk_offset_x; - if (y_ret) - *y_ret = rect.top + _gdk_offset_y; -} - -void -_gdk_input_configure_event (GdkWindow *window) -{ - GdkInputWindow *input_window; - int root_x, root_y; - - input_window = _gdk_input_window_find (window); - g_return_if_fail (window != NULL); - - gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), - &root_x, &root_y); - - input_window->root_x = root_x; - input_window->root_y = root_y; -} - -void -_gdk_input_enter_event (GdkWindow *window) -{ - GdkInputWindow *input_window; - int root_x, root_y; - - input_window = _gdk_input_window_find (window); - g_return_if_fail (window != NULL); - - gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y); - - input_window->root_x = root_x; - input_window->root_y = root_y; -} - -/* - * Get the currently active keyboard modifiers (ignoring the mouse buttons) - * We could use gdk_window_get_pointer but that function does a lot of other - * expensive things besides getting the modifiers. This code is somewhat based - * on build_pointer_event_state from gdkevents-win32.c - */ -static guint -get_modifier_key_state (void) -{ - guint state; - - state = 0; - /* High-order bit is up/down, low order bit is toggled/untoggled */ - if (GetKeyState (VK_CONTROL) < 0) - state |= GDK_CONTROL_MASK; - if (GetKeyState (VK_SHIFT) < 0) - state |= GDK_SHIFT_MASK; - if (GetKeyState (VK_MENU) < 0) - state |= GDK_MOD1_MASK; - if (GetKeyState (VK_CAPITAL) & 0x1) - state |= GDK_LOCK_MASK; - - return state; -} - -static guint ignore_core_timer = 0; - -static gboolean -ignore_core_timefunc (gpointer data) -{ - /* The delay has passed */ - _gdk_input_ignore_core = FALSE; - ignore_core_timer = 0; - - return FALSE; /* remove timeout */ -} - -/* - * Set or unset the _gdk_input_ignore_core variable that tells GDK - * to ignore events for the core pointer when the tablet is in proximity - * The unsetting is delayed slightly so that if a tablet event arrives - * just after proximity out, it does not cause a core pointer event - * which e.g. causes GIMP to switch tools. - */ -static void -set_ignore_core (gboolean ignore) -{ - if (ignore) - { - _gdk_input_ignore_core = TRUE; - /* Remove any pending clear */ - if (ignore_core_timer) - { - g_source_remove (ignore_core_timer); - ignore_core_timer = 0; - } - } - else - if (!ignore_core_timer) - ignore_core_timer = gdk_threads_add_timeout (PROXIMITY_OUT_DELAY, - ignore_core_timefunc, NULL); -} - -gboolean -_gdk_input_other_event (GdkEvent *event, - MSG *msg, - GdkWindow *window) -{ - GdkDisplay *display; - GdkWindowObject *obj, *grab_obj; - GdkInputWindow *input_window; - GdkDevicePrivate *gdkdev = NULL; - GdkEventMask masktest; - guint key_state; - POINT pt; - - PACKET packet; - gint k; - gint x, y; - guint translated_buttons, button_diff, button_mask; - /* Translation from tablet button state to GDK button state for - * buttons 1-3 - swap button 2 and 3. - */ - static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7}; - - if (event->any.window != wintab_window) - { - g_warning ("_gdk_input_other_event: not wintab_window?"); - return FALSE; - } - - window = gdk_window_at_pointer (&x, &y); - if (window == NULL) - window = _gdk_root; - - g_object_ref (window); - display = gdk_drawable_get_display (window); - - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("_gdk_input_other_event: window=%p %+d%+d\n", - GDK_WINDOW_HWND (window), x, y)); - - if (msg->message == WT_PACKET) - { - if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet)) - return FALSE; - } - - obj = GDK_WINDOW_OBJECT (window); - - switch (msg->message) - { - case WT_PACKET: - /* Don't produce any button or motion events while a window is being - * moved or resized, see bug #151090. - */ - if (_modal_operation_in_progress) - { - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n")); - return FALSE; - } - if (window == _gdk_root && x_grab_window == NULL) - { - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n")); - return FALSE; - } - - if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam, - packet.pkCursor)) == NULL) - return FALSE; - - if (gdkdev->info.mode == GDK_MODE_DISABLED) - return FALSE; - - k = 0; - if (gdkdev->pktdata & PK_X) - gdkdev->last_axis_data[k++] = packet.pkX; - if (gdkdev->pktdata & PK_Y) - gdkdev->last_axis_data[k++] = packet.pkY; - if (gdkdev->pktdata & PK_NORMAL_PRESSURE) - gdkdev->last_axis_data[k++] = packet.pkNormalPressure; - if (gdkdev->pktdata & PK_ORIENTATION) - { - decode_tilt (gdkdev->last_axis_data + k, - gdkdev->orientation_axes, &packet); - k += 2; - } - - g_assert (k == gdkdev->info.num_axes); - - translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07); - - if (translated_buttons != gdkdev->button_state) - { - /* At least one button has changed state so produce a button event - * If more than one button has changed state (unlikely), - * just care about the first and act on the next the next time - * we get a packet - */ - button_diff = translated_buttons ^ gdkdev->button_state; - - /* Gdk buttons are numbered 1.. */ - event->button.button = 1; - - for (button_mask = 1; button_mask != 0x80000000; - button_mask <<= 1, event->button.button++) - { - if (button_diff & button_mask) - { - /* Found a button that has changed state */ - break; - } - } - - if (!(translated_buttons & button_mask)) - { - event->any.type = GDK_BUTTON_RELEASE; - masktest = GDK_BUTTON_RELEASE_MASK; - } - else - { - event->any.type = GDK_BUTTON_PRESS; - masktest = GDK_BUTTON_PRESS_MASK; - } - gdkdev->button_state ^= button_mask; - } - else - { - event->any.type = GDK_MOTION_NOTIFY; - masktest = GDK_POINTER_MOTION_MASK; - if (gdkdev->button_state & (1 << 0)) - masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK; - if (gdkdev->button_state & (1 << 1)) - masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK; - if (gdkdev->button_state & (1 << 2)) - masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK; - } - - /* See if input is grabbed */ - /* FIXME: x_grab_owner_events should probably be handled somehow */ - if (x_grab_window != NULL) - { - grab_obj = GDK_WINDOW_OBJECT (x_grab_window); - if (!GDK_WINDOW_IMPL_WIN32 (grab_obj->impl)->extension_events_selected - || !(grab_obj->extension_events & masktest) - || !(x_grab_mask && masktest)) - { - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("... grabber doesn't want it\n")); - return FALSE; - } - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... to grabber\n")); - - g_object_ref(x_grab_window); - g_object_unref(window); - window = x_grab_window; - obj = grab_obj; - } - /* Now we can check if the window wants the event, and - * propagate if necessary. - */ - loop: - if (!GDK_WINDOW_IMPL_WIN32 (obj->impl)->extension_events_selected - || !(obj->extension_events & masktest)) - { - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n")); - - if (obj->parent == GDK_WINDOW_OBJECT (_gdk_root)) - return FALSE; - - /* It is not good to propagate the extended events up to the parent - * if this window wants normal (not extended) motion/button events */ - if (obj->event_mask & masktest) - { - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("... wants ordinary event, ignoring this\n")); - return FALSE; - } - - pt.x = x; - pt.y = y; - ClientToScreen (GDK_WINDOW_HWND (window), &pt); - g_object_unref (window); - window = (GdkWindow *) obj->parent; - obj = GDK_WINDOW_OBJECT (window); - g_object_ref (window); - ScreenToClient (GDK_WINDOW_HWND (window), &pt); - x = pt.x; - y = pt.y; - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n", - GDK_WINDOW_HWND (window), x, y)); - goto loop; - } - - input_window = _gdk_input_window_find (window); - - g_assert (input_window != NULL); - - if (gdkdev->info.mode == GDK_MODE_WINDOW - && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR) - return FALSE; - - event->any.window = window; - key_state = get_modifier_key_state (); - if (event->any.type == GDK_BUTTON_PRESS - || event->any.type == GDK_BUTTON_RELEASE) - { - event->button.time = _gdk_win32_get_next_tick (msg->time); - event->button.device = &gdkdev->info; - - event->button.axes = g_new(gdouble, gdkdev->info.num_axes); - - gdk_input_translate_coordinates (gdkdev, input_window, - gdkdev->last_axis_data, - event->button.axes, - &event->button.x, - &event->button.y); - - /* Also calculate root coordinates. Note that input_window->root_x - is in GDK root coordinates. */ - event->button.x_root = event->button.x + input_window->root_x; - event->button.y_root = event->button.y + input_window->root_y; - - event->button.state = ((gdkdev->button_state << 8) - & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK - | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK - | GDK_BUTTON5_MASK)) - | key_state; - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("WINTAB button %s:%d %g,%g\n", - (event->button.type == GDK_BUTTON_PRESS ? - "press" : "release"), - event->button.button, - event->button.x, event->button.y)); - } - else - { - event->motion.time = _gdk_win32_get_next_tick (msg->time); - event->motion.is_hint = FALSE; - event->motion.device = &gdkdev->info; - - event->motion.axes = g_new(gdouble, gdkdev->info.num_axes); - - gdk_input_translate_coordinates (gdkdev, input_window, - gdkdev->last_axis_data, - event->motion.axes, - &event->motion.x, - &event->motion.y); - - /* Also calculate root coordinates. Note that input_window->root_x - is in GDK root coordinates. */ - event->motion.x_root = event->motion.x + input_window->root_x; - event->motion.y_root = event->motion.y + input_window->root_y; - - event->motion.state = ((gdkdev->button_state << 8) - & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK - | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK - | GDK_BUTTON5_MASK)) - | key_state; - - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("WINTAB motion: %g,%g\n", - event->motion.x, event->motion.y)); - } - return TRUE; - - case WT_PROXIMITY: - if (LOWORD (msg->lParam) == 0) - { - event->proximity.type = GDK_PROXIMITY_OUT; - set_ignore_core (FALSE); - } - else - { - event->proximity.type = GDK_PROXIMITY_IN; - set_ignore_core (TRUE); - } - event->proximity.time = _gdk_win32_get_next_tick (msg->time); - event->proximity.device = &gdkdev->info; - - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("WINTAB proximity %s\n", - (event->proximity.type == GDK_PROXIMITY_IN ? - "in" : "out"))); - return TRUE; - } - return FALSE; -} - -gboolean -_gdk_input_enable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev) -{ - GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); - - impl->extension_events_selected = TRUE; - - return TRUE; -} - -gboolean -_gdk_input_disable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev) -{ - GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); - - impl->extension_events_selected = FALSE; - - return TRUE; -} - -gint -_gdk_input_grab_pointer (GdkWindow *window, - gint owner_events, - GdkEventMask event_mask, - GdkWindow *confine_to, - guint32 time) -{ - GdkInputWindow *input_window, *new_window; - gboolean need_ungrab; - GdkDevicePrivate *gdkdev; - GList *tmp_list; - - tmp_list = _gdk_input_windows; - new_window = NULL; - need_ungrab = FALSE; - - GDK_NOTE (INPUT, g_print ("_gdk_input_grab_pointer: %p %d %p\n", - GDK_WINDOW_HWND (window), - owner_events, - (confine_to ? GDK_WINDOW_HWND (confine_to) : 0))); - - while (tmp_list) - { - input_window = (GdkInputWindow *)tmp_list->data; - - if (input_window->window == window) - new_window = input_window; - else if (input_window->grabbed) - { - input_window->grabbed = FALSE; - need_ungrab = TRUE; - } - - tmp_list = tmp_list->next; - } - - if (new_window) - { - new_window->grabbed = TRUE; - x_grab_window = window; - x_grab_mask = event_mask; - x_grab_owner_events = owner_events; - - /* FIXME: Do we need to handle confine_to and time? */ - - tmp_list = _gdk_input_devices; - while (tmp_list) - { - gdkdev = (GdkDevicePrivate *)tmp_list->data; - if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx) - { -#if 0 - /* XXX */ - gdk_input_common_find_events (window, gdkdev, - event_mask, - event_classes, &num_classes); - - result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice, - GDK_WINDOW_XWINDOW (window), - owner_events, num_classes, event_classes, - GrabModeAsync, GrabModeAsync, time); - - /* FIXME: if failure occurs on something other than the first - device, things will be badly inconsistent */ - if (result != Success) - return result; -#endif - } - tmp_list = tmp_list->next; - } - } - else - { - x_grab_window = NULL; -#if 0 - tmp_list = _gdk_input_devices; - while (tmp_list) - { - gdkdev = (GdkDevicePrivate *)tmp_list->data; - if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx && - ((gdkdev->button_state != 0) || need_ungrab)) - { -#if 0 - /* XXX */ - XUngrabDevice (gdk_display, gdkdev->xdevice, time); -#endif - gdkdev->button_state = 0; - } - - tmp_list = tmp_list->next; - } -#endif - } - - return GDK_GRAB_SUCCESS; -} - -void -_gdk_input_ungrab_pointer (guint32 time) -{ - GdkInputWindow *input_window; - GdkDevicePrivate *gdkdev; - GList *tmp_list; - - GDK_NOTE (INPUT, g_print ("_gdk_input_ungrab_pointer\n")); - - tmp_list = _gdk_input_windows; - while (tmp_list) - { - input_window = (GdkInputWindow *)tmp_list->data; - if (input_window->grabbed) - break; - tmp_list = tmp_list->next; - } - - if (tmp_list) /* we found a grabbed window */ - { - input_window->grabbed = FALSE; - - tmp_list = _gdk_input_devices; - while (tmp_list) - { - gdkdev = (GdkDevicePrivate *)tmp_list->data; -#if 0 - /* XXX */ - if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice) - XUngrabDevice (gdk_display, gdkdev->xdevice, time); -#endif - tmp_list = tmp_list->next; - } - } - x_grab_window = NULL; -} - -gboolean -_gdk_device_get_history (GdkDevice *device, - GdkWindow *window, - guint32 start, - guint32 stop, - GdkTimeCoord ***events, - gint *n_events) -{ - return FALSE; -} - -void -gdk_device_get_state (GdkDevice *device, - GdkWindow *window, - gdouble *axes, - GdkModifierType *mask) -{ - g_return_if_fail (device != NULL); - g_return_if_fail (GDK_IS_WINDOW (window)); - - if (GDK_IS_CORE (device)) - { - 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; - } - } - else - { - GdkDevicePrivate *gdkdev; - GdkInputWindow *input_window; - - gdkdev = (GdkDevicePrivate *)device; - /* For now just use the last known button and axis state of the device. - * Since graphical tablets send an insane amount of motion events each - * second, the info should be fairly up to date */ - if (mask) - { - gdk_window_get_pointer (window, NULL, NULL, mask); - *mask &= 0xFF; /* Mask away core pointer buttons */ - *mask |= ((gdkdev->button_state << 8) - & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK - | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK - | GDK_BUTTON5_MASK)); - } - input_window = _gdk_input_window_find (window); - g_return_if_fail (input_window != NULL); - /* For some reason, input_window is sometimes NULL when I use The GIMP 2 - * (bug #141543?). Avoid crashing if debugging is disabled. */ - if (axes && gdkdev->last_axis_data && input_window) - gdk_input_translate_coordinates (gdkdev, input_window, - gdkdev->last_axis_data, - axes, NULL, NULL); - } -} - -void -_gdk_input_set_tablet_active (void) -{ - GList *tmp_list; - HCTX *hctx; - - /* Bring the contexts to the top of the overlap order when one of the - * application's windows is activated */ - - if (!wintab_contexts) - return; /* No tablet devices found, or Wintab not initialized yet */ - - GDK_NOTE (INPUT, g_print ("_gdk_input_set_tablet_active: " - "Bringing Wintab contexts to the top of the overlap order\n")); - - tmp_list = wintab_contexts; - while (tmp_list) - { - hctx = (HCTX *) (tmp_list->data); - (*p_WTOverlap) (*hctx, TRUE); - tmp_list = tmp_list->next; - } -} - -void -_gdk_input_init (GdkDisplay *display) -{ - _gdk_input_ignore_core = FALSE; - _gdk_input_devices = NULL; - - _gdk_init_input_core (display); -#ifdef WINTAB_NO_LAZY_INIT - /* Normally, Wintab is only initialized when the application performs - * an action that requires it, such as enabling extended input events - * for a window or enumerating the devices. - */ - _gdk_input_wintab_init_check (); -#endif /* WINTAB_NO_LAZY_INIT */ - - _gdk_input_devices = g_list_append (_gdk_input_devices, display->core_pointer); -} - diff --git a/gdk/win32/gdkinput-win32.h b/gdk/win32/gdkinput-win32.h deleted file mode 100644 index 608d8f99d6..0000000000 --- a/gdk/win32/gdkinput-win32.h +++ /dev/null @@ -1,147 +0,0 @@ -/* GDK - The GIMP Drawing Kit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#ifndef __GDK_INPUT_WIN32_H__ -#define __GDK_INPUT_WIN32_H__ - -#include <windows.h> -#include <wintab.h> - -typedef struct _GdkAxisInfo GdkAxisInfo; -typedef struct _GdkDevicePrivate GdkDevicePrivate; - -/* information about a device axis */ -struct _GdkAxisInfo -{ - /* calibrated resolution (for aspect ratio) - only relative values - between axes used */ - gint resolution; - - /* calibrated minimum/maximum values */ - gint min_value, max_value; -}; - -struct _GdkDeviceClass -{ - GObjectClass parent_class; -}; - -struct _GdkDevicePrivate -{ - GdkDevice info; - - /* information about the axes */ - GdkAxisInfo *axes; - - gint button_state; - - gint *last_axis_data; - - /* WINTAB stuff: */ - HCTX hctx; - /* Cursor number */ - UINT cursor; - /* The cursor's CSR_PKTDATA */ - WTPKT pktdata; - /* Azimuth and altitude axis */ - AXIS orientation_axes[2]; -}; - -struct _GdkInputWindow -{ - /* gdk window */ - GdkWindow *window; - - /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */ - GdkExtensionMode mode; - - /* position relative to root window */ - gint root_x; - gint root_y; - - /* rectangles relative to window of windows obscuring this one */ - GdkRectangle *obscuring; - gint num_obscuring; - - /* Is there a pointer grab for this window ? */ - gint grabbed; -}; - -/* Global data */ - -#define GDK_IS_CORE(d) (((GdkDevice *)(d)) == gdk_display_get_default ()->core_pointer) - -extern GList *_gdk_input_devices; -extern GList *_gdk_input_windows; - -extern gint _gdk_input_ignore_core; - -/* Function declarations */ -void _gdk_init_input_core (GdkDisplay *display); - -GdkTimeCoord ** _gdk_device_allocate_history (GdkDevice *device, - gint n_events); - -/* The following functions are provided by each implementation - * (just wintab for now) - */ -void _gdk_input_configure_event (GdkWindow *window); -void _gdk_input_enter_event (GdkWindow *window); -gboolean _gdk_input_other_event (GdkEvent *event, - MSG *msg, - GdkWindow *window); - -void _gdk_input_crossing_event (GdkWindow *window, - gboolean enter); - - -/* These should be in gdkinternals.h */ - -GdkInputWindow *_gdk_input_window_find (GdkWindow *window); - -void _gdk_input_window_destroy (GdkWindow *window); - -gint _gdk_input_enable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev); -gint _gdk_input_disable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev); -gint _gdk_input_grab_pointer (GdkWindow *window, - gint owner_events, - GdkEventMask event_mask, - GdkWindow *confine_to, - guint32 time); -void _gdk_input_ungrab_pointer (guint32 time); -gboolean _gdk_device_get_history (GdkDevice *device, - GdkWindow *window, - guint32 start, - guint32 stop, - GdkTimeCoord ***events, - gint *n_events); - -void _gdk_input_wintab_init_check (void); -void _gdk_input_set_tablet_active (void); - -#endif /* __GDK_INPUT_WIN32_H__ */ diff --git a/gdk/win32/gdkinput.c b/gdk/win32/gdkinput.c index e5ab44b720..32de7fc28d 100644 --- a/gdk/win32/gdkinput.c +++ b/gdk/win32/gdkinput.c @@ -37,63 +37,13 @@ #include "gdkinput.h" #include "gdkprivate-win32.h" -#include "gdkinput-win32.h" - -static GdkDeviceAxis gdk_input_core_axes[] = { - { GDK_AXIS_X, 0, 0 }, - { GDK_AXIS_Y, 0, 0 } -}; - -/* Global variables */ +#include "gdkdevicemanager-win32.h" gint _gdk_input_ignore_core; GList *_gdk_input_devices; GList *_gdk_input_windows; -void -_gdk_init_input_core (GdkDisplay *display) -{ - display->core_pointer = g_object_new (GDK_TYPE_DEVICE, NULL); - - display->core_pointer->name = "Core Pointer"; - display->core_pointer->source = GDK_SOURCE_MOUSE; - display->core_pointer->mode = GDK_MODE_SCREEN; - display->core_pointer->has_cursor = TRUE; - display->core_pointer->num_axes = 2; - display->core_pointer->axes = gdk_input_core_axes; - display->core_pointer->num_keys = 0; - display->core_pointer->keys = NULL; -} - -GType -gdk_device_get_type (void) -{ - static GType object_type = 0; - - if (!object_type) - { - const GTypeInfo object_info = - { - sizeof (GdkDeviceClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) NULL, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GdkDevicePrivate), - 0, /* n_preallocs */ - (GInstanceInitFunc) NULL, - }; - - object_type = g_type_register_static (G_TYPE_OBJECT, - g_intern_static_string ("GdkDevice"), - &object_info, 0); - } - - return object_type; -} - GList * gdk_devices_list (void) { @@ -105,188 +55,9 @@ gdk_display_list_devices (GdkDisplay *dpy) { g_return_val_if_fail (dpy == _gdk_display, NULL); - _gdk_input_wintab_init_check (); return _gdk_input_devices; } -G_CONST_RETURN gchar * -gdk_device_get_name (GdkDevice *device) -{ - g_return_val_if_fail (GDK_IS_DEVICE (device), NULL); - - return device->name; -} - -GdkInputSource -gdk_device_get_source (GdkDevice *device) -{ - g_return_val_if_fail (GDK_IS_DEVICE (device), 0); - - return device->source; -} - -GdkInputMode -gdk_device_get_mode (GdkDevice *device) -{ - g_return_val_if_fail (GDK_IS_DEVICE (device), 0); - - return device->mode; -} - -gboolean -gdk_device_get_has_cursor (GdkDevice *device) -{ - g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE); - - return device->has_cursor; -} - -void -gdk_device_set_source (GdkDevice *device, - GdkInputSource source) -{ - g_return_if_fail (device != NULL); - - device->source = source; -} - -void -gdk_device_get_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); - - if (!device->keys[index].keyval && - !device->keys[index].modifiers) - return; - - if (keyval) - *keyval = device->keys[index].keyval; - - if (modifiers) - *modifiers = device->keys[index].modifiers; -} - -void -gdk_device_set_key (GdkDevice *device, - guint index, - guint keyval, - GdkModifierType modifiers) -{ - g_return_if_fail (device != NULL); - g_return_if_fail (index < device->num_keys); - - device->keys[index].keyval = keyval; - device->keys[index].modifiers = modifiers; -} - -GdkAxisUse -gdk_device_get_axis_use (GdkDevice *device, - guint index) -{ - g_return_val_if_fail (GDK_IS_DEVICE (device), GDK_AXIS_IGNORE); - g_return_val_if_fail (index < device->num_axes, GDK_AXIS_IGNORE); - - return device->axes[index].use; -} - -void -gdk_device_set_axis_use (GdkDevice *device, - guint index, - GdkAxisUse use) -{ - g_return_if_fail (device != NULL); - 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; - } -} - -gboolean -gdk_device_get_history (GdkDevice *device, - GdkWindow *window, - guint32 start, - guint32 stop, - GdkTimeCoord ***events, - gint *n_events) -{ - g_return_val_if_fail (window != NULL, FALSE); - g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); - g_return_val_if_fail (events != NULL, FALSE); - g_return_val_if_fail (n_events != NULL, FALSE); - - if (n_events) - *n_events = 0; - if (events) - *events = NULL; - - if (GDK_WINDOW_DESTROYED (window)) - return FALSE; - - if (GDK_IS_CORE (device)) - return FALSE; - else - return _gdk_device_get_history (device, window, start, stop, events, n_events); -} - -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; -} - -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); -} - -GdkInputWindow * -_gdk_input_window_find(GdkWindow *window) -{ - GList *tmp_list; - - for (tmp_list=_gdk_input_windows; tmp_list; tmp_list=tmp_list->next) - if (((GdkInputWindow *)(tmp_list->data))->window == window) - return (GdkInputWindow *)(tmp_list->data); - - return NULL; /* Not found */ -} - /* FIXME: this routine currently needs to be called between creation and the corresponding configure event (because it doesn't get the root_relative_geometry). This should work with @@ -295,212 +66,60 @@ _gdk_input_window_find(GdkWindow *window) void gdk_input_set_extension_events (GdkWindow *window, gint mask, - GdkExtensionMode mode) + GdkExtensionMode mode) { + GdkDeviceManager *device_manager; GdkWindowObject *window_private; - GList *tmp_list; - GdkInputWindow *iw; + GList *devices, *d; - g_return_if_fail (window != NULL); g_return_if_fail (GDK_IS_WINDOW (window)); - window_private = (GdkWindowObject*) window; if (GDK_WINDOW_DESTROYED (window)) return; if (mode == GDK_EXTENSION_EVENTS_NONE) mask = 0; - if (mask != 0) - { - _gdk_input_wintab_init_check (); - - iw = g_new(GdkInputWindow,1); - - iw->window = window; - iw->mode = mode; - - iw->obscuring = NULL; - iw->num_obscuring = 0; - iw->grabbed = FALSE; + window_private = (GdkWindowObject *) window; + window_private->extension_events = mask; - _gdk_input_windows = g_list_append(_gdk_input_windows,iw); - window_private->extension_events = mask; + device_manager = gdk_display_get_device_manager (_gdk_display); + devices = gdk_device_manager_list_devices (device_manager, + GDK_DEVICE_TYPE_FLOATING); - /* Add enter window events to the event mask */ - if (g_list_length (_gdk_input_devices) > 1) - gdk_window_set_events (window, - gdk_window_get_events (window) | - GDK_ENTER_NOTIFY_MASK); - } - else + for (d = devices; d; d = d->next) { - iw = _gdk_input_window_find (window); - if (iw) - { - _gdk_input_windows = g_list_remove(_gdk_input_windows,iw); - g_free(iw); - } + GdkDevice *dev; + gint dev_mask; - window_private->extension_events = 0; - } + dev = d->data; + dev_mask = mask; - for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next) - { - GdkDevicePrivate *gdkdev = tmp_list->data; + if (gdk_device_get_mode (dev) == GDK_MODE_DISABLED || + (!gdk_device_get_has_cursor (dev) && mode == GDK_EXTENSION_EVENTS_CURSOR)) + dev_mask = 0; - if (!GDK_IS_CORE (gdkdev)) - { - if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED - && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL)) - _gdk_input_enable_window (window,gdkdev); - else - _gdk_input_disable_window (window,gdkdev); - } + gdk_window_set_device_events (window, dev, mask); } -} - -void -_gdk_input_window_destroy (GdkWindow *window) -{ - GdkInputWindow *input_window; - input_window = _gdk_input_window_find (window); - g_return_if_fail (input_window != NULL); - - _gdk_input_windows = g_list_remove (_gdk_input_windows,input_window); - g_free(input_window); -} - -void -_gdk_input_crossing_event (GdkWindow *window, - gboolean enter) -{ - if (enter) - { -#if 0 /* No idea what to do... */ - GdkWindowObject *priv = (GdkWindowObject *)window; - GdkInputWindow *input_window; - gint root_x, root_y; -#if 0 - gdk_input_check_proximity(display); -#endif - input_window = priv->input_window; - if (input_window != NULL) - { - _gdk_input_get_root_relative_geometry (window, &root_x, &root_y); - input_window->root_x = root_x; - input_window->root_y = root_y; - } -#endif - } - else - _gdk_input_ignore_core = FALSE; + g_list_free (devices); } void -_gdk_input_exit (void) +_gdk_input_init (GdkDisplay *display) { - GList *tmp_list; - GdkDevicePrivate *gdkdev; + GdkDeviceManagerWin32 *device_manager; - for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next) - { - gdkdev = (GdkDevicePrivate *)(tmp_list->data); - if (!GDK_IS_CORE (gdkdev)) - { - gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED); + _gdk_input_ignore_core = FALSE; - g_free(gdkdev->info.name); - g_free(gdkdev->axes); - g_free(gdkdev->info.axes); - g_free(gdkdev->info.keys); - g_free(gdkdev); - } - } - - g_list_free(_gdk_input_devices); - - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - g_free(tmp_list->data); - - g_list_free(_gdk_input_windows); -} - -gboolean -gdk_device_get_axis (GdkDevice *device, - gdouble *axes, - GdkAxisUse use, - gdouble *value) -{ - gint i; - - g_return_val_if_fail (device != NULL, FALSE); + device_manager = g_object_new (GDK_TYPE_DEVICE_MANAGER_WIN32, + "display", display, + NULL); + display->device_manager = GDK_DEVICE_MANAGER (device_manager); - if (axes == NULL) - return FALSE; - - for (i=0; i<device->num_axes; i++) - if (device->axes[i].use == use) - { - if (value) - *value = axes[i]; - return TRUE; - } - - return FALSE; -} - -gboolean -gdk_device_set_mode (GdkDevice *device, - GdkInputMode mode) -{ - GList *tmp_list; - GdkDevicePrivate *gdkdev; - GdkInputMode old_mode; - GdkInputWindow *input_window; - - if (GDK_IS_CORE (device)) - return FALSE; - - gdkdev = (GdkDevicePrivate *)device; - - if (device->mode == mode) - return TRUE; - - old_mode = device->mode; - device->mode = mode; - - if (mode == GDK_MODE_WINDOW) - { - device->has_cursor = FALSE; - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - { - input_window = (GdkInputWindow *)tmp_list->data; - if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR) - _gdk_input_enable_window (input_window->window, gdkdev); - else - if (old_mode != GDK_MODE_DISABLED) - _gdk_input_disable_window (input_window->window, gdkdev); - } - } - else if (mode == GDK_MODE_SCREEN) - { - device->has_cursor = TRUE; - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - _gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window, - gdkdev); - } - else /* mode == GDK_MODE_DISABLED */ - { - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - { - input_window = (GdkInputWindow *)tmp_list->data; - if (old_mode != GDK_MODE_WINDOW || - input_window->mode != GDK_EXTENSION_EVENTS_CURSOR) - _gdk_input_disable_window (input_window->window, gdkdev); - } - } + display->core_pointer = device_manager->core_pointer; - return TRUE; + _gdk_input_devices = g_list_append (NULL, display->core_pointer); + _gdk_input_devices = g_list_concat (_gdk_input_devices, + g_list_copy (device_manager->wintab_devices)); } diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c index 94b7ac793c..4ea4c8fbe2 100644 --- a/gdk/win32/gdkmain-win32.c +++ b/gdk/win32/gdkmain-win32.c @@ -39,10 +39,11 @@ #include "gdkinternals.h" #include "gdkintl.h" #include "gdkprivate-win32.h" -#include "gdkinput-win32.h" #include <objbase.h> +#include <windows.h> +#include <wintab.h> #include <imm.h> static gboolean gdk_synchronize = FALSE; diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c index 55ca651efe..d44d8f464e 100644 --- a/gdk/win32/gdkwindow-win32.c +++ b/gdk/win32/gdkwindow-win32.c @@ -33,7 +33,8 @@ #include "gdk.h" #include "gdkwindowimpl.h" #include "gdkprivate-win32.h" -#include "gdkinput-win32.h" +#include "gdkdeviceprivate.h" +#include "gdkdevicemanager-win32.h" #include "gdkenumtypes.h" static GdkColormap* gdk_window_impl_win32_get_colormap (GdkDrawable *drawable); @@ -787,9 +788,6 @@ _gdk_win32_window_destroy (GdkWindow *window, GDK_NOTE (MISC, g_print ("_gdk_win32_window_destroy: %p\n", GDK_WINDOW_HWND (window))); - if (private->extension_events != 0) - _gdk_input_window_destroy (window); - /* Remove ourself from the modal stack */ _gdk_remove_modal_window (window); @@ -1829,12 +1827,12 @@ gdk_win32_window_set_back_pixmap (GdkWindow *window, } static void -gdk_win32_window_set_cursor (GdkWindow *window, - GdkCursor *cursor) +gdk_win32_window_set_device_cursor (GdkWindow *window, + GdkDevice *device, + GdkCursor *cursor) { GdkWindowImplWin32 *impl; GdkCursorPrivate *cursor_private; - GdkWindowObject *parent_window; HCURSOR hcursor; HCURSOR hprevcursor; @@ -1859,6 +1857,8 @@ gdk_win32_window_set_cursor (GdkWindow *window, */ hprevcursor = impl->hcursor; + GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor); + if (hcursor == NULL) impl->hcursor = NULL; else @@ -1875,62 +1875,10 @@ gdk_win32_window_set_cursor (GdkWindow *window, hcursor, impl->hcursor)); } - if (impl->hcursor != NULL) - { - /* If the pointer is over our window, set new cursor */ - GdkWindow *curr_window = gdk_window_get_pointer (window, NULL, NULL, NULL); - if (curr_window == window || - (curr_window && window == gdk_window_get_toplevel (curr_window))) - SetCursor (impl->hcursor); - else - { - /* Climb up the tree and find whether our window is the - * first ancestor that has cursor defined, and if so, set - * new cursor. - */ - GdkWindowObject *curr_window_obj = GDK_WINDOW_OBJECT (curr_window); - while (curr_window_obj && - !GDK_WINDOW_IMPL_WIN32 (curr_window_obj->impl)->hcursor) - { - curr_window_obj = curr_window_obj->parent; - if (curr_window_obj == GDK_WINDOW_OBJECT (window)) - { - SetCursor (impl->hcursor); - break; - } - } - } - } - - /* Destroy the previous cursor: Need to make sure it's no longer in - * use before we destroy it, in case we're not over our window but - * the cursor is still set to our old one. - */ + /* Destroy the previous cursor */ if (hprevcursor != NULL) { - if (GetCursor () == hprevcursor) - { - /* Look for a suitable cursor to use instead */ - hcursor = NULL; - parent_window = GDK_WINDOW_OBJECT (window)->parent; - while (hcursor == NULL) - { - if (parent_window) - { - impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl); - hcursor = impl->hcursor; - parent_window = parent_window->parent; - } - else - { - hcursor = LoadCursor (NULL, IDC_ARROW); - } - } - SetCursor (hcursor); - } - GDK_NOTE (MISC, g_print ("... DestroyCursor (%p)\n", hprevcursor)); - API_CALL (DestroyCursor, (hprevcursor)); } } @@ -2113,87 +2061,43 @@ gdk_window_get_frame_extents (GdkWindow *window, r.left, r.top)); } - -static GdkModifierType -get_current_mask (void) -{ - GdkModifierType mask; - BYTE kbd[256]; - - GetKeyboardState (kbd); - mask = 0; - if (kbd[VK_SHIFT] & 0x80) - mask |= GDK_SHIFT_MASK; - if (kbd[VK_CAPITAL] & 0x80) - mask |= GDK_LOCK_MASK; - if (kbd[VK_CONTROL] & 0x80) - mask |= GDK_CONTROL_MASK; - if (kbd[VK_MENU] & 0x80) - mask |= GDK_MOD1_MASK; - if (kbd[VK_LBUTTON] & 0x80) - mask |= GDK_BUTTON1_MASK; - if (kbd[VK_MBUTTON] & 0x80) - mask |= GDK_BUTTON2_MASK; - if (kbd[VK_RBUTTON] & 0x80) - mask |= GDK_BUTTON3_MASK; - - return mask; -} - static gboolean -gdk_window_win32_get_pointer (GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask) +gdk_window_win32_get_device_state (GdkWindow *window, + GdkDevice *device, + gint *x, + gint *y, + GdkModifierType *mask) { - gboolean return_val; - POINT point; - HWND hwnd, hwndc; + GdkWindow *child; g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE); - - return_val = TRUE; - - hwnd = GDK_WINDOW_HWND (window); - GetCursorPos (&point); - ScreenToClient (hwnd, &point); - *x = point.x; - *y = point.y; - - if (window == _gdk_root) - { - *x += _gdk_offset_x; - *y += _gdk_offset_y; - } - - hwndc = ChildWindowFromPoint (hwnd, point); - if (hwndc != NULL && hwndc != hwnd && - !gdk_win32_handle_table_lookup ((GdkNativeWindow) hwndc)) - return_val = FALSE; /* Direct child unknown to gdk */ - - *mask = get_current_mask (); - - return return_val; + GDK_DEVICE_GET_CLASS (device)->query_state (device, window, + NULL, &child, + NULL, NULL, + x, y, mask); + return (child != NULL); } void -_gdk_windowing_get_pointer (GdkDisplay *display, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask) +_gdk_windowing_get_device_state (GdkDisplay *display, + GdkDevice *device, + GdkScreen **screen, + gint *x, + gint *y, + GdkModifierType *mask) { - POINT point; - g_return_if_fail (display == _gdk_display); - - *screen = _gdk_screen; - GetCursorPos (&point); - *x = point.x + _gdk_offset_x; - *y = point.y + _gdk_offset_y; - *mask = get_current_mask (); + if (screen) + *screen = _gdk_screen; + + GDK_DEVICE_GET_CLASS (device)->query_state (device, + gdk_screen_get_root_window (_gdk_screen), + NULL, NULL, + x, y, + NULL, NULL, + mask); } void @@ -2202,64 +2106,40 @@ gdk_display_warp_pointer (GdkDisplay *display, gint x, gint y) { + GdkDeviceManagerWin32 *device_manager; + g_return_if_fail (display == _gdk_display); g_return_if_fail (screen == _gdk_screen); - SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y); + device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (display)); + GDK_DEVICE_GET_CLASS (device_manager->core_pointer)->warp (device_manager->core_pointer, + screen, x, y); } -GdkWindow* -_gdk_windowing_window_at_pointer (GdkDisplay *display, - gint *win_x, - gint *win_y, - GdkModifierType *mask, - gboolean get_toplevel) +void +gdk_display_warp_device (GdkDisplay *display, + GdkDevice *device, + GdkScreen *screen, + gint x, + gint y) { - GdkWindow *window; - POINT point, pointc; - HWND hwnd, hwndc; - RECT rect; - - GetCursorPos (&pointc); - point = pointc; - hwnd = WindowFromPoint (point); - - if (hwnd == NULL) - { - window = _gdk_root; - *win_x = pointc.x + _gdk_offset_x; - *win_y = pointc.y + _gdk_offset_y; - return window; - } - - ScreenToClient (hwnd, &point); - - do { - if (get_toplevel && - (window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd)) != NULL && - GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN) - break; - - hwndc = ChildWindowFromPoint (hwnd, point); - ClientToScreen (hwnd, &point); - ScreenToClient (hwndc, &point); - } while (hwndc != hwnd && (hwnd = hwndc, 1)); - - window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); - - if (window && (win_x || win_y)) - { - GetClientRect (hwnd, &rect); - *win_x = point.x - rect.left; - *win_y = point.y - rect.top; - } + g_return_if_fail (display == _gdk_display); + g_return_if_fail (screen == _gdk_screen); + g_return_if_fail (GDK_IS_DEVICE (device)); + g_return_if_fail (display == gdk_device_get_display (device)); - GDK_NOTE (MISC, g_print ("_gdk_windowing_window_at_pointer: %+d%+d %p%s\n", - *win_x, *win_y, - hwnd, - (window == NULL ? " NULL" : ""))); + GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y); +} - return window; +GdkWindow* +_gdk_windowing_window_at_device_position (GdkDisplay *display, + GdkDevice *device, + gint *win_x, + gint *win_y, + GdkModifierType *mask, + gboolean get_toplevel) +{ + return GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel); } static GdkEventMask @@ -3485,9 +3365,9 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->set_background = gdk_win32_window_set_background; iface->set_back_pixmap = gdk_win32_window_set_back_pixmap; iface->reparent = gdk_win32_window_reparent; - iface->set_cursor = gdk_win32_window_set_cursor; + iface->set_device_cursor = gdk_win32_window_set_device_cursor; iface->get_geometry = gdk_win32_window_get_geometry; - iface->get_pointer = gdk_window_win32_get_pointer; + iface->get_device_state = gdk_window_win32_get_device_state; iface->get_root_coords = gdk_win32_window_get_root_coords; iface->shape_combine_region = gdk_win32_window_shape_combine_region; iface->input_shape_combine_region = gdk_win32_input_shape_combine_region; @@ -3496,6 +3376,4 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->queue_antiexpose = _gdk_win32_window_queue_antiexpose; iface->queue_translation = _gdk_win32_window_queue_translation; iface->destroy = _gdk_win32_window_destroy; - iface->input_window_destroy = _gdk_input_window_destroy; - iface->input_window_crossing = _gdk_input_crossing_event; } |