From: Luca Bacci Date: Fri, 2 Jul 2021 09:13:06 +0000 (+0200) Subject: Initialize WinPointer and enumerate devices X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~1^2~6^2~7 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b54f4cf5d4d634be96910229b2807c5ca2f5d2b8;p=gtk4.git Initialize WinPointer and enumerate devices --- diff --git a/gdk/win32/gdkdevice-winpointer.c b/gdk/win32/gdkdevice-winpointer.c index b5639bf114..a2190ed4d5 100644 --- a/gdk/win32/gdkdevice-winpointer.c +++ b/gdk/win32/gdkdevice-winpointer.c @@ -204,6 +204,9 @@ gdk_device_winpointer_finalize (GObject *object) { GdkDeviceWinpointer *device_winpointer = GDK_DEVICE_WINPOINTER (object); + g_clear_object (&device_winpointer->tool_pen); + g_clear_object (&device_winpointer->tool_eraser); + G_OBJECT_CLASS (gdk_device_winpointer_parent_class)->finalize (object); } diff --git a/gdk/win32/gdkdevice-winpointer.h b/gdk/win32/gdkdevice-winpointer.h index de13d51415..70d6f042c6 100644 --- a/gdk/win32/gdkdevice-winpointer.h +++ b/gdk/win32/gdkdevice-winpointer.h @@ -50,6 +50,9 @@ struct _GdkDeviceWinpointer double scale_y; GdkModifierType last_button_mask; + + GdkDeviceTool *tool_pen; + GdkDeviceTool *tool_eraser; }; struct _GdkDeviceWinpointerClass diff --git a/gdk/win32/gdkdevicemanager-win32.c b/gdk/win32/gdkdevicemanager-win32.c index 19203ab8fe..4ab0cc705d 100644 --- a/gdk/win32/gdkdevicemanager-win32.c +++ b/gdk/win32/gdkdevicemanager-win32.c @@ -29,6 +29,7 @@ #include "gdkdevice-win32.h" #include "gdkdevice-virtual.h" #include "gdkdevice-wintab.h" +#include "gdkinput-winpointer.h" #include "gdkdisplayprivate.h" #include "gdkseatdefaultprivate.h" @@ -727,6 +728,8 @@ gdk_device_manager_win32_constructed (GObject *object) gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), device_manager->system_keyboard); g_object_unref (seat); + _gdk_device_manager = device_manager; + tablet_input_api_user_preference = g_getenv ("GDK_WIN32_TABLET_INPUT_API"); if (g_strcmp0 (tablet_input_api_user_preference, "none") == 0) { @@ -738,12 +741,22 @@ gdk_device_manager_win32_constructed (GObject *object) have_tablet_input_api_preference = TRUE; _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINTAB; } + else if (g_strcmp0 (tablet_input_api_user_preference, "winpointer") == 0) + { + have_tablet_input_api_preference = TRUE; + _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINPOINTER; + } else { have_tablet_input_api_preference = FALSE; - _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINTAB; + _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINPOINTER; } + if (_gdk_win32_tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER) + { + if (!gdk_winpointer_initialize () && !have_tablet_input_api_preference) + _gdk_win32_tablet_input_api = GDK_WIN32_TABLET_INPUT_API_WINTAB; + } if (_gdk_win32_tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINTAB) { /* Only call Wintab init stuff after the default display diff --git a/gdk/win32/gdkdevicemanager-win32.h b/gdk/win32/gdkdevicemanager-win32.h index 5a93a2df41..26b5c761ac 100644 --- a/gdk/win32/gdkdevicemanager-win32.h +++ b/gdk/win32/gdkdevicemanager-win32.h @@ -40,6 +40,8 @@ struct _GdkDeviceManagerWin32 /* Fake physical devices */ GdkDevice *system_pointer; GdkDevice *system_keyboard; + + GList *winpointer_devices; GList *wintab_devices; /* Bumped up every time a wintab device enters the proximity diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index db4f7d1aa7..44a6792169 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -57,6 +57,7 @@ #include "gdkdeviceprivate.h" #include "gdkdevice-virtual.h" #include "gdkdevice-wintab.h" +#include "gdkinput-winpointer.h" #include "gdkwin32dnd.h" #include "gdkwin32dnd-private.h" #include "gdkdisplay-win32.h" @@ -72,8 +73,9 @@ #endif #include - #include +#include +#include #define GDK_MOD2_MASK (1 << 4) @@ -2976,6 +2978,13 @@ gdk_event_translate (MSG *msg, *ret_valp = 0; break; + case WM_DESTROY: + if (_gdk_win32_tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER) + gdk_winpointer_finalize_surface (window); + + return_val = FALSE; + break; + case WM_NCDESTROY: if ((pointer_grab != NULL && pointer_grab->surface == window) || (keyboard_grab && keyboard_grab->surface == window)) @@ -3081,6 +3090,16 @@ gdk_event_translate (MSG *msg, GET_Y_LPARAM (msg->lParam), ret_valp); break; + case WM_TABLET_QUERYSYSTEMGESTURESTATUS: + *ret_valp = TABLET_DISABLE_PRESSANDHOLD | + TABLET_DISABLE_PENTAPFEEDBACK | + TABLET_DISABLE_PENBARRELFEEDBACK | + TABLET_DISABLE_FLICKS | + TABLET_DISABLE_FLICKFALLBACKKEYS; + return_val = TRUE; + break; + + /* Handle WINTAB events here, as we know that the device manager will * use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the * constants as case labels. diff --git a/gdk/win32/gdkinput-winpointer.c b/gdk/win32/gdkinput-winpointer.c new file mode 100644 index 0000000000..5628cb5df9 --- /dev/null +++ b/gdk/win32/gdkinput-winpointer.c @@ -0,0 +1,602 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2021 the GTK team + * + * 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 . + */ + +#include "config.h" + +#include +#include "gdkwin32.h" +#include "gdkprivate-win32.h" +#include "gdkdevicemanager-win32.h" +#include "gdkdevice-winpointer.h" +#include "gdkdeviceprivate.h" +#include "gdkdisplayprivate.h" +#include "gdkseatdefaultprivate.h" +#include "gdkdevicetoolprivate.h" + +#include + +#include +#include +#include + +#define HID_STRING_BYTES_LIMIT 200 +#define VID_PID_CHARS 4 + +typedef BOOL +(WINAPI *registerPointerDeviceNotifications_t)(HWND window, BOOL notifyRange); +typedef BOOL +(WINAPI *getPointerDevices_t)(UINT32 *deviceCount, POINTER_DEVICE_INFO *pointerDevices); +typedef BOOL +(WINAPI *getPointerDeviceCursors_t)(HANDLE device, UINT32 *cursorCount, POINTER_DEVICE_CURSOR_INFO *deviceCursors); +typedef BOOL +(WINAPI *getPointerDeviceRects_t)(HANDLE device, RECT *pointerDeviceRect, RECT *displayRect); +typedef BOOL +(WINAPI *getPointerType_t)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType); +typedef BOOL +(WINAPI *getPointerCursorId_t)(UINT32 pointerId, UINT32 *cursorId); +typedef BOOL +(WINAPI *getPointerPenInfoHistory_t)(UINT32 pointerId, UINT32 *entriesCount, POINTER_PEN_INFO *penInfo); +typedef BOOL +(WINAPI *getPointerTouchInfoHistory_t)(UINT32 pointerId, UINT32 *entriesCount, POINTER_TOUCH_INFO *touchInfo); +typedef BOOL +(WINAPI *setGestureConfig_t)(HWND hwnd, DWORD dwReserved, UINT cIDs, PGESTURECONFIG pGestureConfig, UINT cbSize); + +static registerPointerDeviceNotifications_t registerPointerDeviceNotifications; +static getPointerDevices_t getPointerDevices; +static getPointerDeviceCursors_t getPointerDeviceCursors; +static getPointerDeviceRects_t getPointerDeviceRects; +static getPointerType_t getPointerType; +static getPointerCursorId_t getPointerCursorId; +static getPointerPenInfoHistory_t getPointerPenInfoHistory; +static getPointerTouchInfoHistory_t getPointerTouchInfoHistory; +static setGestureConfig_t setGestureConfig; + +static ATOM notifications_window_class; +static HWND notifications_window_handle; + +static inline double +utils_rect_width (RECT *rect) +{ + return rect->right - rect->left; +} + +static inline double +utils_rect_height (RECT *rect) +{ + return rect->bottom - rect->top; +} + +static inline gboolean +utils_rect_is_degenerate (RECT *rect) +{ + return utils_rect_width (rect) == 0 || utils_rect_height (rect) == 0; +} + +static gboolean +winpointer_device_update_scale_factors (GdkDeviceWinpointer *device) +{ + RECT device_rect; + RECT display_rect; + + if (!getPointerDeviceRects (device->device_handle, &device_rect, &display_rect)) + { + WIN32_API_FAILED ("GetPointerDeviceRects"); + return FALSE; + } + + if (utils_rect_is_degenerate (&device_rect)) + { + g_warning ("Invalid coordinates from GetPointerDeviceRects"); + return FALSE; + } + + device->origin_x = display_rect.left; + device->origin_y = display_rect.top; + device->scale_x = utils_rect_width (&display_rect) / utils_rect_width (&device_rect); + device->scale_y = utils_rect_height (&display_rect) / utils_rect_height (&device_rect); + + return TRUE; +} + +static void +winpointer_get_device_details (HANDLE device, + char *vid, + char *pid, + char **manufacturer, + char **product) +{ + RID_DEVICE_INFO info; + UINT wchars_count = 0; + UINT size = 0; + + memset (&info, 0, sizeof (info)); + + info.cbSize = sizeof (info); + size = sizeof (info); + + if (GetRawInputDeviceInfoW (device, RIDI_DEVICEINFO, &info, &size) > 0 && + info.dwType == RIM_TYPEHID && + info.hid.dwVendorId > 0 && + info.hid.dwProductId > 0) + { + const char *format_string = "%0" G_STRINGIFY (VID_PID_CHARS) "x"; + + g_snprintf (vid, VID_PID_CHARS + 1, format_string, (unsigned) info.hid.dwVendorId); + g_snprintf (pid, VID_PID_CHARS + 1, format_string, (unsigned) info.hid.dwProductId); + } + + if (GetRawInputDeviceInfoW (device, RIDI_DEVICENAME, NULL, &wchars_count) == 0) + { + gunichar2 *device_path = g_new0 (gunichar2, wchars_count); + + if (GetRawInputDeviceInfoW (device, RIDI_DEVICENAME, device_path, &wchars_count) > 0) + { + HANDLE device_file = CreateFileW (device_path, + 0, + FILE_SHARE_READ | + FILE_SHARE_WRITE | + FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_SESSION_AWARE, + NULL); + + if (device_file != INVALID_HANDLE_VALUE) + { + gunichar2 *buffer = g_malloc0 (HID_STRING_BYTES_LIMIT); + + if (HidD_GetManufacturerString (device_file, buffer, HID_STRING_BYTES_LIMIT)) + if (buffer[0]) + *manufacturer = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL); + + if (HidD_GetProductString (device_file, buffer, HID_STRING_BYTES_LIMIT)) + if (buffer[0]) + *product = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL); + + g_free (buffer); + CloseHandle (device_file); + } + } + + g_free (device_path); + } +} + +static void +winpointer_create_device (POINTER_DEVICE_INFO *info, + GdkInputSource source) +{ + GdkDeviceWinpointer *device = NULL; + GdkSeat *seat = NULL; + unsigned num_touches = 0; + char vid[VID_PID_CHARS + 1]; + char pid[VID_PID_CHARS + 1]; + char *manufacturer = NULL; + char *product = NULL; + char *base_name = NULL; + char *name = NULL; + UINT32 num_cursors = 0; + GdkAxisFlags axes_flags = 0; + + seat = gdk_display_get_default_seat (_gdk_display); + + memset (pid, 0, VID_PID_CHARS + 1); + memset (vid, 0, VID_PID_CHARS + 1); + + if (!getPointerDeviceCursors (info->device, &num_cursors, NULL)) + { + WIN32_API_FAILED ("GetPointerDeviceCursors"); + return; + } + + if (num_cursors == 0) + return; + + winpointer_get_device_details (info->device, vid, pid, &manufacturer, &product); + + /* build up the name */ + if (!manufacturer && vid[0]) + manufacturer = g_strdup (vid); + + if (!product && pid[0]) + product = g_strdup (pid); + + if (manufacturer && product) + base_name = g_strconcat (manufacturer, " ", product, NULL); + + if (!base_name && info->productString[0]) + base_name = g_utf16_to_utf8 (info->productString, -1, NULL, NULL, NULL); + + if (!base_name) + base_name = g_strdup ("Unnamed"); + + switch (source) + { + case GDK_SOURCE_PEN: + name = g_strconcat (base_name, " Pen", NULL); + break; + + case GDK_SOURCE_TOUCHSCREEN: + num_touches = info->maxActiveContacts; + name = g_strconcat (base_name, " Finger touch", NULL); + break; + + default: + name = g_strdup (base_name); + break; + } + + device = g_object_new (GDK_TYPE_DEVICE_WINPOINTER, + "display", _gdk_display, + "seat", seat, + "has-cursor", TRUE, + "source", source, + "name", name, + "num-touches", num_touches, + "vendor-id", vid[0] ? vid : NULL, + "product-id", pid[0] ? pid : NULL, + NULL); + + switch (source) + { + case GDK_SOURCE_PEN: + _gdk_device_add_axis (GDK_DEVICE (device), GDK_AXIS_PRESSURE, 0.0, 1.0, 1.0 / 1024.0); + axes_flags |= GDK_AXIS_FLAG_PRESSURE; + + _gdk_device_add_axis (GDK_DEVICE (device), GDK_AXIS_XTILT, -1.0, 1.0, 1.0 / 90.0); + axes_flags |= GDK_AXIS_FLAG_XTILT; + + _gdk_device_add_axis (GDK_DEVICE (device), GDK_AXIS_YTILT, -1.0, 1.0, 1.0 / 90.0); + axes_flags |= GDK_AXIS_FLAG_YTILT; + + _gdk_device_add_axis (GDK_DEVICE (device), GDK_AXIS_ROTATION, 0.0, 1.0, 1.0 / 360.0); + axes_flags |= GDK_AXIS_FLAG_ROTATION; + break; + + case GDK_SOURCE_TOUCHSCREEN: + _gdk_device_add_axis (GDK_DEVICE (device), GDK_AXIS_PRESSURE, 0.0, 1.0, 1.0 / 1024.0); + axes_flags |= GDK_AXIS_FLAG_PRESSURE; + break; + + default: + g_warn_if_reached (); + break; + } + + device->device_handle = info->device; + device->start_cursor_id = info->startingCursorId; + device->end_cursor_id = info->startingCursorId + num_cursors - 1; + + if (!winpointer_device_update_scale_factors (device)) + { + g_set_object (&device, NULL); + goto cleanup; + } + + switch (source) + { + case GDK_SOURCE_PEN: + { + device->tool_pen = gdk_device_tool_new (0, 0, GDK_DEVICE_TOOL_TYPE_PEN, axes_flags); + gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), device->tool_pen); + + device->tool_eraser = gdk_device_tool_new (0, 0, GDK_DEVICE_TOOL_TYPE_ERASER, axes_flags); + gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), device->tool_eraser); + } + break; + case GDK_SOURCE_TOUCHSCREEN: + break; + default: + g_warn_if_reached (); + break; + } + + _gdk_device_manager->winpointer_devices = g_list_append (_gdk_device_manager->winpointer_devices, device); + + _gdk_device_set_associated_device (GDK_DEVICE (device), _gdk_device_manager->core_pointer); + _gdk_device_add_physical_device (_gdk_device_manager->core_pointer, GDK_DEVICE (device)); + + gdk_seat_default_add_physical_device (GDK_SEAT_DEFAULT (seat), GDK_DEVICE (device)); + +cleanup: + g_free (name); + g_free (base_name); + g_free (product); + g_free (manufacturer); +} + +static void +winpointer_create_devices (POINTER_DEVICE_INFO *info) +{ + switch (info->pointerDeviceType) + { + case POINTER_DEVICE_TYPE_INTEGRATED_PEN: + case POINTER_DEVICE_TYPE_EXTERNAL_PEN: + winpointer_create_device (info, GDK_SOURCE_PEN); + break; + case POINTER_DEVICE_TYPE_TOUCH: + winpointer_create_device (info, GDK_SOURCE_TOUCHSCREEN); + break; + default: + g_warn_if_reached (); + break; + } +} + +static gboolean +winpointer_find_device_in_system_list (GdkDeviceWinpointer *device, + POINTER_DEVICE_INFO *infos, + UINT32 infos_count) +{ + for (UINT32 i = 0; i < infos_count; i++) + { + if (device->device_handle == infos[i].device && + device->start_cursor_id == infos[i].startingCursorId) + { + return TRUE; + } + } + + return FALSE; +} + +static gboolean +winpointer_find_system_device_in_device_manager (POINTER_DEVICE_INFO *info) +{ + for (GList *l = _gdk_device_manager->winpointer_devices; l != NULL; l = l->next) + { + GdkDeviceWinpointer *device = GDK_DEVICE_WINPOINTER (l->data); + + if (device->device_handle == info->device && + device->start_cursor_id == info->startingCursorId) + { + return TRUE; + } + } + + return FALSE; +} + +static void +winpointer_enumerate_devices (void) +{ + POINTER_DEVICE_INFO *infos = NULL; + UINT32 infos_count = 0; + UINT32 i = 0; + GList *current = NULL; + + do + { + infos = g_new0 (POINTER_DEVICE_INFO, infos_count); + if (!getPointerDevices (&infos_count, infos)) + { + WIN32_API_FAILED ("GetPointerDevices"); + g_free (infos); + return; + } + } + while (infos_count > 0 && !infos); + + current = _gdk_device_manager->winpointer_devices; + + while (current != NULL) + { + GdkDeviceWinpointer *device = GDK_DEVICE_WINPOINTER (current->data); + GList *next = current->next; + + if (!winpointer_find_device_in_system_list (device, infos, infos_count)) + { + GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (device)); + + _gdk_device_manager->winpointer_devices = g_list_delete_link (_gdk_device_manager->winpointer_devices, + current); + + gdk_device_update_tool (GDK_DEVICE (device), NULL); + + if (device->tool_pen) + gdk_seat_default_remove_tool (GDK_SEAT_DEFAULT (seat), device->tool_pen); + + if (device->tool_eraser) + gdk_seat_default_remove_tool (GDK_SEAT_DEFAULT (seat), device->tool_eraser); + + _gdk_device_set_associated_device (GDK_DEVICE (device), NULL); + _gdk_device_remove_physical_device (_gdk_device_manager->core_pointer, GDK_DEVICE (device)); + + gdk_seat_default_remove_physical_device (GDK_SEAT_DEFAULT (seat), GDK_DEVICE (device)); + + g_object_unref (device); + } + else + { + winpointer_device_update_scale_factors (device); + } + + current = next; + } + + /* create new gdk devices */ + for (i = 0; i < infos_count; i++) + { + if (!winpointer_find_system_device_in_device_manager (&infos[i])) + { + winpointer_create_devices (&infos[i]); + } + } + + g_free (infos); +} + +static LRESULT CALLBACK +winpointer_notifications_window_procedure (HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) + { + case WM_POINTERDEVICECHANGE: + winpointer_enumerate_devices (); + return 0; + } + + return DefWindowProcW (hWnd, uMsg, wParam, lParam); +} + +static gboolean +winpointer_notif_window_create (void) +{ + WNDCLASSEXW wndclassex; + + memset (&wndclassex, 0, sizeof (wndclassex)); + wndclassex.cbSize = sizeof (wndclassex); + wndclassex.lpszClassName = L"GdkWin32WinpointerNotificationsWindowClass"; + wndclassex.lpfnWndProc = winpointer_notifications_window_procedure; + wndclassex.hInstance = _gdk_dll_hinstance; + + if ((notifications_window_class = RegisterClassExW (&wndclassex)) == 0) + { + WIN32_API_FAILED ("RegisterClassExW"); + return FALSE; + } + + if (!(notifications_window_handle = CreateWindowExW (0, + (LPCWSTR)(guintptr)notifications_window_class, + L"GdkWin32 Winpointer Notifications", + 0, + 0, 0, 0, 0, + HWND_MESSAGE, + NULL, + _gdk_dll_hinstance, + NULL))) + { + WIN32_API_FAILED ("CreateWindowExW"); + return FALSE; + } + + return TRUE; +} + +static gboolean +winpointer_ensure_procedures (void) +{ + static HMODULE user32_dll = NULL; + + if (!user32_dll) + { + user32_dll = LoadLibraryW (L"user32.dll"); + if (!user32_dll) + { + WIN32_API_FAILED ("LoadLibraryW"); + return FALSE; + } + + registerPointerDeviceNotifications = (registerPointerDeviceNotifications_t) + GetProcAddress (user32_dll, "RegisterPointerDeviceNotifications"); + getPointerDevices = (getPointerDevices_t) + GetProcAddress (user32_dll, "GetPointerDevices"); + getPointerDeviceCursors = (getPointerDeviceCursors_t) + GetProcAddress (user32_dll, "GetPointerDeviceCursors"); + getPointerDeviceRects = (getPointerDeviceRects_t) + GetProcAddress (user32_dll, "GetPointerDeviceRects"); + getPointerType = (getPointerType_t) + GetProcAddress (user32_dll, "GetPointerType"); + getPointerCursorId = (getPointerCursorId_t) + GetProcAddress (user32_dll, "GetPointerCursorId"); + getPointerPenInfoHistory = (getPointerPenInfoHistory_t) + GetProcAddress (user32_dll, "GetPointerPenInfoHistory"); + getPointerTouchInfoHistory = (getPointerTouchInfoHistory_t) + GetProcAddress (user32_dll, "GetPointerTouchInfoHistory"); + setGestureConfig = (setGestureConfig_t) + GetProcAddress (user32_dll, "SetGestureConfig"); + } + + return registerPointerDeviceNotifications && + getPointerDevices && + getPointerDeviceCursors && + getPointerDeviceRects && + getPointerType && + getPointerCursorId && + getPointerPenInfoHistory && + getPointerTouchInfoHistory && + setGestureConfig; +} + +gboolean +gdk_winpointer_initialize (void) +{ + if (!winpointer_ensure_procedures ()) + return FALSE; + + if (!winpointer_notif_window_create ()) + return FALSE; + + if (!registerPointerDeviceNotifications (notifications_window_handle, FALSE)) + { + WIN32_API_FAILED ("RegisterPointerDeviceNotifications"); + return FALSE; + } + + winpointer_enumerate_devices (); + + return TRUE; +} + +#ifndef MICROSOFT_TABLETPENSERVICE_PROPERTY +#define MICROSOFT_TABLETPENSERVICE_PROPERTY \ +_T("MicrosoftTabletPenServiceProperty") +#endif + +void +gdk_winpointer_initialize_surface (GdkSurface *surface) +{ + HWND hwnd = GDK_SURFACE_HWND (surface); + ATOM key = 0; + HANDLE val = (HANDLE)(TABLET_DISABLE_PRESSANDHOLD | + TABLET_DISABLE_PENTAPFEEDBACK | + TABLET_DISABLE_PENBARRELFEEDBACK | + TABLET_DISABLE_FLICKS | + TABLET_DISABLE_FLICKFALLBACKKEYS); + + winpointer_ensure_procedures (); + + key = GlobalAddAtom (MICROSOFT_TABLETPENSERVICE_PROPERTY); + API_CALL (SetPropW, (hwnd, (LPCWSTR)(guintptr)key, val)); + GlobalDeleteAtom (key); + + if (setGestureConfig != NULL) + { + GESTURECONFIG gesture_config; + memset (&gesture_config, 0, sizeof (gesture_config)); + + gesture_config.dwID = 0; + gesture_config.dwWant = 0; + gesture_config.dwBlock = GC_ALLGESTURES; + + API_CALL (setGestureConfig, (hwnd, 0, 1, &gesture_config, sizeof (gesture_config))); + } +} + +void +gdk_winpointer_finalize_surface (GdkSurface *surface) +{ + HWND hwnd = GDK_SURFACE_HWND (surface); + ATOM key = 0; + + key = GlobalAddAtom (MICROSOFT_TABLETPENSERVICE_PROPERTY); + RemovePropW (hwnd, (LPCWSTR)(guintptr)key); + GlobalDeleteAtom (key); +} diff --git a/gdk/win32/gdkinput-winpointer.h b/gdk/win32/gdkinput-winpointer.h new file mode 100644 index 0000000000..d8a55c8f07 --- /dev/null +++ b/gdk/win32/gdkinput-winpointer.h @@ -0,0 +1,28 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2021 the GTK team + * + * 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 . + */ + +#ifndef __GDK_INPUT_WINPOINTER_H__ +#define __GDK_INPUT_WINPOINTER_H__ + +#include "winpointer.h" + +gboolean gdk_winpointer_initialize (void); + +void gdk_winpointer_initialize_surface (GdkSurface *surface); +void gdk_winpointer_finalize_surface (GdkSurface *surface); + +#endif /* __GDK_INPUT_WINPOINTER_H__ */ diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c index 3570b28dfa..ee9c3e3477 100644 --- a/gdk/win32/gdksurface-win32.c +++ b/gdk/win32/gdksurface-win32.c @@ -43,6 +43,7 @@ #include "gdkmonitorprivate.h" #include "gdkwin32surface.h" #include "gdkwin32cursor.h" +#include "gdkinput-winpointer.h" #include "gdkglcontext-win32.h" #include "gdkdisplay-win32.h" #include "gdkdevice-win32.h" @@ -645,6 +646,9 @@ _gdk_win32_display_create_surface (GdkDisplay *display, return NULL; } + if (_gdk_win32_tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER) + gdk_winpointer_initialize_surface (surface); + _gdk_win32_surface_enable_transparency (surface); _gdk_win32_surface_register_dnd (surface); diff --git a/gdk/win32/meson.build b/gdk/win32/meson.build index b46699ee4a..93c55fa6d8 100644 --- a/gdk/win32/meson.build +++ b/gdk/win32/meson.build @@ -17,6 +17,7 @@ gdk_win32_sources = files([ 'gdkglcontext-win32-wgl.c', 'gdkglobals-win32.c', 'gdkhdataoutputstream-win32.c', + 'gdkinput-winpointer.c', 'gdkkeys-win32.c', 'gdkwin32langnotification.c', 'gdkmain-win32.c', @@ -52,8 +53,9 @@ if win32_has_egl gdk_win32_sources += ['gdkglcontext-win32-egl.c'] endif -gdk_win32_deps = [ # FIXME - pangowin32_dep +gdk_win32_deps = [ + pangowin32_dep, # FIXME + cc.find_library('hid'), ] libgdk_win32 = static_library('gdk-win32',