1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <math.h>
23
24 #include <gdk/gdk.h>
25 #include "gdkwin32.h"
26 #include "gdkprivate-win32.h"
27 #include "gdkdevicemanager-win32.h"
28 #include "gdkdeviceprivate.h"
29 #include "gdkdevice-win32.h"
30 #include "gdkdevice-virtual.h"
31 #include "gdkdevice-winpointer.h"
32 #include "gdkdevice-wintab.h"
33 #include "gdkdisplayprivate.h"
34 #include "gdkdevicetoolprivate.h"
35 #include "gdkseatdefaultprivate.h"
36
37 #include <tchar.h>
38 #include <tpcshrd.h>
39 #include <hidsdi.h>
40 #include "winpointer.h"
41
42 #define WINTAB32_DLL "Wintab32.dll"
43
44 #define PACKETDATA (PK_CONTEXT | PK_CURSOR | PK_BUTTONS | PK_X | PK_Y | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_TANGENT_PRESSURE)
45 /* We want everything in absolute mode */
46 #define PACKETMODE (0)
47 #include <pktdef.h>
48
49 #define DEBUG_WINTAB 1 /* Verbose debug messages enabled */
50 #define TWOPI (2 * G_PI)
51
52 typedef BOOL
53 (WINAPI *registerPointerDeviceNotifications_t)(HWND window, BOOL notifyRange);
54 typedef BOOL
55 (WINAPI *getPointerDevices_t)(UINT32 *deviceCount, POINTER_DEVICE_INFO *pointerDevices);
56 typedef BOOL
57 (WINAPI *getPointerDeviceCursors_t)(HANDLE device, UINT32 *cursorCount, POINTER_DEVICE_CURSOR_INFO *deviceCursors);
58 typedef BOOL
59 (WINAPI *getPointerDeviceRects_t)(HANDLE device, RECT *pointerDeviceRect, RECT *displayRect);
60 typedef BOOL
61 (WINAPI *getPointerType_t)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
62 typedef BOOL
63 (WINAPI *getPointerCursorId_t)(UINT32 pointerId, UINT32 *cursorId);
64 typedef BOOL
65 (WINAPI *getPointerPenInfo_t)(UINT32 pointerId, POINTER_PEN_INFO *penInfo);
66 typedef BOOL
67 (WINAPI *getPointerTouchInfo_t)(UINT32 pointerId, POINTER_TOUCH_INFO *touchInfo);
68 typedef BOOL
69 (WINAPI *getPointerPenInfoHistory_t)(UINT32 pointerId, UINT32 *entriesCount, POINTER_PEN_INFO *penInfo);
70 typedef BOOL
71 (WINAPI *getPointerTouchInfoHistory_t)(UINT32 pointerId, UINT32 *entriesCount, POINTER_TOUCH_INFO *touchInfo);
72 typedef BOOL
73 (WINAPI *setGestureConfig_t)(HWND hwnd, DWORD dwReserved, UINT cIDs, PGESTURECONFIG pGestureConfig, UINT cbSize);
74 typedef BOOL
75 (WINAPI *setWindowFeedbackSetting_t)(HWND hwnd, FEEDBACK_TYPE feedback, DWORD dwFlags, UINT32 size, const VOID *configuration);
76
77 static registerPointerDeviceNotifications_t registerPointerDeviceNotifications;
78 static getPointerDevices_t getPointerDevices;
79 static getPointerDeviceCursors_t getPointerDeviceCursors;
80 static getPointerDeviceRects_t getPointerDeviceRects;
81 static getPointerType_t getPointerType;
82 static getPointerCursorId_t getPointerCursorId;
83 static getPointerPenInfo_t getPointerPenInfo;
84 static getPointerTouchInfo_t getPointerTouchInfo;
85 static getPointerPenInfoHistory_t getPointerPenInfoHistory;
86 static getPointerTouchInfoHistory_t getPointerTouchInfoHistory;
87 static setGestureConfig_t setGestureConfig;
88 static setWindowFeedbackSetting_t setWindowFeedbackSetting;
89
90 static ATOM winpointer_notif_window_class;
91 static HWND winpointer_notif_window_handle;
92
93 static GPtrArray *winpointer_ignored_interactions;
94
95 static GList *wintab_contexts = NULL;
96 static GdkWindow *wintab_window = NULL;
97 extern gint _gdk_input_ignore_core;
98
99 typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c);
100 typedef UINT (WINAPI *t_WTInfoW) (UINT a, UINT b, LPVOID c);
101 typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b);
102 typedef HCTX (WINAPI *t_WTOpenA) (HWND a, LPLOGCONTEXTA b, BOOL c);
103 typedef BOOL (WINAPI *t_WTGetA) (HCTX a, LPLOGCONTEXTA b);
104 typedef BOOL (WINAPI *t_WTSetA) (HCTX a, LPLOGCONTEXTA b);
105 typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b);
106 typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c);
107 typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b);
108
109 static t_WTInfoA p_WTInfoA;
110 static t_WTInfoW p_WTInfoW;
111 static t_WTEnable p_WTEnable;
112 static t_WTOpenA p_WTOpenA;
113 static t_WTGetA p_WTGetA;
114 static t_WTSetA p_WTSetA;
115 static t_WTOverlap p_WTOverlap;
116 static t_WTPacket p_WTPacket;
117 static t_WTQueueSizeSet p_WTQueueSizeSet;
118
119 static gboolean default_display_opened = FALSE;
120
121 G_DEFINE_TYPE (GdkDeviceManagerWin32, gdk_device_manager_win32, GDK_TYPE_DEVICE_MANAGER)
122
123 static GdkDeviceWintab *gdk_device_manager_find_wintab_device (GdkDeviceManagerWin32 *, HCTX, UINT);
124 UINT _wintab_recognize_new_cursors (GdkDeviceManagerWin32 *, HCTX);
125 int _gdk_find_wintab_device_index (HCTX);
126
127 static GdkDevice *
create_pointer(GdkDeviceManager * device_manager,GType g_type,const char * name,GdkDeviceType type)128 create_pointer (GdkDeviceManager *device_manager,
129 GType g_type,
130 const char *name,
131 GdkDeviceType type)
132 {
133 return g_object_new (g_type,
134 "name", name,
135 "type", type,
136 "input-source", GDK_SOURCE_MOUSE,
137 "input-mode", GDK_MODE_SCREEN,
138 "has-cursor", type == GDK_DEVICE_TYPE_MASTER,
139 "display", gdk_device_manager_get_display (device_manager),
140 "device-manager", device_manager,
141 NULL);
142 }
143
144 static GdkDevice *
create_keyboard(GdkDeviceManager * device_manager,GType g_type,const char * name,GdkDeviceType type)145 create_keyboard (GdkDeviceManager *device_manager,
146 GType g_type,
147 const char *name,
148 GdkDeviceType type)
149 {
150 return g_object_new (g_type,
151 "name", name,
152 "type", type,
153 "input-source", GDK_SOURCE_KEYBOARD,
154 "input-mode", GDK_MODE_SCREEN,
155 "has-cursor", FALSE,
156 "display", gdk_device_manager_get_display (device_manager),
157 "device-manager", device_manager,
158 NULL);
159 }
160
161 static void
gdk_device_manager_win32_init(GdkDeviceManagerWin32 * device_manager_win32)162 gdk_device_manager_win32_init (GdkDeviceManagerWin32 *device_manager_win32)
163 {
164 }
165
166 static void
gdk_device_manager_win32_finalize(GObject * object)167 gdk_device_manager_win32_finalize (GObject *object)
168 {
169 GdkDeviceManagerWin32 *device_manager_win32;
170
171 device_manager_win32 = GDK_DEVICE_MANAGER_WIN32 (object);
172
173 g_object_unref (device_manager_win32->core_pointer);
174 g_object_unref (device_manager_win32->core_keyboard);
175
176 G_OBJECT_CLASS (gdk_device_manager_win32_parent_class)->finalize (object);
177 }
178
179 static inline double
rect_width(RECT * rect)180 rect_width (RECT *rect)
181 {
182 return rect->right - rect->left;
183 }
184
185 static inline double
rect_height(RECT * rect)186 rect_height (RECT *rect)
187 {
188 return rect->bottom - rect->top;
189 }
190
191 static inline gboolean
rect_is_degenerate(RECT * rect)192 rect_is_degenerate (RECT *rect)
193 {
194 return rect_width (rect) == 0 || rect_height (rect) == 0;
195 }
196
197 static gboolean
winpointer_device_update_scale_factors(GdkDeviceWinpointer * device)198 winpointer_device_update_scale_factors (GdkDeviceWinpointer *device)
199 {
200 RECT device_rect;
201 RECT display_rect;
202
203 if (!getPointerDeviceRects (device->device_handle, &device_rect, &display_rect))
204 {
205 WIN32_API_FAILED ("GetPointerDeviceRects");
206 return FALSE;
207 }
208
209 if (rect_is_degenerate (&device_rect))
210 {
211 g_warning ("Invalid coordinates from GetPointerDeviceRects");
212 return FALSE;
213 }
214
215 device->origin_x = display_rect.left;
216 device->origin_y = display_rect.top;
217 device->scale_x = rect_width (&display_rect) / rect_width (&device_rect);
218 device->scale_y = rect_height (&display_rect) / rect_height (&device_rect);
219
220 return TRUE;
221 }
222
223 #define HID_STRING_BYTES_LIMIT 200
224 #define VID_PID_CHARS 4
225
226 static void
winpointer_get_device_details(HANDLE device,char * vid,char * pid,char ** manufacturer,char ** product)227 winpointer_get_device_details (HANDLE device,
228 char *vid,
229 char *pid,
230 char **manufacturer,
231 char **product)
232 {
233 RID_DEVICE_INFO info;
234 UINT wchars_count = 0;
235 UINT size = 0;
236
237 memset (&info, 0, sizeof (info));
238
239 info.cbSize = sizeof (info);
240 size = sizeof (info);
241
242 if (GetRawInputDeviceInfoW (device, RIDI_DEVICEINFO, &info, &size) > 0 &&
243 info.dwType == RIM_TYPEHID &&
244 info.hid.dwVendorId > 0 &&
245 info.hid.dwProductId > 0)
246 {
247 const char *format_string = "%0" G_STRINGIFY (VID_PID_CHARS) "x";
248
249 g_snprintf (vid, VID_PID_CHARS + 1, format_string, (unsigned) info.hid.dwVendorId);
250 g_snprintf (pid, VID_PID_CHARS + 1, format_string, (unsigned) info.hid.dwProductId);
251 }
252
253 if (GetRawInputDeviceInfoW (device, RIDI_DEVICENAME, NULL, &wchars_count) == 0)
254 {
255 gunichar2 *path = g_new0 (gunichar2, wchars_count);
256
257 if (GetRawInputDeviceInfoW (device, RIDI_DEVICENAME, path, &wchars_count) > 0)
258 {
259 HANDLE device_file = CreateFileW (path,
260 0,
261 FILE_SHARE_READ |
262 FILE_SHARE_WRITE |
263 FILE_SHARE_DELETE,
264 NULL,
265 OPEN_EXISTING,
266 FILE_FLAG_SESSION_AWARE,
267 NULL);
268
269 if (device_file != INVALID_HANDLE_VALUE)
270 {
271 gunichar2 *buffer = g_malloc0 (HID_STRING_BYTES_LIMIT);
272
273 if (HidD_GetManufacturerString (device_file, buffer, HID_STRING_BYTES_LIMIT))
274 if (buffer[0])
275 *manufacturer = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
276
277 if (HidD_GetProductString (device_file, buffer, HID_STRING_BYTES_LIMIT))
278 if (buffer[0])
279 *product = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
280
281 g_free (buffer);
282 CloseHandle (device_file);
283 }
284 }
285
286 g_free (path);
287 }
288 }
289
290 static void
winpointer_create_device(GdkDeviceManagerWin32 * device_manager,POINTER_DEVICE_INFO * info,GdkInputSource source)291 winpointer_create_device (GdkDeviceManagerWin32 *device_manager,
292 POINTER_DEVICE_INFO *info,
293 GdkInputSource source)
294 {
295 GdkDisplay *display = NULL;
296 GdkSeat *seat = NULL;
297 GdkDeviceWinpointer *device = NULL;
298 unsigned num_touches = 0;
299 char vid[VID_PID_CHARS + 1];
300 char pid[VID_PID_CHARS + 1];
301 char *manufacturer = NULL;
302 char *product = NULL;
303 char *base_name = NULL;
304 char *name = NULL;
305 UINT32 num_cursors = 0;
306
307 memset (pid, 0, VID_PID_CHARS + 1);
308 memset (vid, 0, VID_PID_CHARS + 1);
309
310 g_object_get (device_manager, "display", &display, NULL);
311 seat = gdk_display_get_default_seat (display);
312
313 if (!getPointerDeviceCursors (info->device, &num_cursors, NULL))
314 {
315 WIN32_API_FAILED ("GetPointerDeviceCursors");
316 return;
317 }
318
319 if (num_cursors == 0)
320 return;
321
322 winpointer_get_device_details (info->device, vid, pid, &manufacturer, &product);
323
324 /* build up the name */
325 if (!manufacturer && vid[0])
326 manufacturer = g_strdup (vid);
327
328 if (!product && pid[0])
329 product = g_strdup (pid);
330
331 if (manufacturer && product)
332 base_name = g_strconcat (manufacturer, " ", product, NULL);
333
334 if (!base_name && info->productString[0])
335 base_name = g_utf16_to_utf8 (info->productString, -1, NULL, NULL, NULL);
336
337 if (!base_name)
338 base_name = g_strdup ("Unnamed");
339
340 switch (source)
341 {
342 case GDK_SOURCE_PEN:
343 name = g_strconcat (base_name, " Pen stylus", NULL);
344 break;
345 case GDK_SOURCE_ERASER:
346 name = g_strconcat (base_name, " Eraser", NULL);
347 break;
348 case GDK_SOURCE_TOUCHSCREEN:
349 num_touches = info->maxActiveContacts;
350 name = g_strconcat (base_name, " Finger touch", NULL);
351 break;
352 default:
353 name = g_strdup (base_name);
354 break;
355 }
356
357 device = g_object_new (GDK_TYPE_DEVICE_WINPOINTER,
358 "display", display,
359 "device-manager", device_manager,
360 "seat", seat,
361 "type", GDK_DEVICE_TYPE_SLAVE,
362 "input-mode", GDK_MODE_SCREEN,
363 "has-cursor", TRUE,
364 "input-source", source,
365 "name", name,
366 "num-touches", num_touches,
367 "vendor-id", vid[0] ? vid : NULL,
368 "product-id", pid[0] ? pid : NULL,
369 NULL);
370
371 switch (source)
372 {
373 case GDK_SOURCE_PEN:
374 case GDK_SOURCE_ERASER:
375 _gdk_device_add_axis (GDK_DEVICE (device), GDK_NONE, GDK_AXIS_PRESSURE, 0.0, 1.0, 1.0 / 1024.0);
376 _gdk_device_add_axis (GDK_DEVICE (device), GDK_NONE, GDK_AXIS_XTILT, -1.0, 1.0, 1.0 / 90.0);
377 _gdk_device_add_axis (GDK_DEVICE (device), GDK_NONE, GDK_AXIS_YTILT, -1.0, 1.0, 1.0 / 90.0);
378 _gdk_device_add_axis (GDK_DEVICE (device), GDK_NONE, GDK_AXIS_ROTATION, 0.0, 1.0, 1.0 / 360.0);
379
380 device->num_axes = 4;
381 break;
382 case GDK_SOURCE_TOUCHSCREEN:
383 _gdk_device_add_axis (GDK_DEVICE (device), GDK_NONE, GDK_AXIS_PRESSURE, 0.0, 1.0, 1.0 / 1024.0);
384
385 device->num_axes = 1;
386 break;
387 }
388
389 device->device_handle = info->device;
390 device->start_cursor_id = info->startingCursorId;
391 device->end_cursor_id = info->startingCursorId + num_cursors - 1;
392
393 device->last_axis_data = g_new0 (double, device->num_axes);
394
395 switch (source)
396 {
397 case GDK_SOURCE_PEN:
398 {
399 GdkAxisFlags axes = gdk_device_get_axes (GDK_DEVICE (device));
400 GdkDeviceTool *tool = gdk_device_tool_new (0, 0, GDK_DEVICE_TOOL_TYPE_PEN, axes);
401
402 gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
403 gdk_device_update_tool (GDK_DEVICE (device), tool);
404 }
405 break;
406 case GDK_SOURCE_ERASER:
407 {
408 GdkAxisFlags axes = gdk_device_get_axes (GDK_DEVICE (device));
409 GdkDeviceTool *tool = gdk_device_tool_new (0, 0, GDK_DEVICE_TOOL_TYPE_ERASER, axes);
410
411 gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
412 gdk_device_update_tool (GDK_DEVICE (device), tool);
413 }
414 break;
415 case GDK_SOURCE_TOUCHSCREEN:
416 break;
417 }
418
419 if (!winpointer_device_update_scale_factors (device))
420 {
421 g_set_object (&device, NULL);
422 goto cleanup;
423 }
424
425 device_manager->winpointer_devices = g_list_append (device_manager->winpointer_devices, device);
426
427 _gdk_device_set_associated_device (GDK_DEVICE (device), device_manager->core_pointer);
428 _gdk_device_add_slave (device_manager->core_pointer, GDK_DEVICE (device));
429
430 gdk_seat_default_add_slave (GDK_SEAT_DEFAULT (seat), GDK_DEVICE (device));
431
432 g_signal_emit_by_name (device_manager, "device-added", device);
433
434 cleanup:
435 g_free (name);
436 g_free (base_name);
437 g_free (product);
438 g_free (manufacturer);
439 }
440
441 static void
winpointer_create_devices(GdkDeviceManagerWin32 * device_manager,POINTER_DEVICE_INFO * info)442 winpointer_create_devices (GdkDeviceManagerWin32 *device_manager,
443 POINTER_DEVICE_INFO *info)
444 {
445 switch (info->pointerDeviceType)
446 {
447 case POINTER_DEVICE_TYPE_INTEGRATED_PEN:
448 case POINTER_DEVICE_TYPE_EXTERNAL_PEN:
449 winpointer_create_device (device_manager, info, GDK_SOURCE_PEN);
450 winpointer_create_device (device_manager, info, GDK_SOURCE_ERASER);
451 break;
452 case POINTER_DEVICE_TYPE_TOUCH:
453 winpointer_create_device (device_manager, info, GDK_SOURCE_TOUCHSCREEN);
454 break;
455 }
456 }
457
458 static gboolean
winpointer_match_device_in_system_list(GdkDeviceWinpointer * device,POINTER_DEVICE_INFO * infos,UINT32 infos_count)459 winpointer_match_device_in_system_list (GdkDeviceWinpointer *device,
460 POINTER_DEVICE_INFO *infos,
461 UINT32 infos_count)
462 {
463 UINT32 i = 0;
464
465 for (i = 0; i < infos_count; i++)
466 {
467 if (device->device_handle == infos[i].device &&
468 device->start_cursor_id == infos[i].startingCursorId)
469 return TRUE;
470 }
471
472 return FALSE;
473 }
474
475 static gboolean
winpointer_match_system_device_in_device_manager(GdkDeviceManagerWin32 * device_manager,POINTER_DEVICE_INFO * info)476 winpointer_match_system_device_in_device_manager (GdkDeviceManagerWin32 *device_manager,
477 POINTER_DEVICE_INFO *info)
478 {
479 GList *l = NULL;
480
481 for (l = device_manager->winpointer_devices; l; l = l->next)
482 {
483 GdkDeviceWinpointer *device = GDK_DEVICE_WINPOINTER (l->data);
484
485 if (device->device_handle == info->device &&
486 device->start_cursor_id == info->startingCursorId)
487 return TRUE;
488 }
489
490 return FALSE;
491 }
492
493 static void
winpointer_enumerate_devices(GdkDeviceManagerWin32 * device_manager)494 winpointer_enumerate_devices (GdkDeviceManagerWin32 *device_manager)
495 {
496 POINTER_DEVICE_INFO *infos = NULL;
497 UINT32 infos_count = 0;
498 UINT32 i = 0;
499 GList *current = NULL;
500
501 do
502 {
503 infos = g_new0 (POINTER_DEVICE_INFO, infos_count);
504 if (!getPointerDevices (&infos_count, infos))
505 {
506 WIN32_API_FAILED ("GetPointerDevices");
507 g_free (infos);
508 return;
509 }
510 }
511 while (infos_count > 0 && !infos);
512
513 /* remove any gdk device not present anymore or update info */
514 current = device_manager->winpointer_devices;
515 while (current != NULL)
516 {
517 GdkDeviceWinpointer *device = GDK_DEVICE_WINPOINTER (current->data);
518 GList *next = current->next;
519
520 if (!winpointer_match_device_in_system_list (device, infos, infos_count))
521 {
522 GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (device));
523
524 gdk_device_update_tool (GDK_DEVICE (device), NULL);
525 gdk_seat_default_remove_tool (GDK_SEAT_DEFAULT (seat), (GDK_DEVICE (device))->last_tool);
526
527 gdk_seat_default_remove_slave (GDK_SEAT_DEFAULT (seat), GDK_DEVICE (device));
528 device_manager->winpointer_devices = g_list_delete_link (device_manager->winpointer_devices,
529 current);
530 g_signal_emit_by_name (device_manager, "device-removed", device);
531
532 _gdk_device_set_associated_device (GDK_DEVICE (device), NULL);
533 _gdk_device_remove_slave (device_manager->core_pointer, GDK_DEVICE (device));
534
535 g_object_unref (device);
536 }
537 else
538 winpointer_device_update_scale_factors (device);
539
540 current = next;
541 }
542
543 /* create new gdk devices */
544 for (i = 0; i < infos_count; i++)
545 if (!winpointer_match_system_device_in_device_manager (device_manager,
546 &infos[i]))
547 winpointer_create_devices (device_manager, &infos[i]);
548
549 g_free (infos);
550 }
551
552 static LRESULT CALLBACK
winpointer_notif_window_proc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)553 winpointer_notif_window_proc (HWND hWnd,
554 UINT uMsg,
555 WPARAM wParam,
556 LPARAM lParam)
557 {
558 switch (uMsg)
559 {
560 case WM_POINTERDEVICECHANGE:
561 {
562 LONG_PTR user_data = GetWindowLongPtrW (hWnd, GWLP_USERDATA);
563 GdkDeviceManagerWin32 *device_manager = GDK_DEVICE_MANAGER_WIN32 (user_data);
564
565 winpointer_enumerate_devices (device_manager);
566 }
567 return 0;
568 }
569
570 return DefWindowProcW (hWnd, uMsg, wParam, lParam);
571 }
572
573 static gboolean
winpointer_notif_window_create()574 winpointer_notif_window_create ()
575 {
576 WNDCLASSEXW wndclass;
577
578 memset (&wndclass, 0, sizeof (wndclass));
579 wndclass.cbSize = sizeof (wndclass);
580 wndclass.lpszClassName = L"GdkWin32WinPointerNotificationsWindowClass";
581 wndclass.lpfnWndProc = winpointer_notif_window_proc;
582 wndclass.hInstance = _gdk_dll_hinstance;
583
584 if ((winpointer_notif_window_class = RegisterClassExW (&wndclass)) == 0)
585 {
586 WIN32_API_FAILED ("RegisterClassExW");
587 return FALSE;
588 }
589
590 if (!(winpointer_notif_window_handle = CreateWindowExW (0,
591 (LPCWSTR) winpointer_notif_window_class,
592 L"GdkWin32 WinPointer Notifications",
593 0,
594 0, 0, 0, 0,
595 HWND_MESSAGE,
596 NULL,
597 _gdk_dll_hinstance,
598 NULL)))
599 {
600 WIN32_API_FAILED ("CreateWindowExW");
601 return FALSE;
602 }
603
604 return TRUE;
605 }
606
607 static gboolean
winpointer_ensure_procedures()608 winpointer_ensure_procedures ()
609 {
610 static HMODULE user32_dll = NULL;
611
612 if (!user32_dll)
613 {
614 user32_dll = LoadLibraryW (L"user32.dll");
615 if (!user32_dll)
616 {
617 WIN32_API_FAILED ("LoadLibraryW");
618 return FALSE;
619 }
620
621 registerPointerDeviceNotifications = (registerPointerDeviceNotifications_t)
622 GetProcAddress (user32_dll, "RegisterPointerDeviceNotifications");
623 getPointerDevices = (getPointerDevices_t)
624 GetProcAddress (user32_dll, "GetPointerDevices");
625 getPointerDeviceCursors = (getPointerDeviceCursors_t)
626 GetProcAddress (user32_dll, "GetPointerDeviceCursors");
627 getPointerDeviceRects = (getPointerDeviceRects_t)
628 GetProcAddress (user32_dll, "GetPointerDeviceRects");
629 getPointerType = (getPointerType_t)
630 GetProcAddress (user32_dll, "GetPointerType");
631 getPointerCursorId = (getPointerCursorId_t)
632 GetProcAddress (user32_dll, "GetPointerCursorId");
633 getPointerPenInfo = (getPointerPenInfo_t)
634 GetProcAddress (user32_dll, "GetPointerPenInfo");
635 getPointerTouchInfo = (getPointerTouchInfo_t)
636 GetProcAddress (user32_dll, "GetPointerTouchInfo");
637 getPointerPenInfoHistory = (getPointerPenInfoHistory_t)
638 GetProcAddress (user32_dll, "GetPointerPenInfoHistory");
639 getPointerTouchInfoHistory = (getPointerTouchInfoHistory_t)
640 GetProcAddress (user32_dll, "GetPointerTouchInfoHistory");
641 setGestureConfig = (setGestureConfig_t)
642 GetProcAddress (user32_dll, "SetGestureConfig");
643 setWindowFeedbackSetting = (setWindowFeedbackSetting_t)
644 GetProcAddress (user32_dll, "SetWindowFeedbackSetting");
645 }
646
647 return registerPointerDeviceNotifications &&
648 getPointerDevices &&
649 getPointerDeviceCursors &&
650 getPointerDeviceRects &&
651 getPointerType &&
652 getPointerCursorId &&
653 getPointerPenInfo &&
654 getPointerTouchInfo &&
655 getPointerPenInfoHistory &&
656 getPointerTouchInfoHistory &&
657 setGestureConfig;
658 }
659
660 static gboolean
winpointer_initialize(GdkDeviceManagerWin32 * device_manager)661 winpointer_initialize (GdkDeviceManagerWin32 *device_manager)
662 {
663 if (!winpointer_ensure_procedures ())
664 return FALSE;
665
666 if (!winpointer_notif_window_create ())
667 return FALSE;
668
669 /* associate device_manager with the window */
670 SetLastError (0);
671 if (SetWindowLongPtrW (winpointer_notif_window_handle,
672 GWLP_USERDATA,
673 (LONG_PTR) device_manager) == 0
674 && GetLastError () != 0)
675 {
676 WIN32_API_FAILED ("SetWindowLongPtrW");
677 return FALSE;
678 }
679
680 if (!registerPointerDeviceNotifications (winpointer_notif_window_handle, FALSE))
681 {
682 WIN32_API_FAILED ("RegisterPointerDeviceNotifications");
683 return FALSE;
684 }
685
686 winpointer_ignored_interactions = g_ptr_array_new ();
687
688 winpointer_enumerate_devices (device_manager);
689
690 return TRUE;
691 }
692
693 void
gdk_winpointer_initialize_window(GdkWindow * window)694 gdk_winpointer_initialize_window (GdkWindow *window)
695 {
696 HWND hwnd = GDK_WINDOW_HWND (window);
697 ATOM key = 0;
698 HANDLE val = (HANDLE)(TABLET_DISABLE_PRESSANDHOLD |
699 TABLET_DISABLE_PENTAPFEEDBACK |
700 TABLET_DISABLE_PENBARRELFEEDBACK |
701 TABLET_DISABLE_FLICKS |
702 TABLET_DISABLE_FLICKFALLBACKKEYS);
703
704 winpointer_ensure_procedures ();
705
706 key = GlobalAddAtom (MICROSOFT_TABLETPENSERVICE_PROPERTY);
707 API_CALL (SetPropW, (hwnd, (LPCWSTR) key, val));
708 GlobalDeleteAtom (key);
709
710 if (setGestureConfig != NULL)
711 {
712 GESTURECONFIG gesture_config;
713 memset (&gesture_config, 0, sizeof (gesture_config));
714
715 gesture_config.dwID = 0;
716 gesture_config.dwWant = 0;
717 gesture_config.dwBlock = GC_ALLGESTURES;
718
719 API_CALL (setGestureConfig, (hwnd, 0, 1, &gesture_config, sizeof (gesture_config)));
720 }
721
722 if (setWindowFeedbackSetting != NULL)
723 {
724 FEEDBACK_TYPE feedbacks[] = {
725 FEEDBACK_TOUCH_CONTACTVISUALIZATION,
726 FEEDBACK_PEN_BARRELVISUALIZATION,
727 FEEDBACK_PEN_TAP,
728 FEEDBACK_PEN_DOUBLETAP,
729 FEEDBACK_PEN_PRESSANDHOLD,
730 FEEDBACK_PEN_RIGHTTAP,
731 FEEDBACK_TOUCH_TAP,
732 FEEDBACK_TOUCH_DOUBLETAP,
733 FEEDBACK_TOUCH_PRESSANDHOLD,
734 FEEDBACK_TOUCH_RIGHTTAP,
735 FEEDBACK_GESTURE_PRESSANDTAP
736 };
737 gsize i = 0;
738
739 for (i = 0; i < G_N_ELEMENTS (feedbacks); i++)
740 {
741 BOOL setting = FALSE;
742
743 API_CALL (setWindowFeedbackSetting, (hwnd, feedbacks[i], 0, sizeof (BOOL), &setting));
744 }
745 }
746 }
747
748 void
gdk_winpointer_finalize_window(GdkWindow * window)749 gdk_winpointer_finalize_window (GdkWindow *window)
750 {
751 HWND hwnd = GDK_WINDOW_HWND (window);
752 ATOM key = 0;
753
754 key = GlobalAddAtom (MICROSOFT_TABLETPENSERVICE_PROPERTY);
755 RemovePropW (hwnd, (LPCWSTR) key);
756 GlobalDeleteAtom (key);
757 }
758
759 #if DEBUG_WINTAB
760
761 static void
print_lc(LOGCONTEXT * lc)762 print_lc(LOGCONTEXT *lc)
763 {
764 g_print ("lcName = %s\n", lc->lcName);
765 g_print ("lcOptions =");
766 if (lc->lcOptions & CXO_SYSTEM) g_print (" CXO_SYSTEM");
767 if (lc->lcOptions & CXO_PEN) g_print (" CXO_PEN");
768 if (lc->lcOptions & CXO_MESSAGES) g_print (" CXO_MESSAGES");
769 if (lc->lcOptions & CXO_MARGIN) g_print (" CXO_MARGIN");
770 if (lc->lcOptions & CXO_MGNINSIDE) g_print (" CXO_MGNINSIDE");
771 if (lc->lcOptions & CXO_CSRMESSAGES) g_print (" CXO_CSRMESSAGES");
772 g_print ("\n");
773 g_print ("lcStatus =");
774 if (lc->lcStatus & CXS_DISABLED) g_print (" CXS_DISABLED");
775 if (lc->lcStatus & CXS_OBSCURED) g_print (" CXS_OBSCURED");
776 if (lc->lcStatus & CXS_ONTOP) g_print (" CXS_ONTOP");
777 g_print ("\n");
778 g_print ("lcLocks =");
779 if (lc->lcLocks & CXL_INSIZE) g_print (" CXL_INSIZE");
780 if (lc->lcLocks & CXL_INASPECT) g_print (" CXL_INASPECT");
781 if (lc->lcLocks & CXL_SENSITIVITY) g_print (" CXL_SENSITIVITY");
782 if (lc->lcLocks & CXL_MARGIN) g_print (" CXL_MARGIN");
783 g_print ("\n");
784 g_print ("lcMsgBase = %#x, lcDevice = %#x, lcPktRate = %d\n",
785 lc->lcMsgBase, lc->lcDevice, lc->lcPktRate);
786 g_print ("lcPktData =");
787 if (lc->lcPktData & PK_CONTEXT) g_print (" PK_CONTEXT");
788 if (lc->lcPktData & PK_STATUS) g_print (" PK_STATUS");
789 if (lc->lcPktData & PK_TIME) g_print (" PK_TIME");
790 if (lc->lcPktData & PK_CHANGED) g_print (" PK_CHANGED");
791 if (lc->lcPktData & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
792 if (lc->lcPktData & PK_CURSOR) g_print (" PK_CURSOR");
793 if (lc->lcPktData & PK_BUTTONS) g_print (" PK_BUTTONS");
794 if (lc->lcPktData & PK_X) g_print (" PK_X");
795 if (lc->lcPktData & PK_Y) g_print (" PK_Y");
796 if (lc->lcPktData & PK_Z) g_print (" PK_Z");
797 if (lc->lcPktData & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
798 if (lc->lcPktData & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
799 if (lc->lcPktData & PK_ORIENTATION) g_print (" PK_ORIENTATION");
800 if (lc->lcPktData & PK_ROTATION) g_print (" PK_ROTATION");
801 g_print ("\n");
802 g_print ("lcPktMode =");
803 if (lc->lcPktMode & PK_CONTEXT) g_print (" PK_CONTEXT");
804 if (lc->lcPktMode & PK_STATUS) g_print (" PK_STATUS");
805 if (lc->lcPktMode & PK_TIME) g_print (" PK_TIME");
806 if (lc->lcPktMode & PK_CHANGED) g_print (" PK_CHANGED");
807 if (lc->lcPktMode & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
808 if (lc->lcPktMode & PK_CURSOR) g_print (" PK_CURSOR");
809 if (lc->lcPktMode & PK_BUTTONS) g_print (" PK_BUTTONS");
810 if (lc->lcPktMode & PK_X) g_print (" PK_X");
811 if (lc->lcPktMode & PK_Y) g_print (" PK_Y");
812 if (lc->lcPktMode & PK_Z) g_print (" PK_Z");
813 if (lc->lcPktMode & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
814 if (lc->lcPktMode & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
815 if (lc->lcPktMode & PK_ORIENTATION) g_print (" PK_ORIENTATION");
816 if (lc->lcPktMode & PK_ROTATION) g_print (" PK_ROTATION");
817 g_print ("\n");
818 g_print ("lcMoveMask =");
819 if (lc->lcMoveMask & PK_CONTEXT) g_print (" PK_CONTEXT");
820 if (lc->lcMoveMask & PK_STATUS) g_print (" PK_STATUS");
821 if (lc->lcMoveMask & PK_TIME) g_print (" PK_TIME");
822 if (lc->lcMoveMask & PK_CHANGED) g_print (" PK_CHANGED");
823 if (lc->lcMoveMask & PK_SERIAL_NUMBER) g_print (" PK_SERIAL_NUMBER");
824 if (lc->lcMoveMask & PK_CURSOR) g_print (" PK_CURSOR");
825 if (lc->lcMoveMask & PK_BUTTONS) g_print (" PK_BUTTONS");
826 if (lc->lcMoveMask & PK_X) g_print (" PK_X");
827 if (lc->lcMoveMask & PK_Y) g_print (" PK_Y");
828 if (lc->lcMoveMask & PK_Z) g_print (" PK_Z");
829 if (lc->lcMoveMask & PK_NORMAL_PRESSURE) g_print (" PK_NORMAL_PRESSURE");
830 if (lc->lcMoveMask & PK_TANGENT_PRESSURE) g_print (" PK_TANGENT_PRESSURE");
831 if (lc->lcMoveMask & PK_ORIENTATION) g_print (" PK_ORIENTATION");
832 if (lc->lcMoveMask & PK_ROTATION) g_print (" PK_ROTATION");
833 g_print ("\n");
834 g_print ("lcBtnDnMask = %#x, lcBtnUpMask = %#x\n",
835 (guint) lc->lcBtnDnMask, (guint) lc->lcBtnUpMask);
836 g_print ("lcInOrgX = %ld, lcInOrgY = %ld, lcInOrgZ = %ld\n",
837 lc->lcInOrgX, lc->lcInOrgY, lc->lcInOrgZ);
838 g_print ("lcInExtX = %ld, lcInExtY = %ld, lcInExtZ = %ld\n",
839 lc->lcInExtX, lc->lcInExtY, lc->lcInExtZ);
840 g_print ("lcOutOrgX = %ld, lcOutOrgY = %ld, lcOutOrgZ = %ld\n",
841 lc->lcOutOrgX, lc->lcOutOrgY, lc->lcOutOrgZ);
842 g_print ("lcOutExtX = %ld, lcOutExtY = %ld, lcOutExtZ = %ld\n",
843 lc->lcOutExtX, lc->lcOutExtY, lc->lcOutExtZ);
844 g_print ("lcSensX = %g, lcSensY = %g, lcSensZ = %g\n",
845 lc->lcSensX / 65536., lc->lcSensY / 65536., lc->lcSensZ / 65536.);
846 g_print ("lcSysMode = %d\n", lc->lcSysMode);
847 g_print ("lcSysOrgX = %d, lcSysOrgY = %d\n",
848 lc->lcSysOrgX, lc->lcSysOrgY);
849 g_print ("lcSysExtX = %d, lcSysExtY = %d\n",
850 lc->lcSysExtX, lc->lcSysExtY);
851 g_print ("lcSysSensX = %g, lcSysSensY = %g\n",
852 lc->lcSysSensX / 65536., lc->lcSysSensY / 65536.);
853 }
854
855 static void
print_cursor(int index)856 print_cursor (int index)
857 {
858 int size;
859 int i;
860 char *name;
861 BOOL active;
862 WTPKT wtpkt;
863 BYTE buttons;
864 BYTE buttonbits;
865 char *btnnames;
866 char *p;
867 BYTE buttonmap[32];
868 BYTE sysbtnmap[32];
869 BYTE npbutton;
870 UINT npbtnmarks[2];
871 UINT *npresponse;
872 BYTE tpbutton;
873 UINT tpbtnmarks[2];
874 UINT *tpresponse;
875 DWORD physid;
876 UINT mode;
877 UINT minpktdata;
878 UINT minbuttons;
879 UINT capabilities;
880
881 size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, NULL);
882 name = g_malloc (size + 1);
883 (*p_WTInfoA) (WTI_CURSORS + index, CSR_NAME, name);
884 g_print ("NAME: %s\n", name);
885 (*p_WTInfoA) (WTI_CURSORS + index, CSR_ACTIVE, &active);
886 g_print ("ACTIVE: %s\n", active ? "YES" : "NO");
887 (*p_WTInfoA) (WTI_CURSORS + index, CSR_PKTDATA, &wtpkt);
888 g_print ("PKTDATA: %#x:", (guint) wtpkt);
889 #define BIT(x) if (wtpkt & PK_##x) g_print (" " #x)
890 BIT (CONTEXT);
891 BIT (STATUS);
892 BIT (TIME);
893 BIT (CHANGED);
894 BIT (SERIAL_NUMBER);
895 BIT (BUTTONS);
896 BIT (X);
897 BIT (Y);
898 BIT (Z);
899 BIT (NORMAL_PRESSURE);
900 BIT (TANGENT_PRESSURE);
901 BIT (ORIENTATION);
902 BIT (ROTATION);
903 #undef BIT
904 g_print ("\n");
905 (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONS, &buttons);
906 g_print ("BUTTONS: %d\n", buttons);
907 (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONBITS, &buttonbits);
908 g_print ("BUTTONBITS: %d\n", buttonbits);
909 size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, NULL);
910 g_print ("BTNNAMES:");
911 if (size > 0)
912 {
913 btnnames = g_malloc (size + 1);
914 (*p_WTInfoA) (WTI_CURSORS + index, CSR_BTNNAMES, btnnames);
915 p = btnnames;
916 while (*p)
917 {
918 g_print (" %s", p);
919 p += strlen (p) + 1;
920 }
921 }
922 g_print ("\n");
923 (*p_WTInfoA) (WTI_CURSORS + index, CSR_BUTTONMAP, buttonmap);
924 g_print ("BUTTONMAP:");
925 for (i = 0; i < buttons; i++)
926 g_print (" %d", buttonmap[i]);
927 g_print ("\n");
928 (*p_WTInfoA) (WTI_CURSORS + index, CSR_SYSBTNMAP, sysbtnmap);
929 g_print ("SYSBTNMAP:");
930 for (i = 0; i < buttons; i++)
931 g_print (" %d", sysbtnmap[i]);
932 g_print ("\n");
933 (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBUTTON, &npbutton);
934 g_print ("NPBUTTON: %d\n", npbutton);
935 (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPBTNMARKS, npbtnmarks);
936 g_print ("NPBTNMARKS: %d %d\n", npbtnmarks[0], npbtnmarks[1]);
937 size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, NULL);
938 g_print ("NPRESPONSE:");
939 if (size > 0)
940 {
941 npresponse = g_malloc (size);
942 (*p_WTInfoA) (WTI_CURSORS + index, CSR_NPRESPONSE, npresponse);
943 for (i = 0; i < size / sizeof (UINT); i++)
944 g_print (" %d", npresponse[i]);
945 }
946 g_print ("\n");
947 (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBUTTON, &tpbutton);
948 g_print ("TPBUTTON: %d\n", tpbutton);
949 (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPBTNMARKS, tpbtnmarks);
950 g_print ("TPBTNMARKS: %d %d\n", tpbtnmarks[0], tpbtnmarks[1]);
951 size = (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, NULL);
952 g_print ("TPRESPONSE:");
953 if (size > 0)
954 {
955 tpresponse = g_malloc (size);
956 (*p_WTInfoA) (WTI_CURSORS + index, CSR_TPRESPONSE, tpresponse);
957 for (i = 0; i < size / sizeof (UINT); i++)
958 g_print (" %d", tpresponse[i]);
959 }
960 g_print ("\n");
961 (*p_WTInfoA) (WTI_CURSORS + index, CSR_PHYSID, &physid);
962 g_print ("PHYSID: %#x\n", (guint) physid);
963 (*p_WTInfoA) (WTI_CURSORS + index, CSR_CAPABILITIES, &capabilities);
964 g_print ("CAPABILITIES: %#x:", capabilities);
965 #define BIT(x) if (capabilities & CRC_##x) g_print (" " #x)
966 BIT (MULTIMODE);
967 BIT (AGGREGATE);
968 BIT (INVERT);
969 #undef BIT
970 g_print ("\n");
971 if (capabilities & CRC_MULTIMODE)
972 {
973 (*p_WTInfoA) (WTI_CURSORS + index, CSR_MODE, &mode);
974 g_print ("MODE: %d\n", mode);
975 }
976 if (capabilities & CRC_AGGREGATE)
977 {
978 (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINPKTDATA, &minpktdata);
979 g_print ("MINPKTDATA: %d\n", minpktdata);
980 (*p_WTInfoA) (WTI_CURSORS + index, CSR_MINBUTTONS, &minbuttons);
981 g_print ("MINBUTTONS: %d\n", minbuttons);
982 }
983 }
984 #endif
985
986 static void
wintab_init_check(GdkDeviceManagerWin32 * device_manager)987 wintab_init_check (GdkDeviceManagerWin32 *device_manager)
988 {
989 GdkDisplay *display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
990 GdkWindow *root = gdk_screen_get_root_window (gdk_display_get_default_screen (display));
991 static gboolean wintab_initialized = FALSE;
992 GdkWindowAttr wa;
993 WORD specversion;
994 HCTX *hctx;
995 UINT ndevices, ncursors;
996 UINT devix;
997 AXIS axis_x, axis_y;
998 int i;
999 wchar_t devname[100];
1000 gchar *devname_utf8;
1001 BOOL defcontext_done;
1002 HMODULE wintab32;
1003 char *wintab32_dll_path;
1004 char dummy;
1005 int n, k;
1006
1007 if (wintab_initialized)
1008 return;
1009
1010 wintab_initialized = TRUE;
1011
1012 wintab_contexts = NULL;
1013
1014 n = GetSystemDirectory (&dummy, 0);
1015
1016 if (n <= 0)
1017 return;
1018
1019 wintab32_dll_path = g_malloc (n + 1 + strlen (WINTAB32_DLL));
1020 k = GetSystemDirectory (wintab32_dll_path, n);
1021
1022 if (k == 0 || k > n)
1023 {
1024 g_free (wintab32_dll_path);
1025 return;
1026 }
1027
1028 if (!G_IS_DIR_SEPARATOR (wintab32_dll_path[strlen (wintab32_dll_path) -1]))
1029 strcat (wintab32_dll_path, G_DIR_SEPARATOR_S);
1030 strcat (wintab32_dll_path, WINTAB32_DLL);
1031
1032 if ((wintab32 = LoadLibrary (wintab32_dll_path)) == NULL)
1033 return;
1034
1035 if ((p_WTInfoA = (t_WTInfoA) GetProcAddress (wintab32, "WTInfoA")) == NULL)
1036 return;
1037 if ((p_WTInfoW = (t_WTInfoW) GetProcAddress (wintab32, "WTInfoW")) == NULL)
1038 return;
1039 if ((p_WTEnable = (t_WTEnable) GetProcAddress (wintab32, "WTEnable")) == NULL)
1040 return;
1041 if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL)
1042 return;
1043 if ((p_WTGetA = (t_WTGetA) GetProcAddress (wintab32, "WTGetA")) == NULL)
1044 return;
1045 if ((p_WTSetA = (t_WTSetA) GetProcAddress (wintab32, "WTSetA")) == NULL)
1046 return;
1047 if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL)
1048 return;
1049 if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL)
1050 return;
1051 if ((p_WTQueueSizeSet = (t_WTQueueSizeSet) GetProcAddress (wintab32, "WTQueueSizeSet")) == NULL)
1052 return;
1053
1054 if (!(*p_WTInfoA) (0, 0, NULL))
1055 return;
1056
1057 (*p_WTInfoA) (WTI_INTERFACE, IFC_SPECVERSION, &specversion);
1058 GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n",
1059 HIBYTE (specversion), LOBYTE (specversion)));
1060 (*p_WTInfoA) (WTI_INTERFACE, IFC_NDEVICES, &ndevices);
1061 (*p_WTInfoA) (WTI_INTERFACE, IFC_NCURSORS, &ncursors);
1062 #if DEBUG_WINTAB
1063 GDK_NOTE (INPUT, g_print ("NDEVICES: %d, NCURSORS: %d\n",
1064 ndevices, ncursors));
1065 #endif
1066 /* Create a dummy window to receive wintab events */
1067 wa.wclass = GDK_INPUT_OUTPUT;
1068 wa.event_mask = GDK_ALL_EVENTS_MASK;
1069 wa.width = 2;
1070 wa.height = 2;
1071 wa.x = -100;
1072 wa.y = -100;
1073 wa.window_type = GDK_WINDOW_TOPLEVEL;
1074 if ((wintab_window = gdk_window_new (root, &wa, GDK_WA_X | GDK_WA_Y)) == NULL)
1075 {
1076 g_warning ("gdk_input_wintab_init: gdk_window_new failed");
1077 return;
1078 }
1079 g_object_ref (wintab_window);
1080
1081 for (devix = 0; devix < ndevices; devix++)
1082 {
1083 LOGCONTEXT lc;
1084
1085 /* We open the Wintab device (hmm, what if there are several, or
1086 * can there even be several, probably not?) as a system
1087 * pointing device, i.e. it controls the normal Windows
1088 * cursor. This seems much more natural.
1089 */
1090
1091 (*p_WTInfoW) (WTI_DEVICES + devix, DVC_NAME, devname);
1092 devname_utf8 = g_utf16_to_utf8 (devname, -1, NULL, NULL, NULL);
1093 #ifdef DEBUG_WINTAB
1094 GDK_NOTE (INPUT, (g_print("Device %u: %s\n", devix, devname_utf8)));
1095 #endif
1096 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x);
1097 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y);
1098
1099 defcontext_done = FALSE;
1100 if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1)
1101 {
1102 /* Try to get device-specific default context */
1103 /* Some drivers, e.g. Aiptek, don't provide this info */
1104 if ((*p_WTInfoA) (WTI_DSCTXS + devix, 0, &lc) > 0)
1105 defcontext_done = TRUE;
1106 #if DEBUG_WINTAB
1107 if (defcontext_done)
1108 GDK_NOTE (INPUT, (g_print("Using device-specific default context\n")));
1109 else
1110 GDK_NOTE (INPUT, (g_print("Note: Driver did not provide device specific default context info despite claiming to support version 1.1\n")));
1111 #endif
1112 }
1113
1114 if (!defcontext_done)
1115 (*p_WTInfoA) (WTI_DEFSYSCTX, 0, &lc);
1116 #if DEBUG_WINTAB
1117 GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc)));
1118 #endif
1119 lc.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES;
1120 lc.lcStatus = 0;
1121 lc.lcMsgBase = WT_DEFBASE;
1122 lc.lcPktRate = 0;
1123 lc.lcPktData = PACKETDATA;
1124 lc.lcPktMode = PACKETMODE;
1125 lc.lcMoveMask = PACKETDATA;
1126 lc.lcBtnUpMask = lc.lcBtnDnMask = ~0;
1127 lc.lcOutOrgX = axis_x.axMin;
1128 lc.lcOutOrgY = axis_y.axMin;
1129 lc.lcOutExtX = axis_x.axMax - axis_x.axMin + 1;
1130 lc.lcOutExtY = axis_y.axMax - axis_y.axMin + 1;
1131 lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */
1132 #if DEBUG_WINTAB
1133 GDK_NOTE (INPUT, (g_print("context for device %u:\n", devix),
1134 print_lc(&lc)));
1135 #endif
1136 hctx = g_new (HCTX, 1);
1137 if ((*hctx = (*p_WTOpenA) (GDK_WINDOW_HWND (wintab_window), &lc, TRUE)) == NULL)
1138 {
1139 g_warning ("gdk_input_wintab_init: WTOpen failed");
1140 return;
1141 }
1142 GDK_NOTE (INPUT, g_print ("opened Wintab device %u %p\n",
1143 devix, *hctx));
1144
1145 wintab_contexts = g_list_append (wintab_contexts, hctx);
1146
1147 /* Set the CXO_SYSTEM flag */
1148 if (!(lc.lcOptions & CXO_SYSTEM))
1149 {
1150 lc.lcOptions |= CXO_SYSTEM;
1151 if (!p_WTSetA (*hctx, &lc))
1152 g_warning ("Could not set the CXO_SYSTEM option in the WINTAB context");
1153 }
1154
1155 (*p_WTOverlap) (*hctx, TRUE);
1156
1157 #if DEBUG_WINTAB
1158 GDK_NOTE (INPUT, (g_print("context for device %u after WTOpen:\n", devix),
1159 print_lc(&lc)));
1160 #endif
1161 /* Increase packet queue size to reduce the risk of lost packets.
1162 * According to the specs, if the function fails we must try again
1163 * with a smaller queue size.
1164 */
1165 GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n"));
1166 for (i = 128; i >= 1; i >>= 1)
1167 {
1168 if ((*p_WTQueueSizeSet) (*hctx, i))
1169 {
1170 GDK_NOTE (INPUT, g_print("Queue size set to %d\n", i));
1171 break;
1172 }
1173 }
1174 if (!i)
1175 GDK_NOTE (INPUT, g_print("Whoops, no queue size could be set\n"));
1176
1177 /* Get the cursors that Wintab is currently aware of */
1178 _wintab_recognize_new_cursors(device_manager, *hctx);
1179 }
1180 }
1181
1182 UINT
_wintab_recognize_new_cursors(GdkDeviceManagerWin32 * device_manager,HCTX hctx)1183 _wintab_recognize_new_cursors (GdkDeviceManagerWin32 *device_manager,
1184 HCTX hctx)
1185 {
1186 GdkDisplay *display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
1187 int devix;
1188 wchar_t devname[100], csrname[100];
1189 gchar *devname_utf8, *csrname_utf8, *device_name;
1190 UINT ncsrtypes, firstcsr, cursorix;
1191 BOOL active;
1192 DWORD physid;
1193 AXIS axis_x, axis_y, axis_npressure, axis_or[3], axis_tpressure;
1194 GdkDeviceWintab *device;
1195 LOGCONTEXT lc;
1196 int num_axes;
1197 UINT num_new_cursors = 0;
1198
1199 devix = _gdk_find_wintab_device_index(hctx);
1200 if (devix == -1)
1201 return num_new_cursors;
1202
1203 (*p_WTInfoW) (WTI_DEVICES + devix, DVC_NAME, devname);
1204 devname_utf8 = g_utf16_to_utf8 (devname, -1, NULL, NULL, NULL);
1205 #ifdef DEBUG_WINTAB
1206 GDK_NOTE (INPUT, (g_print("Finding cursors for device %u: %s\n", devix, devname_utf8)));
1207 #endif
1208
1209 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_FIRSTCSR, &firstcsr);
1210 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NCSRTYPES, &ncsrtypes);
1211 for (cursorix = firstcsr; cursorix < firstcsr + ncsrtypes; cursorix++)
1212 {
1213 #ifdef DEBUG_WINTAB
1214 GDK_NOTE (INPUT, (g_print("Cursor %u:\n", cursorix), print_cursor (cursorix)));
1215 #endif
1216 /* Skip cursors that are already known to us */
1217 if (gdk_device_manager_find_wintab_device(device_manager, hctx, cursorix) != NULL)
1218 continue;
1219
1220 active = FALSE;
1221 (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_ACTIVE, &active);
1222 if (!active)
1223 continue;
1224
1225 /* Wacom tablets iterate through all possible cursors,
1226 * even if the cursor's presence has not been recognized.
1227 * Unrecognized cursors have a physid of zero and are ignored.
1228 * Recognized cursors have a non-zero physid and we create a
1229 * Wintab device object for each of them.
1230 */
1231 (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PHYSID, &physid);
1232 if (wcscmp (devname, L"WACOM Tablet") == 0 && physid == 0)
1233 continue;
1234
1235 if (!(*p_WTGetA) (hctx, &lc))
1236 {
1237 g_warning ("wintab_recognize_new_cursors: Failed to retrieve device LOGCONTEXT");
1238 continue;
1239 }
1240
1241 /* Create a Wintab device for this cursor */
1242 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_X, &axis_x);
1243 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_Y, &axis_y);
1244 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure);
1245 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or);
1246 (*p_WTInfoA) (WTI_DEVICES + devix, DVC_TPRESSURE, &axis_tpressure);
1247 (*p_WTInfoW) (WTI_CURSORS + cursorix, CSR_NAME, csrname);
1248 csrname_utf8 = g_utf16_to_utf8 (csrname, -1, NULL, NULL, NULL);
1249 device_name = g_strconcat (devname_utf8, " ", csrname_utf8, NULL);
1250 g_free (csrname_utf8);
1251
1252 device = g_object_new (GDK_TYPE_DEVICE_WINTAB,
1253 "name", device_name,
1254 "type", GDK_DEVICE_TYPE_FLOATING,
1255 "input-source", GDK_SOURCE_PEN,
1256 "input-mode", GDK_MODE_SCREEN,
1257 "has-cursor", lc.lcOptions & CXO_SYSTEM,
1258 "display", display,
1259 "device-manager", device_manager,
1260 NULL);
1261
1262 device->sends_core = lc.lcOptions & CXO_SYSTEM;
1263 if (device->sends_core)
1264 {
1265 _gdk_device_set_associated_device (device_manager->system_pointer, GDK_DEVICE (device));
1266 _gdk_device_add_slave (device_manager->core_pointer, GDK_DEVICE (device));
1267 }
1268
1269 device->hctx = hctx;
1270 device->cursor = cursorix;
1271 (*p_WTInfoA) (WTI_CURSORS + cursorix, CSR_PKTDATA, &device->pktdata);
1272 num_axes = 0;
1273
1274 if (device->pktdata & PK_X)
1275 {
1276 _gdk_device_add_axis (GDK_DEVICE (device),
1277 GDK_NONE,
1278 GDK_AXIS_X,
1279 axis_x.axMin,
1280 axis_x.axMax,
1281 axis_x.axResolution / 65535);
1282 num_axes++;
1283 }
1284
1285 if (device->pktdata & PK_Y)
1286 {
1287 _gdk_device_add_axis (GDK_DEVICE (device),
1288 GDK_NONE,
1289 GDK_AXIS_Y,
1290 axis_y.axMin,
1291 axis_y.axMax,
1292 axis_y.axResolution / 65535);
1293 num_axes++;
1294 }
1295
1296 if (device->pktdata & PK_NORMAL_PRESSURE)
1297 {
1298 _gdk_device_add_axis (GDK_DEVICE (device),
1299 GDK_NONE,
1300 GDK_AXIS_PRESSURE,
1301 axis_npressure.axMin,
1302 axis_npressure.axMax,
1303 axis_npressure.axResolution / 65535);
1304 num_axes++;
1305 }
1306
1307 if (device->pktdata & PK_ORIENTATION)
1308 {
1309 if (device->pktdata & PK_TANGENT_PRESSURE) /* If we have a wheel, disable the twist axis */
1310 axis_or[2].axResolution = 0;
1311
1312 device->orientation_axes[0] = axis_or[0];
1313 device->orientation_axes[1] = axis_or[1];
1314 device->orientation_axes[2] = axis_or[2];
1315
1316 /* Wintab gives us azimuth and altitude, which
1317 * we convert to x and y tilt in the -1000..1000 range
1318 */
1319 _gdk_device_add_axis (GDK_DEVICE (device),
1320 GDK_NONE,
1321 GDK_AXIS_XTILT,
1322 -1000,
1323 1000,
1324 1000);
1325
1326 _gdk_device_add_axis (GDK_DEVICE (device),
1327 GDK_NONE,
1328 GDK_AXIS_YTILT,
1329 -1000,
1330 1000,
1331 1000);
1332 num_axes += 2;
1333
1334 if (axis_or[2].axResolution != 0) /* If twist is present */
1335 {
1336 /* Wacom's Wintab driver returns the rotation
1337 * of an Art Pen as the orientation twist value.
1338 * We're using GDK_AXIS_WHEEL as it's actually
1339 * called Wheel/Rotation to the user.
1340 * axMin and axMax are back to front on purpose. If you put them
1341 * the "correct" way round, rotation will be flipped!
1342 */
1343 _gdk_device_add_axis (GDK_DEVICE (device),
1344 GDK_NONE,
1345 GDK_AXIS_WHEEL,
1346 axis_or[2].axMax,
1347 axis_or[2].axMin,
1348 axis_or[2].axResolution / 65535);
1349 num_axes++;
1350 }
1351 }
1352
1353 if (device->pktdata & PK_TANGENT_PRESSURE)
1354 {
1355 /* This is the finger wheel on a Wacom Airbrush
1356 */
1357 _gdk_device_add_axis (GDK_DEVICE (device),
1358 GDK_NONE,
1359 GDK_AXIS_WHEEL,
1360 axis_tpressure.axMin,
1361 axis_tpressure.axMax,
1362 axis_tpressure.axResolution / 65535);
1363 num_axes++;
1364 }
1365
1366 device->last_axis_data = g_new (gint, num_axes);
1367
1368 GDK_NOTE (INPUT, g_print ("device: (%u) %s axes: %d\n",
1369 cursorix,
1370 device_name,
1371 num_axes));
1372
1373 #if 0
1374 for (i = 0; i < gdkdev->info.num_axes; i++)
1375 GDK_NOTE (INPUT, g_print ("... axis %d: %d--%d@%d\n",
1376 i,
1377 gdkdev->axes[i].min_value,
1378 gdkdev->axes[i].max_value,
1379 gdkdev->axes[i].resolution));
1380 #endif
1381
1382 device_manager->wintab_devices = g_list_append (device_manager->wintab_devices,
1383 device);
1384 num_new_cursors++;
1385 g_free (device_name);
1386 }
1387 g_free (devname_utf8);
1388 return num_new_cursors;
1389 }
1390
1391 /* Only initialize Wintab after the default display is set for
1392 * the first time. WTOpenA() executes code beyond our control,
1393 * and it can cause messages to be sent to the application even
1394 * before a window is opened. GDK has to be in a fit state to
1395 * handle them when they come.
1396 *
1397 * https://bugzilla.gnome.org/show_bug.cgi?id=774379
1398 */
1399 static void
wintab_default_display_notify_cb(GdkDisplayManager * display_manager)1400 wintab_default_display_notify_cb (GdkDisplayManager *display_manager)
1401 {
1402 GdkDeviceManagerWin32 *device_manager = NULL;
1403 GdkDisplay *display = gdk_display_get_default();
1404
1405 if (default_display_opened)
1406 return;
1407
1408 g_assert (display != NULL);
1409
1410 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1411 device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (display));
1412 G_GNUC_END_IGNORE_DEPRECATIONS;
1413 g_assert (display_manager != NULL);
1414
1415 default_display_opened = TRUE;
1416 GDK_NOTE (INPUT, g_print ("wintab init: doing delayed initialization\n"));
1417 wintab_init_check (device_manager);
1418 }
1419
1420 static void
gdk_device_manager_win32_constructed(GObject * object)1421 gdk_device_manager_win32_constructed (GObject *object)
1422 {
1423 GdkDeviceManagerWin32 *device_manager;
1424 GdkSeat *seat;
1425 GdkDisplayManager *display_manager = NULL;
1426 GdkDisplay *default_display = NULL;
1427 const char *tablet_input_api_user_preference = NULL;
1428 gboolean have_tablet_input_api_preference = FALSE;
1429
1430 device_manager = GDK_DEVICE_MANAGER_WIN32 (object);
1431 device_manager->core_pointer =
1432 create_pointer (GDK_DEVICE_MANAGER (device_manager),
1433 GDK_TYPE_DEVICE_VIRTUAL,
1434 "Virtual Core Pointer",
1435 GDK_DEVICE_TYPE_MASTER);
1436 device_manager->system_pointer =
1437 create_pointer (GDK_DEVICE_MANAGER (device_manager),
1438 GDK_TYPE_DEVICE_WIN32,
1439 "System Aggregated Pointer",
1440 GDK_DEVICE_TYPE_SLAVE);
1441 _gdk_device_virtual_set_active (device_manager->core_pointer,
1442 device_manager->system_pointer);
1443 _gdk_device_set_associated_device (device_manager->system_pointer, device_manager->core_pointer);
1444 _gdk_device_add_slave (device_manager->core_pointer, device_manager->system_pointer);
1445
1446 device_manager->core_keyboard =
1447 create_keyboard (GDK_DEVICE_MANAGER (device_manager),
1448 GDK_TYPE_DEVICE_VIRTUAL,
1449 "Virtual Core Keyboard",
1450 GDK_DEVICE_TYPE_MASTER);
1451 device_manager->system_keyboard =
1452 create_keyboard (GDK_DEVICE_MANAGER (device_manager),
1453 GDK_TYPE_DEVICE_WIN32,
1454 "System Aggregated Keyboard",
1455 GDK_DEVICE_TYPE_SLAVE);
1456 _gdk_device_virtual_set_active (device_manager->core_keyboard,
1457 device_manager->system_keyboard);
1458 _gdk_device_set_associated_device (device_manager->system_keyboard, device_manager->core_keyboard);
1459 _gdk_device_add_slave (device_manager->core_keyboard, device_manager->system_keyboard);
1460
1461 _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
1462 _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
1463
1464 seat = gdk_seat_default_new_for_master_pair (device_manager->core_pointer,
1465 device_manager->core_keyboard);
1466 gdk_display_add_seat (gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object)), seat);
1467 gdk_seat_default_add_slave (GDK_SEAT_DEFAULT (seat), device_manager->system_pointer);
1468 gdk_seat_default_add_slave (GDK_SEAT_DEFAULT (seat), device_manager->system_keyboard);
1469 g_object_unref (seat);
1470
1471 tablet_input_api_user_preference = g_getenv ("GDK_WIN32_TABLET_INPUT_API");
1472 if (g_strcmp0 (tablet_input_api_user_preference, "none") == 0)
1473 {
1474 have_tablet_input_api_preference = TRUE;
1475 _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_NONE;
1476 }
1477 else if (g_strcmp0 (tablet_input_api_user_preference, "wintab") == 0)
1478 {
1479 have_tablet_input_api_preference = TRUE;
1480 _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINTAB;
1481 }
1482 else if (g_strcmp0 (tablet_input_api_user_preference, "winpointer") == 0)
1483 {
1484 have_tablet_input_api_preference = TRUE;
1485 _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINPOINTER;
1486 }
1487 else
1488 {
1489 have_tablet_input_api_preference = FALSE;
1490 _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINPOINTER;
1491 }
1492
1493 if (_gdk_win32_tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
1494 {
1495 if (!winpointer_initialize (device_manager) &&
1496 !have_tablet_input_api_preference)
1497 _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINTAB;
1498 }
1499
1500 if (_gdk_win32_tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINTAB)
1501 {
1502 /* Only call Wintab init stuff after the default display
1503 * is globally known and accessible through the display manager
1504 * singleton. Approach lifted from gtkmodules.c.
1505 */
1506 display_manager = gdk_display_manager_get();
1507 g_assert (display_manager != NULL);
1508 default_display = gdk_display_manager_get_default_display (display_manager);
1509 g_assert (default_display == NULL);
1510
1511 g_signal_connect (display_manager, "notify::default-display",
1512 G_CALLBACK (wintab_default_display_notify_cb),
1513 NULL);
1514 }
1515 }
1516
1517 static GList *
gdk_device_manager_win32_list_devices(GdkDeviceManager * device_manager,GdkDeviceType type)1518 gdk_device_manager_win32_list_devices (GdkDeviceManager *device_manager,
1519 GdkDeviceType type)
1520 {
1521 GdkDeviceManagerWin32 *device_manager_win32;
1522 GList *devices = NULL, *l;
1523
1524 device_manager_win32 = (GdkDeviceManagerWin32 *) device_manager;
1525
1526 if (type == GDK_DEVICE_TYPE_MASTER)
1527 {
1528 devices = g_list_prepend (devices, device_manager_win32->core_keyboard);
1529 devices = g_list_prepend (devices, device_manager_win32->core_pointer);
1530 }
1531 else
1532 {
1533 if (type == GDK_DEVICE_TYPE_SLAVE)
1534 {
1535 devices = g_list_prepend (devices, device_manager_win32->system_keyboard);
1536 devices = g_list_prepend (devices, device_manager_win32->system_pointer);
1537 }
1538
1539 for (l = device_manager_win32->winpointer_devices; l != NULL; l = l->next)
1540 {
1541 GdkDevice *device = l->data;
1542
1543 if (gdk_device_get_device_type (device) == type)
1544 devices = g_list_prepend (devices, device);
1545 }
1546
1547 for (l = device_manager_win32->wintab_devices; l != NULL; l = l->next)
1548 {
1549 GdkDevice *device = l->data;
1550
1551 if (gdk_device_get_device_type (device) == type)
1552 devices = g_list_prepend (devices, device);
1553 }
1554 }
1555
1556 return g_list_reverse (devices);
1557 }
1558
1559 static GdkDevice *
gdk_device_manager_win32_get_client_pointer(GdkDeviceManager * device_manager)1560 gdk_device_manager_win32_get_client_pointer (GdkDeviceManager *device_manager)
1561 {
1562 GdkDeviceManagerWin32 *device_manager_win32;
1563
1564 device_manager_win32 = (GdkDeviceManagerWin32 *) device_manager;
1565 return device_manager_win32->core_pointer;
1566 }
1567
1568 static void
gdk_device_manager_win32_class_init(GdkDeviceManagerWin32Class * klass)1569 gdk_device_manager_win32_class_init (GdkDeviceManagerWin32Class *klass)
1570 {
1571 GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
1572 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1573
1574 object_class->finalize = gdk_device_manager_win32_finalize;
1575 object_class->constructed = gdk_device_manager_win32_constructed;
1576 device_manager_class->list_devices = gdk_device_manager_win32_list_devices;
1577 device_manager_class->get_client_pointer = gdk_device_manager_win32_get_client_pointer;
1578 }
1579
1580 static inline void
winpointer_ignore_interaction(UINT32 pointer_id)1581 winpointer_ignore_interaction (UINT32 pointer_id)
1582 {
1583 g_ptr_array_add (winpointer_ignored_interactions, GUINT_TO_POINTER (pointer_id));
1584 }
1585
1586 static inline void
winpointer_remove_ignored_interaction(UINT32 pointer_id)1587 winpointer_remove_ignored_interaction (UINT32 pointer_id)
1588 {
1589 g_ptr_array_remove_fast (winpointer_ignored_interactions, GUINT_TO_POINTER (pointer_id));
1590 }
1591
1592 static inline gboolean
winpointer_should_ignore_interaction(UINT32 pointer_id)1593 winpointer_should_ignore_interaction (UINT32 pointer_id)
1594 {
1595 return g_ptr_array_find (winpointer_ignored_interactions, GUINT_TO_POINTER (pointer_id), NULL);
1596 }
1597
1598 static inline guint32
winpointer_get_time(MSG * msg,POINTER_INFO * info)1599 winpointer_get_time (MSG *msg, POINTER_INFO *info)
1600 {
1601 return info->dwTime != 0 ? info->dwTime : msg->time;
1602 }
1603
1604 static inline gboolean
winpointer_is_eraser(POINTER_PEN_INFO * pen_info)1605 winpointer_is_eraser (POINTER_PEN_INFO *pen_info)
1606 {
1607 return (pen_info->penFlags & (PEN_FLAG_INVERTED | PEN_FLAG_ERASER)) != 0;
1608 }
1609
1610 static inline gboolean
winpointer_should_filter_message(MSG * msg,POINTER_INPUT_TYPE type)1611 winpointer_should_filter_message (MSG *msg,
1612 POINTER_INPUT_TYPE type)
1613 {
1614 switch (type)
1615 {
1616 case PT_TOUCH:
1617 return msg->message == WM_POINTERENTER ||
1618 msg->message == WM_POINTERLEAVE;
1619 break;
1620 }
1621
1622 return FALSE;
1623 }
1624
1625 static GdkDeviceWinpointer*
winpointer_find_device_with_source(GdkDeviceManagerWin32 * device_manager,HANDLE device_handle,UINT32 cursor_id,GdkInputSource input_source)1626 winpointer_find_device_with_source (GdkDeviceManagerWin32 *device_manager,
1627 HANDLE device_handle,
1628 UINT32 cursor_id,
1629 GdkInputSource input_source)
1630 {
1631 GList *l;
1632
1633 for (l = device_manager->winpointer_devices; l; l = l->next)
1634 {
1635 GdkDeviceWinpointer *device = (GdkDeviceWinpointer*) l->data;
1636
1637 if (device->device_handle == device_handle &&
1638 device->start_cursor_id <= cursor_id &&
1639 device->end_cursor_id >= cursor_id &&
1640 gdk_device_get_source (GDK_DEVICE (device)) == input_source)
1641 return device;
1642 }
1643
1644 return NULL;
1645 }
1646
1647 static GdkEvent*
winpointer_allocate_event(MSG * msg,POINTER_INFO * info)1648 winpointer_allocate_event (MSG *msg,
1649 POINTER_INFO *info)
1650 {
1651 switch (info->pointerType)
1652 {
1653 case PT_PEN:
1654 switch (msg->message)
1655 {
1656 case WM_POINTERENTER:
1657 g_return_val_if_fail (IS_POINTER_NEW_WPARAM (msg->wParam), NULL);
1658 return gdk_event_new (GDK_PROXIMITY_IN);
1659 break;
1660 case WM_POINTERLEAVE:
1661 g_return_val_if_fail (!IS_POINTER_INRANGE_WPARAM (msg->wParam), NULL);
1662 return gdk_event_new (GDK_PROXIMITY_OUT);
1663 break;
1664 case WM_POINTERDOWN:
1665 return gdk_event_new (GDK_BUTTON_PRESS);
1666 break;
1667 case WM_POINTERUP:
1668 return gdk_event_new (GDK_BUTTON_RELEASE);
1669 break;
1670 case WM_POINTERUPDATE:
1671 return gdk_event_new (GDK_MOTION_NOTIFY);
1672 break;
1673 }
1674 break;
1675 case PT_TOUCH:
1676 if (IS_POINTER_CANCELED_WPARAM (msg->wParam) ||
1677 !HAS_POINTER_CONFIDENCE_WPARAM (msg->wParam))
1678 {
1679 winpointer_ignore_interaction (GET_POINTERID_WPARAM (msg->wParam));
1680
1681 if (((info->pointerFlags & POINTER_FLAG_INCONTACT) &&
1682 (info->pointerFlags & POINTER_FLAG_UPDATE))
1683 || (info->pointerFlags & POINTER_FLAG_UP))
1684 return gdk_event_new (GDK_TOUCH_CANCEL);
1685 else
1686 return NULL;
1687 }
1688
1689 g_return_val_if_fail (msg->message != WM_POINTERENTER &&
1690 msg->message != WM_POINTERLEAVE, NULL);
1691
1692 switch (msg->message)
1693 {
1694 case WM_POINTERDOWN:
1695 return gdk_event_new (GDK_TOUCH_BEGIN);
1696 break;
1697 case WM_POINTERUP:
1698 return gdk_event_new (GDK_TOUCH_END);
1699 break;
1700 case WM_POINTERUPDATE:
1701 if (IS_POINTER_INCONTACT_WPARAM (msg->wParam))
1702 return gdk_event_new (GDK_TOUCH_UPDATE);
1703 else if (IS_POINTER_PRIMARY_WPARAM (msg->wParam))
1704 return gdk_event_new (GDK_MOTION_NOTIFY);
1705 else
1706 return NULL;
1707 break;
1708 }
1709 break;
1710 }
1711
1712 g_warn_if_reached ();
1713 return NULL;
1714 }
1715
1716 static void
winpointer_make_event(GdkDisplay * display,GdkDeviceManagerWin32 * device_manager,GdkDeviceWinpointer * device,GdkWindow * window,MSG * msg,POINTER_INFO * info)1717 winpointer_make_event (GdkDisplay *display,
1718 GdkDeviceManagerWin32 *device_manager,
1719 GdkDeviceWinpointer *device,
1720 GdkWindow *window,
1721 MSG *msg,
1722 POINTER_INFO *info)
1723 {
1724 guint32 time = 0;
1725 double x_root = 0.0;
1726 double y_root = 0.0;
1727 double x = 0.0;
1728 double y = 0.0;
1729 unsigned int state = 0;
1730 double *axes = NULL;
1731 unsigned int button = 0;
1732 GdkEventSequence *sequence = NULL;
1733 gboolean emulating_pointer = FALSE;
1734 POINT client_area_coordinates;
1735 GdkWindowImplWin32 *impl = NULL;
1736 GdkEvent *evt = NULL;
1737
1738 evt = winpointer_allocate_event (msg, info);
1739 if (!evt)
1740 return;
1741
1742 time = winpointer_get_time (msg, info);
1743
1744 x_root = device->origin_x + info->ptHimetricLocation.x * device->scale_x;
1745 y_root = device->origin_y + info->ptHimetricLocation.y * device->scale_y;
1746
1747 client_area_coordinates.x = 0;
1748 client_area_coordinates.y = 0;
1749 ClientToScreen (GDK_WINDOW_HWND (window), &client_area_coordinates);
1750 x = x_root - client_area_coordinates.x;
1751 y = y_root - client_area_coordinates.y;
1752
1753 /* bring potential win32 negative screen coordinates to
1754 the non-negative screen coordinates that GDK expects. */
1755 x_root += _gdk_offset_x;
1756 y_root += _gdk_offset_y;
1757
1758 /* handle DPI scaling */
1759 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
1760 x_root /= impl->window_scale;
1761 y_root /= impl->window_scale;
1762 x /= impl->window_scale;
1763 y /= impl->window_scale;
1764
1765 state = 0;
1766 if (info->dwKeyStates & POINTER_MOD_CTRL)
1767 state |= GDK_CONTROL_MASK;
1768 if (info->dwKeyStates & POINTER_MOD_SHIFT)
1769 state |= GDK_SHIFT_MASK;
1770 if (GetKeyState (VK_MENU) < 0)
1771 state |= GDK_MOD1_MASK;
1772 if (GetKeyState (VK_CAPITAL) & 0x1)
1773 state |= GDK_LOCK_MASK;
1774
1775 device->last_button_mask = 0;
1776 if (((info->pointerFlags & POINTER_FLAG_FIRSTBUTTON) &&
1777 (info->ButtonChangeType != POINTER_CHANGE_FIRSTBUTTON_DOWN))
1778 || info->ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP)
1779 device->last_button_mask |= GDK_BUTTON1_MASK;
1780 if (((info->pointerFlags & POINTER_FLAG_SECONDBUTTON) &&
1781 (info->ButtonChangeType != POINTER_CHANGE_SECONDBUTTON_DOWN))
1782 || info->ButtonChangeType == POINTER_CHANGE_SECONDBUTTON_UP)
1783 device->last_button_mask |= GDK_BUTTON3_MASK;
1784 state |= device->last_button_mask;
1785
1786 switch (info->pointerType)
1787 {
1788 case PT_PEN:
1789 {
1790 POINTER_PEN_INFO *pen_info = (POINTER_PEN_INFO*) info;
1791
1792 axes = g_new (double, device->num_axes);
1793 axes[0] = (pen_info->penMask & PEN_MASK_PRESSURE) ? pen_info->pressure / 1024.0 :
1794 (pen_info->pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT) ? 1.0 : 0.0;
1795 axes[1] = (pen_info->penMask & PEN_MASK_TILT_X) ? pen_info->tiltX / 90.0 : 0.0;
1796 axes[2] = (pen_info->penMask & PEN_MASK_TILT_Y) ? pen_info->tiltY / 90.0 : 0.0;
1797 axes[3] = (pen_info->penMask & PEN_MASK_ROTATION) ? pen_info->rotation / 360.0 : 0.0;
1798 }
1799 break;
1800 case PT_TOUCH:
1801 {
1802 POINTER_TOUCH_INFO *touch_info = (POINTER_TOUCH_INFO*) info;
1803
1804 axes = g_new (double, device->num_axes);
1805 axes[0] = (touch_info->touchMask & TOUCH_MASK_PRESSURE) ? touch_info->pressure / 1024.0 :
1806 (touch_info->pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT) ? 1.0 : 0.0;
1807 }
1808 break;
1809 }
1810
1811 if (axes)
1812 {
1813 memcpy (device->last_axis_data, axes, sizeof (double) * device->num_axes);
1814 }
1815
1816 sequence = (GdkEventSequence*) GUINT_TO_POINTER (info->pointerId);
1817 emulating_pointer = (info->pointerFlags & POINTER_FLAG_PRIMARY) != 0;
1818 button = (info->pointerFlags & POINTER_FLAG_FIRSTBUTTON) ||
1819 (info->ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP) ? 1 : 3;
1820
1821 switch (evt->any.type)
1822 {
1823 case GDK_PROXIMITY_IN:
1824 case GDK_PROXIMITY_OUT:
1825 evt->proximity.time = time;
1826 break;
1827 case GDK_BUTTON_PRESS:
1828 case GDK_BUTTON_RELEASE:
1829 evt->button.time = time;
1830 evt->button.x_root = x_root;
1831 evt->button.y_root = y_root;
1832 evt->button.x = x;
1833 evt->button.y = y;
1834 evt->button.state = state;
1835 evt->button.axes = axes;
1836 evt->button.button = button;
1837 break;
1838 case GDK_MOTION_NOTIFY:
1839 evt->motion.time = time;
1840 evt->motion.x_root = x_root;
1841 evt->motion.y_root = y_root;
1842 evt->motion.x = x;
1843 evt->motion.y = y;
1844 evt->motion.state = state;
1845 evt->motion.axes = axes;
1846 break;
1847 case GDK_TOUCH_BEGIN:
1848 case GDK_TOUCH_UPDATE:
1849 case GDK_TOUCH_CANCEL:
1850 case GDK_TOUCH_END:
1851 evt->touch.time = time;
1852 evt->touch.x_root = x_root;
1853 evt->touch.y_root = y_root;
1854 evt->touch.x = x;
1855 evt->touch.y = y;
1856 evt->touch.state = state;
1857 evt->touch.axes = axes;
1858 evt->touch.sequence = sequence;
1859 evt->touch.emulating_pointer = emulating_pointer;
1860 gdk_event_set_pointer_emulated (evt, emulating_pointer);
1861 break;
1862 }
1863
1864 evt->any.send_event = FALSE;
1865 evt->any.window = window;
1866 gdk_event_set_device (evt, device_manager->core_pointer);
1867 gdk_event_set_source_device (evt, GDK_DEVICE (device));
1868 gdk_event_set_device_tool (evt, ((GdkDevice*)device)->last_tool);
1869 gdk_event_set_seat (evt, gdk_device_get_seat (device_manager->core_pointer));
1870 gdk_event_set_screen (evt, gdk_display_get_default_screen (display));
1871
1872 _gdk_device_virtual_set_active (device_manager->core_pointer, GDK_DEVICE (device));
1873
1874 _gdk_win32_append_event (evt);
1875 }
1876
1877 void
gdk_winpointer_input_events(GdkDisplay * display,GdkWindow * window,crossing_cb_t crossing_cb,MSG * msg)1878 gdk_winpointer_input_events (GdkDisplay *display,
1879 GdkWindow *window,
1880 crossing_cb_t crossing_cb,
1881 MSG *msg)
1882 {
1883 GdkDeviceManagerWin32 *device_manager = NULL;
1884 UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
1885 POINTER_INPUT_TYPE type = PT_POINTER;
1886 UINT32 cursor_id = 0;
1887
1888 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1889 device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (display));
1890 G_GNUC_END_IGNORE_DEPRECATIONS;
1891
1892 if (!getPointerType (pointer_id, &type))
1893 {
1894 WIN32_API_FAILED_LOG_ONCE ("GetPointerType");
1895 return;
1896 }
1897
1898 if (!getPointerCursorId (pointer_id, &cursor_id))
1899 {
1900 WIN32_API_FAILED_LOG_ONCE ("GetPointerCursorId");
1901 return;
1902 }
1903
1904 if (winpointer_should_filter_message (msg, type))
1905 {
1906 return;
1907 }
1908
1909 if (winpointer_should_ignore_interaction (pointer_id))
1910 {
1911 return;
1912 }
1913
1914 switch (type)
1915 {
1916 case PT_PEN:
1917 {
1918 POINTER_PEN_INFO *infos = NULL;
1919 UINT32 history_count = 0;
1920 GdkDeviceWinpointer *device = NULL;
1921 UINT32 h = 0;
1922
1923 do
1924 {
1925 infos = g_new0 (POINTER_PEN_INFO, history_count);
1926 if (!getPointerPenInfoHistory (pointer_id, &history_count, infos))
1927 {
1928 WIN32_API_FAILED_LOG_ONCE ("GetPointerPenInfoHistory");
1929 g_free (infos);
1930 return;
1931 }
1932 }
1933 while (!infos && history_count > 0);
1934
1935 if (history_count == 0)
1936 return;
1937
1938 device = winpointer_find_device_with_source (device_manager,
1939 infos->pointerInfo.sourceDevice,
1940 cursor_id,
1941 winpointer_is_eraser (infos) ?
1942 GDK_SOURCE_ERASER : GDK_SOURCE_PEN);
1943 if (!device)
1944 {
1945 g_free (infos);
1946 return;
1947 }
1948
1949 h = history_count - 1;
1950
1951 if (crossing_cb)
1952 {
1953 POINT screen_pt = infos[h].pointerInfo.ptPixelLocation;
1954 guint32 event_time = winpointer_get_time (msg, &infos[h].pointerInfo);
1955
1956 crossing_cb(display, GDK_DEVICE (device), window, &screen_pt, event_time);
1957 }
1958
1959 do
1960 winpointer_make_event (display,
1961 device_manager,
1962 device,
1963 window,
1964 msg,
1965 (POINTER_INFO*) &infos[h]);
1966 while (h-- > 0);
1967
1968 g_free (infos);
1969 }
1970 break;
1971 case PT_TOUCH:
1972 {
1973 POINTER_TOUCH_INFO *infos = NULL;
1974 UINT32 history_count = 0;
1975 GdkDeviceWinpointer *device = NULL;
1976 UINT32 h = 0;
1977
1978 do
1979 {
1980 infos = g_new0 (POINTER_TOUCH_INFO, history_count);
1981 if (!getPointerTouchInfoHistory (pointer_id, &history_count, infos))
1982 {
1983 WIN32_API_FAILED_LOG_ONCE ("GetPointerTouchInfoHistory");
1984 g_free (infos);
1985 return;
1986 }
1987 }
1988 while (!infos && history_count > 0);
1989
1990 if (history_count == 0)
1991 return;
1992
1993 device = winpointer_find_device_with_source (device_manager,
1994 infos->pointerInfo.sourceDevice,
1995 cursor_id,
1996 GDK_SOURCE_TOUCHSCREEN);
1997 if (!device)
1998 {
1999 g_free (infos);
2000 return;
2001 }
2002
2003 h = history_count - 1;
2004
2005 if (crossing_cb)
2006 {
2007 POINT screen_pt = infos[h].pointerInfo.ptPixelLocation;
2008 guint32 event_time = winpointer_get_time (msg, &infos[h].pointerInfo);
2009
2010 crossing_cb(display, GDK_DEVICE (device), window, &screen_pt, event_time);
2011 }
2012
2013 do
2014 winpointer_make_event (display,
2015 device_manager,
2016 device,
2017 window,
2018 msg,
2019 (POINTER_INFO*) &infos[h]);
2020 while (h-- > 0);
2021
2022 g_free (infos);
2023 }
2024 break;
2025 }
2026 }
2027
2028 gboolean
gdk_winpointer_get_message_info(GdkDisplay * display,MSG * msg,GdkDevice ** device,guint32 * time_)2029 gdk_winpointer_get_message_info (GdkDisplay *display,
2030 MSG *msg,
2031 GdkDevice **device,
2032 guint32 *time_)
2033 {
2034 GdkDeviceManagerWin32 *device_manager = NULL;
2035 UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
2036 POINTER_INPUT_TYPE type = PT_POINTER;
2037 UINT32 cursor_id = 0;
2038
2039 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
2040 device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (display));
2041 G_GNUC_END_IGNORE_DEPRECATIONS;
2042
2043 if (!getPointerType (pointer_id, &type))
2044 {
2045 WIN32_API_FAILED_LOG_ONCE ("GetPointerType");
2046 return FALSE;
2047 }
2048
2049 if (!getPointerCursorId (pointer_id, &cursor_id))
2050 {
2051 WIN32_API_FAILED_LOG_ONCE ("GetPointerCursorId");
2052 return FALSE;
2053 }
2054
2055 switch (type)
2056 {
2057 case PT_PEN:
2058 {
2059 POINTER_PEN_INFO pen_info;
2060
2061 if (!getPointerPenInfo (pointer_id, &pen_info))
2062 {
2063 WIN32_API_FAILED_LOG_ONCE ("GetPointerPenInfo");
2064 return FALSE;
2065 }
2066
2067 *device = GDK_DEVICE (winpointer_find_device_with_source (device_manager,
2068 pen_info.pointerInfo.sourceDevice,
2069 cursor_id,
2070 winpointer_is_eraser (&pen_info) ?
2071 GDK_SOURCE_ERASER : GDK_SOURCE_PEN));
2072
2073 *time_ = winpointer_get_time (msg, &pen_info.pointerInfo);
2074 }
2075 break;
2076 case PT_TOUCH:
2077 {
2078 POINTER_TOUCH_INFO touch_info;
2079
2080 if (!getPointerTouchInfo (pointer_id, &touch_info))
2081 {
2082 WIN32_API_FAILED_LOG_ONCE ("GetPointerTouchInfo");
2083 return FALSE;
2084 }
2085
2086 *device = GDK_DEVICE (winpointer_find_device_with_source (device_manager,
2087 touch_info.pointerInfo.sourceDevice,
2088 cursor_id,
2089 GDK_SOURCE_TOUCHSCREEN));
2090
2091 *time_ = winpointer_get_time (msg, &touch_info.pointerInfo);
2092 }
2093 break;
2094 default:
2095 g_warn_if_reached ();
2096 return FALSE;
2097 break;
2098 }
2099
2100 return *device ? TRUE : FALSE;
2101 }
2102
2103 gboolean
gdk_winpointer_should_forward_message(MSG * msg)2104 gdk_winpointer_should_forward_message (MSG *msg)
2105 {
2106 UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
2107 POINTER_INPUT_TYPE type = PT_POINTER;
2108
2109 if (!getPointerType (pointer_id, &type))
2110 {
2111 WIN32_API_FAILED_LOG_ONCE ("GetPointerType");
2112 return TRUE;
2113 }
2114
2115 return !(type == PT_PEN || type == PT_TOUCH);
2116 }
2117
2118 void
gdk_winpointer_interaction_ended(MSG * msg)2119 gdk_winpointer_interaction_ended (MSG *msg)
2120 {
2121 winpointer_remove_ignored_interaction (GET_POINTERID_WPARAM (msg->wParam));
2122 }
2123
2124 void
_gdk_wintab_set_tablet_active(void)2125 _gdk_wintab_set_tablet_active (void)
2126 {
2127 GList *tmp_list;
2128 HCTX *hctx;
2129
2130 /* Bring the contexts to the top of the overlap order when one of the
2131 * application's windows is activated */
2132
2133 if (!wintab_contexts)
2134 return; /* No tablet devices found, or Wintab not initialized yet */
2135
2136 GDK_NOTE (INPUT, g_print ("_gdk_wintab_set_tablet_active: "
2137 "Bringing Wintab contexts to the top of the overlap order\n"));
2138
2139 tmp_list = wintab_contexts;
2140
2141 while (tmp_list)
2142 {
2143 hctx = (HCTX *) (tmp_list->data);
2144 (*p_WTOverlap) (*hctx, TRUE);
2145 tmp_list = tmp_list->next;
2146 }
2147 }
2148
2149 static void
decode_tilt(gint * axis_data,AXIS * axes,PACKET * packet)2150 decode_tilt (gint *axis_data,
2151 AXIS *axes,
2152 PACKET *packet)
2153 {
2154 double az, el;
2155
2156 g_return_if_fail (axis_data != NULL);
2157
2158 /* The wintab driver for the Wacom ArtPad II reports
2159 * PK_ORIENTATION in CSR_PKTDATA, but the tablet doesn't
2160 * actually sense tilt. Catch this by noticing that the
2161 * orientation axis's azimuth resolution is zero.
2162 *
2163 * The same is true of the Huion H610PRO, but in this case
2164 * it's the altitude resolution that's zero. GdkEvents with
2165 * sensible tilts will need both, so only add the GDK tilt axes
2166 * if both wintab axes are going to be well-behaved in use.
2167 */
2168 if (axes == NULL)
2169 return;
2170
2171 if ((axes[0].axResolution == 0) ||
2172 (axes[1].axResolution == 0))
2173 {
2174 axis_data[0] = 0;
2175 axis_data[1] = 0;
2176 }
2177 else
2178 {
2179 /*
2180 * Tested with a Wacom Intuos 5 touch M (PTH-650) + Wacom drivers 6.3.18-5.
2181 * Wintab's reference angle leads gdk's by 90 degrees.
2182 */
2183 az = TWOPI * packet->pkOrientation.orAzimuth /
2184 (axes[0].axResolution / 65536.);
2185 az -= G_PI / 2;
2186 el = TWOPI * packet->pkOrientation.orAltitude /
2187 (axes[1].axResolution / 65536.);
2188
2189 /* X tilt */
2190 axis_data[0] = cos (az) * cos (el) * 1000;
2191 /* Y tilt */
2192 axis_data[1] = sin (az) * cos (el) * 1000;
2193 }
2194
2195 /* Twist (Rotation) if present */
2196 if (axes[2].axResolution != 0)
2197 axis_data[2] = packet->pkOrientation.orTwist;
2198 }
2199
2200 /*
2201 * Get the currently active keyboard modifiers (ignoring the mouse buttons)
2202 * We could use gdk_window_get_pointer but that function does a lot of other
2203 * expensive things besides getting the modifiers. This code is somewhat based
2204 * on build_pointer_event_state from gdkevents-win32.c
2205 */
2206 static guint
get_modifier_key_state(void)2207 get_modifier_key_state (void)
2208 {
2209 guint state;
2210
2211 state = 0;
2212 /* High-order bit is up/down, low order bit is toggled/untoggled */
2213 if (GetKeyState (VK_CONTROL) < 0)
2214 state |= GDK_CONTROL_MASK;
2215 if (GetKeyState (VK_SHIFT) < 0)
2216 state |= GDK_SHIFT_MASK;
2217 if (GetKeyState (VK_MENU) < 0)
2218 state |= GDK_MOD1_MASK;
2219 if (GetKeyState (VK_CAPITAL) & 0x1)
2220 state |= GDK_LOCK_MASK;
2221
2222 return state;
2223 }
2224
2225 int
_gdk_find_wintab_device_index(HCTX hctx)2226 _gdk_find_wintab_device_index (HCTX hctx)
2227 {
2228 GList *tmp_list;
2229 int devix;
2230
2231 /* Find the index of the Wintab driver's input device (probably zero) */
2232 if (!wintab_contexts)
2233 return -1; /* No tablet devices found or Wintab not initialized yet */
2234
2235 tmp_list = wintab_contexts;
2236 devix = 0;
2237 while (tmp_list)
2238 {
2239 if ((*(HCTX *) (tmp_list->data)) == hctx)
2240 return devix;
2241 else
2242 {
2243 devix++;
2244 tmp_list = tmp_list->next;
2245 }
2246 }
2247 return -1;
2248 }
2249
2250 static GdkDeviceWintab *
gdk_device_manager_find_wintab_device(GdkDeviceManagerWin32 * device_manager,HCTX hctx,UINT cursor)2251 gdk_device_manager_find_wintab_device (GdkDeviceManagerWin32 *device_manager,
2252 HCTX hctx,
2253 UINT cursor)
2254 {
2255 GdkDeviceWintab *device;
2256 GList *tmp_list;
2257
2258 for (tmp_list = device_manager->wintab_devices; tmp_list != NULL; tmp_list = tmp_list->next)
2259 {
2260 device = tmp_list->data;
2261
2262 if (device->hctx == hctx &&
2263 device->cursor == cursor)
2264 return device;
2265 }
2266
2267 return NULL;
2268 }
2269
2270 gboolean
gdk_wintab_input_events(GdkDisplay * display,GdkEvent * event,MSG * msg,GdkWindow * window)2271 gdk_wintab_input_events (GdkDisplay *display,
2272 GdkEvent *event,
2273 MSG *msg,
2274 GdkWindow *window)
2275 {
2276 GdkDeviceManagerWin32 *device_manager;
2277 GdkDeviceWintab *source_device = NULL;
2278 GdkDeviceGrabInfo *last_grab;
2279 GdkEventMask masktest;
2280 guint key_state;
2281 POINT pt;
2282 GdkWindowImplWin32 *impl;
2283
2284 PACKET packet;
2285 gint root_x, root_y;
2286 gint num_axes;
2287 gint x, y;
2288 guint translated_buttons, button_diff, button_mask;
2289 /* Translation from tablet button state to GDK button state for
2290 * buttons 1-3 - swap button 2 and 3.
2291 */
2292 static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7};
2293
2294 if (event->any.window != wintab_window)
2295 {
2296 g_warning ("gdk_wintab_input_events: not wintab_window?");
2297 return FALSE;
2298 }
2299
2300 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
2301 device_manager = GDK_DEVICE_MANAGER_WIN32 (gdk_display_get_device_manager (display));
2302 G_GNUC_END_IGNORE_DEPRECATIONS;
2303 window = gdk_device_get_window_at_position (device_manager->core_pointer, &x, &y);
2304 if (window == NULL)
2305 window = gdk_get_default_root_window ();
2306
2307 g_object_ref (window);
2308
2309 GDK_NOTE (EVENTS_OR_INPUT,
2310 g_print ("gdk_wintab_input_events: window=%p %+d%+d\n",
2311 GDK_WINDOW_HWND (window), x, y));
2312
2313 if (msg->message == WT_PACKET || msg->message == WT_CSRCHANGE)
2314 {
2315 if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet))
2316 return FALSE;
2317 }
2318
2319 switch (msg->message)
2320 {
2321 case WT_PACKET:
2322 source_device = gdk_device_manager_find_wintab_device (device_manager,
2323 (HCTX) msg->lParam,
2324 packet.pkCursor);
2325
2326 /* Check this first, as we get WT_PROXIMITY for disabled devices too */
2327 if (device_manager->dev_entered_proximity > 0)
2328 {
2329 /* This is the same code as in WT_CSRCHANGE. Some drivers send
2330 * WT_CSRCHANGE after each WT_PROXIMITY with LOWORD(lParam) != 0,
2331 * this code is for those that don't.
2332 */
2333 device_manager->dev_entered_proximity -= 1;
2334
2335 if (source_device != NULL &&
2336 source_device->sends_core &&
2337 gdk_device_get_mode (GDK_DEVICE (source_device)) != GDK_MODE_DISABLED)
2338 {
2339 _gdk_device_virtual_set_active (device_manager->core_pointer,
2340 GDK_DEVICE (source_device));
2341 _gdk_input_ignore_core += 1;
2342 }
2343 }
2344 else if (source_device != NULL &&
2345 source_device->sends_core &&
2346 gdk_device_get_mode (GDK_DEVICE (source_device)) != GDK_MODE_DISABLED &&
2347 _gdk_input_ignore_core == 0)
2348 {
2349 /* A fallback for cases when two devices (disabled and enabled)
2350 * were in proximity simultaneously.
2351 * In this case the removal of a disabled device would also
2352 * make the system pointer active, as we don't know which
2353 * device was removed and assume it was the enabled one.
2354 * If we are still getting packets for the enabled device,
2355 * it means that the device that was removed was the disabled
2356 * device, so we must make the enabled device active again and
2357 * start ignoring the core pointer events. In practice this means that
2358 * removing a disabled device while an enabled device is still
2359 * in proximity might briefly make the core pointer active/visible.
2360 */
2361 _gdk_device_virtual_set_active (device_manager->core_pointer,
2362 GDK_DEVICE (source_device));
2363 _gdk_input_ignore_core += 1;
2364 }
2365
2366 if (source_device == NULL ||
2367 gdk_device_get_mode (GDK_DEVICE (source_device)) == GDK_MODE_DISABLED)
2368 return FALSE;
2369
2370 /* Don't produce any button or motion events while a window is being
2371 * moved or resized, see bug #151090.
2372 */
2373 if (_modal_operation_in_progress & GDK_WIN32_MODAL_OP_SIZEMOVE_MASK)
2374 {
2375 GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
2376 return FALSE;
2377 }
2378
2379 last_grab = _gdk_display_get_last_device_grab (display, GDK_DEVICE (source_device));
2380
2381 if (last_grab && last_grab->window)
2382 {
2383 g_object_unref (window);
2384
2385 window = g_object_ref (last_grab->window);
2386 }
2387
2388 if (window == gdk_get_default_root_window ())
2389 {
2390 GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n"));
2391 return FALSE;
2392 }
2393
2394 num_axes = 0;
2395 if (source_device->pktdata & PK_X)
2396 source_device->last_axis_data[num_axes++] = packet.pkX;
2397 if (source_device->pktdata & PK_Y)
2398 source_device->last_axis_data[num_axes++] = packet.pkY;
2399 if (source_device->pktdata & PK_NORMAL_PRESSURE)
2400 source_device->last_axis_data[num_axes++] = packet.pkNormalPressure;
2401 if (source_device->pktdata & PK_ORIENTATION)
2402 {
2403 decode_tilt (source_device->last_axis_data + num_axes,
2404 source_device->orientation_axes, &packet);
2405 /* we could have 3 axes if twist is present */
2406 if (source_device->orientation_axes[2].axResolution == 0)
2407 {
2408 num_axes += 2;
2409 }
2410 else
2411 {
2412 num_axes += 3;
2413 }
2414 }
2415 if (source_device->pktdata & PK_TANGENT_PRESSURE)
2416 source_device->last_axis_data[num_axes++] = packet.pkTangentPressure;
2417
2418 translated_buttons = button_map[packet.pkButtons & 0x07] | (packet.pkButtons & ~0x07);
2419
2420 if (translated_buttons != source_device->button_state)
2421 {
2422 /* At least one button has changed state so produce a button event
2423 * If more than one button has changed state (unlikely),
2424 * just care about the first and act on the next the next time
2425 * we get a packet
2426 */
2427 button_diff = translated_buttons ^ source_device->button_state;
2428
2429 /* Gdk buttons are numbered 1.. */
2430 event->button.button = 1;
2431
2432 for (button_mask = 1; button_mask != 0x80000000;
2433 button_mask <<= 1, event->button.button++)
2434 {
2435 if (button_diff & button_mask)
2436 {
2437 /* Found a button that has changed state */
2438 break;
2439 }
2440 }
2441
2442 if (!(translated_buttons & button_mask))
2443 {
2444 event->any.type = GDK_BUTTON_RELEASE;
2445 masktest = GDK_BUTTON_RELEASE_MASK;
2446 }
2447 else
2448 {
2449 event->any.type = GDK_BUTTON_PRESS;
2450 masktest = GDK_BUTTON_PRESS_MASK;
2451 }
2452 source_device->button_state ^= button_mask;
2453 }
2454 else
2455 {
2456 event->any.type = GDK_MOTION_NOTIFY;
2457 masktest = GDK_POINTER_MOTION_MASK;
2458 if (source_device->button_state & (1 << 0))
2459 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK;
2460 if (source_device->button_state & (1 << 1))
2461 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK;
2462 if (source_device->button_state & (1 << 2))
2463 masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK;
2464 }
2465
2466 /* Now we can check if the window wants the event, and
2467 * propagate if necessary.
2468 */
2469 while ((gdk_window_get_device_events (window, GDK_DEVICE (source_device)) & masktest) == 0 &&
2470 (gdk_device_get_device_type (GDK_DEVICE (source_device)) == GDK_DEVICE_TYPE_SLAVE &&
2471 (gdk_window_get_events (window) & masktest) == 0))
2472 {
2473 GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n"));
2474
2475 if (window->parent == gdk_get_default_root_window () || window->parent == NULL)
2476 return FALSE;
2477
2478 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2479 pt.x = x * impl->window_scale;
2480 pt.y = y * impl->window_scale;
2481 ClientToScreen (GDK_WINDOW_HWND (window), &pt);
2482 g_object_unref (window);
2483 window = window->parent;
2484 impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
2485 g_object_ref (window);
2486 ScreenToClient (GDK_WINDOW_HWND (window), &pt);
2487 x = pt.x / impl->window_scale;
2488 y = pt.y / impl->window_scale;
2489 GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n",
2490 GDK_WINDOW_HWND (window), x, y));
2491 }
2492
2493 event->any.window = window;
2494 key_state = get_modifier_key_state ();
2495 if (event->any.type == GDK_BUTTON_PRESS ||
2496 event->any.type == GDK_BUTTON_RELEASE)
2497 {
2498 event->button.time = _gdk_win32_get_next_tick (msg->time);
2499 if (source_device->sends_core)
2500 gdk_event_set_device (event, device_manager->core_pointer);
2501 else
2502 gdk_event_set_device (event, GDK_DEVICE (source_device));
2503 gdk_event_set_source_device (event, GDK_DEVICE (source_device));
2504 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
2505
2506 event->button.axes = g_new (gdouble, num_axes);
2507 gdk_window_get_origin (window, &root_x, &root_y);
2508
2509 _gdk_device_wintab_translate_axes (source_device,
2510 window,
2511 event->button.axes,
2512 &event->button.x,
2513 &event->button.y);
2514
2515 event->button.x_root = event->button.x + root_x;
2516 event->button.y_root = event->button.y + root_y;
2517
2518 event->button.state =
2519 key_state | ((source_device->button_state << 8)
2520 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
2521 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
2522 | GDK_BUTTON5_MASK));
2523
2524 GDK_NOTE (EVENTS_OR_INPUT,
2525 g_print ("WINTAB button %s:%d %g,%g\n",
2526 (event->button.type == GDK_BUTTON_PRESS ?
2527 "press" : "release"),
2528 event->button.button,
2529 event->button.x, event->button.y));
2530 }
2531 else
2532 {
2533 event->motion.time = _gdk_win32_get_next_tick (msg->time);
2534 event->motion.is_hint = FALSE;
2535 if (source_device->sends_core)
2536 gdk_event_set_device (event, device_manager->core_pointer);
2537 else
2538 gdk_event_set_device (event, GDK_DEVICE (source_device));
2539 gdk_event_set_source_device (event, GDK_DEVICE (source_device));
2540 gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
2541
2542 event->motion.axes = g_new (gdouble, num_axes);
2543 gdk_window_get_origin (window, &root_x, &root_y);
2544
2545 _gdk_device_wintab_translate_axes (source_device,
2546 window,
2547 event->motion.axes,
2548 &event->motion.x,
2549 &event->motion.y);
2550
2551 event->motion.x_root = event->motion.x + root_x;
2552 event->motion.y_root = event->motion.y + root_y;
2553
2554 event->motion.state =
2555 key_state | ((source_device->button_state << 8)
2556 & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK
2557 | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK
2558 | GDK_BUTTON5_MASK));
2559
2560 GDK_NOTE (EVENTS_OR_INPUT,
2561 g_print ("WINTAB motion: %g,%g\n",
2562 event->motion.x, event->motion.y));
2563 }
2564 return TRUE;
2565
2566 case WT_CSRCHANGE:
2567 if (device_manager->dev_entered_proximity > 0)
2568 device_manager->dev_entered_proximity -= 1;
2569
2570 if ((source_device =
2571 gdk_device_manager_find_wintab_device (device_manager,
2572 (HCTX) msg->lParam,
2573 packet.pkCursor)) == NULL)
2574 {
2575 /* Check for new cursors and try again */
2576 if (_wintab_recognize_new_cursors(device_manager,
2577 (HCTX) msg->lParam) == 0)
2578 return FALSE;
2579 if ((source_device =
2580 gdk_device_manager_find_wintab_device (device_manager,
2581 (HCTX) msg->lParam,
2582 packet.pkCursor)) == NULL)
2583 return FALSE;
2584 }
2585
2586 if (source_device->sends_core &&
2587 gdk_device_get_mode (GDK_DEVICE (source_device)) != GDK_MODE_DISABLED)
2588 {
2589 _gdk_device_virtual_set_active (device_manager->core_pointer,
2590 GDK_DEVICE (source_device));
2591 _gdk_input_ignore_core += 1;
2592 }
2593 return FALSE;
2594
2595 case WT_PROXIMITY:
2596 if (LOWORD (msg->lParam) == 0)
2597 {
2598 if (_gdk_input_ignore_core > 0)
2599 {
2600 _gdk_input_ignore_core -= 1;
2601
2602 if (_gdk_input_ignore_core == 0)
2603 _gdk_device_virtual_set_active (device_manager->core_pointer,
2604 device_manager->system_pointer);
2605 }
2606 }
2607 else
2608 {
2609 device_manager->dev_entered_proximity += 1;
2610 }
2611
2612 return FALSE;
2613 }
2614
2615 return FALSE;
2616 }
2617