Initialize WinPointer and enumerate devices
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ struct _GdkDeviceWinpointer
|
||||
double scale_y;
|
||||
|
||||
GdkModifierType last_button_mask;
|
||||
|
||||
GdkDeviceTool *tool_pen;
|
||||
GdkDeviceTool *tool_eraser;
|
||||
};
|
||||
|
||||
struct _GdkDeviceWinpointerClass
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <objbase.h>
|
||||
|
||||
#include <imm.h>
|
||||
#include <tchar.h>
|
||||
#include <tpcshrd.h>
|
||||
|
||||
#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.
|
||||
|
||||
602
gdk/win32/gdkinput-winpointer.c
Normal file
602
gdk/win32/gdkinput-winpointer.c
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#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 <windows.h>
|
||||
|
||||
#include <tchar.h>
|
||||
#include <tpcshrd.h>
|
||||
#include <hidsdi.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
28
gdk/win32/gdkinput-winpointer.h
Normal file
28
gdk/win32/gdkinput-winpointer.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user