Compare commits

...

28 Commits

Author SHA1 Message Date
Carlos Garnacho
f71c85b163 gtk3-demo: Add tool information to "Event axes" demo
Print tool type and serial, if found.
2016-04-05 14:37:25 +02:00
Carlos Garnacho
fbc5a8c772 wayland: Hook tablets to GdkSeat
Those are now also grabbed togetther with other master pointers,
so everything is able to interoperate on eg. popups triggered by
other devices.
2016-04-05 14:37:25 +02:00
Carlos Garnacho
3061589507 wayland: Translate pen buttons into button events
up/down already take GDK_BUTTON_PRIMARY, we translate BTN_STYLUS(2)
into GDK_BUTTON_MIDDLE/SECONDARY.
2016-04-05 14:37:25 +02:00
Stephen Chandler Paul
8cb68a1f3d Wayland: Translate wl_tablet.down/up into button events
These are sent with button=GDK_BUTTON_PRIMARY, axes must be also
included in these events, in addition to motion ones.
2016-04-05 14:37:25 +02:00
Stephen Chandler Paul
0414fe5251 Wayland: Translate tool axes in motion events
On wayland, such axes are per-tool, we must update device capabilities
on the fly as new tools enter proximity, first the slave device so
it matches the current tool, and then the master device so it looks
the same than the current slave device.
2016-04-05 14:37:25 +02:00
Stephen Chandler Paul
604125e991 Wayland: Implement proximity/crossing/motion event emission on tablets
Each tablet will update its own GdkWaylandPointerData separately. This
commit only adds plain motion event emission so far, no axes are managed
yet.
2016-04-05 14:37:25 +02:00
Stephen Chandler Paul
25b0318505 Wayland: Add initial support for drawing tablets
Only the management of tablets and tools is added so far. No tablet events
are yet interpreted.

As it's been the tradition in GTK+, erasers are split into their own device,
whereas the rest of the tools are meant to be routed through the
GDK_SOURCE_PEN device. Both pen/eraser devices are slaves to a master
pointer device, separate to wl_pointer's. This is so each tablet can
maintain its own cursor/positioning accounting.

Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com>
2016-04-05 14:37:25 +02:00
Carlos Garnacho
ab11dcc94a wayland: Refactor master pointer data into a separate struct
This will enable multiple "pointers" to have separate data here.
Will come out useful when adding support for tablets, as they
will have a separate cursor for all purposes.
2016-04-05 14:37:25 +02:00
Stephen Chandler Paul
cc7901077f gdkcursor-wayland.c: Minor indentation fix
Changed the tabs to spaces

Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com>
2016-04-05 14:37:24 +02:00
Carlos Garnacho
d9acfd5e6a x11: Emit proximity in/out events out of Wacom Serial ID property changes
We have no proximity events in XI2, but the changes around this property
will roughly match the times when it would be emitted, so can be used
as the base to emulate these.

Changes for this property will be received independently of the pointer
position, so we should take care to not emit it if the pointer is not
above any known window, emission around crossing events should be
taken care of too, left for a next commit.
2016-04-05 14:37:24 +02:00
Carlos Garnacho
0eaf32a27d x11: Use XInternAtom directly on poking device hardware IDs
This way we don't cache the property if it wasn't previously there,
added by the driver itself. Bailing out is due there.
2016-04-05 14:37:24 +02:00
Carlos Garnacho
b1d63e509c demos: Enable multidevice behavior on event-axes demo
On wayland we get separate master/slaves for each tablet, we will
need to receive crossing events for each master pointer if there's
more than one around.
2016-04-05 14:37:24 +02:00
Carlos Garnacho
9e5a430ac1 demos: Set crossing events mask explicitly on event-axes demo. 2016-04-05 14:37:24 +02:00
Carlos Garnacho
b00b99511a gtk3-demo: Show multiple master devices on the "Event axes" demo 2016-04-05 14:37:24 +02:00
Stephen Chandler Paul
55563a1a96 gtk-demo: Add support for distance in event_axes
Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com>
2016-04-05 14:37:24 +02:00
Stephen Chandler Paul
c1b585214e gtk-demo: Use GdkAxisUse instead of axis labels
Axis labels are very X specific, and are not really possible to port to other
backends such as Wayland. As such, it makes more sense to use GdkAxisUse and
GdkAxisUseFlag in order to determine the axis capabilities of a device and draw
their axes.

Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com>
2016-04-05 14:37:24 +02:00
Stephen Chandler Paul
45ed5478e4 GdkDeviceTool: Add GdkAxisFlags info to tablet tools
Different tools may have different sets of axes, we should store that
info somewhere.
2016-04-05 14:37:24 +02:00
Stephen Chandler Paul
e0c29664c8 GdkDeviceTool: Add GdkDeviceToolType to identify the physical tool type
Because there are multiple different types of styluses that can be used with
tablets, we have to have some sort of identifier for them attached to the
GdkDeviceTool, especially since knowing the actual tool type for a GdkDeviceTool
is necessary for matching up a GdkDeviceTool with it's appropriate
GdkInputSource in Wayland (eg. matching up a GdkDeviceTool eraser with the
GDK_SOURCE_ERASER GdkInputSource of a wayland tablet).

Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com>
2016-04-05 14:37:24 +02:00
Carlos Garnacho
b963df69a6 x11: Set GdkDeviceTool on motion/button events
The last known tool from the device is used here. If no tool is known,
the event will just have a NULL pointer there.
2016-04-05 14:37:24 +02:00
Carlos Garnacho
436bf19e9d x11: Update GdkDevices on "Wacom Serial IDs" property changes
This takes care of the emission of GdkDevice::tool-changed, plus the
updating of the internal device accounting.
2016-04-05 14:37:24 +02:00
Carlos Garnacho
50d02d752f gdk: Forward tools in client-side windows event translation 2016-04-05 14:36:34 +02:00
Carlos Garnacho
44b23556a4 events: Add gdk_event_[gs]et_device_tool()
This getter/setter will manage the tool pointer in GdkEventPrivate. The
setter should be most notably used by backends.
2016-04-05 13:29:15 +02:00
Carlos Garnacho
b712ad53ff GdkSeatDefault: Add functions to add/remove tools
This may be used by any backend using GdkSeatDefault as its seat
implementation.
2016-04-04 18:42:02 +02:00
Carlos Garnacho
f7e76c5332 gdk: Add GdkSeat::tool-added/removed signals
And a helper function to lookup a tool from the seat. Those are
tracker per-seat, and may be shared across devices.
2016-04-04 18:42:02 +02:00
Carlos Garnacho
13e408278f gdkdevice: Add GdkDevice::tool-changed signal
On the devices and backends that support it, this signal will be emitted
on slave/floating devices whenever the tool they are interacting with
changes. These notifications may also work as a sort of proximity events,
as the tool will be unset when the pen moves too far.

