win32: Fix up wintab support

We now have a proper MASTER/SLAVE input device split, where
the masters are virtual core input devices and we add fake hw
slave devices for the system pointer and real slave devices for
wintab devices.

We also set the proper source_device on the events so you can
tell which device sent it and properly decode the axis info.
This commit is contained in:
Alexander Larsson 2012-03-30 14:59:17 +02:00
parent ddd24761fd
commit 24f9ca92ab
10 changed files with 779 additions and 398 deletions

View File

@ -29,6 +29,8 @@ libgdk_win32_la_SOURCES = \
gdkcursor-win32.c \
gdkdevicemanager-win32.c \
gdkdevicemanager-win32.h \
gdkdevice-virtual.c \
gdkdevice-virtual.h \
gdkdevice-win32.c \
gdkdevice-win32.h \
gdkdevice-wintab.c \

View File

@ -0,0 +1,429 @@
/* 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdkwindow.h>
#include <windowsx.h>
#include <objbase.h>
#include "gdkdisplayprivate.h"
#include "gdkdevice-virtual.h"
#include "gdkwin32.h"
static gboolean gdk_device_virtual_get_history (GdkDevice *device,
GdkWindow *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events);
static void gdk_device_virtual_get_state (GdkDevice *device,
GdkWindow *window,
gdouble *axes,
GdkModifierType *mask);
static void gdk_device_virtual_set_window_cursor (GdkDevice *device,
GdkWindow *window,
GdkCursor *cursor);
static void gdk_device_virtual_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y);
static void gdk_device_virtual_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_virtual_grab (GdkDevice *device,
GdkWindow *window,
gboolean owner_events,
GdkEventMask event_mask,
GdkWindow *confine_to,
GdkCursor *cursor,
guint32 time_);
static void gdk_device_virtual_ungrab (GdkDevice *device,
guint32 time_);
static GdkWindow * gdk_device_virtual_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
static void gdk_device_virtual_select_window_events (GdkDevice *device,
GdkWindow *window,
GdkEventMask event_mask);
G_DEFINE_TYPE (GdkDeviceVirtual, gdk_device_virtual, GDK_TYPE_DEVICE)
static void
gdk_device_virtual_class_init (GdkDeviceVirtualClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_history = gdk_device_virtual_get_history;
device_class->get_state = gdk_device_virtual_get_state;
device_class->set_window_cursor = gdk_device_virtual_set_window_cursor;
device_class->warp = gdk_device_virtual_warp;
device_class->query_state = gdk_device_virtual_query_state;
device_class->grab = gdk_device_virtual_grab;
device_class->ungrab = gdk_device_virtual_ungrab;
device_class->window_at_position = gdk_device_virtual_window_at_position;
device_class->select_window_events = gdk_device_virtual_select_window_events;
}
static void
gdk_device_virtual_init (GdkDeviceVirtual *device_virtual)
{
GdkDevice *device;
device = GDK_DEVICE (device_virtual);
}
void
_gdk_device_virtual_set_active (GdkDevice *device,
GdkDevice *new_active)
{
GdkDeviceVirtual *virtual = GDK_DEVICE_VIRTUAL (device);
int n_axes, i;
GdkAtom label_atom;
GdkAxisUse use;
gdouble min_value, max_value, resolution;
if (virtual->active_device == new_active)
return;
virtual->active_device = new_active;
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
{
_gdk_device_reset_axes (device);
n_axes = gdk_device_get_n_axes (new_active);
for (i = 0; i < n_axes; i++)
{
_gdk_device_get_axis_info (new_active, i,
&label_atom, &use,
&min_value, &max_value, &resolution);
_gdk_device_add_axis (device,
label_atom, use,
min_value, max_value, resolution);
}
}
g_signal_emit_by_name (G_OBJECT (device), "changed");
}
static gboolean
gdk_device_virtual_get_history (GdkDevice *device,
GdkWindow *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
/* History is only per slave device */
return FALSE;
}
static void
gdk_device_virtual_get_state (GdkDevice *device,
GdkWindow *window,
gdouble *axes,
GdkModifierType *mask)
{
GdkDeviceVirtual *virtual = GDK_DEVICE_VIRTUAL (device);
GdkDevice *active = virtual->active_device;
GDK_DEVICE_GET_CLASS (active)->get_state (active,
window, axes, mask);
}
static void
gdk_device_virtual_set_window_cursor (GdkDevice *device,
GdkWindow *window,
GdkCursor *cursor)
{
GdkWin32Cursor *cursor_private;
GdkWindow *parent_window;
GdkWindowImplWin32 *impl;
HCURSOR hcursor;
HCURSOR hprevcursor;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
cursor_private = (GdkWin32Cursor*) 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.
*/
while (curr_window && curr_window->impl &&
!GDK_WINDOW_IMPL_WIN32 (curr_window->impl)->hcursor)
{
curr_window = curr_window->parent;
if (curr_window == GDK_WINDOW (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 (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_virtual_warp (GdkDevice *device,
GdkScreen *screen,
gint x,
gint y)
{
SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y);
}
static void
gdk_device_virtual_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)
{
GdkDeviceVirtual *virtual = GDK_DEVICE_VIRTUAL (device);
_gdk_device_query_state (virtual->active_device,
window, root_window, child_window,
root_x, root_y,
win_x, win_y,
mask);
}
static GdkGrabStatus
gdk_device_virtual_grab (GdkDevice *device,
GdkWindow *window,
gboolean owner_events,
GdkEventMask event_mask,
GdkWindow *confine_to,
GdkCursor *cursor,
guint32 time_)
{
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
HCURSOR hcursor;
GdkWin32Cursor *cursor_private;
cursor_private = (GdkWin32Cursor*) cursor;
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
{
if (!cursor)
hcursor = NULL;
else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
WIN32_API_FAILED ("CopyCursor");
if (_gdk_win32_grab_cursor != NULL)
{
if (GetCursor () == _gdk_win32_grab_cursor)
SetCursor (NULL);
DestroyCursor (_gdk_win32_grab_cursor);
}
_gdk_win32_grab_cursor = hcursor;
if (_gdk_win32_grab_cursor != NULL)
SetCursor (_gdk_win32_grab_cursor);
else if (impl->hcursor != NULL)
SetCursor (impl->hcursor);
else
SetCursor (LoadCursor (NULL, IDC_ARROW));
SetCapture (GDK_WINDOW_HWND (window));
}
return GDK_GRAB_SUCCESS;
}
static void
gdk_device_virtual_ungrab (GdkDevice *device,
guint32 time_)
{
GdkDeviceGrabInfo *info;
GdkDisplay *display;
display = gdk_device_get_display (device);
info = _gdk_display_get_last_device_grab (display, device);
if (info)
info->serial_end = 0;
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
{
if (_gdk_win32_grab_cursor != NULL)
{
if (GetCursor () == _gdk_win32_grab_cursor)
SetCursor (NULL);
DestroyCursor (_gdk_win32_grab_cursor);
}
_gdk_win32_grab_cursor = NULL;
ReleaseCapture ();
}
_gdk_display_device_grab_update (display, device, NULL, 0);
}
static void
screen_to_client (HWND hwnd, POINT screen_pt, POINT *client_pt)
{
*client_pt = screen_pt;
ScreenToClient (hwnd, client_pt);
}
static GdkWindow *
gdk_device_virtual_window_at_position (GdkDevice *device,
gint *win_x,
gint *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
GdkWindow *window = NULL;
POINT screen_pt, client_pt;
HWND hwnd, hwndc;
RECT rect;
GetCursorPos (&screen_pt);
if (get_toplevel)
{
/* Only consider visible children of the desktop to avoid the various
* non-visible windows you often find on a running Windows box. These
* might overlap our windows and cause our walk to fail. As we assume
* WindowFromPoint() can find our windows, we follow similar logic
* here, and ignore invisible and disabled windows.
*/
hwnd = GetDesktopWindow ();
do {
window = gdk_win32_handle_table_lookup (hwnd);
if (window != NULL &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT &&
GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
break;
screen_to_client (hwnd, screen_pt, &client_pt);
hwndc = ChildWindowFromPointEx (hwnd, client_pt, CWP_SKIPDISABLED |
CWP_SKIPINVISIBLE);
/* Verify that we're really inside the client area of the window */
if (hwndc != hwnd)
{
GetClientRect (hwndc, &rect);
screen_to_client (hwndc, screen_pt, &client_pt);
if (!PtInRect (&rect, client_pt))
hwndc = hwnd;
}
} while (hwndc != hwnd && (hwnd = hwndc, 1));
}
else
{
hwnd = WindowFromPoint (screen_pt);
/* Verify that we're really inside the client area of the window */
GetClientRect (hwnd, &rect);
screen_to_client (hwnd, screen_pt, &client_pt);
if (!PtInRect (&rect, client_pt))
hwnd = NULL;
/* If we didn't hit any window at that point, return the desktop */
if (hwnd == NULL)
{
if (win_x)
*win_x = screen_pt.x + _gdk_offset_x;
if (win_y)
*win_y = screen_pt.y + _gdk_offset_y;
return _gdk_root;
}
window = gdk_win32_handle_table_lookup (hwnd);
}
if (window && (win_x || win_y))
{
if (win_x)
*win_x = client_pt.x;
if (win_y)
*win_y = client_pt.y;
}
return window;
}
static void
gdk_device_virtual_select_window_events (GdkDevice *device,
GdkWindow *window,
GdkEventMask event_mask)
{
}

View File

@ -0,0 +1,54 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_DEVICE_VIRTUAL_H__
#define __GDK_DEVICE_VIRTUAL_H__
#include <gdk/gdkdeviceprivate.h>
G_BEGIN_DECLS
#define GDK_TYPE_DEVICE_VIRTUAL (gdk_device_virtual_get_type ())
#define GDK_DEVICE_VIRTUAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_VIRTUAL, GdkDeviceVirtual))
#define GDK_DEVICE_VIRTUAL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE_VIRTUAL, GdkDeviceVirtualClass))
#define GDK_IS_DEVICE_VIRTUAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_VIRTUAL))
#define GDK_IS_DEVICE_VIRTUAL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE_VIRTUAL))
#define GDK_DEVICE_VIRTUAL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE_VIRTUAL, GdkDeviceVirtualClass))
typedef struct _GdkDeviceVirtual GdkDeviceVirtual;
typedef struct _GdkDeviceVirtualClass GdkDeviceVirtualClass;
struct _GdkDeviceVirtual
{
GdkDevice parent_instance;
GdkDevice *active_device;
};
struct _GdkDeviceVirtualClass
{
GdkDeviceClass parent_class;
};
GType gdk_device_virtual_get_type (void) G_GNUC_CONST;
void _gdk_device_virtual_set_active (GdkDevice *device,
GdkDevice *new_active);
G_END_DECLS
#endif /* __GDK_DEVICE_VIRTUAL_H__ */

View File

@ -133,74 +133,6 @@ gdk_device_win32_set_window_cursor (GdkDevice *device,
GdkWindow *window,
GdkCursor *cursor)
{
GdkWin32Cursor *cursor_private;
GdkWindow *parent_window;
GdkWindowImplWin32 *impl;
HCURSOR hcursor;
HCURSOR hprevcursor;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
cursor_private = (GdkWin32Cursor*) 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.
*/
while (curr_window && curr_window->impl &&
!GDK_WINDOW_IMPL_WIN32 (curr_window->impl)->hcursor)
{
curr_window = curr_window->parent;
if (curr_window == GDK_WINDOW (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 (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
@ -209,7 +141,6 @@ gdk_device_win32_warp (GdkDevice *device,
gint x,
gint y)
{
SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y);
}
static GdkModifierType
@ -309,68 +240,14 @@ gdk_device_win32_grab (GdkDevice *device,
GdkCursor *cursor,
guint32 time_)
{
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
HCURSOR hcursor;
GdkWin32Cursor *cursor_private;
cursor_private = (GdkWin32Cursor*) cursor;
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
{
if (!cursor)
hcursor = NULL;
else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
WIN32_API_FAILED ("CopyCursor");
if (_gdk_win32_grab_cursor != NULL)
{
if (GetCursor () == _gdk_win32_grab_cursor)
SetCursor (NULL);
DestroyCursor (_gdk_win32_grab_cursor);
}
_gdk_win32_grab_cursor = hcursor;
if (_gdk_win32_grab_cursor != NULL)
SetCursor (_gdk_win32_grab_cursor);
else if (impl->hcursor != NULL)
SetCursor (impl->hcursor);
else
SetCursor (LoadCursor (NULL, IDC_ARROW));
SetCapture (GDK_WINDOW_HWND (window));
}
return GDK_GRAB_SUCCESS;
/* No support for grabbing the slave atm */
return GDK_GRAB_NOT_VIEWABLE;
}
static void
gdk_device_win32_ungrab (GdkDevice *device,
guint32 time_)
{
GdkDeviceGrabInfo *info;
GdkDisplay *display;
display = gdk_device_get_display (device);
info = _gdk_display_get_last_device_grab (display, device);
if (info)
info->serial_end = 0;
if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
{
if (_gdk_win32_grab_cursor != NULL)
{
if (GetCursor () == _gdk_win32_grab_cursor)
SetCursor (NULL);
DestroyCursor (_gdk_win32_grab_cursor);
}
_gdk_win32_grab_cursor = NULL;
ReleaseCapture ();
}
_gdk_display_device_grab_update (display, device, NULL, 0);
}
static void

View File

@ -25,16 +25,6 @@
#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,
@ -96,8 +86,6 @@ gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
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
@ -119,6 +107,32 @@ gdk_device_wintab_get_history (GdkDevice *device,
return FALSE;
}
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 void
gdk_device_wintab_get_state (GdkDevice *device,
GdkWindow *window,
@ -134,7 +148,7 @@ gdk_device_wintab_get_state (GdkDevice *device,
* second, the info should be fairly up to date */
if (mask)
{
gdk_window_get_pointer (window, NULL, NULL, mask);
*mask = get_current_mask ();
*mask &= 0xFF; /* Mask away core pointer buttons */
*mask |= ((device_wintab->button_state << 8)
& (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
@ -142,7 +156,7 @@ gdk_device_wintab_get_state (GdkDevice *device,
| GDK_BUTTON5_MASK));
}
if (device_wintab->last_axis_data)
if (axes && device_wintab->last_axis_data)
_gdk_device_wintab_translate_axes (device_wintab, window, axes, NULL, NULL);
}
@ -172,7 +186,66 @@ gdk_device_wintab_query_state (GdkDevice *device,
gint *win_y,
GdkModifierType *mask)
{
g_warning ("query_state unimplemented for wintab devices. Expect bad things.");
GdkDeviceWintab *device_wintab;
POINT point;
HWND hwnd, hwndc;
device_wintab = GDK_DEVICE_WINTAB (device);
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 (hwndc);
else
*child_window = NULL; /* Direct child unknown to gdk */
}
if (root_window)
{
GdkScreen *screen;
screen = gdk_window_get_screen (window);
*root_window = gdk_screen_get_root_window (screen);
}
if (mask)
{
*mask = get_current_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));
}
}
static GdkGrabStatus
@ -203,112 +276,11 @@ gdk_device_wintab_window_at_position (GdkDevice *device,
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);
}
}
}
gboolean
_gdk_device_wintab_wants_events (GdkWindow *window)
{
GdkWindowInputInfo *info;
info = g_object_get_qdata (G_OBJECT (window),
quark_window_input_info);
return info != NULL;
}
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
@ -320,7 +292,7 @@ _gdk_device_wintab_translate_axes (GdkDeviceWintab *device_wintab,
{
GdkDevice *device;
GdkWindow *impl_window;
gdouble root_x, root_y;
gint root_x, root_y;
gdouble temp_x, temp_y;
gint i;
@ -328,8 +300,7 @@ _gdk_device_wintab_translate_axes (GdkDeviceWintab *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;
gdk_window_get_origin (impl_window, &root_x, &root_y);
for (i = 0; i < gdk_device_get_n_axes (device); i++)
{

View File

@ -39,6 +39,7 @@ struct _GdkDeviceWintab
{
GdkDevice parent_instance;
gboolean sends_core;
gint *last_axis_data;
gint button_state;
@ -59,14 +60,6 @@ struct _GdkDeviceWintabClass
GType gdk_device_wintab_get_type (void) G_GNUC_CONST;
gboolean _gdk_device_wintab_wants_events (GdkWindow *window);
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,

View File

@ -27,6 +27,7 @@
#include "gdkdevicemanager-win32.h"
#include "gdkdeviceprivate.h"
#include "gdkdevice-win32.h"
#include "gdkdevice-virtual.h"
#include "gdkdevice-wintab.h"
#include "gdkdisplayprivate.h"
@ -38,18 +39,18 @@
#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_WTGetA) (HCTX a, LPLOGCONTEXTA b);
typedef BOOL (WINAPI *t_WTSetA) (HCTX a, LPLOGCONTEXTA b);
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);
@ -58,6 +59,8 @@ static t_WTInfoA p_WTInfoA;
static t_WTInfoW p_WTInfoW;
static t_WTEnable p_WTEnable;
static t_WTOpenA p_WTOpenA;
static t_WTGetA p_WTGetA;
static t_WTSetA p_WTSetA;
static t_WTOverlap p_WTOverlap;
static t_WTPacket p_WTPacket;
static t_WTQueueSizeSet p_WTQueueSizeSet;
@ -86,25 +89,31 @@ gdk_device_manager_win32_class_init (GdkDeviceManagerWin32Class *klass)
}
static GdkDevice *
create_core_pointer (GdkDeviceManager *device_manager)
create_pointer (GdkDeviceManager *device_manager,
GType g_type,
const char *name,
GdkDeviceType type)
{
return g_object_new (GDK_TYPE_DEVICE_WIN32,
"name", "Core Pointer",
"type", GDK_DEVICE_TYPE_MASTER,
return g_object_new (g_type,
"name", name,
"type", type,
"input-source", GDK_SOURCE_MOUSE,
"input-mode", GDK_MODE_SCREEN,
"has-cursor", TRUE,
"has-cursor", type == GDK_DEVICE_TYPE_MASTER,
"display", _gdk_display,
"device-manager", device_manager,
NULL);
}
static GdkDevice *
create_core_keyboard (GdkDeviceManager *device_manager)
create_keyboard (GdkDeviceManager *device_manager,
GType g_type,
const char *name,
GdkDeviceType type)
{
return g_object_new (GDK_TYPE_DEVICE_WIN32,
"name", "Core Keyboard",
"type", GDK_DEVICE_TYPE_MASTER,
return g_object_new (g_type,
"name", name,
"type", type,
"input-source", GDK_SOURCE_KEYBOARD,
"input-mode", GDK_MODE_SCREEN,
"has-cursor", FALSE,
@ -419,6 +428,10 @@ _gdk_input_wintab_init_check (GdkDeviceManager *_device_manager)
return;
if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL)
return;
if ((p_WTGetA = (t_WTGetA) GetProcAddress (wintab32, "WTGetA")) == NULL)
return;
if ((p_WTSetA = (t_WTSetA) GetProcAddress (wintab32, "WTSetA")) == NULL)
return;
if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL)
return;
if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL)
@ -496,7 +509,7 @@ _gdk_input_wintab_init_check (GdkDeviceManager *_device_manager)
#if DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc)));
#endif
lc.lcOptions |= CXO_MESSAGES;
lc.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
lc.lcStatus = 0;
lc.lcMsgBase = WT_DEFBASE;
lc.lcPktRate = 0;
@ -506,8 +519,8 @@ _gdk_input_wintab_init_check (GdkDeviceManager *_device_manager)
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.lcOutExtX = axis_x.axMax - axis_x.axMin + 1;
lc.lcOutExtY = axis_y.axMax - axis_y.axMin + 1;
lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
#if DEBUG_WINTAB
GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix),
@ -537,7 +550,7 @@ _gdk_input_wintab_init_check (GdkDeviceManager *_device_manager)
* with a smaller queue size.
*/
GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
for (i = 32; i >= 1; i >>= 1)
for (i = 128; i >= 1; i >>= 1)
{
if ((*p_WTQueueSizeSet) (*hctx, i))
{
@ -575,14 +588,21 @@ _gdk_input_wintab_init_check (GdkDeviceManager *_device_manager)
device = g_object_new (GDK_TYPE_DEVICE_WINTAB,
"name", device_name,
"type", GDK_DEVICE_TYPE_SLAVE,
"type", GDK_DEVICE_TYPE_FLOATING,
"input-source", GDK_SOURCE_PEN,
"input-mode", GDK_MODE_SCREEN,
"has-cursor", FALSE,
"has-cursor", lc.lcOptions & CXO_SYSTEM,
"display", _gdk_display,
"device-manager", device_manager,
NULL);
device->sends_core = lc.lcOptions & CXO_SYSTEM;
if (device->sends_core)
{
_gdk_device_set_associated_device (device_manager->system_pointer, GDK_DEVICE (device));
_gdk_device_add_slave (device_manager->core_pointer, GDK_DEVICE (device));
}
g_free (csrname_utf8);
device->hctx = *hctx;
@ -684,8 +704,35 @@ 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));
device_manager->core_pointer =
create_pointer (GDK_DEVICE_MANAGER (device_manager),
GDK_TYPE_DEVICE_VIRTUAL,
"Virtual Core Pointer",
GDK_DEVICE_TYPE_MASTER);
device_manager->system_pointer =
create_pointer (GDK_DEVICE_MANAGER (device_manager),
GDK_TYPE_DEVICE_WIN32,
"System Aggregated Pointer",
GDK_DEVICE_TYPE_SLAVE);
_gdk_device_virtual_set_active (device_manager->core_pointer,
device_manager->system_pointer);
_gdk_device_set_associated_device (device_manager->system_pointer, device_manager->core_pointer);
_gdk_device_add_slave (device_manager->core_pointer, device_manager->system_pointer);
device_manager->core_keyboard =
create_keyboard (GDK_DEVICE_MANAGER (device_manager),
GDK_TYPE_DEVICE_VIRTUAL,
"Virtual Core Keyboard",
GDK_DEVICE_TYPE_MASTER);
device_manager->system_keyboard =
create_keyboard (GDK_DEVICE_MANAGER (device_manager),
GDK_TYPE_DEVICE_WIN32,
"System Aggregated Keyboard",
GDK_DEVICE_TYPE_SLAVE);
_gdk_device_virtual_set_active (device_manager->core_keyboard,
device_manager->system_keyboard);
_gdk_device_set_associated_device (device_manager->system_keyboard, device_manager->core_keyboard);
_gdk_device_add_slave (device_manager->core_keyboard, device_manager->system_keyboard);
_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);
@ -696,7 +743,7 @@ gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager,
GdkDeviceType type)
{
GdkDeviceManagerWin32 *device_manager_win32;
GList *devices = NULL;
GList *devices = NULL, *l;
device_manager_win32 = (GdkDeviceManagerWin32 *) device_manager;
@ -705,10 +752,24 @@ gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager,
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);
else
{
if (type == GDK_DEVICE_TYPE_SLAVE)
{
devices = g_list_prepend (devices, device_manager_win32->system_keyboard);
devices = g_list_prepend (devices, device_manager_win32->system_pointer);
}
return devices;
for (l = device_manager_win32->wintab_devices; l != NULL; l = l->next)
{
GdkDevice *device = l->data;
if (gdk_device_get_device_type (device) == type)
devices = g_list_prepend (devices, device);
}
}
return g_list_reverse (devices);
}
static GdkDevice *
@ -791,41 +852,6 @@ get_modifier_key_state (void)
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)
@ -855,15 +881,16 @@ _gdk_input_other_event (GdkEvent *event,
MSG *msg,
GdkWindow *window)
{
GdkDeviceManagerWin32 *device_manager;
GdkDisplay *display;
GdkDeviceWintab *device = NULL;
GdkDeviceWintab *source_device = NULL;
GdkDeviceGrabInfo *last_grab;
GdkEventMask masktest;
guint key_state;
POINT pt;
PACKET packet;
gdouble root_x, root_y;
gint root_x, root_y;
gint num_axes;
gint x, y;
guint translated_buttons, button_diff, button_mask;
@ -878,6 +905,8 @@ _gdk_input_other_event (GdkEvent *event,
return FALSE;
}
device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (_gdk_display));
window = gdk_window_at_pointer (&x, &y);
if (window == NULL)
window = _gdk_root;
@ -889,7 +918,7 @@ _gdk_input_other_event (GdkEvent *event,
g_print ("_gdk_input_other_event: window=%p %+d%+d\n",
GDK_WINDOW_HWND (window), x, y));
if (msg->message == WT_PACKET)
if (msg->message == WT_PACKET || msg->message == WT_CSRCHANGE)
{
if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet))
return FALSE;
@ -907,14 +936,14 @@ _gdk_input_other_event (GdkEvent *event,
return FALSE;
}
if ((device = _gdk_device_manager_find_wintab_device ((HCTX) msg->lParam,
packet.pkCursor)) == NULL)
if ((source_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)
if (gdk_device_get_mode (GDK_DEVICE (source_device)) == GDK_MODE_DISABLED)
return FALSE;
last_grab = _gdk_display_get_last_device_grab (_gdk_display, GDK_DEVICE (device));
last_grab = _gdk_display_get_last_device_grab (_gdk_display, GDK_DEVICE (source_device));
if (last_grab && last_grab->window)
{
@ -930,29 +959,29 @@ _gdk_input_other_event (GdkEvent *event,
}
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)
if (source_device->pktdata & PK_X)
source_device->last_axis_data[num_axes++] = packet.pkX;
if (source_device->pktdata & PK_Y)
source_device->last_axis_data[num_axes++] = packet.pkY;
if (source_device->pktdata & PK_NORMAL_PRESSURE)
source_device->last_axis_data[num_axes++] = packet.pkNormalPressure;
if (source_device->pktdata & PK_ORIENTATION)
{
decode_tilt (device->last_axis_data + num_axes,
device->orientation_axes, &packet);
decode_tilt (source_device->last_axis_data + num_axes,
source_device->orientation_axes, &packet);
num_axes += 2;
}
translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07);
if (translated_buttons != device->button_state)
if (translated_buttons != source_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;
button_diff = translated_buttons ^ source_device->button_state;
/* Gdk buttons are numbered 1.. */
event->button.button = 1;
@ -977,39 +1006,33 @@ _gdk_input_other_event (GdkEvent *event,
event->any.type = GDK_BUTTON_PRESS;
masktest = GDK_BUTTON_PRESS_MASK;
}
device->button_state ^= button_mask;
source_device->button_state ^= button_mask;
}
else
{
event->any.type = GDK_MOTION_NOTIFY;
masktest = GDK_POINTER_MOTION_MASK;
if (device->button_state & (1 << 0))
if (source_device->button_state & (1 << 0))
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
if (device->button_state & (1 << 1))
if (source_device->button_state & (1 << 1))
masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
if (device->button_state & (1 << 2))
if (source_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)
while ((gdk_window_get_device_events (window, GDK_DEVICE (source_device)) & masktest) == 0 &&
(gdk_device_get_device_type (GDK_DEVICE (source_device)) == GDK_DEVICE_TYPE_SLAVE &&
(gdk_window_get_events (window) & masktest) == 0))
{
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n"));
if (window->parent == GDK_WINDOW (_gdk_root))
if (window->parent == GDK_WINDOW (_gdk_root) ||
window->parent == NULL)
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 (window->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);
@ -1023,21 +1046,20 @@ _gdk_input_other_event (GdkEvent *event,
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));
if (source_device->sends_core)
gdk_event_set_device (event, device_manager->core_pointer);
gdk_event_set_source_device (event, GDK_DEVICE (source_device));
event->button.axes = g_new (gdouble, num_axes);
_gdk_device_wintab_get_window_coords (window, &root_x, &root_y);
gdk_window_get_origin (window, &root_x, &root_y);
_gdk_device_wintab_translate_axes (device,
_gdk_device_wintab_translate_axes (source_device,
window,
event->button.axes,
&event->button.x,
@ -1047,7 +1069,7 @@ _gdk_input_other_event (GdkEvent *event,
event->button.y_root = event->button.y + root_y;
event->button.state =
key_state | ((device->button_state << 8)
key_state | ((source_device->button_state << 8)
& (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
| GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
| GDK_BUTTON5_MASK));
@ -1063,12 +1085,13 @@ _gdk_input_other_event (GdkEvent *event,
{
event->motion.time = _gdk_win32_get_next_tick (msg->time);
event->motion.is_hint = FALSE;
gdk_event_set_device (event, GDK_DEVICE (device));
gdk_event_set_device (event, device_manager->core_pointer);
gdk_event_set_source_device (event, GDK_DEVICE (source_device));
event->motion.axes = g_new (gdouble, num_axes);
_gdk_device_wintab_get_window_coords (window, &root_x, &root_y);
gdk_window_get_origin (window, &root_x, &root_y);
_gdk_device_wintab_translate_axes (device,
_gdk_device_wintab_translate_axes (source_device,
window,
event->motion.axes,
&event->motion.x,
@ -1078,7 +1101,7 @@ _gdk_input_other_event (GdkEvent *event,
event->motion.y_root = event->motion.y + root_y;
event->motion.state =
key_state | ((device->button_state << 8)
key_state | ((source_device->button_state << 8)
& (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
| GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
| GDK_BUTTON5_MASK));
@ -1089,25 +1112,31 @@ _gdk_input_other_event (GdkEvent *event,
}
return TRUE;
case WT_CSRCHANGE:
if ((source_device = _gdk_device_manager_find_wintab_device ((HCTX) msg->lParam,
packet.pkCursor)) == NULL)
return FALSE;
if (gdk_device_get_mode (GDK_DEVICE (source_device)) == GDK_MODE_DISABLED)
return FALSE;
if (source_device->sends_core)
{
_gdk_device_virtual_set_active (device_manager->core_pointer, GDK_DEVICE (source_device));
_gdk_input_ignore_core = TRUE;
}
return FALSE;
case WT_PROXIMITY:
if (LOWORD (msg->lParam) == 0)
{
event->proximity.type = GDK_PROXIMITY_OUT;
set_ignore_core (FALSE);
_gdk_input_ignore_core = FALSE;
_gdk_device_virtual_set_active (device_manager->core_pointer,
device_manager->system_pointer);
}
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;
}
return FALSE;

View File

@ -35,8 +35,12 @@ typedef struct _GdkDeviceManagerWin32Class GdkDeviceManagerWin32Class;
struct _GdkDeviceManagerWin32
{
GdkDeviceManager parent_object;
/* Master Devices */
GdkDevice *core_pointer;
GdkDevice *core_keyboard;
/* Fake slave devices */
GdkDevice *system_pointer;
GdkDevice *system_keyboard;
GList *wintab_devices;
};

View File

@ -192,14 +192,17 @@ generate_focus_event (GdkDeviceManager *device_manager,
gboolean in)
{
GdkDevice *device;
GdkDevice *source_device;
GdkEvent *event;
device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard;
source_device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->system_keyboard;
event = gdk_event_new (GDK_FOCUS_CHANGE);
event->focus_change.window = window;
event->focus_change.in = in;
gdk_event_set_device (event, device);
gdk_event_set_source_device (event, source_device);
_gdk_win32_append_event (event);
}
@ -212,11 +215,18 @@ generate_grab_broken_event (GdkDeviceManager *device_manager,
{
GdkEvent *event = gdk_event_new (GDK_GRAB_BROKEN);
GdkDevice *device;
GdkDevice *source_device;
if (keyboard)
device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard;
{
device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard;
source_device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->system_keyboard;
}
else
device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_pointer;
{
device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_pointer;
source_device = GDK_DEVICE_MANAGER_WIN32 (device_manager)->system_pointer;
}
event->grab_broken.window = window;
event->grab_broken.send_event = 0;
@ -224,6 +234,7 @@ generate_grab_broken_event (GdkDeviceManager *device_manager,
event->grab_broken.implicit = FALSE;
event->grab_broken.grab_window = grab_window;
gdk_event_set_device (event, device);
gdk_event_set_source_device (event, device);
_gdk_win32_append_event (event);
}
@ -1130,13 +1141,10 @@ send_crossing_event (GdkDisplay *display,
event->crossing.detail = notify_type;
event->crossing.focus = FALSE;
event->crossing.state = mask;
gdk_event_set_device (event, _gdk_display->core_pointer);
gdk_event_set_device (event, device_manager->core_pointer);
gdk_event_set_source_device (event, device_manager->system_pointer);
_gdk_win32_append_event (event);
if (type == GDK_ENTER_NOTIFY &&
_gdk_device_wintab_wants_events (window))
_gdk_device_wintab_update_window_coords (window);
}
static GdkWindow *
@ -1655,6 +1663,12 @@ generate_button_event (GdkEventType type,
MSG *msg)
{
GdkEvent *event = gdk_event_new (type);
GdkDeviceManagerWin32 *device_manager;
if (_gdk_input_ignore_core)
return;
device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (_gdk_display));
event->button.window = window;
event->button.time = _gdk_win32_get_next_tick (msg->time);
@ -1665,7 +1679,8 @@ generate_button_event (GdkEventType type,
event->button.axes = NULL;
event->button.state = build_pointer_event_state (msg);
event->button.button = button;
gdk_event_set_device (event, _gdk_display->core_pointer);
gdk_event_set_device (event, device_manager->core_pointer);
gdk_event_set_source_device (event, device_manager->system_pointer);
_gdk_win32_append_event (event);
}
@ -1841,6 +1856,7 @@ gdk_event_translate (MSG *msg,
GdkWindow *orig_window, *new_window;
GdkDeviceManager *device_manager;
GdkDeviceManagerWin32 *device_manager_win32;
GdkDeviceGrabInfo *keyboard_grab = NULL;
GdkDeviceGrabInfo *pointer_grab = NULL;
@ -1892,11 +1908,12 @@ gdk_event_translate (MSG *msg,
}
device_manager = gdk_display_get_device_manager (_gdk_display);
device_manager_win32 = GDK_DEVICE_MANAGER_WIN32 (device_manager);
keyboard_grab = _gdk_display_get_last_device_grab (_gdk_display,
GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_keyboard);
device_manager_win32->core_keyboard);
pointer_grab = _gdk_display_get_last_device_grab (_gdk_display,
GDK_DEVICE_MANAGER_WIN32 (device_manager)->core_pointer);
device_manager_win32->core_pointer);
g_object_ref (window);
@ -2051,7 +2068,8 @@ 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);
gdk_event_set_device (event, device_manager_win32->core_keyboard);
gdk_event_set_source_device (event, device_manager_win32->system_keyboard);
if (HIWORD (msg->lParam) & KF_EXTENDED)
{
switch (msg->wParam)
@ -2168,7 +2186,8 @@ 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);
gdk_event_set_device (event, device_manager_win32->core_keyboard);
gdk_event_set_source_device (event, device_manager_win32->system_keyboard);
build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
_gdk_win32_append_event (event);
@ -2179,7 +2198,8 @@ 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);
gdk_event_set_device (event, device_manager_win32->core_keyboard);
gdk_event_set_source_device (event, device_manager_win32->system_keyboard);
build_wm_ime_composition_event (event, msg, wbuf[i], key_state);
_gdk_win32_append_event (event);
@ -2361,19 +2381,23 @@ gdk_event_translate (MSG *msg,
current_root_x = msg->pt.x + _gdk_offset_x;
current_root_y = msg->pt.y + _gdk_offset_y;
event = gdk_event_new (GDK_MOTION_NOTIFY);
event->motion.window = window;
event->motion.time = _gdk_win32_get_next_tick (msg->time);
event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
event->motion.x_root = current_root_x;
event->motion.y_root = current_root_y;
event->motion.axes = NULL;
event->motion.state = build_pointer_event_state (msg);
event->motion.is_hint = FALSE;
gdk_event_set_device (event, _gdk_display->core_pointer);
if (!_gdk_input_ignore_core)
{
event = gdk_event_new (GDK_MOTION_NOTIFY);
event->motion.window = window;
event->motion.time = _gdk_win32_get_next_tick (msg->time);
event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
event->motion.x_root = current_root_x;
event->motion.y_root = current_root_y;
event->motion.axes = NULL;
event->motion.state = build_pointer_event_state (msg);
event->motion.is_hint = FALSE;
gdk_event_set_device (event, device_manager_win32->core_pointer);
gdk_event_set_source_device (event, device_manager_win32->system_pointer);
_gdk_win32_append_event (event);
_gdk_win32_append_event (event);
}
return_val = TRUE;
break;
@ -2485,7 +2509,8 @@ 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);
gdk_event_set_device (event, _gdk_display->core_pointer);
gdk_event_set_device (event, device_manager_win32->core_pointer);
gdk_event_set_source_device (event, device_manager_win32->system_pointer);
_gdk_win32_append_event (event);
@ -2763,9 +2788,6 @@ gdk_event_translate (MSG *msg,
!IsIconic (msg->hwnd) &&
!GDK_WINDOW_DESTROYED (window))
_gdk_win32_emit_configure_event (window);
if (_gdk_device_wintab_wants_events (window))
_gdk_device_wintab_update_window_coords (window);
}
if ((windowpos->flags & SWP_HIDEWINDOW) &&

View File

@ -75,6 +75,6 @@ _gdk_input_init (GdkDisplay *display)
_gdk_input_devices = g_list_concat (_gdk_input_devices,
g_list_copy (device_manager->wintab_devices));
_gdk_input_wintab_init_check (device_manager);
_gdk_input_wintab_init_check (GDK_DEVICE_MANAGER (device_manager));
}