629 lines
19 KiB
C
629 lines
19 KiB
C
|
/*
|
||
|
* Copyright © 2020 Red Hat, Inc.
|
||
|
* Copyright © 2021 Amazon.com, Inc. and its affiliates. All Rights Reserved.
|
||
|
*
|
||
|
* 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.1 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/>.
|
||
|
*
|
||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||
|
*/
|
||
|
|
||
|
#include "config.h"
|
||
|
|
||
|
#include <gdk/gdk.h>
|
||
|
|
||
|
#include "gdkdeviceprivate.h"
|
||
|
#include "gdkdevicetoolprivate.h"
|
||
|
|
||
|
#include "gdkmacosdevice.h"
|
||
|
#include "gdkmacosseat-private.h"
|
||
|
|
||
|
#include "gdkprivate.h"
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
NSUInteger device_id;
|
||
|
char *name;
|
||
|
|
||
|
GdkDevice *logical_device;
|
||
|
GdkDevice *stylus_device;
|
||
|
GdkSeat *seat;
|
||
|
|
||
|
GdkDeviceTool *current_tool;
|
||
|
|
||
|
int axis_indices[GDK_AXIS_LAST];
|
||
|
double axes[GDK_AXIS_LAST];
|
||
|
} GdkMacosTabletData;
|
||
|
|
||
|
struct _GdkMacosSeat
|
||
|
{
|
||
|
GdkSeat parent_instance;
|
||
|
|
||
|
GdkMacosDisplay *display;
|
||
|
|
||
|
GdkDevice *logical_pointer;
|
||
|
GdkDevice *logical_keyboard;
|
||
|
|
||
|
GdkMacosTabletData *current_tablet;
|
||
|
GPtrArray *tablets;
|
||
|
GPtrArray *tools;
|
||
|
};
|
||
|
|
||
|
struct _GdkMacosSeatClass
|
||
|
{
|
||
|
GdkSeatClass parent_class;
|
||
|
};
|
||
|
|
||
|
G_DEFINE_TYPE (GdkMacosSeat, gdk_macos_seat, GDK_TYPE_SEAT)
|
||
|
|
||
|
#define KEYBOARD_EVENTS (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | \
|
||
|
GDK_FOCUS_CHANGE_MASK)
|
||
|
#define TOUCH_EVENTS (GDK_TOUCH_MASK)
|
||
|
#define POINTER_EVENTS (GDK_POINTER_MOTION_MASK | \
|
||
|
GDK_BUTTON_PRESS_MASK | \
|
||
|
GDK_BUTTON_RELEASE_MASK | \
|
||
|
GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK | \
|
||
|
GDK_ENTER_NOTIFY_MASK | \
|
||
|
GDK_LEAVE_NOTIFY_MASK | \
|
||
|
GDK_PROXIMITY_IN_MASK | \
|
||
|
GDK_PROXIMITY_OUT_MASK)
|
||
|
|
||
|
static void
|
||
|
gdk_macos_tablet_data_free (gpointer user_data)
|
||
|
{
|
||
|
GdkMacosTabletData *tablet = user_data;
|
||
|
|
||
|
gdk_seat_device_removed (GDK_SEAT (tablet->seat), tablet->stylus_device);
|
||
|
gdk_seat_device_removed (GDK_SEAT (tablet->seat), tablet->logical_device);
|
||
|
|
||
|
_gdk_device_set_associated_device (tablet->logical_device, NULL);
|
||
|
_gdk_device_set_associated_device (tablet->stylus_device, NULL);
|
||
|
|
||
|
g_object_unref (tablet->logical_device);
|
||
|
g_object_unref (tablet->stylus_device);
|
||
|
|
||
|
g_free (tablet->name);
|
||
|
g_free (tablet);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gdk_macos_seat_dispose (GObject *object)
|
||
|
{
|
||
|
GdkMacosSeat *self = GDK_MACOS_SEAT (object);
|
||
|
|
||
|
if (self->logical_pointer)
|
||
|
{
|
||
|
gdk_seat_device_removed (GDK_SEAT (self), self->logical_pointer);
|
||
|
g_clear_object (&self->logical_pointer);
|
||
|
}
|
||
|
|
||
|
if (self->logical_keyboard)
|
||
|
{
|
||
|
gdk_seat_device_removed (GDK_SEAT (self), self->logical_keyboard);
|
||
|
g_clear_object (&self->logical_pointer);
|
||
|
}
|
||
|
|
||
|
g_clear_pointer (&self->tablets, g_ptr_array_unref);
|
||
|
g_clear_pointer (&self->tools, g_ptr_array_unref);
|
||
|
|
||
|
G_OBJECT_CLASS (gdk_macos_seat_parent_class)->dispose (object);
|
||
|
}
|
||
|
|
||
|
static GdkSeatCapabilities
|
||
|
gdk_macos_seat_get_capabilities (GdkSeat *seat)
|
||
|
{
|
||
|
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||
|
GdkSeatCapabilities caps = 0;
|
||
|
|
||
|
if (self->logical_pointer)
|
||
|
caps |= GDK_SEAT_CAPABILITY_POINTER;
|
||
|
if (self->logical_keyboard)
|
||
|
caps |= GDK_SEAT_CAPABILITY_KEYBOARD;
|
||
|
|
||
|
return caps;
|
||
|
}
|
||
|
|
||
|
static GdkGrabStatus
|
||
|
gdk_macos_seat_grab (GdkSeat *seat,
|
||
|
GdkSurface *surface,
|
||
|
GdkSeatCapabilities capabilities,
|
||
|
gboolean owner_events,
|
||
|
GdkCursor *cursor,
|
||
|
GdkEvent *event,
|
||
|
GdkSeatGrabPrepareFunc prepare_func,
|
||
|
gpointer prepare_func_data)
|
||
|
{
|
||
|
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||
|
guint32 evtime = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
|
||
|
GdkGrabStatus status = GDK_GRAB_SUCCESS;
|
||
|
gboolean was_visible;
|
||
|
|
||
|
was_visible = gdk_surface_get_mapped (surface);
|
||
|
|
||
|
if (prepare_func)
|
||
|
(prepare_func) (seat, surface, prepare_func_data);
|
||
|
|
||
|
if (!gdk_surface_get_mapped (surface))
|
||
|
{
|
||
|
g_critical ("Surface %p has not been mapped in GdkSeatGrabPrepareFunc",
|
||
|
surface);
|
||
|
return GDK_GRAB_NOT_VIEWABLE;
|
||
|
}
|
||
|
|
||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||
|
|
||
|
if (capabilities & GDK_SEAT_CAPABILITY_ALL_POINTING)
|
||
|
{
|
||
|
/* ALL_POINTING spans 3 capabilities; get the mask for the ones we have */
|
||
|
GdkEventMask pointer_evmask = 0;
|
||
|
|
||
|
/* We let tablet styli take over the pointer cursor */
|
||
|
if (capabilities & (GDK_SEAT_CAPABILITY_POINTER |
|
||
|
GDK_SEAT_CAPABILITY_TABLET_STYLUS))
|
||
|
{
|
||
|
pointer_evmask |= POINTER_EVENTS;
|
||
|
}
|
||
|
|
||
|
if (capabilities & GDK_SEAT_CAPABILITY_TOUCH)
|
||
|
pointer_evmask |= TOUCH_EVENTS;
|
||
|
|
||
|
status = gdk_device_grab (self->logical_pointer, surface,
|
||
|
owner_events,
|
||
|
pointer_evmask, cursor,
|
||
|
evtime);
|
||
|
}
|
||
|
|
||
|
if (status == GDK_GRAB_SUCCESS &&
|
||
|
capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)
|
||
|
{
|
||
|
status = gdk_device_grab (self->logical_keyboard, surface,
|
||
|
owner_events,
|
||
|
KEYBOARD_EVENTS, cursor,
|
||
|
evtime);
|
||
|
|
||
|
if (status != GDK_GRAB_SUCCESS)
|
||
|
{
|
||
|
if (capabilities & ~GDK_SEAT_CAPABILITY_KEYBOARD)
|
||
|
gdk_device_ungrab (self->logical_pointer, evtime);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (status != GDK_GRAB_SUCCESS && !was_visible)
|
||
|
gdk_surface_hide (surface);
|
||
|
|
||
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gdk_macos_seat_ungrab (GdkSeat *seat)
|
||
|
{
|
||
|
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||
|
|
||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||
|
gdk_device_ungrab (self->logical_pointer, GDK_CURRENT_TIME);
|
||
|
gdk_device_ungrab (self->logical_keyboard, GDK_CURRENT_TIME);
|
||
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||
|
}
|
||
|
|
||
|
static GdkDevice *
|
||
|
gdk_macos_seat_get_logical_device (GdkSeat *seat,
|
||
|
GdkSeatCapabilities capability)
|
||
|
{
|
||
|
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||
|
|
||
|
/* There must be only one flag set */
|
||
|
switch ((guint) capability)
|
||
|
{
|
||
|
case GDK_SEAT_CAPABILITY_POINTER:
|
||
|
case GDK_SEAT_CAPABILITY_TOUCH:
|
||
|
return self->logical_pointer;
|
||
|
case GDK_SEAT_CAPABILITY_KEYBOARD:
|
||
|
return self->logical_keyboard;
|
||
|
default:
|
||
|
g_warning ("Unhandled capability %x", capability);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static GList *
|
||
|
gdk_macos_seat_get_devices (GdkSeat *seat,
|
||
|
GdkSeatCapabilities capabilities)
|
||
|
{
|
||
|
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||
|
GList *physical_devices = NULL;
|
||
|
|
||
|
if (self->logical_pointer && (capabilities & GDK_SEAT_CAPABILITY_POINTER))
|
||
|
physical_devices = g_list_prepend (physical_devices, self->logical_pointer);
|
||
|
|
||
|
if (self->logical_keyboard && (capabilities & GDK_SEAT_CAPABILITY_KEYBOARD))
|
||
|
physical_devices = g_list_prepend (physical_devices, self->logical_keyboard);
|
||
|
|
||
|
if (capabilities & GDK_SEAT_CAPABILITY_TABLET_STYLUS)
|
||
|
{
|
||
|
for (guint i = 0; i < self->tablets->len; i++)
|
||
|
{
|
||
|
GdkMacosTabletData *tablet = g_ptr_array_index (self->tablets, i);
|
||
|
|
||
|
physical_devices = g_list_prepend (physical_devices, tablet->stylus_device);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return physical_devices;
|
||
|
}
|
||
|
|
||
|
static GList *
|
||
|
gdk_macos_seat_get_tools (GdkSeat *seat)
|
||
|
{
|
||
|
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||
|
GdkDeviceTool *tool;
|
||
|
GList *tools = NULL;
|
||
|
|
||
|
for (guint i = 0; i < self->tools->len; i++)
|
||
|
{
|
||
|
tool = g_ptr_array_index (self->tools, i);
|
||
|
tools = g_list_prepend (tools, tool);
|
||
|
}
|
||
|
|
||
|
return tools;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gdk_macos_seat_class_init (GdkMacosSeatClass *klass)
|
||
|
{
|
||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
|
GdkSeatClass *seat_class = GDK_SEAT_CLASS (klass);
|
||
|
|
||
|
object_class->dispose = gdk_macos_seat_dispose;
|
||
|
|
||
|
seat_class->get_capabilities = gdk_macos_seat_get_capabilities;
|
||
|
seat_class->grab = gdk_macos_seat_grab;
|
||
|
seat_class->ungrab = gdk_macos_seat_ungrab;
|
||
|
seat_class->get_logical_device = gdk_macos_seat_get_logical_device;
|
||
|
seat_class->get_devices = gdk_macos_seat_get_devices;
|
||
|
seat_class->get_tools = gdk_macos_seat_get_tools;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gdk_macos_seat_init (GdkMacosSeat *self)
|
||
|
{
|
||
|
self->tablets = g_ptr_array_new_with_free_func (gdk_macos_tablet_data_free);
|
||
|
self->tools = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
init_devices (GdkMacosSeat *self)
|
||
|
{
|
||
|
/* pointer */
|
||
|
self->logical_pointer = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||
|
"name", "Core Pointer",
|
||
|
"source", GDK_SOURCE_MOUSE,
|
||
|
"has-cursor", TRUE,
|
||
|
"display", self->display,
|
||
|
"seat", self,
|
||
|
NULL);
|
||
|
|
||
|
/* keyboard */
|
||
|
self->logical_keyboard = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||
|
"name", "Core Keyboard",
|
||
|
"source", GDK_SOURCE_KEYBOARD,
|
||
|
"has-cursor", FALSE,
|
||
|
"display", self->display,
|
||
|
"seat", self,
|
||
|
NULL);
|
||
|
|
||
|
/* link both */
|
||
|
_gdk_device_set_associated_device (self->logical_pointer, self->logical_keyboard);
|
||
|
_gdk_device_set_associated_device (self->logical_keyboard, self->logical_pointer);
|
||
|
|
||
|
gdk_seat_device_added (GDK_SEAT (self), self->logical_pointer);
|
||
|
gdk_seat_device_added (GDK_SEAT (self), self->logical_keyboard);
|
||
|
}
|
||
|
|
||
|
GdkSeat *
|
||
|
_gdk_macos_seat_new (GdkMacosDisplay *display)
|
||
|
{
|
||
|
GdkMacosSeat *self;
|
||
|
|
||
|
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
|
||
|
|
||
|
self = g_object_new (GDK_TYPE_MACOS_SEAT,
|
||
|
"display", display,
|
||
|
NULL);
|
||
|
|
||
|
self->display = display;
|
||
|
|
||
|
init_devices (self);
|
||
|
|
||
|
return GDK_SEAT (g_steal_pointer (&self));
|
||
|
}
|
||
|
|
||
|
static GdkDeviceToolType
|
||
|
get_device_tool_type_from_nsevent (NSEvent *nsevent)
|
||
|
{
|
||
|
GdkDeviceToolType tool_type;
|
||
|
|
||
|
switch ([nsevent pointingDeviceType])
|
||
|
{
|
||
|
case NSPointingDeviceTypePen:
|
||
|
tool_type = GDK_DEVICE_TOOL_TYPE_PEN;
|
||
|
break;
|
||
|
case NSPointingDeviceTypeEraser:
|
||
|
tool_type = GDK_DEVICE_TOOL_TYPE_ERASER;
|
||
|
break;
|
||
|
case NSPointingDeviceTypeCursor:
|
||
|
tool_type = GDK_DEVICE_TOOL_TYPE_MOUSE;
|
||
|
break;
|
||
|
case NSPointingDeviceTypeUnknown:
|
||
|
default:
|
||
|
tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||
|
}
|
||
|
|
||
|
return tool_type;
|
||
|
}
|
||
|
|
||
|
static GdkAxisFlags
|
||
|
get_device_tool_axes_from_nsevent (NSEvent *nsevent)
|
||
|
{
|
||
|
/* TODO: do we need to be smarter about the capabilities? */
|
||
|
return GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT | GDK_AXIS_FLAG_PRESSURE |
|
||
|
GDK_AXIS_FLAG_ROTATION;
|
||
|
}
|
||
|
|
||
|
static GdkMacosTabletData *
|
||
|
create_tablet_data_from_nsevent (GdkMacosSeat *self,
|
||
|
NSEvent *nsevent)
|
||
|
{
|
||
|
GdkMacosTabletData *tablet;
|
||
|
GdkDisplay *display = gdk_seat_get_display (GDK_SEAT (self));
|
||
|
GdkDevice *logical_device, *stylus_device;
|
||
|
char *logical_name;
|
||
|
char *vid, *pid;
|
||
|
|
||
|
tablet = g_new0 (GdkMacosTabletData, 1);
|
||
|
tablet->seat = GDK_SEAT (self);
|
||
|
tablet->device_id = [nsevent deviceID];
|
||
|
/* FIXME: find a better name */
|
||
|
tablet->name = g_strdup_printf ("Tablet %lu", [nsevent deviceID]);
|
||
|
|
||
|
vid = g_strdup_printf ("%.4lx", [nsevent vendorID]);
|
||
|
pid = g_strdup_printf ("%.4lx", [nsevent tabletID]);
|
||
|
|
||
|
logical_name = g_strdup_printf ("Logical pointer for %s", tablet->name);
|
||
|
logical_device = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||
|
"name", logical_name,
|
||
|
"source", GDK_SOURCE_MOUSE,
|
||
|
"has-cursor", TRUE,
|
||
|
"display", display,
|
||
|
"seat", self,
|
||
|
NULL);
|
||
|
|
||
|
stylus_device = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||
|
"name", tablet->name,
|
||
|
"source", GDK_SOURCE_PEN,
|
||
|
"has-cursor", FALSE,
|
||
|
"display", display,
|
||
|
"seat", self,
|
||
|
"vendor-id", vid,
|
||
|
"product-id", pid,
|
||
|
NULL);
|
||
|
|
||
|
tablet->logical_device = logical_device;
|
||
|
tablet->stylus_device = stylus_device;
|
||
|
|
||
|
_gdk_device_set_associated_device (logical_device, self->logical_keyboard);
|
||
|
_gdk_device_set_associated_device (stylus_device, logical_device);
|
||
|
|
||
|
gdk_seat_device_added (GDK_SEAT (self), logical_device);
|
||
|
gdk_seat_device_added (GDK_SEAT (self), stylus_device);
|
||
|
|
||
|
g_free (logical_name);
|
||
|
g_free (vid);
|
||
|
g_free (pid);
|
||
|
|
||
|
return tablet;
|
||
|
}
|
||
|
|
||
|
static GdkMacosTabletData *
|
||
|
get_tablet_data_from_nsevent (GdkMacosSeat *self,
|
||
|
NSEvent *nsevent)
|
||
|
{
|
||
|
GdkMacosTabletData *tablet = NULL;
|
||
|
|
||
|
for (guint i = 0; i < self->tablets->len; i++)
|
||
|
{
|
||
|
GdkMacosTabletData *t = g_ptr_array_index (self->tablets, i);
|
||
|
|
||
|
if (t->device_id == [nsevent deviceID])
|
||
|
{
|
||
|
tablet = t;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!tablet)
|
||
|
tablet = create_tablet_data_from_nsevent (self, nsevent);
|
||
|
|
||
|
return tablet;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
device_tablet_clone_tool_axes (GdkMacosTabletData *tablet,
|
||
|
GdkDeviceTool *tool)
|
||
|
{
|
||
|
int axis_pos;
|
||
|
|
||
|
g_object_freeze_notify (G_OBJECT (tablet->stylus_device));
|
||
|
_gdk_device_reset_axes (tablet->stylus_device);
|
||
|
|
||
|
_gdk_device_add_axis (tablet->stylus_device, GDK_AXIS_X, 0, 0, 0);
|
||
|
_gdk_device_add_axis (tablet->stylus_device, GDK_AXIS_Y, 0, 0, 0);
|
||
|
|
||
|
if (tool->tool_axes & (GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT))
|
||
|
{
|
||
|
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||
|
GDK_AXIS_XTILT, -1.0, 1.0, 0);
|
||
|
tablet->axis_indices[GDK_AXIS_XTILT] = axis_pos;
|
||
|
|
||
|
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||
|
GDK_AXIS_YTILT, -1.0, 1.0, 0);
|
||
|
tablet->axis_indices[GDK_AXIS_YTILT] = axis_pos;
|
||
|
}
|
||
|
|
||
|
if (tool->tool_axes & GDK_AXIS_FLAG_PRESSURE)
|
||
|
{
|
||
|
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||
|
GDK_AXIS_PRESSURE, 0.0, 1.0, 0);
|
||
|
tablet->axis_indices[GDK_AXIS_PRESSURE] = axis_pos;
|
||
|
}
|
||
|
|
||
|
if (tool->tool_axes & GDK_AXIS_FLAG_ROTATION)
|
||
|
{
|
||
|
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||
|
GDK_AXIS_ROTATION, 0.0, 1.0, 0);
|
||
|
tablet->axis_indices[GDK_AXIS_ROTATION] = axis_pos;
|
||
|
}
|
||
|
|
||
|
g_object_thaw_notify (G_OBJECT (tablet->stylus_device));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
mimic_device_axes (GdkDevice *logical,
|
||
|
GdkDevice *physical)
|
||
|
{
|
||
|
double axis_min, axis_max, axis_resolution;
|
||
|
GdkAxisUse axis_use;
|
||
|
int axis_count;
|
||
|
|
||
|
g_object_freeze_notify (G_OBJECT (logical));
|
||
|
_gdk_device_reset_axes (logical);
|
||
|
axis_count = gdk_device_get_n_axes (physical);
|
||
|
|
||
|
for (int i = 0; i < axis_count; i++)
|
||
|
{
|
||
|
_gdk_device_get_axis_info (physical, i, &axis_use, &axis_min,
|
||
|
&axis_max, &axis_resolution);
|
||
|
_gdk_device_add_axis (logical, axis_use, axis_min,
|
||
|
axis_max, axis_resolution);
|
||
|
}
|
||
|
|
||
|
g_object_thaw_notify (G_OBJECT (logical));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
_gdk_macos_seat_handle_tablet_tool_event (GdkMacosSeat *seat,
|
||
|
NSEvent *nsevent)
|
||
|
{
|
||
|
GdkDeviceToolType tool_type;
|
||
|
GdkMacosTabletData *tablet;
|
||
|
GdkDeviceTool *tool;
|
||
|
|
||
|
g_return_if_fail (GDK_IS_MACOS_SEAT (seat));
|
||
|
g_return_if_fail (nsevent != NULL);
|
||
|
|
||
|
tablet = get_tablet_data_from_nsevent (seat, nsevent);
|
||
|
|
||
|
tool_type = get_device_tool_type_from_nsevent (nsevent);
|
||
|
|
||
|
if (tool_type == GDK_DEVICE_TOOL_TYPE_UNKNOWN)
|
||
|
{
|
||
|
g_warning ("Unknown device tool detected");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
tool = gdk_seat_get_tool (GDK_SEAT (seat), [nsevent tabletID], [nsevent deviceID], tool_type);
|
||
|
|
||
|
if ([nsevent isEnteringProximity])
|
||
|
{
|
||
|
if (!tool)
|
||
|
{
|
||
|
tool = gdk_device_tool_new ([nsevent tabletID], [nsevent vendorID], tool_type,
|
||
|
get_device_tool_axes_from_nsevent (nsevent));
|
||
|
g_ptr_array_add (seat->tools, tool);
|
||
|
}
|
||
|
|
||
|
gdk_device_update_tool (tablet->stylus_device, tool);
|
||
|
tablet->current_tool = tool;
|
||
|
device_tablet_clone_tool_axes (tablet, tool);
|
||
|
mimic_device_axes (tablet->logical_device, tablet->stylus_device);
|
||
|
seat->current_tablet = tablet;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gdk_device_update_tool (tablet->stylus_device, NULL);
|
||
|
tablet->current_tool = NULL;
|
||
|
seat->current_tablet = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
_gdk_macos_seat_get_tablet (GdkMacosSeat *seat,
|
||
|
GdkDevice **logical_device,
|
||
|
GdkDeviceTool **tool)
|
||
|
{
|
||
|
g_return_val_if_fail (GDK_IS_MACOS_SEAT (seat), FALSE);
|
||
|
|
||
|
if (!seat->current_tablet)
|
||
|
return FALSE;
|
||
|
|
||
|
*logical_device = seat->current_tablet->logical_device;
|
||
|
*tool = seat->current_tablet->current_tool;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
double *
|
||
|
_gdk_macos_seat_get_tablet_axes_from_nsevent (GdkMacosSeat *seat,
|
||
|
NSEvent *nsevent)
|
||
|
{
|
||
|
GdkMacosTabletData *tablet;
|
||
|
int axis_index;
|
||
|
|
||
|
g_return_val_if_fail (GDK_IS_MACOS_SEAT (seat), NULL);
|
||
|
g_return_val_if_fail (nsevent != NULL, NULL);
|
||
|
|
||
|
tablet = seat->current_tablet;
|
||
|
if (!tablet || !tablet->current_tool)
|
||
|
return NULL;
|
||
|
|
||
|
if (tablet->current_tool->tool_axes & (GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT))
|
||
|
{
|
||
|
axis_index = tablet->axis_indices[GDK_AXIS_XTILT];
|
||
|
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||
|
[nsevent tilt].x, &tablet->axes[GDK_AXIS_XTILT]);
|
||
|
|
||
|
axis_index = tablet->axis_indices[GDK_AXIS_YTILT];
|
||
|
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||
|
[nsevent tilt].y, &tablet->axes[GDK_AXIS_YTILT]);
|
||
|
}
|
||
|
|
||
|
if (tablet->current_tool->tool_axes & GDK_AXIS_FLAG_PRESSURE)
|
||
|
{
|
||
|
axis_index = tablet->axis_indices[GDK_AXIS_PRESSURE];
|
||
|
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||
|
[nsevent pressure], &tablet->axes[GDK_AXIS_PRESSURE]);
|
||
|
}
|
||
|
|
||
|
if (tablet->current_tool->tool_axes & GDK_AXIS_FLAG_ROTATION)
|
||
|
{
|
||
|
axis_index = tablet->axis_indices[GDK_AXIS_ROTATION];
|
||
|
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||
|
[nsevent rotation], &tablet->axes[GDK_AXIS_ROTATION]);
|
||
|
}
|
||
|
|
||
|
return g_memdup2 (tablet->axes, sizeof (double) * GDK_AXIS_LAST);
|
||
|
}
|