For backends, gdk_device_update_tool() has been included, all that should
be done on their side is just calling this whenever any tool might have
changed.
2016-04-04 18:42:01 +02:00
Carlos Garnacho
b94d09999d gdkdevice: Add GdkDeviceTool to identify device tools
GdkDeviceTool is an opaque object that can be used to identify a given
tool (eg. pens on tablets) during the app/device lifetime. Tools are only
set on non-master devices, and are owned by these.

The accounting functions are made private, the only public call on
GdkDeviceTool so far is gdk_device_tool_get_serial(), useful to identify
the tool across runs.
2016-04-04 18:42:01 +02:00
Carlos Garnacho
9a4ca1784c device: Add gdk_device_get_axes(), and ::axes property
This returns a GdkAxisFlags, holding the axes currently available
through this device.
2016-04-04 16:15:47 +02:00
Carlos Garnacho
30c4abd63d device: Add distance/rotation/slider GdkAxisUse values
These are possible to handle in tablets, so add a value for these in the
axis enum.
2016-04-04 16:15:47 +02:00
19 changed files with 2063 additions and 325 deletions

View File

@@ -24,14 +24,15 @@
typedef struct {
GdkDevice *last_source;
GHashTable *axes; /* axis label atom -> value */
GdkDeviceTool *last_tool;
gdouble *axes;
GdkRGBA color;
gdouble x;
gdouble y;
} AxesInfo;
typedef struct {
AxesInfo *pointer_info;
GHashTable *pointer_info; /* GdkDevice -> AxesInfo */
GHashTable *touch_info; /* GdkEventSequence -> AxesInfo */
} EventData;
@@ -59,8 +60,6 @@ axes_info_new (void)
info = g_new0 (AxesInfo, 1);
gdk_rgba_parse (&info->color, colors[cur_color]);
info->axes = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) g_free);
cur_color = (cur_color + 1) % G_N_ELEMENTS (colors);
@@ -70,38 +69,17 @@ axes_info_new (void)
static void
axes_info_free (AxesInfo *info)
{
g_hash_table_destroy (info->axes);
g_free (info);
}
static gboolean
axes_info_lookup (AxesInfo *info,
const gchar *axis_label,
gdouble *value)
{
gdouble *val;
GdkAtom atom;
atom = gdk_atom_intern (axis_label, FALSE);
if (atom == GDK_NONE)
return FALSE;
val = g_hash_table_lookup (info->axes, GDK_ATOM_TO_POINTER (atom));
if (!val)
return FALSE;
*value = *val;
return TRUE;
}
static EventData *
event_data_new (void)
{
EventData *data;
data = g_new0 (EventData, 1);
data->pointer_info = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) axes_info_free);
data->touch_info = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) axes_info_free);
@@ -111,8 +89,7 @@ event_data_new (void)
static void
event_data_free (EventData *data)
{
if (data->pointer_info)
axes_info_free (data->pointer_info);
g_hash_table_destroy (data->pointer_info);
g_hash_table_destroy (data->touch_info);
g_free (data);
}
@@ -123,13 +100,14 @@ update_axes_from_event (GdkEvent *event,
{
GdkDevice *device, *source_device;
GdkEventSequence *sequence;
gdouble x, y, value;
GList *l, *axes;
GdkDeviceTool *tool;
gdouble x, y;
AxesInfo *info;
device = gdk_event_get_device (event);
source_device = gdk_event_get_source_device (event);
sequence = gdk_event_get_event_sequence (event);
tool = gdk_event_get_device_tool (event);
if (event->type == GDK_TOUCH_END ||
event->type == GDK_TOUCH_CANCEL)
@@ -139,17 +117,19 @@ update_axes_from_event (GdkEvent *event,
}
else if (event->type == GDK_LEAVE_NOTIFY)
{
if (data->pointer_info)
axes_info_free (data->pointer_info);
data->pointer_info = NULL;
g_hash_table_remove (data->pointer_info, device);
return;
}
if (!sequence)
{
if (!data->pointer_info)
data->pointer_info = axes_info_new ();
info = data->pointer_info;
info = g_hash_table_lookup (data->pointer_info, device);
if (!info)
{
info = axes_info_new ();
g_hash_table_insert (data->pointer_info, device, info);
}
}
else
{
@@ -163,10 +143,10 @@ update_axes_from_event (GdkEvent *event,
}
if (info->last_source != source_device)
{
g_hash_table_remove_all (info->axes);
info->last_source = source_device;
}
info->last_source = source_device;
if (info->last_tool != tool)
info->last_tool = tool;
if (event->type == GDK_TOUCH_BEGIN ||
event->type == GDK_TOUCH_UPDATE ||
@@ -174,30 +154,15 @@ update_axes_from_event (GdkEvent *event,
event->type == GDK_BUTTON_PRESS ||
event->type == GDK_BUTTON_RELEASE)
{
axes = gdk_device_list_axes (device);
if (sequence && event->touch.emulating_pointer)
{
if (data->pointer_info)
axes_info_free (data->pointer_info);
data->pointer_info = NULL;
}
g_hash_table_remove (data->pointer_info, device);
for (l = axes; l; l = l->next)
{
gdouble *ptr;
if (info->axes)
g_free (info->axes);
/* All those event types are compatible wrt axes position in the struct */
if (!gdk_device_get_axis_value (device, event->motion.axes,
l->data, &value))
continue;
ptr = g_new0 (gdouble, 1);
*ptr = value;
g_hash_table_insert (info->axes, GDK_ATOM_TO_POINTER (l->data), ptr);
}
g_list_free (axes);
info->axes =
g_memdup (event->motion.axes,
sizeof(gdouble) * gdk_device_get_n_axes (source_device));
}
if (gdk_event_get_coords (event, &x, &y))
@@ -242,7 +207,8 @@ draw_axes_info (cairo_t *cr,
AxesInfo *info,
GtkAllocation *allocation)
{
gdouble pressure, tilt_x, tilt_y, wheel;
gdouble pressure, tilt_x, tilt_y, distance, wheel;
GdkAxisFlags axes = gdk_device_get_axes (info->last_source);
cairo_save (cr);
@@ -257,10 +223,13 @@ draw_axes_info (cairo_t *cr,
cairo_translate (cr, info->x, info->y);
if (axes_info_lookup (info, "Abs Pressure", &pressure))
if (axes & GDK_AXIS_FLAG_PRESSURE)
{
cairo_pattern_t *pattern;
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_PRESSURE,
&pressure);
pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, 100);
cairo_pattern_add_color_stop_rgba (pattern, pressure, 1, 0, 0, pressure);
cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 1, 0);
@@ -273,12 +242,49 @@ draw_axes_info (cairo_t *cr,
cairo_pattern_destroy (pattern);
}
if (axes_info_lookup (info, "Abs Tilt X", &tilt_x) &&
axes_info_lookup (info, "Abs Tilt Y", &tilt_y))
render_arrow (cr, tilt_x * 100, tilt_y * 100, "Tilt");
if (axes_info_lookup (info, "Abs Wheel", &wheel))
if (axes & GDK_AXIS_FLAG_XTILT &&
axes & GDK_AXIS_FLAG_YTILT)
{
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_XTILT,
&tilt_x);
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_YTILT,
&tilt_y);
render_arrow (cr, tilt_x * 100, tilt_y * 100, "Tilt");
}
if (axes & GDK_AXIS_FLAG_DISTANCE)
{
double dashes[] = { 5.0, 5.0 };
cairo_text_extents_t extents;
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_DISTANCE,
&distance);
cairo_save (cr);
cairo_move_to (cr, distance * 100, 0);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_set_dash (cr, dashes, 2, 0.0);
cairo_arc (cr, 0, 0, distance * 100, 0, 2 * G_PI);
cairo_stroke (cr);
cairo_move_to (cr, 0, -distance * 100);
cairo_text_extents (cr, "Distance", &extents);
cairo_rel_move_to (cr, -extents.width / 2, 0);
cairo_show_text (cr, "Distance");
cairo_move_to (cr, 0, 0);
cairo_restore (cr);
}
if (axes & GDK_AXIS_FLAG_WHEEL)
{
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_WHEEL,
&wheel);
cairo_save (cr);
cairo_set_line_width (cr, 10);
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
@@ -292,6 +298,31 @@ draw_axes_info (cairo_t *cr,
cairo_restore (cr);
}
static const gchar *
tool_type_to_string (GdkDeviceToolType tool_type)
{
switch (tool_type)
{
case GDK_DEVICE_TOOL_TYPE_PEN:
return "Pen";
case GDK_DEVICE_TOOL_TYPE_ERASER:
return "Eraser";
case GDK_DEVICE_TOOL_TYPE_BRUSH:
return "Brush";
case GDK_DEVICE_TOOL_TYPE_PENCIL:
return "Pencil";
case GDK_DEVICE_TOOL_TYPE_AIRBRUSH:
return "Airbrush";
case GDK_DEVICE_TOOL_TYPE_MOUSE:
return "Mouse";
case GDK_DEVICE_TOOL_TYPE_LENS:
return "Lens cursor";
case GDK_DEVICE_TOOL_TYPE_UNKNOWN:
default:
return "Unknown";
}
}
static void
draw_device_info (GtkWidget *widget,
cairo_t *cr,
@@ -313,6 +344,19 @@ draw_device_info (GtkWidget *widget,
g_string_append_printf (string, "\nSequence: %d",
GPOINTER_TO_UINT (sequence));
if (info->last_tool)
{
const gchar *tool_type;
guint64 serial;
tool_type = tool_type_to_string (gdk_device_tool_get_tool_type (info->last_tool));
serial = gdk_device_tool_get_serial (info->last_tool);
g_string_append_printf (string, "\nTool: %s", tool_type);
if (serial != 0)
g_string_append_printf (string, ", Serial: %lx", serial);
}
cairo_move_to (cr, 10, *y);
layout = gtk_widget_create_pango_layout (widget, string->str);
pango_cairo_show_layout (cr, layout);
@@ -341,7 +385,7 @@ draw_cb (GtkWidget *widget,
{
EventData *data = user_data;
GtkAllocation allocation;
AxesInfo *touch_info;
AxesInfo *info;
GHashTableIter iter;
gpointer key, value;
gint y = 0;
@@ -349,27 +393,37 @@ draw_cb (GtkWidget *widget,
gtk_widget_get_allocation (widget, &allocation);
/* Draw Abs info */
if (data->pointer_info)
draw_axes_info (cr, data->pointer_info, &allocation);
g_hash_table_iter_init (&iter, data->pointer_info);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
info = value;
draw_axes_info (cr, info, &allocation);
}
g_hash_table_iter_init (&iter, data->touch_info);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
touch_info = value;
draw_axes_info (cr, touch_info, &allocation);
info = value;
draw_axes_info (cr, info, &allocation);
}
/* Draw name, color legend and misc data */
if (data->pointer_info)
draw_device_info (widget, cr, NULL, &y, data->pointer_info);
g_hash_table_iter_init (&iter, data->pointer_info);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
info = value;
draw_device_info (widget, cr, NULL, &y, info);
}
g_hash_table_iter_init (&iter, data->touch_info);
while (g_hash_table_iter_next (&iter, &key, &value))
{
touch_info = value;
draw_device_info (widget, cr, key, &y, touch_info);
info = value;
draw_device_info (widget, cr, key, &y, info);
}
return FALSE;
@@ -393,11 +447,14 @@ do_event_axes (GtkWidget *toplevel)
box = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (window), box);
gtk_widget_set_support_multidevice (box, TRUE);
gtk_widget_add_events (box,
GDK_POINTER_MOTION_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_SMOOTH_SCROLL_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_TOUCH_MASK);
event_data = event_data_new ();

View File

@@ -715,6 +715,8 @@ GdkDevice
GdkInputSource
GdkInputMode
GdkAxisUse
GdkAxisFlags
GdkDeviceToolType
GdkDeviceType
GdkGrabOwnership
@@ -736,6 +738,7 @@ gdk_device_get_display
gdk_device_get_has_cursor
gdk_device_get_n_axes
gdk_device_get_n_keys
gdk_device_get_axes
gdk_device_warp
gdk_device_get_seat
@@ -757,6 +760,10 @@ gdk_device_list_axes
gdk_device_get_axis_value
gdk_device_get_last_event_window
<SUBSECTION>
gdk_device_tool_get_serial
gdk_device_tool_get_tool_type
<SUBSECTION Standard>
GDK_TYPE_AXIS_USE
GDK_TYPE_EXTENSION_MODE
@@ -883,6 +890,8 @@ gdk_event_get_device
gdk_event_set_device
gdk_event_get_source_device
gdk_event_set_source_device
gdk_event_get_device_tool
gdk_event_set_device_tool
<SUBSECTION>
gdk_setting_get

View File

@@ -57,6 +57,7 @@ struct _GdkAxisInfo
enum {
CHANGED,
TOOL_CHANGED,
LAST_SIGNAL
};
@@ -92,6 +93,7 @@ enum {
PROP_PRODUCT_ID,
PROP_SEAT,
PROP_NUM_TOUCHES,
PROP_AXES,
LAST_PROP
};
@@ -305,6 +307,19 @@ gdk_device_class_init (GdkDeviceClass *klass)
0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
* GdkDevice:axes:
*
* The axes currently available for this device.
*
* Since: 3.22
*/
device_props[PROP_AXES] =
g_param_spec_flags ("axes",
P_("Axes"),
P_("Axes"),
GDK_TYPE_AXIS_FLAGS, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, LAST_PROP, device_props);
@@ -327,6 +342,24 @@ gdk_device_class_init (GdkDeviceClass *klass)
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* GdkDevice::tool-changed:
* @device: the #GdkDevice that changed.
* @tool: The new current tool
*
* The ::tool-changed signal is emitted on pen/eraser
* #GdkDevice<!-- -->s whenever tools enter or leave proximity.
*
* Since: 3.22
*/
signals[TOOL_CHANGED] =
g_signal_new (g_intern_static_string ("tool-changed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1, GDK_TYPE_DEVICE_TOOL);
}
static void
@@ -374,6 +407,8 @@ gdk_device_dispose (GObject *object)
g_object_unref (associated);
}
g_clear_object (&device->last_tool);
G_OBJECT_CLASS (gdk_device_parent_class)->dispose (object);
}
@@ -477,6 +512,9 @@ gdk_device_get_property (GObject *object,
case PROP_NUM_TOUCHES:
g_value_set_uint (value, device->num_touches);
break;
case PROP_AXES:
g_value_set_flags (value, device->axis_flags);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1515,7 +1553,10 @@ _gdk_device_reset_axes (GdkDevice *device)
for (i = device->axes->len - 1; i >= 0; i--)
g_array_remove_index (device->axes, i);
device->axis_flags = 0;
g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_N_AXES]);
g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_AXES]);
}
guint
@@ -1556,7 +1597,10 @@ _gdk_device_add_axis (GdkDevice *device,
device->axes = g_array_append_val (device->axes, axis_info);
pos = device->axes->len - 1;
device->axis_flags |= (1 << use);
g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_N_AXES]);
g_object_notify_by_pspec (G_OBJECT (device), device_props[PROP_AXES]);
return pos;
}
@@ -1964,3 +2008,178 @@ gdk_device_get_seat (GdkDevice *device)
return device->seat;
}
/**
* gdk_device_get_axes:
* @device: a #GdkDevice
*
* Returns the axes currently available on the device.
*
* Since: 3.22
**/
GdkAxisFlags
gdk_device_get_axes (GdkDevice *device)
{
g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
return device->axis_flags;
}
G_DEFINE_TYPE (GdkDeviceTool, gdk_device_tool, G_TYPE_OBJECT)
enum {
TOOL_PROP_0,
TOOL_PROP_SERIAL,
TOOL_PROP_TOOL_TYPE,
TOOL_PROP_AXES,
N_TOOL_PROPS
};
GParamSpec *tool_props[N_TOOL_PROPS] = { 0 };
static void
gdk_device_tool_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkDeviceTool *tool = GDK_DEVICE_TOOL (object);
switch (prop_id)
{
case TOOL_PROP_SERIAL:
tool->serial = g_value_get_uint64 (value);
break;
case TOOL_PROP_TOOL_TYPE:
tool->type = g_value_get_enum (value);
break;
case TOOL_PROP_AXES:
tool->tool_axes = g_value_get_flags (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_device_tool_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkDeviceTool *tool = GDK_DEVICE_TOOL (object);
switch (prop_id)
{
case TOOL_PROP_SERIAL:
g_value_set_uint64 (value, tool->serial);
break;
case TOOL_PROP_TOOL_TYPE:
g_value_set_enum (value, tool->type);
break;
case TOOL_PROP_AXES:
g_value_set_flags (value, tool->tool_axes);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_device_tool_class_init (GdkDeviceToolClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = gdk_device_tool_set_property;
object_class->get_property = gdk_device_tool_get_property;
tool_props[TOOL_PROP_SERIAL] = g_param_spec_uint64 ("serial",
"Serial",
"Serial number",
0, G_MAXUINT64, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
tool_props[TOOL_PROP_TOOL_TYPE] = g_param_spec_enum ("tool-type",
"Tool type",
"Tool type",
GDK_TYPE_DEVICE_TOOL_TYPE,
GDK_DEVICE_TOOL_TYPE_UNKNOWN,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
tool_props[TOOL_PROP_AXES] = g_param_spec_flags ("axes",
"Axes",
"Tool axes",
GDK_TYPE_AXIS_FLAGS, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, N_TOOL_PROPS, tool_props);
}
static void
gdk_device_tool_init (GdkDeviceTool *tool)
{
}
GdkDeviceTool *
gdk_device_tool_new (guint64 serial,
GdkDeviceToolType type,
GdkAxisFlags tool_axes)
{
return g_object_new (GDK_TYPE_DEVICE_TOOL,
"serial", serial,
"tool-type", type,
"axes", tool_axes,
NULL);
}
void
gdk_device_update_tool (GdkDevice *device,
GdkDeviceTool *tool)
{
g_return_if_fail (GDK_IS_DEVICE (device));
g_return_if_fail (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER);
if (g_set_object (&device->last_tool, tool))
g_signal_emit (device, signals[TOOL_CHANGED], 0, tool);
}
/**
* gdk_device_tool_get_serial:
* @tool: a #GdkDeviceTool
*
* Gets the serial of this tool, this value can be used to identify a
* physical tool (eg. a tablet pen) across program executions.
*
* Returns: The serial ID for this tool
*
* Since: 3.22
**/
guint
gdk_device_tool_get_serial (GdkDeviceTool *tool)
{
g_return_val_if_fail (tool != NULL, 0);
return tool->serial;
}
/**
* gdk_device_tool_get_tool_type:
* @tool: a #GdkDeviceTool
*
* Gets the #GdkDeviceToolType of the tool.
*
* Returns: The physical type for this tool. This can be used to figure out what
* sort of pen is being used, such as an airbrush or a pencil.
*
* Since: 3.22
**/
GdkDeviceToolType
gdk_device_tool_get_tool_type (GdkDeviceTool *tool)
{
g_return_val_if_fail (tool != NULL, GDK_DEVICE_TOOL_TYPE_UNKNOWN);
return tool->type;
}

View File

@@ -32,7 +32,12 @@ G_BEGIN_DECLS
#define GDK_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE, GdkDevice))
#define GDK_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE))
#define GDK_TYPE_DEVICE_TOOL (gdk_device_tool_get_type ())
#define GDK_DEVICE_TOOL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE_TOOL, GdkDeviceTool))
#define GDK_IS_DEVICE_TOOL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE_TOOL))
typedef struct _GdkTimeCoord GdkTimeCoord;
typedef struct _GdkDeviceTool GdkDeviceTool;
/**
* GdkInputSource:
@@ -89,6 +94,9 @@ typedef enum
* @GDK_AXIS_XTILT: the axis is used for x tilt information.
* @GDK_AXIS_YTILT: the axis is used for y tilt information.
* @GDK_AXIS_WHEEL: the axis is used for wheel information.
* @GDK_AXIS_DISTANCE: the axis is used for pen/tablet distance information. (Since: 3.22)
* @GDK_AXIS_ROTATION: the axis is used for pen rotation information. (Since: 3.22)
* @GDK_AXIS_SLIDER: the axis is used for pen slider information. (Since: 3.22)
* @GDK_AXIS_LAST: a constant equal to the numerically highest axis value.
*
* An enumeration describing the way in which a device
@@ -104,9 +112,41 @@ typedef enum
GDK_AXIS_XTILT,
GDK_AXIS_YTILT,
GDK_AXIS_WHEEL,
GDK_AXIS_DISTANCE,
GDK_AXIS_ROTATION,
GDK_AXIS_SLIDER,
GDK_AXIS_LAST
} GdkAxisUse;
/**
* GdkAxisFlags:
* @GDK_AXIS_FLAG_X: X axis is present
* @GDK_AXIS_FLAG_Y: Y axis is present
* @GDK_AXIS_FLAG_PRESSURE: Pressure axis is present
* @GDK_AXIS_FLAG_XTILT: X tilt axis is present
* @GDK_AXIS_FLAG_YTILT: Y tilt axis is present
* @GDK_AXIS_FLAG_WHEEL: Wheel axis is present
* @GDK_AXIS_FLAG_DISTANCE: Distance axis is present
* @GDK_AXIS_FLAG_ROTATION: Z-axis rotation is present
* @GDK_AXIS_FLAG_SLIDER: Slider axis is present
*
* Flags describing the current capabilities of a device/tool.
*
* Since: 3.22
*/
typedef enum
{
GDK_AXIS_FLAG_X = 1 << GDK_AXIS_X,
GDK_AXIS_FLAG_Y = 1 << GDK_AXIS_Y,
GDK_AXIS_FLAG_PRESSURE = 1 << GDK_AXIS_PRESSURE,
GDK_AXIS_FLAG_XTILT = 1 << GDK_AXIS_XTILT,
GDK_AXIS_FLAG_YTILT = 1 << GDK_AXIS_YTILT,
GDK_AXIS_FLAG_WHEEL = 1 << GDK_AXIS_WHEEL,
GDK_AXIS_FLAG_DISTANCE = 1 << GDK_AXIS_DISTANCE,
GDK_AXIS_FLAG_ROTATION = 1 << GDK_AXIS_ROTATION,
GDK_AXIS_FLAG_SLIDER = 1 << GDK_AXIS_SLIDER,
} GdkAxisFlags;
/**
* GdkDeviceType:
* @GDK_DEVICE_TYPE_MASTER: Device is a master (or virtual) device. There will
@@ -124,6 +164,33 @@ typedef enum {
GDK_DEVICE_TYPE_FLOATING
} GdkDeviceType;
/**
* GdkDeviceToolType:
* @GDK_DEVICE_TOOL_TYPE_UNKNOWN: Tool is of an unknown type.
* @GDK_DEVICE_TOOL_TYPE_PEN: Tool is a standard tablet stylus.
* @GDK_DEVICE_TOOL_TYPE_ERASER: Tool is standard tablet eraser.
* @GDK_DEVICE_TOOL_TYPE_BRUSH: Tool is a brush stylus.
* @GDK_DEVICE_TOOL_TYPE_PENCIL: Tool is a pencil stylus.
* @GDK_DEVICE_TOOL_TYPE_AIRBRUSH: Tool is an airbrush stylus.
* @GDK_DEVICE_TOOL_TYPE_MOUSE: Tool is a mouse.
* @GDK_DEVICE_TOOL_TYPE_LENS: Tool is a lens cursor.
*
* Indicates the specific type of tool being used being a tablet. Such as an
* airbrush, pencil, etc.
*
* Since: 3.22
*/
typedef enum {
GDK_DEVICE_TOOL_TYPE_UNKNOWN,
GDK_DEVICE_TOOL_TYPE_PEN,
GDK_DEVICE_TOOL_TYPE_ERASER,
GDK_DEVICE_TOOL_TYPE_BRUSH,
GDK_DEVICE_TOOL_TYPE_PENCIL,
GDK_DEVICE_TOOL_TYPE_AIRBRUSH,
GDK_DEVICE_TOOL_TYPE_MOUSE,
GDK_DEVICE_TOOL_TYPE_LENS,
} GdkDeviceToolType;
/* We don't allocate each coordinate this big, but we use it to
* be ANSI compliant and avoid accessing past the defined limits.
*/
@@ -282,6 +349,18 @@ const gchar *gdk_device_get_product_id (GdkDevice *device);
GDK_AVAILABLE_IN_3_20
GdkSeat *gdk_device_get_seat (GdkDevice *device);
GDK_AVAILABLE_IN_3_22
GdkAxisFlags gdk_device_get_axes (GdkDevice *device);
GDK_AVAILABLE_IN_3_22
GType gdk_device_tool_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_22
guint gdk_device_tool_get_serial (GdkDeviceTool *tool);
GDK_AVAILABLE_IN_3_22
GdkDeviceToolType gdk_device_tool_get_tool_type (GdkDeviceTool *tool);
G_END_DECLS
#endif /* __GDK_DEVICE_H__ */

View File

@@ -30,8 +30,22 @@ G_BEGIN_DECLS
#define GDK_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE, GdkDeviceClass))
typedef struct _GdkDeviceClass GdkDeviceClass;
typedef struct _GdkDeviceToolClass GdkDeviceToolClass;
typedef struct _GdkDeviceKey GdkDeviceKey;
struct _GdkDeviceTool
{
GObject parent_instance;
guint64 serial;
GdkDeviceToolType type;
GdkAxisFlags tool_axes;
};
struct _GdkDeviceToolClass
{
GObjectClass parent_class;
};
struct _GdkDeviceKey
{
guint keyval;
@@ -47,6 +61,7 @@ struct _GdkDevice
GdkInputMode mode;
gboolean has_cursor;
gint num_keys;
GdkAxisFlags axis_flags;
GdkDeviceKey *keys;
GdkDeviceManager *manager;
GdkDisplay *display;
@@ -63,6 +78,7 @@ struct _GdkDevice
gchar *product_id;
GdkSeat *seat;
GdkDeviceTool *last_tool;
};
struct _GdkDeviceClass
@@ -183,6 +199,13 @@ GdkWindow * _gdk_device_window_at_position (GdkDevice *device,
void gdk_device_set_seat (GdkDevice *device,
GdkSeat *seat);
/* Device tools */
GdkDeviceTool *gdk_device_tool_new (guint64 serial,
GdkDeviceToolType type,
GdkAxisFlags tool_axes);
void gdk_device_update_tool (GdkDevice *device,
GdkDeviceTool *tool);
G_END_DECLS
#endif /* __GDK_DEVICE_PRIVATE_H__ */

View File

@@ -650,6 +650,7 @@ gdk_event_copy (const GdkEvent *event)
new_private->device = private->device ? g_object_ref (private->device) : NULL;
new_private->source_device = private->source_device ? g_object_ref (private->source_device) : NULL;
new_private->seat = private->seat;
new_private->tool = private->tool;
}
switch (event->any.type)
@@ -2412,3 +2413,54 @@ gdk_event_set_seat (GdkEvent *event,
priv->seat = seat;
}
}
/**
* gdk_event_get_device_tool:
* @event: a #GdkEvent
*
* If the event was generated by a device that supports
* different tools (eg. a tablet), this function will
* return a #GdkDeviceTool representing the tool that
* caused the event. Otherwise, %NULL will be returned.
*
* Note: the #GdkDeviceTool<!-- -->s will be constant during
* the application lifetime, if settings must be stored
* persistently across runs, see gdk_device_tool_get_serial()
*
* Returns: (transfer none): The current device tool, or %NULL
*
* Since: 3.22
**/
GdkDeviceTool *
gdk_event_get_device_tool (const GdkEvent *event)
{
GdkEventPrivate *private;
if (!gdk_event_is_allocated (event))
return NULL;
private = (GdkEventPrivate *) event;
return private->tool;
}
/**
* gdk_event_set_device_tool:
* @event: a #GdkEvent
* @tool: (nullable): tool to set on the event, or %NULL
*
* Sets the device tool for this event, should be rarely used.
*
* Since: 3.22
**/
void
gdk_event_set_device_tool (GdkEvent *event,
GdkDeviceTool *tool)
{
GdkEventPrivate *private;
if (!gdk_event_is_allocated (event))
return;
private = (GdkEventPrivate *) event;
private->tool = tool;
}

View File

@@ -1443,6 +1443,13 @@ GDK_AVAILABLE_IN_ALL
gboolean gdk_setting_get (const gchar *name,
GValue *value);
GDK_AVAILABLE_IN_3_16
GdkDeviceTool *gdk_event_get_device_tool (const GdkEvent *event);
GDK_AVAILABLE_IN_3_16
void gdk_event_set_device_tool (GdkEvent *event,
GdkDeviceTool *tool);
G_END_DECLS
#endif /* __GDK_EVENTS_H__ */

View File

@@ -189,6 +189,7 @@ struct _GdkEventPrivate
GdkDevice *device;
GdkDevice *source_device;
GdkSeat *seat;
GdkDeviceTool *tool;
};
typedef struct _GdkWindowPaint GdkWindowPaint;

View File

@@ -46,6 +46,8 @@ struct _GdkSeatPrivate
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
TOOL_ADDED,
TOOL_REMOVED,
N_SIGNALS
};
@@ -146,6 +148,48 @@ gdk_seat_class_init (GdkSeatClass *klass)
G_TYPE_NONE, 1,
GDK_TYPE_DEVICE);
/**
* GdkSeat::tool-added:
* @seat: the object on which the signal is emitted
* @tool: the new #GdkDeviceTool known to the seat
*
* The ::tool-added signal is emitted whenever a new tool
* is made known to the seat. The tool may later be assigned
* to a device (i.e. on proximity with a tablet). The device
* will emit the #GdkDevice::tool-changed signal accordingly.
*
* A same tool may be used by several devices.
*
* Since: 3.22
*/
signals [TOOL_ADDED] =
g_signal_new (g_intern_static_string ("tool-added"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
GDK_TYPE_DEVICE_TOOL);
/**
* GdkSeat::tool-removed:
* @seat: the object on which the signal is emitted
* @tool: the just removed #GdkDeviceTool
*
* This signal is emitted whenever a tool is no longer known
* to this @seat.
*
* Since: 3.22
*/
signals [TOOL_REMOVED] =
g_signal_new (g_intern_static_string ("tool-removed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
GDK_TYPE_DEVICE_TOOL);
/**
* GdkSeat:display:
*
@@ -388,3 +432,29 @@ gdk_seat_get_display (GdkSeat *seat)
return priv->display;
}
void
gdk_seat_tool_added (GdkSeat *seat,
GdkDeviceTool *tool)
{
g_signal_emit (seat, signals[TOOL_ADDED], 0, tool);
}
void
gdk_seat_tool_removed (GdkSeat *seat,
GdkDeviceTool *tool)
{
g_signal_emit (seat, signals[TOOL_REMOVED], 0, tool);
}
GdkDeviceTool *
gdk_seat_get_tool (GdkSeat *seat,
guint64 serial)
{
GdkSeatClass *seat_class;
g_return_val_if_fail (GDK_IS_SEAT (seat), NULL);
seat_class = GDK_SEAT_GET_CLASS (seat);
return seat_class->get_tool (seat, serial);
}

View File

@@ -29,6 +29,8 @@ struct _GdkSeatDefaultPrivate
GList *slave_pointers;
GList *slave_keyboards;
GdkSeatCapabilities capabilities;
GPtrArray *tools;
};
#define KEYBOARD_EVENTS (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | \
@@ -76,6 +78,12 @@ gdk_seat_dispose (GObject *object)
g_object_unref (l->data);
}
if (priv->tools)
{
g_ptr_array_unref (priv->tools);
priv->tools = NULL;
}
g_list_free (priv->slave_pointers);
g_list_free (priv->slave_keyboards);
priv->slave_pointers = NULL;
@@ -248,6 +256,30 @@ gdk_seat_default_get_slaves (GdkSeat *seat,
return devices;
}
static GdkDeviceTool *
gdk_seat_default_get_tool (GdkSeat *seat,
guint64 serial)
{
GdkSeatDefaultPrivate *priv;
GdkDeviceTool *tool;
guint i;
priv = gdk_seat_default_get_instance_private (GDK_SEAT_DEFAULT (seat));
if (!priv->tools)
return NULL;
for (i = 0; i < priv->tools->len; i++)
{
tool = g_ptr_array_index (priv->tools, i);
if (tool->serial == serial)
return tool;
}
return NULL;
}
static void
gdk_seat_default_class_init (GdkSeatDefaultClass *klass)
{
@@ -263,6 +295,8 @@ gdk_seat_default_class_init (GdkSeatDefaultClass *klass)
seat_class->get_master = gdk_seat_default_get_master;
seat_class->get_slaves = gdk_seat_default_get_slaves;
seat_class->get_tool = gdk_seat_default_get_tool;
}
static void
@@ -355,3 +389,40 @@ gdk_seat_default_remove_slave (GdkSeatDefault *seat,
gdk_seat_device_removed (GDK_SEAT (seat), device);
}
}
void
gdk_seat_default_add_tool (GdkSeatDefault *seat,
GdkDeviceTool *tool)
{
GdkSeatDefaultPrivate *priv;
g_return_if_fail (GDK_IS_SEAT_DEFAULT (seat));
g_return_if_fail (tool != NULL);
priv = gdk_seat_default_get_instance_private (seat);
if (!priv->tools)
priv->tools = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
g_ptr_array_add (priv->tools, g_object_ref (tool));
g_signal_emit_by_name (seat, "tool-added", tool);
}
void
gdk_seat_default_remove_tool (GdkSeatDefault *seat,
GdkDeviceTool *tool)
{
GdkSeatDefaultPrivate *priv;
g_return_if_fail (GDK_IS_SEAT_DEFAULT (seat));
g_return_if_fail (tool != NULL);
priv = gdk_seat_default_get_instance_private (seat);
if (tool != gdk_seat_get_tool (GDK_SEAT (seat),
gdk_device_tool_get_serial (tool)))
return;
g_signal_emit_by_name (seat, "tool-removed", tool);
g_ptr_array_remove (priv->tools, tool);
}

View File

@@ -52,5 +52,9 @@ void gdk_seat_default_add_slave (GdkSeatDefault *seat,
GdkDevice *device);
void gdk_seat_default_remove_slave (GdkSeatDefault *seat,
GdkDevice *device);
void gdk_seat_default_add_tool (GdkSeatDefault *seat,
GdkDeviceTool *tool);
void gdk_seat_default_remove_tool (GdkSeatDefault *seat,
GdkDeviceTool *tool);
#endif /* __GDK_SEAT_DEFAULT_PRIVATE_H__ */

View File

@@ -55,6 +55,9 @@ struct _GdkSeatClass
GdkSeatCapabilities capability);
GList * (* get_slaves) (GdkSeat *seat,
GdkSeatCapabilities capabilities);
GdkDeviceTool * (* get_tool) (GdkSeat *seat,
guint64 serial);
};
void gdk_seat_device_added (GdkSeat *seat,
@@ -62,4 +65,13 @@ void gdk_seat_device_added (GdkSeat *seat,
void gdk_seat_device_removed (GdkSeat *seat,
GdkDevice *device);
void gdk_seat_tool_added (GdkSeat *seat,
GdkDeviceTool *tool);
void gdk_seat_tool_removed (GdkSeat *seat,
GdkDeviceTool *tool);
GdkDeviceTool *
gdk_seat_get_tool (GdkSeat *seat,
guint64 serial);
#endif /* __GDK_SEAT_PRIVATE_H__ */

View File

@@ -9039,6 +9039,7 @@ proxy_pointer_event (GdkDisplay *display,
gdk_event_set_device (event, gdk_event_get_device (source_event));
gdk_event_set_source_device (event, source_device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
gdk_event_set_device_tool (event, gdk_event_get_device_tool (source_event));
if (event_type == GDK_TOUCH_UPDATE)
{
@@ -9280,6 +9281,7 @@ proxy_button_event (GdkEvent *source_event,
gdk_event_set_device (event, gdk_event_get_device (source_event));
gdk_event_set_source_device (event, source_device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
gdk_event_set_device_tool (event, gdk_event_get_device_tool (source_event));
if (is_touch_type (source_event->type))
{

View File

@@ -26,6 +26,8 @@ BUILT_SOURCES = \
xdg-shell-unstable-v5-protocol.c \
gtk-primary-selection-client-protocol.h \
gtk-primary-selection-protocol.c \
tablet-unstable-v1-client-protocol.h \
tablet-unstable-v1-protocol.c \
gtk-shell-client-protocol.h \
gtk-shell-protocol.c

View File

@@ -216,7 +216,7 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
int *hotspot_y,
int *w,
int *h,
int *scale)
int *scale)
{
GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor);

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,7 @@
#include "gdkprivate-wayland.h"
#include "gdkglcontext-wayland.h"
#include "pointer-gestures-unstable-v1-client-protocol.h"
#include "tablet-unstable-v1-client-protocol.h"
/**
* SECTION:wayland_interaction
@@ -418,6 +419,12 @@ gdk_registry_handle_global (void *data,
wl_registry_bind(display_wayland->wl_registry, id,
&gtk_primary_selection_device_manager_interface, 1);
}
else if (strcmp (interface, "zwp_tablet_manager_v1") == 0)
{
display_wayland->tablet_manager =
wl_registry_bind(display_wayland->wl_registry, id,
&zwp_tablet_manager_v1_interface, 1);
}
else
handled = FALSE;

View File

@@ -27,6 +27,7 @@
#include <wayland-client.h>
#include <wayland-cursor.h>
#include <wayland-egl.h>
#include <gdk/wayland/tablet-unstable-v1-client-protocol.h>
#include <gdk/wayland/gtk-shell-client-protocol.h>
#include <gdk/wayland/xdg-shell-unstable-v5-client-protocol.h>
@@ -72,6 +73,7 @@ struct _GdkWaylandDisplay
struct wl_subcompositor *subcompositor;
struct zwp_pointer_gestures_v1 *pointer_gestures;
struct gtk_primary_selection_device_manager *primary_selection_manager;
struct zwp_tablet_manager_v1 *tablet_manager;
GList *async_roundtrips;

View File

@@ -345,13 +345,17 @@ get_device_ids (GdkDisplay *display,
gulong nitems, bytes_after;
guint32 *data;
int rc, format;
Atom type;
Atom prop, type;
gdk_x11_display_error_trap_push (display);
prop = XInternAtom (GDK_DISPLAY_XDISPLAY (display), "Device Product ID", True);
if (prop == None)
return 0;
rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
info->deviceid,
gdk_x11_get_xatom_by_name_for_display (display, "Device Product ID"),
info->deviceid, prop,
0, 2, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
(guchar **) &data);
gdk_x11_display_error_trap_pop_ignored (display);
@@ -726,6 +730,7 @@ gdk_x11_device_manager_xi2_constructed (GObject *object)
screen = gdk_display_get_default_screen (display);
XISetMask (mask, XI_HierarchyChanged);
XISetMask (mask, XI_DeviceChanged);
XISetMask (mask, XI_PropertyEvent);
event_mask.deviceid = XIAllDevices;
event_mask.mask_len = sizeof (mask);
@@ -966,6 +971,111 @@ handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
}
static guint
device_get_tool_serial (GdkDevice *device)
{
GdkDisplay *display;
gulong nitems, bytes_after;
guint serial_id = 0;
guint32 *data;
int rc, format;
Atom type;
display = gdk_device_get_display (device);
gdk_x11_display_error_trap_push (display);
rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
gdk_x11_device_get_id (device),
gdk_x11_get_xatom_by_name_for_display (display, "Wacom Serial IDs"),
0, 4, False, XA_INTEGER, &type, &format, &nitems, &bytes_after,
(guchar **) &data);
gdk_x11_display_error_trap_pop_ignored (display);
if (rc != Success)
return 0;
if (type == XA_INTEGER && format == 32 && nitems >= 4)
serial_id = data[3];
XFree (data);
return serial_id;
}
static void
translate_proximity (GdkDevice *device,
GdkDeviceTool *tool,
GdkEvent *event,
XIPropertyEvent *ev)
{
GdkDevice *master = NULL;
GdkWindow *window;
if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
master = gdk_device_get_associated_device (device);
if (!master)
master = device;
window = gdk_device_get_window_at_position (master, NULL, NULL);
if (!window)
return;
event->proximity.type = tool ? GDK_PROXIMITY_IN : GDK_PROXIMITY_OUT;
event->proximity.window = window;
event->proximity.time = ev->time;
event->proximity.send_event = FALSE;
gdk_event_set_device (event, master);
gdk_event_set_source_device (event, device);
}
static gboolean
handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
XIPropertyEvent *ev,
GdkEvent *event)
{
GdkDisplay *display;
GdkDevice *device;
Atom wacom_serial_prop;
device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (ev->deviceid));
display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
wacom_serial_prop = XInternAtom (GDK_DISPLAY_XDISPLAY (display),
"Wacom Serial IDs", True);
if (wacom_serial_prop != None && ev->property == wacom_serial_prop)
{
GdkDeviceTool *tool = NULL;
guint serial_id;
GdkSeat *seat;
if (ev->what != XIPropertyDeleted)
{
serial_id = device_get_tool_serial (device);
seat = gdk_device_get_seat (device);
tool = gdk_seat_get_tool (seat, serial_id);
if (!tool && serial_id > 0)
{
tool = gdk_device_tool_new (serial_id,
GDK_DEVICE_TOOL_TYPE_UNKNOWN, 0);
gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
}
}
gdk_device_update_tool (device, tool);
translate_proximity (device, tool, event, ev);
return TRUE;
}
return FALSE;
}
static GdkCrossingMode
translate_crossing_mode (gint mode)
{
@@ -1366,6 +1476,12 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
(XIDeviceChangedEvent *) ev);
return_val = FALSE;
break;
case XI_PropertyEvent:
if (!handle_property_change (device_manager,
(XIPropertyEvent *) ev,
event))
return_val = FALSE;
break;
case XI_KeyPress:
case XI_KeyRelease:
{
@@ -1508,6 +1624,7 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
GUINT_TO_POINTER (xev->sourceid));
gdk_event_set_source_device (event, source_device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
gdk_event_set_device_tool (event, source_device->last_tool);
event->button.axes = translate_axes (event->button.device,
event->button.x,
@@ -1616,6 +1733,7 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
event->motion.device = device;
gdk_event_set_source_device (event, source_device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
gdk_event_set_device_tool (event, source_device->last_tool);
event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);