Compare commits
69 Commits
3.24.3
...
wip/tablet
Author | SHA1 | Date | |
---|---|---|---|
ec5d127cd2 | |||
1c1785ea6e | |||
aef997f7a1 | |||
27477cbd30 | |||
ed73efa63f | |||
98f26bf01a | |||
edda88a7dd | |||
5815259897 | |||
1f7c7bdeaa | |||
05a5c86203 | |||
c90d7a373b | |||
6225cc6e60 | |||
4c4b40d468 | |||
02ce6c5865 | |||
522989494f | |||
ab851fc6e5 | |||
185eabd3e3 | |||
67f5b89659 | |||
c7e0b87d7e | |||
ec50fcd320 | |||
982802d66c | |||
0dcca308e7 | |||
b68247d51e | |||
499851d404 | |||
ef113d708b | |||
e2b8b0bf67 | |||
ec2ab05d8e | |||
69955471fc | |||
e59a32afa5 | |||
1c0b063855 | |||
0cd46afa8f | |||
c73cc5138b | |||
f51972c2aa | |||
f81e0f8922 | |||
1bf263f038 | |||
257b16680f | |||
ed6eb8c94b | |||
95181bdbaa | |||
59be5bf3b1 | |||
7f8932b489 | |||
f2feb6d53d | |||
47067e6d17 | |||
3386e5dc39 | |||
384400cd24 | |||
be9997c717 | |||
d3be071196 | |||
de704e591b | |||
a14f0edcae | |||
bf5324a339 | |||
9855ff010a | |||
6bd06cf40b | |||
01fd218e17 | |||
f8c0301ecc | |||
2354643d55 | |||
c1d1477c64 | |||
04629d2bc2 | |||
c789459a31 | |||
2f7602f297 | |||
d5459427d5 | |||
379c6fb81a | |||
fc5af32cdc | |||
b71d7058db | |||
1d9d176c3f | |||
cd911584eb | |||
2ff629a984 | |||
b0a3c472ea | |||
7ecbca6291 | |||
780c66fa73 | |||
ffa991d422 |
@ -131,9 +131,16 @@ struct _ClutterInputDevice
|
||||
|
||||
gchar *vendor_id;
|
||||
gchar *product_id;
|
||||
gchar *node_path;
|
||||
|
||||
GPtrArray *tools;
|
||||
|
||||
gint n_rings;
|
||||
gint n_strips;
|
||||
gint n_mode_groups;
|
||||
|
||||
ClutterInputDeviceMapping mapping_mode;
|
||||
|
||||
guint has_cursor : 1;
|
||||
guint is_enabled : 1;
|
||||
};
|
||||
|
@ -794,6 +794,10 @@ typedef enum { /*< prefix=CLUTTER >*/
|
||||
CLUTTER_TOUCHPAD_SWIPE,
|
||||
CLUTTER_PROXIMITY_IN,
|
||||
CLUTTER_PROXIMITY_OUT,
|
||||
CLUTTER_PAD_BUTTON_PRESS,
|
||||
CLUTTER_PAD_BUTTON_RELEASE,
|
||||
CLUTTER_PAD_STRIP,
|
||||
CLUTTER_PAD_RING,
|
||||
|
||||
CLUTTER_EVENT_LAST /* helper */
|
||||
} ClutterEventType;
|
||||
@ -900,6 +904,7 @@ typedef enum { /*< prefix=CLUTTER_FLOW >*/
|
||||
* @CLUTTER_PEN_DEVICE: A pen device
|
||||
* @CLUTTER_ERASER_DEVICE: An eraser device
|
||||
* @CLUTTER_CURSOR_DEVICE: A cursor device
|
||||
* @CLUTTER_PAD_DEVICE: A tablet pad
|
||||
* @CLUTTER_N_DEVICE_TYPES: The number of device types
|
||||
*
|
||||
* The types of input devices available.
|
||||
@ -920,6 +925,7 @@ typedef enum {
|
||||
CLUTTER_PEN_DEVICE,
|
||||
CLUTTER_ERASER_DEVICE,
|
||||
CLUTTER_CURSOR_DEVICE,
|
||||
CLUTTER_PAD_DEVICE,
|
||||
|
||||
CLUTTER_N_DEVICE_TYPES
|
||||
} ClutterInputDeviceType;
|
||||
@ -1520,6 +1526,16 @@ typedef enum {
|
||||
CLUTTER_INPUT_DEVICE_TOOL_LENS
|
||||
} ClutterInputDeviceToolType;
|
||||
|
||||
typedef enum {
|
||||
CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN,
|
||||
CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER,
|
||||
} ClutterInputDevicePadSource;
|
||||
|
||||
typedef enum {
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE,
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE,
|
||||
} ClutterInputDeviceMapping;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ENUMS_H__ */
|
||||
|
@ -413,6 +413,10 @@ clutter_event_get_position (const ClutterEvent *event,
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
clutter_point_init (position, 0.f, 0.f);
|
||||
break;
|
||||
|
||||
@ -483,6 +487,10 @@ clutter_event_set_coords (ClutterEvent *event,
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
@ -811,9 +819,15 @@ clutter_event_get_button (const ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event != NULL, 0);
|
||||
g_return_val_if_fail (event->type == CLUTTER_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_BUTTON_RELEASE, 0);
|
||||
event->type == CLUTTER_BUTTON_RELEASE ||
|
||||
event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE, 0);
|
||||
|
||||
return event->button.button;
|
||||
if (event->type == CLUTTER_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_BUTTON_RELEASE)
|
||||
return event->button.button;
|
||||
else
|
||||
return event->pad_button.button;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1133,6 +1147,19 @@ clutter_event_set_device (ClutterEvent *event,
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
event->proximity.device = device;
|
||||
break;
|
||||
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
event->pad_button.device = device;
|
||||
break;
|
||||
|
||||
case CLUTTER_PAD_STRIP:
|
||||
event->pad_strip.device = device;
|
||||
break;
|
||||
|
||||
case CLUTTER_PAD_RING:
|
||||
event->pad_ring.device = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1217,6 +1244,19 @@ clutter_event_get_device (const ClutterEvent *event)
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
device = event->proximity.device;
|
||||
break;
|
||||
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
device = event->pad_button.device;
|
||||
break;
|
||||
|
||||
case CLUTTER_PAD_STRIP:
|
||||
device = event->pad_strip.device;
|
||||
break;
|
||||
|
||||
case CLUTTER_PAD_RING:
|
||||
device = event->pad_ring.device;
|
||||
break;
|
||||
}
|
||||
|
||||
return device;
|
||||
@ -1708,6 +1748,10 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
|
||||
case CLUTTER_TOUCHPAD_PINCH:
|
||||
case CLUTTER_TOUCHPAD_SWIPE:
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2108,3 +2152,24 @@ clutter_event_get_scroll_finish_flags (const ClutterEvent *event)
|
||||
|
||||
return event->scroll.finish_flags;
|
||||
}
|
||||
|
||||
guint
|
||||
clutter_event_get_mode_group (const ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE ||
|
||||
event->type == CLUTTER_PAD_RING ||
|
||||
event->type == CLUTTER_PAD_STRIP, 0);
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
return event->pad_button.group;
|
||||
case CLUTTER_PAD_RING:
|
||||
return event->pad_ring.group;
|
||||
case CLUTTER_PAD_STRIP:
|
||||
return event->pad_strip.group;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +118,9 @@ typedef struct _ClutterTouchEvent ClutterTouchEvent;
|
||||
typedef struct _ClutterTouchpadPinchEvent ClutterTouchpadPinchEvent;
|
||||
typedef struct _ClutterTouchpadSwipeEvent ClutterTouchpadSwipeEvent;
|
||||
typedef struct _ClutterProximityEvent ClutterProximityEvent;
|
||||
typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent;
|
||||
typedef struct _ClutterPadStripEvent ClutterPadStripEvent;
|
||||
typedef struct _ClutterPadRingEvent ClutterPadRingEvent;
|
||||
|
||||
/**
|
||||
* ClutterAnyEvent:
|
||||
@ -493,6 +496,49 @@ struct _ClutterTouchpadSwipeEvent
|
||||
gfloat dy;
|
||||
};
|
||||
|
||||
struct _ClutterPadButtonEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
|
||||
guint32 button;
|
||||
guint32 group;
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
struct _ClutterPadStripEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDevicePadSource strip_source;
|
||||
guint32 strip_number;
|
||||
guint32 group;
|
||||
gdouble value;
|
||||
};
|
||||
|
||||
struct _ClutterPadRingEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDevicePadSource ring_source;
|
||||
guint32 ring_number;
|
||||
guint32 group;
|
||||
gdouble angle;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterEvent:
|
||||
*
|
||||
@ -516,6 +562,9 @@ union _ClutterEvent
|
||||
ClutterTouchpadPinchEvent touchpad_pinch;
|
||||
ClutterTouchpadSwipeEvent touchpad_swipe;
|
||||
ClutterProximityEvent proximity;
|
||||
ClutterPadButtonEvent pad_button;
|
||||
ClutterPadStripEvent pad_strip;
|
||||
ClutterPadRingEvent pad_ring;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -722,6 +771,10 @@ void clutter_event_get_gesture_motion_delta (const Clut
|
||||
ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event);
|
||||
ClutterScrollFinishFlags clutter_event_get_scroll_finish_flags (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
guint clutter_event_get_mode_group (const ClutterEvent *event);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_EVENT_H__ */
|
||||
|
@ -34,12 +34,14 @@ struct _ClutterInputDeviceToolPrivate
|
||||
{
|
||||
ClutterInputDeviceToolType type;
|
||||
guint64 serial;
|
||||
guint64 id;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_TYPE,
|
||||
PROP_SERIAL,
|
||||
PROP_ID,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -66,6 +68,9 @@ clutter_input_device_tool_set_property (GObject *object,
|
||||
case PROP_SERIAL:
|
||||
priv->serial = g_value_get_uint64 (value);
|
||||
break;
|
||||
case PROP_ID:
|
||||
priv->id = g_value_get_uint64 (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@ -90,6 +95,9 @@ clutter_input_device_tool_get_property (GObject *object,
|
||||
case PROP_SERIAL:
|
||||
g_value_set_uint64 (value, priv->serial);
|
||||
break;
|
||||
case PROP_ID:
|
||||
g_value_set_uint64 (value, priv->id);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@ -116,6 +124,12 @@ clutter_input_device_tool_class_init (ClutterInputDeviceToolClass *klass)
|
||||
P_("Tool serial"),
|
||||
0, G_MAXUINT64, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
props[PROP_ID] =
|
||||
g_param_spec_uint64 ("id",
|
||||
P_("Tool ID"),
|
||||
P_("Tool ID"),
|
||||
0, G_MAXUINT64, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, props);
|
||||
}
|
||||
@ -136,7 +150,7 @@ clutter_input_device_tool_init (ClutterInputDeviceTool *tool)
|
||||
*
|
||||
* Since: 1.28
|
||||
**/
|
||||
guint
|
||||
guint64
|
||||
clutter_input_device_tool_get_serial (ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterInputDeviceToolPrivate *priv;
|
||||
@ -170,3 +184,24 @@ clutter_input_device_tool_get_tool_type (ClutterInputDeviceTool *tool)
|
||||
|
||||
return priv->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_tool_get_id:
|
||||
* @tool: a #ClutterInputDeviceTool
|
||||
*
|
||||
* Gets the ID of this tool, this value can be used to identify a
|
||||
* physical tool (eg. a tablet pen) across program executions.
|
||||
*
|
||||
* Returns: The tool ID for this tool
|
||||
**/
|
||||
guint64
|
||||
clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterInputDeviceToolPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), 0);
|
||||
|
||||
priv = clutter_input_device_tool_get_instance_private (tool);
|
||||
|
||||
return priv->id;
|
||||
}
|
||||
|
@ -56,11 +56,14 @@ CLUTTER_AVAILABLE_IN_ALL
|
||||
GType clutter_input_device_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
guint clutter_input_device_tool_get_serial (ClutterInputDeviceTool *tool);
|
||||
guint64 clutter_input_device_tool_get_serial (ClutterInputDeviceTool *tool);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
ClutterInputDeviceToolType clutter_input_device_tool_get_tool_type (ClutterInputDeviceTool *tool);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
guint64 clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_TOOL_H__ */
|
||||
|
@ -70,6 +70,12 @@ enum
|
||||
PROP_VENDOR_ID,
|
||||
PROP_PRODUCT_ID,
|
||||
|
||||
PROP_N_STRIPS,
|
||||
PROP_N_RINGS,
|
||||
PROP_N_MODE_GROUPS,
|
||||
PROP_DEVICE_NODE,
|
||||
PROP_MAPPING_MODE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -195,6 +201,26 @@ clutter_input_device_set_property (GObject *gobject,
|
||||
self->product_id = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_N_RINGS:
|
||||
self->n_rings = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_N_STRIPS:
|
||||
self->n_strips = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_N_MODE_GROUPS:
|
||||
self->n_mode_groups = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_DEVICE_NODE:
|
||||
self->node_path = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_MAPPING_MODE:
|
||||
self->mapping_mode = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@ -255,6 +281,26 @@ clutter_input_device_get_property (GObject *gobject,
|
||||
g_value_set_string (value, self->product_id);
|
||||
break;
|
||||
|
||||
case PROP_N_RINGS:
|
||||
g_value_set_int (value, self->n_rings);
|
||||
break;
|
||||
|
||||
case PROP_N_STRIPS:
|
||||
g_value_set_int (value, self->n_strips);
|
||||
break;
|
||||
|
||||
case PROP_N_MODE_GROUPS:
|
||||
g_value_set_int (value, self->n_mode_groups);
|
||||
break;
|
||||
|
||||
case PROP_DEVICE_NODE:
|
||||
g_value_set_string (value, self->node_path);
|
||||
break;
|
||||
|
||||
case PROP_MAPPING_MODE:
|
||||
g_value_set_enum (value, self->mapping_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@ -432,6 +478,42 @@ clutter_input_device_class_init (ClutterInputDeviceClass *klass)
|
||||
NULL,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
obj_props[PROP_N_RINGS] =
|
||||
g_param_spec_int ("n-rings",
|
||||
P_("Number of rings"),
|
||||
P_("Number of rings (circular sliders) in this device"),
|
||||
0, G_MAXINT, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
obj_props[PROP_N_STRIPS] =
|
||||
g_param_spec_int ("n-strips",
|
||||
P_("Number of strips"),
|
||||
P_("Number of strips (linear sliders) in this device"),
|
||||
0, G_MAXINT, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
obj_props[PROP_N_MODE_GROUPS] =
|
||||
g_param_spec_int ("n-mode-groups",
|
||||
P_("Number of mode groups"),
|
||||
P_("Number of mode groups"),
|
||||
0, G_MAXINT, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
obj_props[PROP_DEVICE_NODE] =
|
||||
g_param_spec_string ("device-node",
|
||||
P_("Device node path"),
|
||||
P_("Device node path"),
|
||||
NULL,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
obj_props[PROP_MAPPING_MODE] =
|
||||
g_param_spec_enum ("mapping-mode",
|
||||
P_("Device mapping mode"),
|
||||
P_("Device mapping mode"),
|
||||
CLUTTER_TYPE_INPUT_DEVICE_MAPPING,
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
|
||||
gobject_class->dispose = clutter_input_device_dispose;
|
||||
gobject_class->set_property = clutter_input_device_set_property;
|
||||
gobject_class->get_property = clutter_input_device_get_property;
|
||||
@ -2066,3 +2148,64 @@ clutter_input_device_update_from_tool (ClutterInputDevice *device,
|
||||
if (device_class->update_from_tool)
|
||||
device_class->update_from_tool (device, tool);
|
||||
}
|
||||
|
||||
gint
|
||||
clutter_input_device_get_n_rings (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
|
||||
|
||||
return device->n_rings;
|
||||
}
|
||||
|
||||
gint
|
||||
clutter_input_device_get_n_strips (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
|
||||
|
||||
return device->n_strips;
|
||||
}
|
||||
|
||||
gint
|
||||
clutter_input_device_get_n_mode_groups (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (device) ==
|
||||
CLUTTER_PAD_DEVICE, 0);
|
||||
|
||||
return device->n_mode_groups;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
clutter_input_device_get_device_node (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
|
||||
return device->node_path;
|
||||
}
|
||||
|
||||
ClutterInputDeviceMapping
|
||||
clutter_input_device_get_mapping_mode (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (device) ==
|
||||
CLUTTER_TABLET_DEVICE,
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE);
|
||||
|
||||
return device->mapping_mode;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_device_set_mapping_mode (ClutterInputDevice *device,
|
||||
ClutterInputDeviceMapping mapping)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
g_return_if_fail (clutter_input_device_get_device_type (device) ==
|
||||
CLUTTER_TABLET_DEVICE);
|
||||
|
||||
if (device->mapping_mode == mapping)
|
||||
return;
|
||||
|
||||
device->mapping_mode = mapping;
|
||||
g_object_notify (G_OBJECT (device), "mapping-mode");
|
||||
}
|
||||
|
@ -140,6 +140,23 @@ const gchar * clutter_input_device_get_vendor_id (ClutterInputDev
|
||||
CLUTTER_AVAILABLE_IN_1_22
|
||||
const gchar * clutter_input_device_get_product_id (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
gint clutter_input_device_get_n_rings (ClutterInputDevice *device);
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
gint clutter_input_device_get_n_strips (ClutterInputDevice *device);
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
gint clutter_input_device_get_n_mode_groups (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
const gchar * clutter_input_device_get_device_node (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
ClutterInputDeviceMapping clutter_input_device_get_mapping_mode (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_input_device_set_mapping_mode (ClutterInputDevice *device,
|
||||
ClutterInputDeviceMapping mapping);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_H__ */
|
||||
|
@ -2163,6 +2163,10 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
{
|
||||
ClutterActor *actor = NULL;
|
||||
|
||||
|
@ -183,6 +183,7 @@ static const char *device_type_str[] = {
|
||||
"pen", /* CLUTTER_PEN_DEVICE */
|
||||
"eraser", /* CLUTTER_ERASER_DEVICE */
|
||||
"cursor", /* CLUTTER_CURSOR_DEVICE */
|
||||
"pad", /* CLUTTER_PAD_DEVICE */
|
||||
};
|
||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
@ -549,6 +550,24 @@ notify_relative_motion (ClutterInputDevice *input_device,
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_relative_tool_motion (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
gfloat dx,
|
||||
gfloat dy,
|
||||
gdouble *axes)
|
||||
{
|
||||
ClutterEvent *event;
|
||||
gfloat x, y;
|
||||
|
||||
x = input_device->current_x + dx;
|
||||
y = input_device->current_y + dy;
|
||||
event = new_absolute_motion_event (input_device, time_us, x, y, axes);
|
||||
_clutter_evdev_event_set_relative_motion (event, dx, dy, 0, 0);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static ClutterScrollDirection
|
||||
discrete_to_direction (gdouble discrete_x,
|
||||
gdouble discrete_y)
|
||||
@ -949,6 +968,133 @@ notify_proximity (ClutterInputDevice *input_device,
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_pad_button (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
guint32 button,
|
||||
guint32 mode_group,
|
||||
guint32 pressed)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event;
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
stage = _clutter_input_device_get_stage (input_device);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
if (pressed)
|
||||
event = clutter_event_new (CLUTTER_PAD_BUTTON_PRESS);
|
||||
else
|
||||
event = clutter_event_new (CLUTTER_PAD_BUTTON_RELEASE);
|
||||
|
||||
device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
event->pad_button.stage = stage;
|
||||
event->pad_button.button = button;
|
||||
event->pad_button.group = mode_group;
|
||||
clutter_event_set_device (event, input_device);
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
clutter_event_set_time (event, us2ms (time_us));
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_pad_strip (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
guint32 strip_number,
|
||||
guint32 strip_source,
|
||||
guint32 mode_group,
|
||||
gdouble value)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
ClutterInputDevicePadSource source;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event;
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
stage = _clutter_input_device_get_stage (input_device);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
if (strip_source == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER)
|
||||
source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER;
|
||||
else
|
||||
source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN;
|
||||
|
||||
device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
event = clutter_event_new (CLUTTER_PAD_STRIP);
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
event->pad_strip.strip_source = source;
|
||||
event->pad_strip.stage = stage;
|
||||
event->pad_strip.strip_number = strip_number;
|
||||
event->pad_strip.value = value;
|
||||
event->pad_strip.group = mode_group;
|
||||
clutter_event_set_device (event, input_device);
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
clutter_event_set_time (event, us2ms (time_us));
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_pad_ring (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
guint32 ring_number,
|
||||
guint32 ring_source,
|
||||
guint32 mode_group,
|
||||
gdouble angle)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
ClutterInputDevicePadSource source;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event;
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
stage = _clutter_input_device_get_stage (input_device);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
if (ring_source == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER)
|
||||
source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER;
|
||||
else
|
||||
source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN;
|
||||
|
||||
device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
event = clutter_event_new (CLUTTER_PAD_RING);
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
event->pad_ring.ring_source = source;
|
||||
event->pad_ring.stage = stage;
|
||||
event->pad_ring.ring_number = ring_number;
|
||||
event->pad_ring.angle = angle;
|
||||
event->pad_ring.group = mode_group;
|
||||
clutter_event_set_device (event, input_device);
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
clutter_event_set_time (event, us2ms (time_us));
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_libinput (ClutterDeviceManagerEvdev *manager_evdev)
|
||||
{
|
||||
@ -2009,12 +2155,15 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||
{
|
||||
guint64 time;
|
||||
double x, y, *axes;
|
||||
double x, y, dx, dy, *axes;
|
||||
gfloat stage_width, stage_height;
|
||||
ClutterStage *stage;
|
||||
struct libinput_event_tablet_tool *tablet_event =
|
||||
libinput_event_get_tablet_tool_event (event);
|
||||
ClutterInputDeviceEvdev *evdev_device;
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (device);
|
||||
|
||||
stage = _clutter_input_device_get_stage (device);
|
||||
if (!stage)
|
||||
@ -2028,10 +2177,22 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
|
||||
|
||||
time = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
x = libinput_event_tablet_tool_get_x_transformed (tablet_event, stage_width);
|
||||
y = libinput_event_tablet_tool_get_y_transformed (tablet_event, stage_height);
|
||||
|
||||
notify_absolute_motion (device, time, x, y, axes);
|
||||
if (clutter_input_device_get_mapping_mode (device) == CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE ||
|
||||
clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_MOUSE ||
|
||||
clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_LENS)
|
||||
{
|
||||
dx = libinput_event_tablet_tool_get_dx (tablet_event);
|
||||
dy = libinput_event_tablet_tool_get_dy (tablet_event);
|
||||
notify_relative_tool_motion (device, time, dx, dy, axes);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = libinput_event_tablet_tool_get_x_transformed (tablet_event, stage_width);
|
||||
y = libinput_event_tablet_tool_get_y_transformed (tablet_event, stage_height);
|
||||
notify_absolute_motion (device, time, x, y, axes);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
|
||||
@ -2084,6 +2245,68 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
notify_button (device, time, BTN_TOUCH, button_state);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
{
|
||||
guint64 time;
|
||||
guint32 button_state, button, group;
|
||||
struct libinput_tablet_pad_mode_group *mode_group;
|
||||
struct libinput_event_tablet_pad *pad_event =
|
||||
libinput_event_get_tablet_pad_event (event);
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time = libinput_event_tablet_pad_get_time_usec (pad_event);
|
||||
|
||||
mode_group = libinput_event_tablet_pad_get_mode_group (pad_event);
|
||||
group = libinput_tablet_pad_mode_group_get_index (mode_group);
|
||||
|
||||
button = libinput_event_tablet_pad_get_button_number (pad_event);
|
||||
button_state = libinput_event_tablet_pad_get_button_state (pad_event) ==
|
||||
LIBINPUT_BUTTON_STATE_PRESSED;
|
||||
notify_pad_button (device, time, button, group, button_state);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
|
||||
{
|
||||
guint64 time;
|
||||
guint32 number, source, group;
|
||||
struct libinput_tablet_pad_mode_group *mode_group;
|
||||
struct libinput_event_tablet_pad *pad_event =
|
||||
libinput_event_get_tablet_pad_event (event);
|
||||
gdouble value;
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time = libinput_event_tablet_pad_get_time_usec (pad_event);
|
||||
number = libinput_event_tablet_pad_get_strip_number (pad_event);
|
||||
value = libinput_event_tablet_pad_get_strip_position (pad_event);
|
||||
source = libinput_event_tablet_pad_get_strip_source (pad_event);
|
||||
|
||||
mode_group = libinput_event_tablet_pad_get_mode_group (pad_event);
|
||||
group = libinput_tablet_pad_mode_group_get_index (mode_group);
|
||||
|
||||
notify_pad_strip (device, time, number, source, group, value);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_PAD_RING:
|
||||
{
|
||||
guint64 time;
|
||||
guint32 number, source, group;
|
||||
struct libinput_tablet_pad_mode_group *mode_group;
|
||||
struct libinput_event_tablet_pad *pad_event =
|
||||
libinput_event_get_tablet_pad_event (event);
|
||||
gdouble angle;
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time = libinput_event_tablet_pad_get_time_usec (pad_event);
|
||||
number = libinput_event_tablet_pad_get_ring_number (pad_event);
|
||||
angle = libinput_event_tablet_pad_get_ring_position (pad_event);
|
||||
source = libinput_event_tablet_pad_get_ring_source (pad_event);
|
||||
|
||||
mode_group = libinput_event_tablet_pad_get_mode_group (pad_event);
|
||||
group = libinput_tablet_pad_mode_group_get_index (mode_group);
|
||||
|
||||
notify_pad_ring (device, time, number, source, group, angle);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
handled = FALSE;
|
||||
}
|
||||
|
@ -141,13 +141,24 @@ _clutter_input_device_evdev_new (ClutterDeviceManager *manager,
|
||||
ClutterInputDeviceType type;
|
||||
ClutterDeviceManagerEvdev *manager_evdev;
|
||||
gchar *vendor, *product;
|
||||
gint device_id;
|
||||
gint device_id, n_rings = 0, n_strips = 0, n_groups = 1;
|
||||
gchar *node_path;
|
||||
|
||||
type = _clutter_input_device_evdev_determine_type (libinput_device);
|
||||
vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device));
|
||||
product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device));
|
||||
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
||||
device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev);
|
||||
node_path = g_strdup_printf ("/dev/input/%s", libinput_device_get_sysname (libinput_device));
|
||||
|
||||
if (libinput_device_has_capability (libinput_device,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
||||
{
|
||||
n_rings = libinput_device_tablet_pad_get_num_rings (libinput_device);
|
||||
n_strips = libinput_device_tablet_pad_get_num_strips (libinput_device);
|
||||
n_groups = libinput_device_tablet_pad_get_num_mode_groups (libinput_device);
|
||||
}
|
||||
|
||||
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV,
|
||||
"id", device_id,
|
||||
"name", libinput_device_get_name (libinput_device),
|
||||
@ -157,6 +168,10 @@ _clutter_input_device_evdev_new (ClutterDeviceManager *manager,
|
||||
"enabled", TRUE,
|
||||
"vendor-id", vendor,
|
||||
"product-id", product,
|
||||
"n-rings", n_rings,
|
||||
"n-strips", n_strips,
|
||||
"n-mode-groups", n_groups,
|
||||
"device-node", node_path,
|
||||
NULL);
|
||||
|
||||
device->seat = seat;
|
||||
@ -243,6 +258,8 @@ _clutter_input_device_evdev_determine_type (struct libinput_device *ldev)
|
||||
return CLUTTER_TOUCHPAD_DEVICE;
|
||||
else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_TOOL))
|
||||
return CLUTTER_TABLET_DEVICE;
|
||||
else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
||||
return CLUTTER_PAD_DEVICE;
|
||||
else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_POINTER))
|
||||
return CLUTTER_POINTER_DEVICE;
|
||||
else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
|
@ -63,6 +63,7 @@ clutter_input_device_tool_evdev_new (struct libinput_tablet_tool *tool,
|
||||
evdev_tool = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV,
|
||||
"type", type,
|
||||
"serial", serial,
|
||||
"id", libinput_tablet_tool_get_tool_id (tool),
|
||||
NULL);
|
||||
|
||||
evdev_tool->tool = libinput_tablet_tool_ref (tool);
|
||||
|
@ -321,6 +321,42 @@ get_device_ids (ClutterBackendX11 *backend_x11,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_device_node_path (ClutterBackendX11 *backend_x11,
|
||||
XIDeviceInfo *info)
|
||||
{
|
||||
gulong nitems, bytes_after;
|
||||
guchar *data;
|
||||
int rc, format;
|
||||
Atom prop, type;
|
||||
gchar *node_path;
|
||||
|
||||
prop = XInternAtom (backend_x11->xdpy, "Device Node", False);
|
||||
if (prop == None)
|
||||
return NULL;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
rc = XIGetProperty (backend_x11->xdpy,
|
||||
info->deviceid, prop, 0, 1024, False,
|
||||
XA_STRING, &type, &format, &nitems, &bytes_after,
|
||||
(guchar **) &data);
|
||||
|
||||
if (clutter_x11_untrap_x_errors ())
|
||||
return NULL;
|
||||
|
||||
if (rc != Success || type != XA_STRING || format != 8)
|
||||
{
|
||||
XFree (data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
node_path = g_strdup ((char *) data);
|
||||
XFree (data);
|
||||
|
||||
return node_path;
|
||||
}
|
||||
|
||||
static ClutterInputDevice *
|
||||
create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
ClutterBackendX11 *backend_x11,
|
||||
@ -331,7 +367,7 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
ClutterInputMode mode;
|
||||
gboolean is_enabled;
|
||||
guint num_touches = 0;
|
||||
gchar *vendor_id = NULL, *product_id = NULL;
|
||||
gchar *vendor_id = NULL, *product_id = NULL, *node_path = NULL;
|
||||
|
||||
if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
|
||||
{
|
||||
@ -391,7 +427,10 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
|
||||
if (info->use != XIMasterKeyboard &&
|
||||
info->use != XIMasterPointer)
|
||||
get_device_ids (backend_x11, info, &vendor_id, &product_id);
|
||||
{
|
||||
get_device_ids (backend_x11, info, &vendor_id, &product_id);
|
||||
node_path = get_device_node_path (backend_x11, info);
|
||||
}
|
||||
|
||||
retval = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_XI2,
|
||||
"name", info->name,
|
||||
@ -404,6 +443,7 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
"enabled", is_enabled,
|
||||
"vendor-id", vendor_id,
|
||||
"product-id", product_id,
|
||||
"device-node", node_path,
|
||||
NULL);
|
||||
|
||||
translate_device_classes (backend_x11->xdpy, retval,
|
||||
|
26
configure.ac
26
configure.ac
@ -59,6 +59,8 @@ AM_PATH_GLIB_2_0([2.49.0])
|
||||
CANBERRA_GTK=libcanberra-gtk3
|
||||
CANBERRA_GTK_VERSION=0.26
|
||||
|
||||
LIBWACOM_VERSION=0.19
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.19.8
|
||||
gio-unix-2.0 >= 2.35.1
|
||||
@ -109,6 +111,11 @@ AC_ARG_WITH(libcanberra,
|
||||
[disable the use of libcanberra for playing sounds]),,
|
||||
with_libcanberra=auto)
|
||||
|
||||
AC_ARG_WITH(libwacom,
|
||||
AC_HELP_STRING([--without-libwacom],
|
||||
[disable the use of libwacom for advanced tablet management]),,
|
||||
with_libwacom=auto)
|
||||
|
||||
AC_ARG_WITH([xwayland-path],
|
||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||
[XWAYLAND_PATH="$withval"],
|
||||
@ -170,6 +177,24 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
have_libwacom=no
|
||||
AC_MSG_CHECKING([libwacom])
|
||||
if test x$with_libwacom = xno ; then
|
||||
AC_MSG_RESULT([disabled])
|
||||
else
|
||||
if $PKG_CONFIG --exists libwacom '>=' $LIBWACOM_VERSION; then
|
||||
have_libwacom=yes
|
||||
AC_MSG_RESULT(yes)
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES libwacom"
|
||||
AC_DEFINE([HAVE_LIBWACOM], 1, [Building with libwacom for advanced tablet management])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test x$with_libwacom = xyes ; then
|
||||
AC_MSG_ERROR([libwacom forced but not found])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
INTROSPECTION_VERSION=0.9.5
|
||||
GOBJECT_INTROSPECTION_CHECK([$INTROSPECTION_VERSION])
|
||||
|
||||
@ -423,6 +448,7 @@ mutter-$VERSION
|
||||
|
||||
Startup notification: ${have_startup_notification}
|
||||
libcanberra: ${have_libcanberra}
|
||||
libwacom: ${have_libwacom}
|
||||
Introspection: ${found_introspection}
|
||||
Session management: ${found_sm}
|
||||
Wayland: ${have_wayland}
|
||||
|
@ -67,8 +67,8 @@ mutter_built_sources += \
|
||||
relative-pointer-unstable-v1-server-protocol.h \
|
||||
pointer-constraints-unstable-v1-protocol.c \
|
||||
pointer-constraints-unstable-v1-server-protocol.h \
|
||||
tablet-unstable-v1-protocol.c \
|
||||
tablet-unstable-v1-server-protocol.h \
|
||||
tablet-unstable-v2-protocol.c \
|
||||
tablet-unstable-v2-server-protocol.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
@ -317,12 +317,22 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-tablet-seat.h \
|
||||
wayland/meta-wayland-tablet-tool.c \
|
||||
wayland/meta-wayland-tablet-tool.h \
|
||||
wayland/meta-wayland-tablet-pad.c \
|
||||
wayland/meta-wayland-tablet-pad.h \
|
||||
wayland/meta-wayland-tablet-pad-group.c \
|
||||
wayland/meta-wayland-tablet-pad-group.h \
|
||||
wayland/meta-wayland-tablet-pad-ring.c \
|
||||
wayland/meta-wayland-tablet-pad-ring.h \
|
||||
wayland/meta-wayland-tablet-pad-strip.c \
|
||||
wayland/meta-wayland-tablet-pad-strip.h \
|
||||
wayland/meta-wayland-touch.c \
|
||||
wayland/meta-wayland-touch.h \
|
||||
wayland/meta-wayland-surface.c \
|
||||
wayland/meta-wayland-surface.h \
|
||||
wayland/meta-wayland-surface-role-cursor.c \
|
||||
wayland/meta-wayland-surface-role-cursor.h \
|
||||
wayland/meta-wayland-surface-role-tablet-cursor.c \
|
||||
wayland/meta-wayland-surface-role-tablet-cursor.h \
|
||||
wayland/meta-wayland-types.h \
|
||||
wayland/meta-wayland-versions.h \
|
||||
wayland/meta-wayland-outputs.c \
|
||||
|
@ -316,7 +316,7 @@ meta_backend_real_post_init (MetaBackend *backend)
|
||||
g_slist_free (devices);
|
||||
}
|
||||
|
||||
priv->input_settings = meta_input_settings_create ();
|
||||
priv->input_settings = meta_input_settings_get ();
|
||||
|
||||
center_pointer (backend);
|
||||
}
|
||||
|
@ -23,9 +23,14 @@
|
||||
#define META_INPUT_SETTINGS_PRIVATE_H
|
||||
|
||||
#include "display-private.h"
|
||||
#include "meta-monitor-manager-private.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
#include <libwacom/libwacom.h>
|
||||
#endif
|
||||
|
||||
#define META_TYPE_INPUT_SETTINGS (meta_input_settings_get_type ())
|
||||
#define META_INPUT_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS, MetaInputSettings))
|
||||
#define META_INPUT_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_INPUT_SETTINGS, MetaInputSettingsClass))
|
||||
@ -78,10 +83,58 @@ struct _MetaInputSettingsClass
|
||||
gboolean repeat,
|
||||
guint delay,
|
||||
guint interval);
|
||||
|
||||
void (* set_tablet_mapping) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
GDesktopTabletMapping mapping);
|
||||
void (* set_tablet_keep_aspect) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaOutput *output,
|
||||
gboolean keep_aspect);
|
||||
void (* set_tablet_area) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
gdouble padding_left,
|
||||
gdouble padding_right,
|
||||
gdouble padding_top,
|
||||
gdouble padding_bottom);
|
||||
};
|
||||
|
||||
GType meta_input_settings_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaInputSettings * meta_input_settings_create (void);
|
||||
MetaInputSettings * meta_input_settings_get (void);
|
||||
|
||||
GSettings * meta_input_settings_get_tablet_settings (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
MetaOutput * meta_input_settings_get_tablet_output (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
GDesktopTabletMapping meta_input_settings_get_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
GDesktopStylusButtonAction meta_input_settings_get_stylus_button_action (MetaInputSettings *settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_device,
|
||||
guint button);
|
||||
gdouble meta_input_settings_translate_tablet_tool_pressure (MetaInputSettings *input_settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_tablet,
|
||||
gdouble pressure);
|
||||
|
||||
gboolean meta_input_settings_is_pad_button_grabbed (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button);
|
||||
|
||||
gboolean meta_input_settings_handle_pad_button (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
gboolean is_press,
|
||||
guint button);
|
||||
gchar * meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice * meta_input_settings_get_tablet_wacom_device (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
#endif
|
||||
|
||||
#endif /* META_INPUT_SETTINGS_PRIVATE_H */
|
||||
|
@ -38,8 +38,11 @@
|
||||
#include "native/meta-input-settings-native.h"
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
static GQuark quark_tool_settings = 0;
|
||||
|
||||
typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
|
||||
typedef struct _DeviceMappingInfo DeviceMappingInfo;
|
||||
|
||||
@ -48,6 +51,9 @@ struct _DeviceMappingInfo
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
GSettings *settings;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MetaInputSettingsPrivate
|
||||
@ -62,6 +68,10 @@ struct _MetaInputSettingsPrivate
|
||||
GSettings *keyboard_settings;
|
||||
|
||||
GHashTable *mappable_devices;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDeviceDatabase *wacom_db;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef void (*ConfigBoolFunc) (MetaInputSettings *input_settings,
|
||||
@ -122,6 +132,9 @@ meta_input_settings_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&priv->monitor_manager);
|
||||
|
||||
if (priv->wacom_db)
|
||||
libwacom_database_destroy (priv->wacom_db);
|
||||
|
||||
G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -595,6 +608,48 @@ meta_input_settings_find_output (MetaInputSettings *input_settings,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
update_tablet_keep_aspect (MetaInputSettings *input_settings,
|
||||
GSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
MetaOutput *output = NULL;
|
||||
gboolean keep_aspect;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
{
|
||||
WacomDevice *wacom_device;
|
||||
|
||||
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
||||
device);
|
||||
/* Keep aspect only makes sense in external tablets */
|
||||
if (wacom_device &&
|
||||
libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
|
||||
if (clutter_input_device_get_mapping_mode (device) ==
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE)
|
||||
{
|
||||
keep_aspect = g_settings_get_boolean (settings, "keep-aspect");
|
||||
output = meta_input_settings_find_output (input_settings, settings, device);
|
||||
}
|
||||
else
|
||||
{
|
||||
keep_aspect = FALSE;
|
||||
}
|
||||
|
||||
input_settings_class->set_tablet_keep_aspect (input_settings, device,
|
||||
output, keep_aspect);
|
||||
}
|
||||
|
||||
static void
|
||||
update_device_display (MetaInputSettings *input_settings,
|
||||
GSettings *settings,
|
||||
@ -605,15 +660,138 @@ update_device_display (MetaInputSettings *input_settings,
|
||||
gfloat matrix[6] = { 1, 0, 0, 0, 1, 0 };
|
||||
MetaOutput *output;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHSCREEN_DEVICE)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
output = meta_input_settings_find_output (input_settings, settings, device);
|
||||
|
||||
/* If mapping is relative, the device can move on all displays */
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_mapping_mode (device) ==
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE)
|
||||
output = meta_input_settings_find_output (input_settings, settings, device);
|
||||
else
|
||||
output = NULL;
|
||||
|
||||
if (output)
|
||||
meta_monitor_manager_get_monitor_matrix (priv->monitor_manager,
|
||||
output, matrix);
|
||||
|
||||
input_settings_class->set_matrix (input_settings, device, matrix);
|
||||
|
||||
/* Ensure the keep-aspect mapping is updated */
|
||||
update_tablet_keep_aspect (input_settings, settings, device);
|
||||
}
|
||||
|
||||
static void
|
||||
update_tablet_mapping (MetaInputSettings *input_settings,
|
||||
GSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
GDesktopTabletMapping mapping;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
{
|
||||
WacomDevice *wacom_device;
|
||||
|
||||
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
||||
device);
|
||||
/* Tablet mapping only makes sense on external tablets */
|
||||
if (wacom_device &&
|
||||
(libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
mapping = g_settings_get_enum (settings, "mapping");
|
||||
|
||||
settings_device_set_uint_setting (input_settings, device,
|
||||
input_settings_class->set_tablet_mapping,
|
||||
mapping);
|
||||
|
||||
/* Relative mapping disables keep-aspect/display */
|
||||
update_tablet_keep_aspect (input_settings, settings, device);
|
||||
update_device_display (input_settings, settings, device);
|
||||
}
|
||||
|
||||
static void
|
||||
update_tablet_area (MetaInputSettings *input_settings,
|
||||
GSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
GVariant *variant;
|
||||
const gdouble *area;
|
||||
gsize n_elems;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
{
|
||||
WacomDevice *wacom_device;
|
||||
|
||||
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
||||
device);
|
||||
/* Tablet area only makes sense on system/display integrated tablets */
|
||||
if (wacom_device &&
|
||||
(libwacom_get_integration_flags (wacom_device) &
|
||||
(WACOM_DEVICE_INTEGRATED_SYSTEM | WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
variant = g_settings_get_value (settings, "area");
|
||||
|
||||
area = g_variant_get_fixed_array (variant, &n_elems, sizeof (gdouble));
|
||||
if (n_elems == 4)
|
||||
{
|
||||
input_settings_class->set_tablet_area (input_settings, device,
|
||||
area[0], area[1],
|
||||
area[2], area[3]);
|
||||
}
|
||||
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
static void
|
||||
update_tablet_left_handed (MetaInputSettings *input_settings,
|
||||
GSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
gboolean enabled;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
{
|
||||
WacomDevice *wacom_device;
|
||||
|
||||
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
||||
device);
|
||||
/* Left handed mode only makes sense on external tablets */
|
||||
if (wacom_device &&
|
||||
(libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
enabled = g_settings_get_boolean (settings, "left-handed");
|
||||
|
||||
settings_device_set_bool_setting (input_settings, device,
|
||||
input_settings_class->set_left_handed,
|
||||
enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -671,6 +849,30 @@ mapped_device_changed_cb (GSettings *settings,
|
||||
{
|
||||
if (strcmp (key, "display") == 0)
|
||||
update_device_display (info->input_settings, settings, info->device);
|
||||
else if (strcmp (key, "mapping") == 0)
|
||||
update_tablet_mapping (info->input_settings, settings, info->device);
|
||||
else if (strcmp (key, "area") == 0)
|
||||
update_tablet_area (info->input_settings, settings, info->device);
|
||||
else if (strcmp (key, "keep-aspect") == 0)
|
||||
update_tablet_keep_aspect (info->input_settings, settings, info->device);
|
||||
else if (strcmp (key, "left-handed") == 0)
|
||||
update_tablet_left_handed (info->input_settings, settings, info->device);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_mappable_device_settings (MetaInputSettings *input_settings,
|
||||
DeviceMappingInfo *info)
|
||||
{
|
||||
update_device_display (input_settings, info->settings, info->device);
|
||||
|
||||
if (clutter_input_device_get_device_type (info->device) == CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_device_type (info->device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
update_tablet_mapping (input_settings, info->settings, info->device);
|
||||
update_tablet_area (input_settings, info->settings, info->device);
|
||||
update_tablet_keep_aspect (input_settings, info->settings, info->device);
|
||||
update_tablet_left_handed (input_settings, info->settings, info->device);
|
||||
}
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
@ -691,7 +893,8 @@ lookup_device_settings (ClutterInputDevice *device)
|
||||
else if (type == CLUTTER_TABLET_DEVICE ||
|
||||
type == CLUTTER_PEN_DEVICE ||
|
||||
type == CLUTTER_ERASER_DEVICE ||
|
||||
type == CLUTTER_CURSOR_DEVICE)
|
||||
type == CLUTTER_CURSOR_DEVICE ||
|
||||
type == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
group = "tablets";
|
||||
schema = "org.gnome.desktop.peripherals.tablet";
|
||||
@ -710,21 +913,86 @@ lookup_device_settings (ClutterInputDevice *device)
|
||||
return settings;
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
lookup_tool_settings (ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
GSettings *settings;
|
||||
guint64 serial;
|
||||
gchar *path;
|
||||
|
||||
settings = g_object_get_qdata (G_OBJECT (tool), quark_tool_settings);
|
||||
|
||||
if (!settings)
|
||||
{
|
||||
serial = clutter_input_device_tool_get_serial (tool);
|
||||
|
||||
if (serial == 0)
|
||||
{
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/",
|
||||
clutter_input_device_get_vendor_id (device),
|
||||
clutter_input_device_get_product_id (device));
|
||||
}
|
||||
else
|
||||
{
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%lx/", serial);
|
||||
}
|
||||
|
||||
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus",
|
||||
path);
|
||||
g_object_set_qdata_full (G_OBJECT (tool), quark_tool_settings, settings,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
lookup_pad_button_settings (ClutterInputDevice *device,
|
||||
guint button)
|
||||
{
|
||||
const gchar *vendor, *product;
|
||||
GSettings *settings;
|
||||
gchar *path;
|
||||
|
||||
vendor = clutter_input_device_get_vendor_id (device);
|
||||
product = clutter_input_device_get_product_id (device);
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/button%c/",
|
||||
vendor, product, 'A' + button);
|
||||
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
|
||||
path);
|
||||
g_free (path);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static void
|
||||
monitors_changed_cb (MetaMonitorManager *monitor_manager,
|
||||
MetaInputSettings *input_settings)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
ClutterInputDevice *device;
|
||||
GSettings *settings;
|
||||
DeviceMappingInfo *info;
|
||||
GHashTableIter iter;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
g_hash_table_iter_init (&iter, priv->mappable_devices);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &device,
|
||||
(gpointer *) &settings))
|
||||
update_device_display (input_settings, settings, device);
|
||||
(gpointer *) &info))
|
||||
update_device_display (input_settings, info->settings, device);
|
||||
}
|
||||
|
||||
static void
|
||||
device_mapping_info_free (DeviceMappingInfo *info)
|
||||
{
|
||||
#ifdef HAVE_LIBWACOM
|
||||
if (info->wacom_device)
|
||||
libwacom_destroy (info->wacom_device);
|
||||
#endif
|
||||
g_object_unref (info->settings);
|
||||
g_slice_free (DeviceMappingInfo, info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -742,18 +1010,37 @@ check_add_mappable_device (MetaInputSettings *input_settings,
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
|
||||
info = g_new0 (DeviceMappingInfo, 1);
|
||||
info = g_slice_new0 (DeviceMappingInfo);
|
||||
info->input_settings = input_settings;
|
||||
info->device = device;
|
||||
info->settings = settings;
|
||||
|
||||
g_signal_connect_data (settings, "changed",
|
||||
G_CALLBACK (mapped_device_changed_cb),
|
||||
info, (GClosureNotify) g_free, 0);
|
||||
#ifdef HAVE_LIBWACOM
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
WacomError *error = libwacom_error_new ();
|
||||
|
||||
g_hash_table_insert (priv->mappable_devices, device, settings);
|
||||
info->wacom_device = libwacom_new_from_path (priv->wacom_db,
|
||||
clutter_input_device_get_device_node (device),
|
||||
WFALLBACK_NONE, error);
|
||||
if (!info->wacom_device)
|
||||
{
|
||||
g_warning ("Could not get tablet information for '%s': %s",
|
||||
clutter_input_device_get_device_name (device),
|
||||
libwacom_error_get_message (error));
|
||||
}
|
||||
|
||||
update_device_display (input_settings, settings, device);
|
||||
libwacom_error_free (&error);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_signal_connect (settings, "changed",
|
||||
G_CALLBACK (mapped_device_changed_cb), info);
|
||||
|
||||
g_hash_table_insert (priv->mappable_devices, device, info);
|
||||
|
||||
apply_mappable_device_settings (input_settings, info);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -837,6 +1124,9 @@ meta_input_settings_class_init (MetaInputSettingsClass *klass)
|
||||
|
||||
object_class->dispose = meta_input_settings_dispose;
|
||||
object_class->constructed = meta_input_settings_constructed;
|
||||
|
||||
quark_tool_settings =
|
||||
g_quark_from_static_string ("meta-input-settings-tool-settings");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -868,14 +1158,21 @@ meta_input_settings_init (MetaInputSettings *settings)
|
||||
G_CALLBACK (meta_input_settings_changed_cb), settings);
|
||||
|
||||
priv->mappable_devices =
|
||||
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
|
||||
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free);
|
||||
|
||||
priv->monitor_manager = g_object_ref (meta_monitor_manager_get ());
|
||||
g_signal_connect (priv->monitor_manager, "monitors-changed",
|
||||
G_CALLBACK (monitors_changed_cb), settings);
|
||||
|
||||
priv->wacom_db = libwacom_database_new ();
|
||||
if (!priv->wacom_db)
|
||||
{
|
||||
g_warning ("Could not create database of Wacom devices, "
|
||||
"expect tablets to misbehave");
|
||||
}
|
||||
}
|
||||
|
||||
MetaInputSettings *
|
||||
static MetaInputSettings *
|
||||
meta_input_settings_create (void)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
@ -891,3 +1188,355 @@ meta_input_settings_create (void)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MetaInputSettings *
|
||||
meta_input_settings_get (void)
|
||||
{
|
||||
static MetaInputSettings *input_settings = NULL;
|
||||
|
||||
if (g_once_init_enter (&input_settings))
|
||||
{
|
||||
MetaInputSettings *settings = meta_input_settings_create ();
|
||||
g_once_init_leave (&input_settings, settings);
|
||||
}
|
||||
|
||||
return input_settings;
|
||||
}
|
||||
|
||||
GSettings *
|
||||
meta_input_settings_get_tablet_settings (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
|
||||
priv = meta_input_settings_get_instance_private (settings);
|
||||
info = g_hash_table_lookup (priv->mappable_devices, device);
|
||||
|
||||
return info ? g_object_ref (info->settings) : NULL;
|
||||
}
|
||||
|
||||
MetaOutput *
|
||||
meta_input_settings_get_tablet_output (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
|
||||
priv = meta_input_settings_get_instance_private (settings);
|
||||
info = g_hash_table_lookup (priv->mappable_devices, device);
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return meta_input_settings_find_output (settings, info->settings, device);
|
||||
}
|
||||
|
||||
GDesktopTabletMapping
|
||||
meta_input_settings_get_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings),
|
||||
G_DESKTOP_TABLET_MAPPING_ABSOLUTE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
|
||||
G_DESKTOP_TABLET_MAPPING_ABSOLUTE);
|
||||
|
||||
priv = meta_input_settings_get_instance_private (settings);
|
||||
info = g_hash_table_lookup (priv->mappable_devices, device);
|
||||
g_return_val_if_fail (info != NULL, G_DESKTOP_TABLET_MAPPING_ABSOLUTE);
|
||||
|
||||
return g_settings_get_enum (info->settings, "mapping");
|
||||
}
|
||||
|
||||
GDesktopStylusButtonAction
|
||||
meta_input_settings_get_stylus_button_action (MetaInputSettings *input_settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_tablet,
|
||||
guint button)
|
||||
{
|
||||
GSettings *settings;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings),
|
||||
G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool),
|
||||
G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT);
|
||||
|
||||
settings = lookup_tool_settings (tool, current_tablet);
|
||||
|
||||
if (button == 2)
|
||||
return g_settings_get_enum (settings, "button-action");
|
||||
else if (button == 3)
|
||||
return g_settings_get_enum (settings, "secondary-button-action");
|
||||
else
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT;
|
||||
}
|
||||
|
||||
static GDesktopPadButtonAction
|
||||
meta_input_settings_get_pad_button_action (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
GSettings *settings;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings),
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad),
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
|
||||
settings = lookup_pad_button_settings (pad, button);
|
||||
action = g_settings_get_enum (settings, "action");
|
||||
g_object_unref (settings);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *
|
||||
meta_input_settings_get_tablet_wacom_device (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
|
||||
priv = meta_input_settings_get_instance_private (settings);
|
||||
info = g_hash_table_lookup (priv->mappable_devices, device);
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->wacom_device;
|
||||
}
|
||||
#endif /* HAVE_LIBWACOM */
|
||||
|
||||
static gboolean
|
||||
cycle_outputs (MetaInputSettings *settings,
|
||||
MetaOutput *current_output,
|
||||
MetaOutput **next_output)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
MetaOutput *next, *outputs;
|
||||
guint n_outputs, current, i;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (settings);
|
||||
outputs = meta_monitor_manager_get_outputs (priv->monitor_manager,
|
||||
&n_outputs);
|
||||
if (n_outputs <= 1)
|
||||
return FALSE;
|
||||
|
||||
/* We cycle between:
|
||||
* - the span of all monitors (current_output = NULL)
|
||||
* - each monitor individually.
|
||||
*/
|
||||
if (!current_output)
|
||||
{
|
||||
next = &outputs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (current_output != &outputs[i])
|
||||
continue;
|
||||
current = i;
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert (i < n_outputs);
|
||||
|
||||
if (current == n_outputs - 1)
|
||||
next = NULL;
|
||||
else
|
||||
next = &outputs[current + 1];
|
||||
}
|
||||
|
||||
*next_output = next;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_cycle_tablet_output (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
MetaOutput *output;
|
||||
const gchar *edid[4] = { 0 };
|
||||
|
||||
g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings));
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
g_return_if_fail (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE);
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
info = g_hash_table_lookup (priv->mappable_devices, device);
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
/* Output rotation only makes sense on external tablets */
|
||||
if (info->wacom_device &&
|
||||
(libwacom_get_integration_flags (info->wacom_device) != WACOM_DEVICE_INTEGRATED_NONE))
|
||||
return;
|
||||
#endif
|
||||
|
||||
output = meta_input_settings_find_output (input_settings,
|
||||
info->settings, device);
|
||||
if (!cycle_outputs (input_settings, output, &output))
|
||||
return;
|
||||
|
||||
edid[0] = output ? output->vendor : "";
|
||||
edid[1] = output ? output->product : "";
|
||||
edid[2] = output ? output->serial : "";
|
||||
g_settings_set_strv (info->settings, "display", edid);
|
||||
}
|
||||
|
||||
static gdouble
|
||||
calculate_bezier_position (gdouble pos,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2)
|
||||
{
|
||||
gdouble int1_y, int2_y;
|
||||
|
||||
pos = CLAMP (pos, 0, 1);
|
||||
|
||||
/* Intersection between 0,0 and x1,y1 */
|
||||
int1_y = pos * y1;
|
||||
|
||||
/* Intersection between x2,y2 and 1,1 */
|
||||
int2_y = (pos * (1 - y2)) + y2;
|
||||
|
||||
/* Find the new position in the line traced by the previous points */
|
||||
return (pos * (int2_y - int1_y)) + int1_y;
|
||||
}
|
||||
|
||||
gdouble
|
||||
meta_input_settings_translate_tablet_tool_pressure (MetaInputSettings *input_settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_tablet,
|
||||
gdouble pressure)
|
||||
{
|
||||
GSettings *settings;
|
||||
GVariant *variant;
|
||||
const gint32 *curve;
|
||||
gsize n_elems;
|
||||
|
||||
pressure = CLAMP (pressure, 0, 1);
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), pressure);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), pressure);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (current_tablet), pressure);
|
||||
|
||||
settings = lookup_tool_settings (tool, current_tablet);
|
||||
|
||||
if (clutter_input_device_tool_get_tool_type (tool) == CLUTTER_INPUT_DEVICE_TOOL_ERASER)
|
||||
variant = g_settings_get_value (settings, "eraser-pressure-curve");
|
||||
else
|
||||
variant = g_settings_get_value (settings, "pressure-curve");
|
||||
|
||||
curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32));
|
||||
if (n_elems != 4)
|
||||
return pressure;
|
||||
|
||||
pressure = calculate_bezier_position (pressure,
|
||||
(gdouble) curve[0] / 100,
|
||||
(gdouble) curve[1] / 100,
|
||||
(gdouble) curve[2] / 100,
|
||||
(gdouble) curve[3] / 100);
|
||||
g_variant_unref (variant);
|
||||
|
||||
return pressure;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_settings_is_pad_button_grabbed (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), FALSE);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
|
||||
CLUTTER_PAD_DEVICE, FALSE);
|
||||
|
||||
return (meta_input_settings_get_pad_button_action (input_settings, pad, button) !=
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_settings_handle_pad_button (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
gboolean is_press,
|
||||
guint button)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), FALSE);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
|
||||
CLUTTER_PAD_DEVICE, FALSE);
|
||||
|
||||
action = meta_input_settings_get_pad_button_action (input_settings, pad, button);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
||||
if (is_press)
|
||||
meta_input_settings_cycle_tablet_output (input_settings, pad);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
||||
if (is_press)
|
||||
meta_display_request_pad_osd (meta_get_display (), pad, FALSE);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gchar *
|
||||
meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), NULL);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
|
||||
CLUTTER_PAD_DEVICE, NULL);
|
||||
|
||||
action = meta_input_settings_get_pad_button_action (input_settings, pad, button);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
||||
{
|
||||
GSettings *settings;
|
||||
gchar *accel;
|
||||
|
||||
settings = lookup_pad_button_settings (pad, button);
|
||||
accel = g_settings_get_string (settings, "keybinding");
|
||||
g_object_unref (settings);
|
||||
|
||||
return accel;
|
||||
}
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
||||
return g_strdup (_("Switch monitor"));
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
||||
return g_strdup (_("Show on-screen help"));
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -241,6 +241,43 @@ meta_input_settings_native_set_keyboard_repeat (MetaInputSettings *settings,
|
||||
clutter_evdev_set_keyboard_repeat (manager, enabled, delay, interval);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
GDesktopTabletMapping mapping)
|
||||
{
|
||||
ClutterInputDeviceMapping dev_mapping;
|
||||
|
||||
if (mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE)
|
||||
dev_mapping = CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE;
|
||||
else if (mapping == G_DESKTOP_TABLET_MAPPING_RELATIVE)
|
||||
dev_mapping = CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE;
|
||||
else
|
||||
return;
|
||||
|
||||
clutter_input_device_set_mapping_mode (device, dev_mapping);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaOutput *output,
|
||||
gboolean keep_aspect)
|
||||
{
|
||||
/* FIXME: Implement */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_tablet_area (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
gdouble padding_left,
|
||||
gdouble padding_right,
|
||||
gdouble padding_top,
|
||||
gdouble padding_bottom)
|
||||
{
|
||||
/* FIXME: Implement */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
|
||||
{
|
||||
@ -256,6 +293,10 @@ meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
|
||||
input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button;
|
||||
input_settings_class->set_click_method = meta_input_settings_native_set_click_method;
|
||||
input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat;
|
||||
|
||||
input_settings_class->set_tablet_mapping = meta_input_settings_native_set_tablet_mapping;
|
||||
input_settings_class->set_tablet_keep_aspect = meta_input_settings_native_set_tablet_keep_aspect;
|
||||
input_settings_class->set_tablet_area = meta_input_settings_native_set_tablet_area;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -305,6 +305,31 @@ meta_input_settings_x11_set_keyboard_repeat (MetaInputSettings *settings,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
GDesktopTabletMapping mapping)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaOutput *output,
|
||||
gboolean keep_aspect)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_tablet_area (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
gdouble padding_left,
|
||||
gdouble padding_right,
|
||||
gdouble padding_top,
|
||||
gdouble padding_bottom)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
|
||||
{
|
||||
@ -320,6 +345,10 @@ meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
|
||||
input_settings_class->set_scroll_button = meta_input_settings_x11_set_scroll_button;
|
||||
input_settings_class->set_click_method = meta_input_settings_x11_set_click_method;
|
||||
input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat;
|
||||
|
||||
input_settings_class->set_tablet_mapping = meta_input_settings_x11_set_tablet_mapping;
|
||||
input_settings_class->set_tablet_keep_aspect = meta_input_settings_x11_set_tablet_keep_aspect;
|
||||
input_settings_class->set_tablet_area = meta_input_settings_x11_set_tablet_area;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -277,6 +277,8 @@ struct _MetaDisplay
|
||||
int xinput_event_base;
|
||||
int xinput_opcode;
|
||||
|
||||
ClutterActor *current_pad_osd;
|
||||
|
||||
MetaStartupNotification *startup_notification;
|
||||
|
||||
int xsync_event_base;
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "backends/meta-stage.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
@ -75,6 +76,8 @@
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/meta-xwayland-private.h"
|
||||
#include "wayland/meta-wayland-tablet-seat.h"
|
||||
#include "wayland/meta-wayland-tablet-pad.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -126,6 +129,7 @@ enum
|
||||
RESTART,
|
||||
SHOW_RESIZE_POPUP,
|
||||
GL_VIDEO_MEMORY_PURGED,
|
||||
SHOW_PAD_OSD,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -351,6 +355,27 @@ meta_display_class_init (MetaDisplayClass *klass)
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* MetaDisplay::show-pad-osd:
|
||||
* @display: the #MetaDisplay instance
|
||||
* @pad: the pad device
|
||||
* @settings: the pad device settings
|
||||
* @layout_path: path to the layout image
|
||||
* @edition_mode: Whether the OSD should be shown in edition mode
|
||||
* @monitor_idx: Monitor to show the OSD on
|
||||
*
|
||||
* Requests the pad button mapping OSD to be shown.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The OSD actor
|
||||
*/
|
||||
display_signals[SHOW_PAD_OSD] =
|
||||
g_signal_new ("show-pad-osd",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL, NULL,
|
||||
CLUTTER_TYPE_ACTOR, 5, CLUTTER_TYPE_INPUT_DEVICE,
|
||||
G_TYPE_SETTINGS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FOCUS_WINDOW,
|
||||
g_param_spec_object ("focus-window",
|
||||
@ -528,6 +553,27 @@ on_startup_notification_changed (MetaStartupNotification *sn,
|
||||
g_signal_emit_by_name (display->screen, "startup-sequence-changed", sequence);
|
||||
}
|
||||
|
||||
static void
|
||||
check_pad_removed (MetaDisplay *display,
|
||||
ClutterInputDevice *device,
|
||||
ClutterDeviceManager *device_manager)
|
||||
{
|
||||
ClutterInputDevice *pad;
|
||||
|
||||
if (!display->current_pad_osd)
|
||||
return;
|
||||
|
||||
pad = g_object_get_data (G_OBJECT (display->current_pad_osd),
|
||||
"meta-pad-osd-device");
|
||||
|
||||
if (pad == device)
|
||||
{
|
||||
/* Close pad OSD */
|
||||
clutter_actor_destroy (display->current_pad_osd);
|
||||
display->current_pad_osd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_open:
|
||||
*
|
||||
@ -951,6 +997,10 @@ meta_display_open (void)
|
||||
|
||||
meta_idle_monitor_init_dbus ();
|
||||
|
||||
g_signal_connect_swapped (clutter_device_manager_get_default (),
|
||||
"device-removed", G_CALLBACK (check_pad_removed),
|
||||
display);
|
||||
|
||||
/* Done opening new display */
|
||||
display->display_opening = FALSE;
|
||||
|
||||
@ -3070,3 +3120,114 @@ meta_display_set_alarm_filter (MetaDisplay *display,
|
||||
display->alarm_filter = filter;
|
||||
display->alarm_filter_data = data;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_request_pad_osd (MetaDisplay *display,
|
||||
ClutterInputDevice *pad,
|
||||
gboolean edition_mode)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
const gchar *layout_path = NULL;
|
||||
ClutterActor *osd;
|
||||
MetaOutput *output;
|
||||
gint monitor_idx;
|
||||
GSettings *settings;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
|
||||
input_settings = meta_input_settings_get ();
|
||||
|
||||
if (display->current_pad_osd)
|
||||
{
|
||||
clutter_actor_destroy (display->current_pad_osd);
|
||||
display->current_pad_osd = NULL;
|
||||
}
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
settings = meta_input_settings_get_tablet_settings (input_settings, pad);
|
||||
output = meta_input_settings_get_tablet_output (input_settings, pad);
|
||||
#ifdef HAVE_LIBWACOM
|
||||
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
||||
pad);
|
||||
layout_path = libwacom_get_layout_filename (wacom_device);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!layout_path || !settings)
|
||||
return;
|
||||
|
||||
if (output && output->crtc)
|
||||
{
|
||||
monitor_idx = meta_screen_get_monitor_index_for_rect (display->screen,
|
||||
&output->crtc->rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
monitor_idx = meta_screen_get_current_monitor (display->screen);
|
||||
}
|
||||
|
||||
g_signal_emit (display, display_signals[SHOW_PAD_OSD], 0,
|
||||
pad, settings, layout_path,
|
||||
edition_mode, monitor_idx, &osd);
|
||||
|
||||
if (osd)
|
||||
{
|
||||
display->current_pad_osd = osd;
|
||||
g_object_set_data (G_OBJECT (display->current_pad_osd),
|
||||
"meta-pad-osd-device", pad);
|
||||
g_object_add_weak_pointer (G_OBJECT (display->current_pad_osd),
|
||||
(gpointer *) &display->current_pad_osd);
|
||||
clutter_actor_grab_key_focus (osd);
|
||||
}
|
||||
|
||||
g_object_unref (settings);
|
||||
}
|
||||
|
||||
gchar *
|
||||
meta_display_get_pad_action_label (MetaDisplay *display,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action_type,
|
||||
guint action_number)
|
||||
{
|
||||
gchar *label;
|
||||
|
||||
/* First, lookup the action, as imposed by settings */
|
||||
if (action_type == META_PAD_ACTION_BUTTON)
|
||||
{
|
||||
MetaInputSettings *settings;
|
||||
|
||||
settings = meta_input_settings_get ();
|
||||
label = meta_input_settings_get_pad_button_action_label (settings, pad, action_number);
|
||||
if (label)
|
||||
return label;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
/* Second, if this wayland, lookup the actions set by the clients */
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
MetaWaylandTabletPad *tablet_pad = NULL;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager,
|
||||
compositor->seat);
|
||||
if (tablet_seat)
|
||||
tablet_pad = meta_wayland_tablet_seat_lookup_pad (tablet_seat, pad);
|
||||
|
||||
if (tablet_pad)
|
||||
{
|
||||
label = meta_wayland_tablet_pad_get_label (tablet_pad, action_type,
|
||||
action_number);
|
||||
}
|
||||
|
||||
if (label)
|
||||
return label;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -299,6 +299,12 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (display->current_pad_osd)
|
||||
{
|
||||
bypass_wayland = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
/* Events that are likely to trigger compositor gestures should
|
||||
|
@ -53,6 +53,13 @@ typedef enum
|
||||
META_TAB_SHOW_INSTANTLY /* Alt-Esc mode */
|
||||
} MetaTabShowType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_PAD_ACTION_BUTTON, /* Action is a button */
|
||||
META_PAD_ACTION_RING, /* Action is a ring */
|
||||
META_PAD_ACTION_STRIP, /* Action is a strip */
|
||||
} MetaPadActionType;
|
||||
|
||||
typedef struct _MetaDisplayClass MetaDisplayClass;
|
||||
|
||||
#define META_TYPE_DISPLAY (meta_display_get_type ())
|
||||
@ -181,4 +188,12 @@ void meta_display_unfreeze_keyboard (MetaDisplay *display,
|
||||
gboolean meta_display_is_pointer_emulating_sequence (MetaDisplay *display,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
void meta_display_request_pad_osd (MetaDisplay *display,
|
||||
ClutterInputDevice *pad,
|
||||
gboolean edition_mode);
|
||||
gchar * meta_display_get_pad_action_label (MetaDisplay *display,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action_type,
|
||||
guint action_number);
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-versions.h"
|
||||
#include "meta-wayland-data-device.h"
|
||||
#include "meta-wayland-tablet-seat.h"
|
||||
|
||||
#define CAPABILITY_ENABLED(prev, cur, capability) ((cur & (capability)) && !(prev & (capability)))
|
||||
#define CAPABILITY_DISABLED(prev, cur, capability) ((prev & (capability)) && !(cur & (capability)))
|
||||
@ -369,11 +370,17 @@ void
|
||||
meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) == 0)
|
||||
return;
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
meta_wayland_keyboard_set_focus (&seat->keyboard, surface);
|
||||
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0)
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (&seat->keyboard, surface);
|
||||
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
|
||||
}
|
||||
|
||||
tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
|
||||
meta_wayland_tablet_seat_set_pad_focus (tablet_seat, surface);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -28,10 +28,10 @@
|
||||
#include "meta-xwayland.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
struct _MetaWaylandSurfaceRoleCursor
|
||||
{
|
||||
MetaWaylandSurfaceRole parent;
|
||||
typedef struct _MetaWaylandSurfaceRoleCursorPrivate MetaWaylandSurfaceRoleCursorPrivate;
|
||||
|
||||
struct _MetaWaylandSurfaceRoleCursorPrivate
|
||||
{
|
||||
int hot_x;
|
||||
int hot_y;
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
@ -39,41 +39,42 @@ struct _MetaWaylandSurfaceRoleCursor
|
||||
MetaWaylandBuffer *buffer;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
|
||||
meta_wayland_surface_role_cursor,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRoleCursor,
|
||||
meta_wayland_surface_role_cursor,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE)
|
||||
|
||||
static void
|
||||
update_cursor_sprite_texture (MetaWaylandSurfaceRoleCursor *cursor_role)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv = meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_role));
|
||||
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
||||
MetaCursorSprite *cursor_sprite = cursor_role->cursor_sprite;
|
||||
MetaCursorSprite *cursor_sprite = priv->cursor_sprite;
|
||||
|
||||
g_return_if_fail (!buffer || buffer->texture);
|
||||
|
||||
if (!cursor_role->cursor_renderer || !cursor_sprite)
|
||||
if (!priv->cursor_renderer || !cursor_sprite)
|
||||
return;
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
meta_cursor_sprite_set_texture (cursor_sprite,
|
||||
buffer->texture,
|
||||
cursor_role->hot_x * surface->scale,
|
||||
cursor_role->hot_y * surface->scale);
|
||||
priv->hot_x * surface->scale,
|
||||
priv->hot_y * surface->scale);
|
||||
|
||||
if (cursor_role->buffer)
|
||||
if (priv->buffer)
|
||||
{
|
||||
struct wl_resource *buffer_resource;
|
||||
|
||||
g_assert (cursor_role->buffer == buffer);
|
||||
g_assert (priv->buffer == buffer);
|
||||
buffer_resource = buffer->resource;
|
||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (cursor_role->cursor_renderer,
|
||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (priv->cursor_renderer,
|
||||
cursor_sprite,
|
||||
buffer_resource);
|
||||
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
g_clear_object (&priv->buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -81,7 +82,7 @@ update_cursor_sprite_texture (MetaWaylandSurfaceRoleCursor *cursor_role)
|
||||
meta_cursor_sprite_set_texture (cursor_sprite, NULL, 0, 0);
|
||||
}
|
||||
|
||||
meta_cursor_renderer_force_update (cursor_role->cursor_renderer);
|
||||
meta_cursor_renderer_force_update (priv->cursor_renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -111,13 +112,15 @@ cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
g_set_object (&cursor_role->buffer, buffer);
|
||||
g_set_object (&priv->buffer, buffer);
|
||||
meta_wayland_surface_ref_buffer_use_count (surface);
|
||||
}
|
||||
|
||||
@ -130,13 +133,15 @@ cursor_surface_role_pre_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
|
||||
if (pending->newly_attached && cursor_role->buffer)
|
||||
if (pending->newly_attached && priv->buffer)
|
||||
{
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
g_clear_object (&priv->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,14 +151,16 @@ cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
||||
|
||||
if (pending->newly_attached)
|
||||
{
|
||||
g_set_object (&cursor_role->buffer, buffer);
|
||||
if (cursor_role->buffer)
|
||||
g_set_object (&priv->buffer, buffer);
|
||||
if (priv->buffer)
|
||||
meta_wayland_surface_ref_buffer_use_count (surface);
|
||||
}
|
||||
|
||||
@ -171,10 +178,12 @@ cursor_surface_role_is_on_output (MetaWaylandSurfaceRole *role,
|
||||
meta_wayland_surface_role_get_surface (role);
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
MetaRectangle rect;
|
||||
|
||||
rect = meta_cursor_renderer_calculate_rect (cursor_role->cursor_renderer,
|
||||
cursor_role->cursor_sprite);
|
||||
rect = meta_cursor_renderer_calculate_rect (priv->cursor_renderer,
|
||||
priv->cursor_sprite);
|
||||
return meta_rectangle_overlap (&rect, &monitor->rect);
|
||||
}
|
||||
|
||||
@ -183,19 +192,21 @@ cursor_surface_role_dispose (GObject *object)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (object);
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (cursor_role->cursor_sprite,
|
||||
g_signal_handlers_disconnect_by_func (priv->cursor_sprite,
|
||||
cursor_sprite_prepare_at, cursor_role);
|
||||
|
||||
g_clear_object (&cursor_role->cursor_renderer);
|
||||
g_clear_object (&cursor_role->cursor_sprite);
|
||||
g_clear_object (&priv->cursor_renderer);
|
||||
g_clear_object (&priv->cursor_sprite);
|
||||
|
||||
if (cursor_role->buffer)
|
||||
if (priv->buffer)
|
||||
{
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
g_clear_object (&priv->buffer);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_surface_role_cursor_parent_class)->dispose (object);
|
||||
@ -204,8 +215,11 @@ cursor_surface_role_dispose (GObject *object)
|
||||
static void
|
||||
meta_wayland_surface_role_cursor_init (MetaWaylandSurfaceRoleCursor *role)
|
||||
{
|
||||
role->cursor_sprite = meta_cursor_sprite_new ();
|
||||
g_signal_connect_object (role->cursor_sprite,
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (role);
|
||||
|
||||
priv->cursor_sprite = meta_cursor_sprite_new ();
|
||||
g_signal_connect_object (priv->cursor_sprite,
|
||||
"prepare-at",
|
||||
G_CALLBACK (cursor_sprite_prepare_at),
|
||||
role,
|
||||
@ -230,7 +244,10 @@ meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *
|
||||
MetaCursorSprite *
|
||||
meta_wayland_surface_role_cursor_get_sprite (MetaWaylandSurfaceRoleCursor *cursor_role)
|
||||
{
|
||||
return cursor_role->cursor_sprite;
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
|
||||
return priv->cursor_sprite;
|
||||
}
|
||||
|
||||
void
|
||||
@ -238,12 +255,15 @@ meta_wayland_surface_role_cursor_set_hotspot (MetaWaylandSurfaceRoleCursor *curs
|
||||
gint hotspot_x,
|
||||
gint hotspot_y)
|
||||
{
|
||||
if (cursor_role->hot_x == hotspot_x &&
|
||||
cursor_role->hot_y == hotspot_y)
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
|
||||
if (priv->hot_x == hotspot_x &&
|
||||
priv->hot_y == hotspot_y)
|
||||
return;
|
||||
|
||||
cursor_role->hot_x = hotspot_x;
|
||||
cursor_role->hot_y = hotspot_y;
|
||||
priv->hot_x = hotspot_x;
|
||||
priv->hot_y = hotspot_y;
|
||||
update_cursor_sprite_texture (cursor_role);
|
||||
}
|
||||
|
||||
@ -252,30 +272,39 @@ meta_wayland_surface_role_cursor_get_hotspot (MetaWaylandSurfaceRoleCursor *curs
|
||||
gint *hotspot_x,
|
||||
gint *hotspot_y)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
|
||||
if (hotspot_x)
|
||||
*hotspot_x = cursor_role->hot_x;
|
||||
*hotspot_x = priv->hot_x;
|
||||
if (hotspot_y)
|
||||
*hotspot_y = cursor_role->hot_y;
|
||||
*hotspot_y = priv->hot_y;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_role_cursor_set_renderer (MetaWaylandSurfaceRoleCursor *cursor_role,
|
||||
MetaCursorRenderer *renderer)
|
||||
{
|
||||
if (cursor_role->cursor_renderer == renderer)
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
|
||||
if (priv->cursor_renderer == renderer)
|
||||
return;
|
||||
|
||||
if (renderer)
|
||||
g_object_ref (renderer);
|
||||
if (cursor_role->cursor_renderer)
|
||||
g_object_unref (cursor_role->cursor_renderer);
|
||||
if (priv->cursor_renderer)
|
||||
g_object_unref (priv->cursor_renderer);
|
||||
|
||||
cursor_role->cursor_renderer = renderer;
|
||||
priv->cursor_renderer = renderer;
|
||||
update_cursor_sprite_texture (cursor_role);
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
meta_wayland_surface_role_cursor_get_renderer (MetaWaylandSurfaceRoleCursor *cursor_role)
|
||||
{
|
||||
return cursor_role->cursor_renderer;
|
||||
MetaWaylandSurfaceRoleCursorPrivate *priv =
|
||||
meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
|
||||
|
||||
return priv->cursor_renderer;
|
||||
}
|
||||
|
@ -25,11 +25,16 @@
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "backends/meta-cursor-renderer.h"
|
||||
|
||||
struct _MetaWaylandSurfaceRoleCursorClass
|
||||
{
|
||||
MetaWaylandSurfaceRoleClass parent_class;
|
||||
};
|
||||
|
||||
#define META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR (meta_wayland_surface_role_cursor_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleCursor,
|
||||
meta_wayland_surface_role_cursor,
|
||||
META, WAYLAND_SURFACE_ROLE_CURSOR,
|
||||
MetaWaylandSurfaceRole);
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaWaylandSurfaceRoleCursor,
|
||||
meta_wayland_surface_role_cursor,
|
||||
META, WAYLAND_SURFACE_ROLE_CURSOR,
|
||||
MetaWaylandSurfaceRole);
|
||||
|
||||
MetaCursorSprite * meta_wayland_surface_role_cursor_get_sprite (MetaWaylandSurfaceRoleCursor *cursor_role);
|
||||
|
||||
|
42
src/wayland/meta-wayland-surface-role-tablet-cursor.c
Normal file
42
src/wayland/meta-wayland-surface-role-tablet-cursor.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "meta-wayland-surface-role-tablet-cursor.h"
|
||||
|
||||
struct _MetaWaylandSurfaceRoleTabletCursor
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandSurfaceRoleTabletCursor,
|
||||
meta_wayland_surface_role_tablet_cursor,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR)
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_tablet_cursor_init (MetaWaylandSurfaceRoleTabletCursor *role)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_tablet_cursor_class_init (MetaWaylandSurfaceRoleTabletCursorClass *klass)
|
||||
{
|
||||
}
|
33
src/wayland/meta-wayland-surface-role-tablet-cursor.h
Normal file
33
src/wayland/meta-wayland-surface-role-tablet-cursor.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_SURFACE_ROLE_TABLET_CURSOR_H
|
||||
#define META_WAYLAND_SURFACE_ROLE_TABLET_CURSOR_H
|
||||
|
||||
#include "meta-wayland-surface-role-cursor.h"
|
||||
|
||||
#define META_TYPE_WAYLAND_SURFACE_ROLE_TABLET_CURSOR (meta_wayland_surface_role_tablet_cursor_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleTabletCursor,
|
||||
meta_wayland_surface_role_tablet_cursor,
|
||||
META, WAYLAND_SURFACE_ROLE_TABLET_CURSOR,
|
||||
MetaWaylandSurfaceRoleCursor);
|
||||
|
||||
#endif /* META_WAYLAND_SURFACE_ROLE_TABLET_CURSOR_H */
|
@ -28,7 +28,7 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v1-server-protocol.h"
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-tablet-manager.h"
|
||||
@ -54,7 +54,8 @@ is_tablet_device (ClutterInputDevice *device)
|
||||
return (device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE ||
|
||||
device_type == CLUTTER_CURSOR_DEVICE);
|
||||
device_type == CLUTTER_CURSOR_DEVICE ||
|
||||
device_type == CLUTTER_PAD_DEVICE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -79,7 +80,7 @@ tablet_manager_destroy (struct wl_client *client,
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_manager_v1_interface tablet_manager_interface = {
|
||||
static const struct zwp_tablet_manager_v2_interface tablet_manager_interface = {
|
||||
tablet_manager_get_tablet_seat,
|
||||
tablet_manager_destroy
|
||||
};
|
||||
@ -94,7 +95,7 @@ bind_tablet_manager (struct wl_client *client,
|
||||
MetaWaylandTabletManager *tablet_manager = compositor->tablet_manager;
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_manager_v1_interface,
|
||||
resource = wl_resource_create (client, &zwp_tablet_manager_v2_interface,
|
||||
MIN (version, 1), id);
|
||||
wl_resource_set_implementation (resource, &tablet_manager_interface,
|
||||
tablet_manager, unbind_resource);
|
||||
@ -116,7 +117,7 @@ meta_wayland_tablet_manager_new (MetaWaylandCompositor *compositor)
|
||||
wl_list_init (&tablet_manager->resource_list);
|
||||
|
||||
wl_global_create (tablet_manager->wl_display,
|
||||
&zwp_tablet_manager_v1_interface, 1,
|
||||
&zwp_tablet_manager_v2_interface, 1,
|
||||
compositor, bind_tablet_manager);
|
||||
|
||||
return tablet_manager;
|
||||
@ -155,7 +156,8 @@ meta_wayland_tablet_manager_lookup_seat (MetaWaylandTabletManager *manager,
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer*) &seat, (gpointer*) &tablet_seat))
|
||||
{
|
||||
if (meta_wayland_tablet_seat_lookup_tablet (tablet_seat, device))
|
||||
if (meta_wayland_tablet_seat_lookup_tablet (tablet_seat, device) ||
|
||||
meta_wayland_tablet_seat_lookup_pad (tablet_seat, device))
|
||||
return tablet_seat;
|
||||
}
|
||||
|
||||
@ -190,6 +192,10 @@ meta_wayland_tablet_manager_update (MetaWaylandTabletManager *manager,
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
meta_wayland_tablet_seat_update (tablet_seat, event);
|
||||
break;
|
||||
default:
|
||||
@ -216,6 +222,10 @@ meta_wayland_tablet_manager_handle_event (MetaWaylandTabletManager *manager,
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
return meta_wayland_tablet_seat_handle_event (tablet_seat, event);
|
||||
default:
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
@ -232,7 +242,7 @@ meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager,
|
||||
|
||||
if (!tablet_seat)
|
||||
{
|
||||
tablet_seat = meta_wayland_tablet_seat_new (manager);
|
||||
tablet_seat = meta_wayland_tablet_seat_new (manager, seat);
|
||||
g_hash_table_insert (manager->seats, seat, tablet_seat);
|
||||
}
|
||||
|
||||
|
458
src/wayland/meta-wayland-tablet-pad-group.c
Normal file
458
src/wayland/meta-wayland-tablet-pad-group.c
Normal file
@ -0,0 +1,458 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-tablet-seat.h"
|
||||
#include "meta-wayland-tablet-pad.h"
|
||||
#include "meta-wayland-tablet-pad-group.h"
|
||||
#include "meta-wayland-tablet-pad-ring.h"
|
||||
#include "meta-wayland-tablet-pad-strip.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
MetaWaylandTabletPadGroup *
|
||||
meta_wayland_tablet_pad_group_new (MetaWaylandTabletPad *pad)
|
||||
{
|
||||
MetaWaylandTabletPadGroup *group;
|
||||
|
||||
group = g_slice_new0 (MetaWaylandTabletPadGroup);
|
||||
wl_list_init (&group->resource_list);
|
||||
wl_list_init (&group->focus_resource_list);
|
||||
group->pad = pad;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_group_free (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
struct wl_resource *resource, *next;
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &group->resource_list)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_init (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
g_list_free (group->rings);
|
||||
g_list_free (group->strips);
|
||||
|
||||
g_slice_free (MetaWaylandTabletPadGroup, group);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_group_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
static const struct zwp_tablet_pad_group_v2_interface group_interface = {
|
||||
tablet_pad_group_destroy
|
||||
};
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_group_create_new_resource (MetaWaylandTabletPadGroup *group,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *pad_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_pad_group_v2_interface,
|
||||
wl_resource_get_version (pad_resource), id);
|
||||
wl_resource_set_implementation (resource, &group_interface,
|
||||
group, unbind_resource);
|
||||
wl_resource_set_user_data (resource, group);
|
||||
wl_list_insert (&group->resource_list, wl_resource_get_link (resource));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_group_lookup_resource (MetaWaylandTabletPadGroup *group,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&group->resource_list, client);
|
||||
|
||||
if (!resource)
|
||||
resource = wl_resource_find_for_client (&group->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static guint
|
||||
tablet_pad_group_get_current_mode (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
struct libinput_device *libinput_device;
|
||||
struct libinput_tablet_pad_mode_group *mode_group;
|
||||
guint n_group;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (group->pad->device);
|
||||
n_group = g_list_index (group->pad->groups, group);
|
||||
mode_group = libinput_device_tablet_pad_get_mode_group (libinput_device, n_group);
|
||||
|
||||
return libinput_tablet_pad_mode_group_get_mode (mode_group);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint
|
||||
tablet_pad_group_get_n_modes (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
guint n_modes = 1;
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
struct libinput_device *libinput_device;
|
||||
struct libinput_tablet_pad_mode_group *mode_group;
|
||||
guint n_group;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (group->pad->device);
|
||||
n_group = g_list_index (group->pad->groups, group);
|
||||
mode_group = libinput_device_tablet_pad_get_mode_group (libinput_device, n_group);
|
||||
n_modes = libinput_tablet_pad_mode_group_get_num_modes (mode_group);
|
||||
}
|
||||
#endif
|
||||
|
||||
return n_modes;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_group_has_button (MetaWaylandTabletPadGroup *group,
|
||||
guint button)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
struct libinput_device *libinput_device;
|
||||
struct libinput_tablet_pad_mode_group *mode_group;
|
||||
guint n_group;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (group->pad->device);
|
||||
n_group = g_list_index (group->pad->groups, group);
|
||||
mode_group = libinput_device_tablet_pad_get_mode_group (libinput_device, n_group);
|
||||
|
||||
return libinput_tablet_pad_mode_group_has_button (mode_group, button);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return g_list_length (group->pad->groups) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_group_send_buttons (MetaWaylandTabletPadGroup *group,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
struct wl_array buttons;
|
||||
guint i;
|
||||
|
||||
wl_array_init (&buttons);
|
||||
|
||||
for (i = 0; i < group->pad->n_buttons; i++)
|
||||
{
|
||||
uint32_t *pos;
|
||||
|
||||
if (!meta_wayland_tablet_pad_group_has_button (group, i))
|
||||
continue;
|
||||
|
||||
pos = wl_array_add (&buttons, sizeof (*pos));
|
||||
*pos = i;
|
||||
}
|
||||
|
||||
zwp_tablet_pad_group_v2_send_buttons (resource, &buttons);
|
||||
wl_array_release (&buttons);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_group_notify (MetaWaylandTabletPadGroup *group,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_array buttons;
|
||||
guint n_modes;
|
||||
GList *l;
|
||||
|
||||
wl_array_init (&buttons);
|
||||
|
||||
/* Buttons */
|
||||
meta_wayland_tablet_pad_group_send_buttons (group, resource);
|
||||
|
||||
/* Rings */
|
||||
for (l = group->rings; l; l = l->next)
|
||||
{
|
||||
MetaWaylandTabletPadRing *ring = l->data;
|
||||
struct wl_resource *ring_resource;
|
||||
|
||||
ring_resource = meta_wayland_tablet_pad_ring_create_new_resource (ring,
|
||||
client,
|
||||
resource,
|
||||
0);
|
||||
zwp_tablet_pad_group_v2_send_ring (resource, ring_resource);
|
||||
}
|
||||
|
||||
/* Strips */
|
||||
for (l = group->strips; l; l = l->next)
|
||||
{
|
||||
MetaWaylandTabletPadStrip *strip = l->data;
|
||||
struct wl_resource *strip_resource;
|
||||
|
||||
strip_resource = meta_wayland_tablet_pad_strip_create_new_resource (strip,
|
||||
client,
|
||||
resource,
|
||||
0);
|
||||
zwp_tablet_pad_group_v2_send_strip (resource, strip_resource);
|
||||
}
|
||||
|
||||
n_modes = tablet_pad_group_get_n_modes (group);
|
||||
zwp_tablet_pad_group_v2_send_modes (resource, n_modes);
|
||||
zwp_tablet_pad_group_v2_send_done (resource);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_group_update (MetaWaylandTabletPadGroup *group,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, event->pad_button.button))
|
||||
group->current_mode = tablet_pad_group_get_current_mode (group);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_pad_ring_event (MetaWaylandTabletPadGroup *group,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTabletPadRing *ring;
|
||||
|
||||
if (event->type != CLUTTER_PAD_RING)
|
||||
return FALSE;
|
||||
|
||||
ring = g_list_nth_data (group->rings, event->pad_ring.ring_number);
|
||||
|
||||
if (!ring)
|
||||
return FALSE;
|
||||
|
||||
return meta_wayland_tablet_pad_ring_handle_event (ring, event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_pad_strip_event (MetaWaylandTabletPadGroup *group,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTabletPadStrip *strip;
|
||||
|
||||
if (event->type != CLUTTER_PAD_STRIP)
|
||||
return FALSE;
|
||||
|
||||
strip = g_list_nth_data (group->strips, event->pad_strip.strip_number);
|
||||
|
||||
if (!strip)
|
||||
return FALSE;
|
||||
|
||||
return meta_wayland_tablet_pad_strip_handle_event (strip, event);
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_group_mode (MetaWaylandTabletPadGroup *group,
|
||||
uint32_t time)
|
||||
{
|
||||
struct wl_display *display = group->pad->tablet_seat->seat->wl_display;
|
||||
struct wl_list *l = &group->focus_resource_list;
|
||||
struct wl_resource *resource;
|
||||
|
||||
group->mode_switch_serial = wl_display_next_serial (display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
zwp_tablet_pad_group_v2_send_mode_switch (resource, time,
|
||||
group->mode_switch_serial,
|
||||
group->current_mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_group_buttons (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
struct wl_list *l = &group->focus_resource_list;
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
meta_wayland_tablet_pad_group_send_buttons (group, resource);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_group_handle_event (MetaWaylandTabletPadGroup *group,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (clutter_event_type (event))
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, event->pad_button.button))
|
||||
{
|
||||
if (event->type == CLUTTER_PAD_BUTTON_PRESS)
|
||||
broadcast_group_mode (group, clutter_event_get_time (event));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case CLUTTER_PAD_RING:
|
||||
return handle_pad_ring_event (group, event);
|
||||
case CLUTTER_PAD_STRIP:
|
||||
return handle_pad_strip_event (group, event);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_group_update_rings_focus (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = group->rings; l; l = l->next)
|
||||
meta_wayland_tablet_pad_ring_sync_focus (l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_group_update_strips_focus (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = group->strips; l; l = l->next)
|
||||
meta_wayland_tablet_pad_strip_sync_focus (l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination, struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_group_sync_focus (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
struct wl_list *l = &group->focus_resource_list;
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
move_resources (&group->resource_list, &group->focus_resource_list);
|
||||
}
|
||||
|
||||
if (group->pad->focus_surface != NULL)
|
||||
{
|
||||
move_resources_for_client (&group->focus_resource_list,
|
||||
&group->resource_list,
|
||||
wl_resource_get_client (group->pad->focus_surface->resource));
|
||||
}
|
||||
|
||||
meta_wayland_tablet_pad_group_update_rings_focus (group);
|
||||
meta_wayland_tablet_pad_group_update_strips_focus (group);
|
||||
|
||||
broadcast_group_mode (group, clutter_get_current_event_time ());
|
||||
broadcast_group_buttons (group);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_group_is_mode_switch_button (MetaWaylandTabletPadGroup *group,
|
||||
guint button)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
struct libinput_device *libinput_device;
|
||||
struct libinput_tablet_pad_mode_group *mode_group;
|
||||
guint n_group;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (group->pad->device);
|
||||
n_group = g_list_index (group->pad->groups, group);
|
||||
mode_group = libinput_device_tablet_pad_get_mode_group (libinput_device, n_group);
|
||||
|
||||
return libinput_tablet_pad_mode_group_button_is_toggle (mode_group, button) != 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
74
src/wayland/meta-wayland-tablet-pad-group.h
Normal file
74
src/wayland/meta-wayland-tablet-pad-group.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_TABLET_PAD_GROUP_H
|
||||
#define META_WAYLAND_TABLET_PAD_GROUP_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
struct _MetaWaylandTabletPadGroup
|
||||
{
|
||||
MetaWaylandTabletPad *pad;
|
||||
GArray *buttons;
|
||||
uint32_t n_modes;
|
||||
uint32_t current_mode;
|
||||
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
uint32_t mode_switch_serial;
|
||||
|
||||
GList *strips;
|
||||
GList *rings;
|
||||
};
|
||||
|
||||
MetaWaylandTabletPadGroup * meta_wayland_tablet_pad_group_new (MetaWaylandTabletPad *pad);
|
||||
void meta_wayland_tablet_pad_group_free (MetaWaylandTabletPadGroup *group);
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_group_create_new_resource (MetaWaylandTabletPadGroup *group,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *pad_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_group_lookup_resource (MetaWaylandTabletPadGroup *group,
|
||||
struct wl_client *client);
|
||||
|
||||
void meta_wayland_tablet_pad_group_notify (MetaWaylandTabletPadGroup *group,
|
||||
struct wl_resource *resource);
|
||||
|
||||
void meta_wayland_tablet_pad_group_update (MetaWaylandTabletPadGroup *group,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_wayland_tablet_pad_group_handle_event (MetaWaylandTabletPadGroup *group,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_tablet_pad_group_sync_focus (MetaWaylandTabletPadGroup *group);
|
||||
|
||||
gboolean meta_wayland_tablet_pad_group_has_button (MetaWaylandTabletPadGroup *group,
|
||||
guint button);
|
||||
gboolean meta_wayland_tablet_pad_group_is_mode_switch_button (MetaWaylandTabletPadGroup *group,
|
||||
guint button);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_PAD_GROUP_H */
|
224
src/wayland/meta-wayland-tablet-pad-ring.c
Normal file
224
src/wayland/meta-wayland-tablet-pad-ring.c
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-tablet-pad.h"
|
||||
#include "meta-wayland-tablet-pad-group.h"
|
||||
#include "meta-wayland-tablet-pad-ring.h"
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
MetaWaylandTabletPadRing *
|
||||
meta_wayland_tablet_pad_ring_new (MetaWaylandTabletPad *pad)
|
||||
{
|
||||
MetaWaylandTabletPadRing *ring;
|
||||
|
||||
ring = g_slice_new0 (MetaWaylandTabletPadRing);
|
||||
wl_list_init (&ring->resource_list);
|
||||
wl_list_init (&ring->focus_resource_list);
|
||||
ring->pad = pad;
|
||||
|
||||
return ring;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_ring_free (MetaWaylandTabletPadRing *ring)
|
||||
{
|
||||
struct wl_resource *resource, *next;
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &ring->resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v2_send_removed (resource);
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_init (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
g_free (ring->feedback);
|
||||
g_slice_free (MetaWaylandTabletPadRing, ring);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_ring_set_feedback (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *str,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandTabletPadRing *ring = wl_resource_get_user_data (resource);
|
||||
|
||||
if (ring->group->mode_switch_serial != serial)
|
||||
return;
|
||||
|
||||
ring->feedback = g_strdup (str);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_ring_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_ring_v2_interface ring_interface = {
|
||||
tablet_pad_ring_set_feedback,
|
||||
tablet_pad_ring_destroy,
|
||||
};
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_create_new_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_pad_ring_v2_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &ring_interface,
|
||||
ring, unbind_resource);
|
||||
wl_resource_set_user_data (resource, ring);
|
||||
wl_list_insert (&ring->resource_list, wl_resource_get_link (resource));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_lookup_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&ring->resource_list, client);
|
||||
|
||||
if (!resource)
|
||||
resource = wl_resource_find_for_client (&ring->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_ring_handle_event (MetaWaylandTabletPadRing *ring,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_list *l = &ring->focus_resource_list;
|
||||
enum zwp_tablet_pad_ring_v2_source source;
|
||||
gboolean source_known = FALSE;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (wl_list_empty (l))
|
||||
return FALSE;
|
||||
if (event->type != CLUTTER_PAD_RING)
|
||||
return FALSE;
|
||||
|
||||
if (event->pad_ring.ring_source == CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER)
|
||||
{
|
||||
source = ZWP_TABLET_PAD_RING_V2_SOURCE_FINGER;
|
||||
source_known = TRUE;
|
||||
}
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
gdouble angle = event->pad_ring.angle;
|
||||
|
||||
if (source_known)
|
||||
zwp_tablet_pad_ring_v2_send_source (resource, source);
|
||||
|
||||
if (angle >= 0)
|
||||
zwp_tablet_pad_ring_v2_send_angle (resource,
|
||||
wl_fixed_from_double (angle));
|
||||
else
|
||||
zwp_tablet_pad_ring_v2_send_stop (resource);
|
||||
|
||||
zwp_tablet_pad_ring_v2_send_frame (resource,
|
||||
clutter_event_get_time (event));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination, struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_ring_sync_focus (MetaWaylandTabletPadRing *ring)
|
||||
{
|
||||
struct wl_list *l = &ring->focus_resource_list;
|
||||
|
||||
g_clear_pointer (&ring->feedback, g_free);
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
move_resources (&ring->resource_list, &ring->focus_resource_list);
|
||||
}
|
||||
|
||||
if (ring->pad->focus_surface != NULL)
|
||||
{
|
||||
move_resources_for_client (&ring->focus_resource_list,
|
||||
&ring->resource_list,
|
||||
wl_resource_get_client (ring->pad->focus_surface->resource));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_ring_set_group (MetaWaylandTabletPadRing *ring,
|
||||
MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
/* Group is static, can only be set once */
|
||||
g_assert (ring->group == NULL);
|
||||
|
||||
ring->group = group;
|
||||
group->rings = g_list_append (group->rings, ring);
|
||||
}
|
63
src/wayland/meta-wayland-tablet-pad-ring.h
Normal file
63
src/wayland/meta-wayland-tablet-pad-ring.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_TABLET_PAD_RING_H
|
||||
#define META_WAYLAND_TABLET_PAD_RING_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
struct _MetaWaylandTabletPadRing
|
||||
{
|
||||
MetaWaylandTabletPad *pad;
|
||||
MetaWaylandTabletPadGroup *group;
|
||||
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
|
||||
gchar *feedback;
|
||||
};
|
||||
|
||||
MetaWaylandTabletPadRing * meta_wayland_tablet_pad_ring_new (MetaWaylandTabletPad *pad);
|
||||
void meta_wayland_tablet_pad_ring_free (MetaWaylandTabletPadRing *ring);
|
||||
|
||||
void meta_wayland_tablet_pad_ring_set_group (MetaWaylandTabletPadRing *ring,
|
||||
MetaWaylandTabletPadGroup *group);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_create_new_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *pad_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_lookup_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client);
|
||||
|
||||
gboolean meta_wayland_tablet_pad_ring_handle_event (MetaWaylandTabletPadRing *ring,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_tablet_pad_ring_sync_focus (MetaWaylandTabletPadRing *ring);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_PAD_RING_H */
|
||||
|
223
src/wayland/meta-wayland-tablet-pad-strip.c
Normal file
223
src/wayland/meta-wayland-tablet-pad-strip.c
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-tablet-pad.h"
|
||||
#include "meta-wayland-tablet-pad-group.h"
|
||||
#include "meta-wayland-tablet-pad-strip.h"
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
MetaWaylandTabletPadStrip *
|
||||
meta_wayland_tablet_pad_strip_new (MetaWaylandTabletPad *pad)
|
||||
{
|
||||
MetaWaylandTabletPadStrip *strip;
|
||||
|
||||
strip = g_slice_new0 (MetaWaylandTabletPadStrip);
|
||||
wl_list_init (&strip->resource_list);
|
||||
wl_list_init (&strip->focus_resource_list);
|
||||
strip->pad = pad;
|
||||
|
||||
return strip;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_strip_free (MetaWaylandTabletPadStrip *strip)
|
||||
{
|
||||
struct wl_resource *resource, *next;
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &strip->resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v2_send_removed (resource);
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_init (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
g_free (strip->feedback);
|
||||
g_slice_free (MetaWaylandTabletPadStrip, strip);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_strip_set_feedback (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *str,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandTabletPadStrip *strip = wl_resource_get_user_data (resource);
|
||||
|
||||
if (strip->group->mode_switch_serial != serial)
|
||||
return;
|
||||
|
||||
strip->feedback = g_strdup (str);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_strip_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_strip_v2_interface strip_interface = {
|
||||
tablet_pad_strip_set_feedback,
|
||||
tablet_pad_strip_destroy,
|
||||
};
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_create_new_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_pad_strip_v2_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &strip_interface,
|
||||
strip, unbind_resource);
|
||||
wl_resource_set_user_data (resource, strip);
|
||||
wl_list_insert (&strip->resource_list, wl_resource_get_link (resource));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_lookup_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&strip->resource_list, client);
|
||||
|
||||
if (!resource)
|
||||
resource = wl_resource_find_for_client (&strip->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_strip_handle_event (MetaWaylandTabletPadStrip *strip,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_list *l = &strip->focus_resource_list;
|
||||
enum zwp_tablet_pad_strip_v2_source source;
|
||||
gboolean source_known = FALSE;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (wl_list_empty (l))
|
||||
return FALSE;
|
||||
if (event->type != CLUTTER_PAD_STRIP)
|
||||
return FALSE;
|
||||
|
||||
if (event->pad_strip.strip_source == CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER)
|
||||
{
|
||||
source = ZWP_TABLET_PAD_STRIP_V2_SOURCE_FINGER;
|
||||
source_known = TRUE;
|
||||
}
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
gdouble value = event->pad_strip.value;
|
||||
|
||||
if (source_known)
|
||||
zwp_tablet_pad_strip_v2_send_source (resource, source);
|
||||
|
||||
if (value >= 0)
|
||||
zwp_tablet_pad_strip_v2_send_position (resource, (uint32_t) (value * 65535));
|
||||
else
|
||||
zwp_tablet_pad_strip_v2_send_stop (resource);
|
||||
|
||||
zwp_tablet_pad_strip_v2_send_frame (resource,
|
||||
clutter_event_get_time (event));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination, struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_strip_sync_focus (MetaWaylandTabletPadStrip *strip)
|
||||
{
|
||||
struct wl_list *l = &strip->focus_resource_list;
|
||||
|
||||
g_clear_pointer (&strip->feedback, g_free);
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
move_resources (&strip->resource_list, &strip->focus_resource_list);
|
||||
}
|
||||
|
||||
if (strip->pad->focus_surface != NULL)
|
||||
{
|
||||
move_resources_for_client (&strip->focus_resource_list,
|
||||
&strip->resource_list,
|
||||
wl_resource_get_client (strip->pad->focus_surface->resource));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_strip_set_group (MetaWaylandTabletPadStrip *strip,
|
||||
MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
/* Group is static, can only be set once */
|
||||
g_assert (strip->group == NULL);
|
||||
|
||||
strip->group = group;
|
||||
group->strips = g_list_append (group->strips, strip);
|
||||
}
|
63
src/wayland/meta-wayland-tablet-pad-strip.h
Normal file
63
src/wayland/meta-wayland-tablet-pad-strip.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_TABLET_PAD_STRIP_H
|
||||
#define META_WAYLAND_TABLET_PAD_STRIP_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
struct _MetaWaylandTabletPadStrip
|
||||
{
|
||||
MetaWaylandTabletPad *pad;
|
||||
MetaWaylandTabletPadGroup *group;
|
||||
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
|
||||
gchar *feedback;
|
||||
};
|
||||
|
||||
MetaWaylandTabletPadStrip * meta_wayland_tablet_pad_strip_new (MetaWaylandTabletPad *pad);
|
||||
void meta_wayland_tablet_pad_strip_free (MetaWaylandTabletPadStrip *strip);
|
||||
|
||||
void meta_wayland_tablet_pad_strip_set_group (MetaWaylandTabletPadStrip *strip,
|
||||
MetaWaylandTabletPadGroup *group);
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_create_new_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *pad_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_lookup_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client);
|
||||
|
||||
gboolean meta_wayland_tablet_pad_strip_handle_event (MetaWaylandTabletPadStrip *strip,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_tablet_pad_strip_sync_focus (MetaWaylandTabletPadStrip *strip);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_PAD_STRIP_H */
|
622
src/wayland/meta-wayland-tablet-pad.c
Normal file
622
src/wayland/meta-wayland-tablet-pad.c
Normal file
@ -0,0 +1,622 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-tablet-seat.h"
|
||||
#include "meta-wayland-tablet.h"
|
||||
#include "meta-wayland-tablet-pad.h"
|
||||
#include "meta-wayland-tablet-pad-group.h"
|
||||
#include "meta-wayland-tablet-pad-ring.h"
|
||||
#include "meta-wayland-tablet-pad-strip.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
pad_handle_focus_surface_destroy (struct wl_listener *listener,
|
||||
void *data)
|
||||
{
|
||||
MetaWaylandTabletPad *pad = wl_container_of (listener, pad, focus_surface_listener);
|
||||
|
||||
meta_wayland_tablet_pad_set_focus (pad, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
group_rings_strips (MetaWaylandTabletPad *pad)
|
||||
{
|
||||
gint n_group, n_elem;
|
||||
GList *g, *l;
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
struct libinput_device *libinput_device = NULL;
|
||||
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (pad->device);
|
||||
#endif
|
||||
|
||||
for (n_group = 0, g = pad->groups; g; g = g->next)
|
||||
{
|
||||
MetaWaylandTabletPadGroup *group = g->data;
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct libinput_tablet_pad_mode_group *mode_group = NULL;
|
||||
|
||||
if (libinput_device)
|
||||
mode_group = libinput_device_tablet_pad_get_mode_group (libinput_device, n_group);
|
||||
#endif
|
||||
|
||||
for (n_elem = 0, l = pad->rings; l; l = l->next)
|
||||
{
|
||||
MetaWaylandTabletPadRing *ring = l->data;
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (mode_group)
|
||||
{
|
||||
if (libinput_tablet_pad_mode_group_has_ring (mode_group, n_elem))
|
||||
meta_wayland_tablet_pad_ring_set_group (ring, group);
|
||||
}
|
||||
else
|
||||
#else
|
||||
{
|
||||
/* Assign everything to the first group */
|
||||
if (n_group == 0)
|
||||
meta_wayland_tablet_pad_ring_set_group (ring, group);
|
||||
}
|
||||
#endif
|
||||
n_elem++;
|
||||
}
|
||||
|
||||
for (n_elem = 0, l = pad->strips; l; l = l->next)
|
||||
{
|
||||
MetaWaylandTabletPadStrip *strip = l->data;
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (mode_group)
|
||||
{
|
||||
if (libinput_tablet_pad_mode_group_has_strip (mode_group, n_elem))
|
||||
meta_wayland_tablet_pad_strip_set_group (strip, group);
|
||||
}
|
||||
else
|
||||
#else
|
||||
{
|
||||
/* Assign everything to the first group */
|
||||
if (n_group == 0)
|
||||
meta_wayland_tablet_pad_strip_set_group (strip, group);
|
||||
}
|
||||
#endif
|
||||
n_elem++;
|
||||
}
|
||||
|
||||
n_group++;
|
||||
}
|
||||
}
|
||||
|
||||
MetaWaylandTabletPad *
|
||||
meta_wayland_tablet_pad_new (ClutterInputDevice *device,
|
||||
MetaWaylandTabletSeat *tablet_seat)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaWaylandTabletPad *pad;
|
||||
guint n_elems, i;
|
||||
|
||||
pad = g_slice_new0 (MetaWaylandTabletPad);
|
||||
wl_list_init (&pad->resource_list);
|
||||
wl_list_init (&pad->focus_resource_list);
|
||||
pad->focus_surface_listener.notify = pad_handle_focus_surface_destroy;
|
||||
pad->device = device;
|
||||
pad->tablet_seat = tablet_seat;
|
||||
|
||||
pad->feedback = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_free);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
/* Buttons, only can be honored this with the native backend */
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
pad->n_buttons = libinput_device_tablet_pad_get_num_buttons (libinput_device);
|
||||
}
|
||||
#endif
|
||||
|
||||
n_elems = clutter_input_device_get_n_mode_groups (pad->device);
|
||||
|
||||
for (i = 0; i < n_elems; i++)
|
||||
{
|
||||
pad->groups = g_list_prepend (pad->groups,
|
||||
meta_wayland_tablet_pad_group_new (pad));
|
||||
}
|
||||
|
||||
n_elems = clutter_input_device_get_n_rings (pad->device);
|
||||
|
||||
for (i = 0; i < n_elems; i++)
|
||||
{
|
||||
MetaWaylandTabletPadRing *ring;
|
||||
|
||||
ring = meta_wayland_tablet_pad_ring_new (pad);
|
||||
pad->rings = g_list_prepend (pad->rings, ring);
|
||||
}
|
||||
|
||||
n_elems = clutter_input_device_get_n_strips (pad->device);
|
||||
|
||||
for (i = 0; i < n_elems; i++)
|
||||
{
|
||||
MetaWaylandTabletPadStrip *strip;
|
||||
|
||||
strip = meta_wayland_tablet_pad_strip_new (pad);
|
||||
pad->strips = g_list_prepend (pad->strips, strip);
|
||||
}
|
||||
|
||||
group_rings_strips (pad);
|
||||
|
||||
return pad;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_free (MetaWaylandTabletPad *pad)
|
||||
{
|
||||
struct wl_resource *resource, *next;
|
||||
GList *l;
|
||||
|
||||
meta_wayland_tablet_pad_set_focus (pad, NULL);
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &pad->resource_list)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_removed (resource);
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_init (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
for (l = pad->groups; l; l = l->next)
|
||||
meta_wayland_tablet_pad_group_free (l->data);
|
||||
for (l = pad->rings; l; l = l->next)
|
||||
meta_wayland_tablet_pad_ring_free (l->data);
|
||||
for (l = pad->strips; l; l = l->next)
|
||||
meta_wayland_tablet_pad_strip_free (l->data);
|
||||
|
||||
g_list_free (pad->groups);
|
||||
g_list_free (pad->rings);
|
||||
g_list_free (pad->strips);
|
||||
g_hash_table_destroy (pad->feedback);
|
||||
|
||||
g_slice_free (MetaWaylandTabletPad, pad);
|
||||
}
|
||||
|
||||
static MetaWaylandTabletPadGroup *
|
||||
tablet_pad_lookup_button_group (MetaWaylandTabletPad *pad,
|
||||
guint button)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = pad->groups; l; l = l->next)
|
||||
{
|
||||
MetaWaylandTabletPadGroup *group = l->data;
|
||||
|
||||
if (meta_wayland_tablet_pad_group_has_button (group, button))
|
||||
return group;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_set_feedback (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t button,
|
||||
const char *str,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandTabletPad *pad = wl_resource_get_user_data (resource);
|
||||
MetaWaylandTabletPadGroup *group = tablet_pad_lookup_button_group (pad, button);
|
||||
MetaInputSettings *input_settings;
|
||||
|
||||
if (!group || group->mode_switch_serial != serial)
|
||||
return;
|
||||
|
||||
input_settings = meta_input_settings_get ();
|
||||
|
||||
if (input_settings &&
|
||||
meta_input_settings_is_pad_button_grabbed (input_settings, pad->device, button))
|
||||
return;
|
||||
|
||||
if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, button))
|
||||
return;
|
||||
|
||||
g_hash_table_insert (pad->feedback, GUINT_TO_POINTER (button), g_strdup (str));
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_pad_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_v2_interface pad_interface = {
|
||||
tablet_pad_set_feedback,
|
||||
tablet_pad_destroy,
|
||||
};
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_notify (MetaWaylandTabletPad *pad,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
GList *l;
|
||||
|
||||
zwp_tablet_pad_v2_send_path (resource, clutter_input_device_get_device_node (pad->device));
|
||||
zwp_tablet_pad_v2_send_buttons (resource, pad->n_buttons);
|
||||
|
||||
for (l = pad->groups; l; l = l->next)
|
||||
{
|
||||
MetaWaylandTabletPadGroup *group = l->data;
|
||||
struct wl_resource *group_resource;
|
||||
|
||||
group_resource = meta_wayland_tablet_pad_group_create_new_resource (group,
|
||||
client,
|
||||
resource,
|
||||
0);
|
||||
zwp_tablet_pad_v2_send_group (resource, group_resource);
|
||||
meta_wayland_tablet_pad_group_notify (group, group_resource);
|
||||
}
|
||||
|
||||
zwp_tablet_pad_v2_send_done (resource);
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_create_new_resource (MetaWaylandTabletPad *pad,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_pad_v2_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &pad_interface,
|
||||
pad, unbind_resource);
|
||||
wl_resource_set_user_data (resource, pad);
|
||||
wl_list_insert (&pad->resource_list, wl_resource_get_link (resource));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_lookup_resource (MetaWaylandTabletPad *pad,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&pad->resource_list, client);
|
||||
|
||||
if (!resource)
|
||||
resource = wl_resource_find_for_client (&pad->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_pad_button_event (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
enum zwp_tablet_pad_v2_button_state button_state;
|
||||
struct wl_list *l = &pad->focus_resource_list;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (wl_list_empty (l))
|
||||
return FALSE;
|
||||
|
||||
if (event->type == CLUTTER_PAD_BUTTON_PRESS)
|
||||
button_state = ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED;
|
||||
else if (event->type == CLUTTER_PAD_BUTTON_RELEASE)
|
||||
button_state = ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_button (resource,
|
||||
clutter_event_get_time (event),
|
||||
event->pad_button.button, button_state);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_update_action (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
guint button;
|
||||
|
||||
button = event->pad_button.button;
|
||||
device = clutter_event_get_source_device (event);
|
||||
input_settings = meta_input_settings_get ();
|
||||
|
||||
if (!input_settings)
|
||||
return;
|
||||
|
||||
meta_input_settings_handle_pad_button (input_settings, device,
|
||||
event->type == CLUTTER_PAD_BUTTON_PRESS,
|
||||
button);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_wayland_tablet_pad_handle_event_action (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
input_settings = meta_input_settings_get ();
|
||||
|
||||
if (input_settings &&
|
||||
meta_input_settings_is_pad_button_grabbed (input_settings, device,
|
||||
event->pad_button.button))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_handle_event (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTabletPadGroup *group;
|
||||
gboolean handled = FALSE;
|
||||
guint n_group;
|
||||
|
||||
n_group = clutter_event_get_mode_group (event);
|
||||
group = g_list_nth_data (pad->groups, n_group);
|
||||
|
||||
switch (clutter_event_type (event))
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
if (group)
|
||||
handled |= meta_wayland_tablet_pad_group_handle_event (group, event);
|
||||
|
||||
handled |= meta_wayland_tablet_pad_handle_event_action (pad, event);
|
||||
|
||||
if (handled)
|
||||
return TRUE;
|
||||
|
||||
return handle_pad_button_event (pad, event);
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
if (group)
|
||||
return meta_wayland_tablet_pad_group_handle_event (group, event);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination, struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_update_groups_focus (MetaWaylandTabletPad *pad)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = pad->groups; l; l = l->next)
|
||||
meta_wayland_tablet_pad_group_sync_focus (l->data);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandTablet *tablet;
|
||||
|
||||
if (pad->focus_surface == surface)
|
||||
return;
|
||||
|
||||
g_hash_table_remove_all (pad->feedback);
|
||||
|
||||
if (pad->focus_surface != NULL)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l = &pad->focus_resource_list;
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_leave (resource, serial, pad->focus_surface->resource);
|
||||
}
|
||||
|
||||
move_resources (&pad->resource_list, &pad->focus_resource_list);
|
||||
}
|
||||
|
||||
wl_list_remove (&pad->focus_surface_listener.link);
|
||||
pad->focus_surface = NULL;
|
||||
}
|
||||
|
||||
tablet = meta_wayland_tablet_seat_lookup_paired_tablet (pad->tablet_seat, pad);
|
||||
|
||||
if (tablet != NULL && surface != NULL)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
pad->focus_surface = surface;
|
||||
wl_resource_add_destroy_listener (pad->focus_surface->resource, &pad->focus_surface_listener);
|
||||
|
||||
move_resources_for_client (&pad->focus_resource_list,
|
||||
&pad->resource_list,
|
||||
wl_resource_get_client (pad->focus_surface->resource));
|
||||
|
||||
l = &pad->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
struct wl_resource *tablet_resource =
|
||||
meta_wayland_tablet_lookup_resource (tablet, client);
|
||||
|
||||
pad->focus_serial = wl_display_next_serial (display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_enter (resource, pad->focus_serial,
|
||||
tablet_resource,
|
||||
pad->focus_surface->resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meta_wayland_tablet_pad_update_groups_focus (pad);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_update (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTabletPadGroup *group;
|
||||
guint n_group;
|
||||
|
||||
n_group = clutter_event_get_mode_group (event);
|
||||
group = g_list_nth_data (pad->groups, n_group);
|
||||
|
||||
if (group)
|
||||
meta_wayland_tablet_pad_group_update (group, event);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
meta_wayland_tablet_pad_update_action (pad, event);
|
||||
break;
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
meta_wayland_tablet_pad_label_mode_switch_button (MetaWaylandTabletPad *pad,
|
||||
guint button)
|
||||
{
|
||||
MetaWaylandTabletPadGroup *group;
|
||||
GList *l;
|
||||
|
||||
for (l = pad->groups; l; l = l->next)
|
||||
{
|
||||
group = l->data;
|
||||
|
||||
if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, button))
|
||||
return g_strdup_printf (_("Mode Switch: Mode %d"), group->current_mode + 1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gchar *
|
||||
meta_wayland_tablet_pad_get_label (MetaWaylandTabletPad *pad,
|
||||
MetaPadActionType type,
|
||||
guint action)
|
||||
{
|
||||
const gchar *label = NULL;
|
||||
gchar *mode_label;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case META_PAD_ACTION_BUTTON:
|
||||
mode_label = meta_wayland_tablet_pad_label_mode_switch_button (pad, action);
|
||||
if (mode_label)
|
||||
return mode_label;
|
||||
|
||||
label = g_hash_table_lookup (pad->feedback, GUINT_TO_POINTER (action));
|
||||
break;
|
||||
case META_PAD_ACTION_RING:
|
||||
{
|
||||
MetaWaylandTabletPadRing *ring;
|
||||
|
||||
ring = g_list_nth_data (pad->rings, action);
|
||||
if (ring)
|
||||
label = ring->feedback;
|
||||
break;
|
||||
}
|
||||
case META_PAD_ACTION_STRIP:
|
||||
{
|
||||
MetaWaylandTabletPadStrip *strip;
|
||||
|
||||
strip = g_list_nth_data (pad->strips, action);
|
||||
if (strip)
|
||||
label = strip->feedback;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return g_strdup (label);
|
||||
}
|
82
src/wayland/meta-wayland-tablet-pad.h
Normal file
82
src/wayland/meta-wayland-tablet-pad.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_TABLET_PAD_H
|
||||
#define META_WAYLAND_TABLET_PAD_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
struct _MetaWaylandTabletPad
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
|
||||
MetaWaylandSurface *focus_surface;
|
||||
struct wl_listener focus_surface_listener;
|
||||
uint32_t focus_serial;
|
||||
|
||||
uint32_t n_buttons;
|
||||
GList *groups;
|
||||
GList *rings;
|
||||
GList *strips;
|
||||
|
||||
GHashTable *feedback;
|
||||
|
||||
MetaWaylandSurface *focus;
|
||||
};
|
||||
|
||||
MetaWaylandTabletPad * meta_wayland_tablet_pad_new (ClutterInputDevice *device,
|
||||
MetaWaylandTabletSeat *tablet_seat);
|
||||
void meta_wayland_tablet_pad_free (MetaWaylandTabletPad *pad);
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_create_new_resource (MetaWaylandTabletPad *pad,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_lookup_resource (MetaWaylandTabletPad *pad,
|
||||
struct wl_client *client);
|
||||
|
||||
void meta_wayland_tablet_pad_notify (MetaWaylandTabletPad *pad,
|
||||
struct wl_resource *resource);
|
||||
|
||||
void meta_wayland_tablet_pad_update (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_wayland_tablet_pad_handle_event (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad,
|
||||
MetaWaylandSurface *surface);
|
||||
|
||||
gchar * meta_wayland_tablet_pad_get_label (MetaWaylandTabletPad *pad,
|
||||
MetaPadActionType type,
|
||||
guint action);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_PAD_H */
|
@ -28,12 +28,18 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v1-server-protocol.h"
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-tablet-seat.h"
|
||||
#include "meta-wayland-tablet.h"
|
||||
#include "meta-wayland-tablet-tool.h"
|
||||
#include "meta-wayland-tablet-pad.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
@ -55,7 +61,7 @@ notify_tool_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
if (!tool_resource)
|
||||
return;
|
||||
|
||||
zwp_tablet_seat_v1_send_tool_added (client_resource, tool_resource);
|
||||
zwp_tablet_seat_v2_send_tool_added (client_resource, tool_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -82,7 +88,7 @@ notify_tablet_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
zwp_tablet_seat_v1_send_tablet_added (client_resource, resource);
|
||||
zwp_tablet_seat_v2_send_tablet_added (client_resource, resource);
|
||||
meta_wayland_tablet_notify (tablet, resource);
|
||||
}
|
||||
|
||||
@ -111,6 +117,59 @@ notify_tablets (MetaWaylandTabletSeat *tablet_seat,
|
||||
notify_tablet_added (tablet_seat, client_resource, device);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_pad_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_resource *client_resource,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandTabletPad *pad;
|
||||
struct wl_client *client;
|
||||
|
||||
pad = g_hash_table_lookup (tablet_seat->pads, device);
|
||||
|
||||
if (!pad)
|
||||
return;
|
||||
|
||||
client = wl_resource_get_client (client_resource);
|
||||
|
||||
if (meta_wayland_tablet_pad_lookup_resource (pad, client))
|
||||
return;
|
||||
|
||||
resource = meta_wayland_tablet_pad_create_new_resource (pad, client,
|
||||
client_resource, 0);
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
zwp_tablet_seat_v2_send_pad_added (client_resource, resource);
|
||||
meta_wayland_tablet_pad_notify (pad, resource);
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_pad_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, &tablet_seat->resource_list)
|
||||
{
|
||||
notify_pad_added (tablet_seat, resource, device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
notify_pads (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_resource *client_resource)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, tablet_seat->pads);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &device, NULL))
|
||||
notify_pad_added (tablet_seat, client_resource, device);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_tablet_device (ClutterInputDevice *device)
|
||||
{
|
||||
@ -127,18 +186,56 @@ is_tablet_device (ClutterInputDevice *device)
|
||||
device_type == CLUTTER_CURSOR_DEVICE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_pad_device (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
|
||||
return FALSE;
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
|
||||
return device_type == CLUTTER_PAD_DEVICE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_seat_device_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaWaylandTablet *tablet;
|
||||
MetaWaylandSurface *pad_focus = tablet_seat->seat->keyboard.focus_surface;
|
||||
|
||||
if (!is_tablet_device (device))
|
||||
return;
|
||||
if (is_tablet_device (device))
|
||||
{
|
||||
MetaWaylandTablet *tablet;
|
||||
GList *pads, *l;
|
||||
|
||||
tablet = meta_wayland_tablet_new (device, tablet_seat);
|
||||
g_hash_table_insert (tablet_seat->tablets, device, tablet);
|
||||
broadcast_tablet_added (tablet_seat, device);
|
||||
tablet = meta_wayland_tablet_new (device, tablet_seat);
|
||||
g_hash_table_insert (tablet_seat->tablets, device, tablet);
|
||||
broadcast_tablet_added (tablet_seat, device);
|
||||
|
||||
/* Because the insertion order is undefined, there might be already
|
||||
* pads that are logically paired to this tablet. Look those up and
|
||||
* refocus them.
|
||||
*/
|
||||
pads = meta_wayland_tablet_seat_lookup_paired_pads (tablet_seat,
|
||||
tablet);
|
||||
|
||||
for (l = pads; l; l = l->next)
|
||||
meta_wayland_tablet_pad_set_focus (l->data, pad_focus);
|
||||
|
||||
g_list_free (pads);
|
||||
}
|
||||
else if (is_pad_device (device))
|
||||
{
|
||||
MetaWaylandTabletPad *pad;
|
||||
|
||||
pad = meta_wayland_tablet_pad_new (device, tablet_seat);
|
||||
g_hash_table_insert (tablet_seat->pads, device, pad);
|
||||
broadcast_pad_added (tablet_seat, device);
|
||||
|
||||
meta_wayland_tablet_pad_set_focus (pad, pad_focus);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -146,6 +243,7 @@ meta_wayland_tablet_seat_device_removed (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
g_hash_table_remove (tablet_seat->tablets, device);
|
||||
g_hash_table_remove (tablet_seat->pads, device);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -155,23 +253,27 @@ tablet_seat_destroy (struct wl_client *client,
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_seat_v1_interface tablet_seat_interface = {
|
||||
static const struct zwp_tablet_seat_v2_interface tablet_seat_interface = {
|
||||
tablet_seat_destroy
|
||||
};
|
||||
|
||||
MetaWaylandTabletSeat *
|
||||
meta_wayland_tablet_seat_new (MetaWaylandTabletManager *manager)
|
||||
meta_wayland_tablet_seat_new (MetaWaylandTabletManager *manager,
|
||||
MetaWaylandSeat *seat)
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
const GSList *devices, *l;
|
||||
|
||||
tablet_seat = g_slice_new0 (MetaWaylandTabletSeat);
|
||||
tablet_seat->manager = manager;
|
||||
tablet_seat->seat = seat;
|
||||
tablet_seat->device_manager = clutter_device_manager_get_default ();
|
||||
tablet_seat->tablets = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) meta_wayland_tablet_free);
|
||||
tablet_seat->tools = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) meta_wayland_tablet_tool_free);
|
||||
tablet_seat->pads = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) meta_wayland_tablet_pad_free);
|
||||
wl_list_init (&tablet_seat->resource_list);
|
||||
|
||||
g_signal_connect_swapped (tablet_seat->device_manager, "device-added",
|
||||
@ -204,6 +306,7 @@ meta_wayland_tablet_seat_free (MetaWaylandTabletSeat *tablet_seat)
|
||||
tablet_seat);
|
||||
g_hash_table_destroy (tablet_seat->tablets);
|
||||
g_hash_table_destroy (tablet_seat->tools);
|
||||
g_hash_table_destroy (tablet_seat->pads);
|
||||
g_slice_free (MetaWaylandTabletSeat, tablet_seat);
|
||||
}
|
||||
|
||||
@ -215,7 +318,7 @@ meta_wayland_tablet_seat_create_new_resource (MetaWaylandTabletSeat *tablet_seat
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_seat_v1_interface,
|
||||
resource = wl_resource_create (client, &zwp_tablet_seat_v2_interface,
|
||||
wl_resource_get_version (manager_resource),
|
||||
id);
|
||||
wl_resource_set_implementation (resource, &tablet_seat_interface,
|
||||
@ -223,8 +326,9 @@ meta_wayland_tablet_seat_create_new_resource (MetaWaylandTabletSeat *tablet_seat
|
||||
wl_resource_set_user_data (resource, tablet_seat);
|
||||
wl_list_insert (&tablet_seat->resource_list, wl_resource_get_link (resource));
|
||||
|
||||
/* Notify client of all available tablets */
|
||||
/* Notify client of all available tablets/pads */
|
||||
notify_tablets (tablet_seat, resource);
|
||||
notify_pads (tablet_seat, resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
@ -250,6 +354,13 @@ meta_wayland_tablet_seat_lookup_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
return g_hash_table_lookup (tablet_seat->tools, tool);
|
||||
}
|
||||
|
||||
MetaWaylandTabletPad *
|
||||
meta_wayland_tablet_seat_lookup_pad (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
return g_hash_table_lookup (tablet_seat->pads, device);
|
||||
}
|
||||
|
||||
static MetaWaylandTabletTool *
|
||||
meta_wayland_tablet_seat_ensure_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device,
|
||||
@ -275,15 +386,9 @@ meta_wayland_tablet_seat_update (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDeviceTool *device_tool;
|
||||
MetaWaylandTabletTool *tool = NULL;
|
||||
MetaWaylandTabletPad *pad = NULL;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
device_tool = clutter_event_get_device_tool (event);
|
||||
|
||||
if (device && device_tool)
|
||||
tool = meta_wayland_tablet_seat_ensure_tool (tablet_seat, device, device_tool);
|
||||
|
||||
if (!tool)
|
||||
return;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
@ -292,8 +397,25 @@ meta_wayland_tablet_seat_update (MetaWaylandTabletSeat *tablet_seat,
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
device_tool = clutter_event_get_device_tool (event);
|
||||
|
||||
if (device && device_tool)
|
||||
tool = meta_wayland_tablet_seat_ensure_tool (tablet_seat, device, device_tool);
|
||||
|
||||
if (!tool)
|
||||
return;
|
||||
|
||||
meta_wayland_tablet_tool_update (tool, event);
|
||||
break;
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
pad = g_hash_table_lookup (tablet_seat->pads, device);
|
||||
if (!pad)
|
||||
return;
|
||||
|
||||
return meta_wayland_tablet_pad_update (pad, event);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -305,14 +427,7 @@ meta_wayland_tablet_seat_handle_event (MetaWaylandTabletSeat *tablet_seat,
|
||||
{
|
||||
ClutterInputDeviceTool *device_tool;
|
||||
MetaWaylandTabletTool *tool = NULL;
|
||||
|
||||
device_tool = clutter_event_get_device_tool (event);
|
||||
|
||||
if (device_tool)
|
||||
tool = g_hash_table_lookup (tablet_seat->tools, device_tool);
|
||||
|
||||
if (!tool)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
MetaWaylandTabletPad *pad = NULL;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
@ -321,8 +436,26 @@ meta_wayland_tablet_seat_handle_event (MetaWaylandTabletSeat *tablet_seat,
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
device_tool = clutter_event_get_device_tool (event);
|
||||
|
||||
if (device_tool)
|
||||
tool = g_hash_table_lookup (tablet_seat->tools, device_tool);
|
||||
|
||||
if (!tool)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
meta_wayland_tablet_tool_handle_event (tool, event);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
pad = g_hash_table_lookup (tablet_seat->pads,
|
||||
clutter_event_get_source_device (event));
|
||||
if (!pad)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
return meta_wayland_tablet_pad_handle_event (pad, event);
|
||||
default:
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
@ -340,3 +473,87 @@ meta_wayland_tablet_seat_notify_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
if (resource)
|
||||
notify_tool_added (tablet_seat, resource, tool);
|
||||
}
|
||||
|
||||
static GList *
|
||||
lookup_grouped_devices (ClutterInputDevice *device,
|
||||
ClutterInputDeviceType type)
|
||||
{
|
||||
struct libinput_device *dev, *libinput_device;
|
||||
ClutterDeviceManager *device_manager;
|
||||
const GSList *devices, *l;
|
||||
GList *group = NULL;
|
||||
|
||||
device_manager = clutter_device_manager_get_default ();
|
||||
devices = clutter_device_manager_peek_devices (device_manager);
|
||||
dev = clutter_evdev_input_device_get_libinput_device (device);
|
||||
|
||||
for (l = devices; l; l = l->next)
|
||||
{
|
||||
if (l->data == device)
|
||||
continue;
|
||||
if (clutter_input_device_get_device_type (l->data) != type)
|
||||
continue;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (l->data);
|
||||
|
||||
if (libinput_device_get_device_group (dev) !=
|
||||
libinput_device_get_device_group (libinput_device))
|
||||
continue;
|
||||
|
||||
group = g_list_prepend (group, l->data);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
MetaWaylandTablet *
|
||||
meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandTabletPad *pad)
|
||||
{
|
||||
MetaWaylandTablet *tablet;
|
||||
GList *devices;
|
||||
|
||||
devices = lookup_grouped_devices (pad->device, CLUTTER_TABLET_DEVICE);
|
||||
|
||||
/* We only accept one device here */
|
||||
if (!devices || devices->next)
|
||||
return NULL;
|
||||
|
||||
tablet = meta_wayland_tablet_seat_lookup_tablet (pad->tablet_seat,
|
||||
devices->data);
|
||||
g_list_free (devices);
|
||||
|
||||
return tablet;
|
||||
}
|
||||
|
||||
GList *
|
||||
meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandTablet *tablet)
|
||||
{
|
||||
GList *l, *devices, *pads = NULL;
|
||||
MetaWaylandTabletPad *pad;
|
||||
|
||||
devices = lookup_grouped_devices (tablet->device, CLUTTER_PAD_DEVICE);
|
||||
|
||||
for (l = devices; l; l = l->next)
|
||||
{
|
||||
pad = meta_wayland_tablet_seat_lookup_pad (tablet_seat, l->data);
|
||||
if (pad)
|
||||
pads = g_list_prepend (pads, pad);
|
||||
}
|
||||
|
||||
return pads;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandTabletPad *pad;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, tablet_seat->pads);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad))
|
||||
meta_wayland_tablet_pad_set_focus (pad, surface);
|
||||
}
|
||||
|
@ -31,14 +31,17 @@
|
||||
struct _MetaWaylandTabletSeat
|
||||
{
|
||||
MetaWaylandTabletManager *manager;
|
||||
MetaWaylandSeat *seat;
|
||||
ClutterDeviceManager *device_manager;
|
||||
struct wl_list resource_list;
|
||||
|
||||
GHashTable *tablets;
|
||||
GHashTable *tools;
|
||||
GHashTable *pads;
|
||||
};
|
||||
|
||||
MetaWaylandTabletSeat *meta_wayland_tablet_seat_new (MetaWaylandTabletManager *tablet_manager);
|
||||
MetaWaylandTabletSeat *meta_wayland_tablet_seat_new (MetaWaylandTabletManager *tablet_manager,
|
||||
MetaWaylandSeat *seat);
|
||||
void meta_wayland_tablet_seat_free (MetaWaylandTabletSeat *tablet_seat);
|
||||
|
||||
struct wl_resource *meta_wayland_tablet_seat_create_new_resource (MetaWaylandTabletSeat *tablet_seat,
|
||||
@ -54,6 +57,9 @@ MetaWaylandTablet *meta_wayland_tablet_seat_lookup_tablet (MetaWayland
|
||||
MetaWaylandTabletTool *meta_wayland_tablet_seat_lookup_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
MetaWaylandTabletPad *meta_wayland_tablet_seat_lookup_pad (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
void meta_wayland_tablet_seat_update (MetaWaylandTabletSeat *tablet_seat,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_wayland_tablet_seat_handle_event (MetaWaylandTabletSeat *tablet_seat,
|
||||
@ -63,4 +69,12 @@ void meta_wayland_tablet_seat_notify_tool (MetaWayland
|
||||
MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client);
|
||||
|
||||
void meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandSurface *surface);
|
||||
|
||||
MetaWaylandTablet *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandTabletPad *pad);
|
||||
GList *meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandTablet *tablet);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_SEAT_H */
|
||||
|
@ -29,22 +29,21 @@
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v1-server-protocol.h"
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-surface-role-cursor.h"
|
||||
#include "meta-wayland-surface-role-tablet-cursor.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-tablet.h"
|
||||
#include "meta-wayland-tablet-seat.h"
|
||||
#include "meta-wayland-tablet-tool.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include <linux/input-event-codes.h>
|
||||
#endif
|
||||
|
||||
#define TABLET_AXIS_MAX 65535
|
||||
#define DEGREES_PRECISION 100 /* wl_tablet_tool.tilt and .rotation define
|
||||
* angles in hundreths of a degree
|
||||
*/
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
@ -138,23 +137,23 @@ input_device_get_capabilities (ClutterInputDevice *device)
|
||||
switch (axis)
|
||||
{
|
||||
case CLUTTER_INPUT_AXIS_PRESSURE:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_PRESSURE;
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_DISTANCE:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_DISTANCE;
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_XTILT:
|
||||
case CLUTTER_INPUT_AXIS_YTILT:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_TILT;
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_TILT;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_ROTATION:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_ROTATION;
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_WHEEL:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_WHEEL;
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_SLIDER:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_SLIDER;
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -164,7 +163,7 @@ input_device_get_capabilities (ClutterInputDevice *device)
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
static enum zwp_tablet_tool_v1_type
|
||||
static enum zwp_tablet_tool_v2_type
|
||||
input_device_tool_get_type (ClutterInputDeviceTool *device_tool)
|
||||
{
|
||||
ClutterInputDeviceToolType tool_type;
|
||||
@ -175,19 +174,19 @@ input_device_tool_get_type (ClutterInputDeviceTool *device_tool)
|
||||
{
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_NONE:
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_PEN:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_PEN;
|
||||
return ZWP_TABLET_TOOL_V2_TYPE_PEN;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_ERASER:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_ERASER;
|
||||
return ZWP_TABLET_TOOL_V2_TYPE_ERASER;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_BRUSH:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_BRUSH;
|
||||
return ZWP_TABLET_TOOL_V2_TYPE_BRUSH;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_PENCIL:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_PENCIL;
|
||||
return ZWP_TABLET_TOOL_V2_TYPE_PENCIL;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_AIRBRUSH;
|
||||
return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_MOUSE:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_MOUSE;
|
||||
return ZWP_TABLET_TOOL_V2_TYPE_MOUSE;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_LENS:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_LENS;
|
||||
return ZWP_TABLET_TOOL_V2_TYPE_LENS;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
@ -202,44 +201,46 @@ meta_wayland_tablet_tool_notify_capabilities (MetaWaylandTabletTool *tool,
|
||||
|
||||
capabilities = input_device_get_capabilities (tool->device);
|
||||
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_PRESSURE))
|
||||
zwp_tablet_tool_v1_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V1_CAPABILITY_PRESSURE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_DISTANCE))
|
||||
zwp_tablet_tool_v1_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V1_CAPABILITY_DISTANCE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_TILT))
|
||||
zwp_tablet_tool_v1_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V1_CAPABILITY_TILT);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_ROTATION))
|
||||
zwp_tablet_tool_v1_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V1_CAPABILITY_ROTATION);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_SLIDER))
|
||||
zwp_tablet_tool_v1_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V1_CAPABILITY_SLIDER);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_WHEEL))
|
||||
zwp_tablet_tool_v1_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V1_CAPABILITY_WHEEL);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE))
|
||||
zwp_tablet_tool_v2_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE))
|
||||
zwp_tablet_tool_v2_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_TILT))
|
||||
zwp_tablet_tool_v2_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V2_CAPABILITY_TILT);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION))
|
||||
zwp_tablet_tool_v2_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER))
|
||||
zwp_tablet_tool_v2_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL))
|
||||
zwp_tablet_tool_v2_send_capability (resource,
|
||||
ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_notify_details (MetaWaylandTabletTool *tool,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
guint64 serial;
|
||||
guint64 serial, id;
|
||||
|
||||
zwp_tablet_tool_v1_send_type (resource,
|
||||
zwp_tablet_tool_v2_send_type (resource,
|
||||
input_device_tool_get_type (tool->device_tool));
|
||||
|
||||
serial = (guint64) clutter_input_device_tool_get_serial (tool->device_tool);
|
||||
zwp_tablet_tool_v1_send_hardware_serial (resource, (uint32_t) (serial >> 32),
|
||||
serial = clutter_input_device_tool_get_serial (tool->device_tool);
|
||||
zwp_tablet_tool_v2_send_hardware_serial (resource, (uint32_t) (serial >> 32),
|
||||
(uint32_t) (serial & G_MAXUINT32));
|
||||
|
||||
id = clutter_input_device_tool_get_id (tool->device_tool);
|
||||
zwp_tablet_tool_v2_send_hardware_id_wacom (resource, (uint32_t) (id >> 32),
|
||||
(uint32_t) (id & G_MAXUINT32));
|
||||
|
||||
meta_wayland_tablet_tool_notify_capabilities (tool, resource);
|
||||
|
||||
/* FIXME: zwp_tablet_tool_v1.hardware_id_wacom missing */
|
||||
|
||||
zwp_tablet_tool_v1_send_done (resource);
|
||||
zwp_tablet_tool_v2_send_done (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -274,7 +275,7 @@ broadcast_proximity_in (MetaWaylandTabletTool *tool)
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_proximity_in (resource, tool->proximity_serial,
|
||||
zwp_tablet_tool_v2_send_proximity_in (resource, tool->proximity_serial,
|
||||
tablet_resource,
|
||||
tool->focus_surface->resource);
|
||||
}
|
||||
@ -287,7 +288,7 @@ broadcast_proximity_out (MetaWaylandTabletTool *tool)
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_proximity_out (resource);
|
||||
zwp_tablet_tool_v2_send_proximity_out (resource);
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,7 +301,7 @@ broadcast_frame (MetaWaylandTabletTool *tool,
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_frame (resource, _time);
|
||||
zwp_tablet_tool_v2_send_frame (resource, _time);
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,7 +411,7 @@ meta_wayland_tablet_tool_free (MetaWaylandTabletTool *tool)
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &tool->resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_removed (resource);
|
||||
zwp_tablet_tool_v2_send_removed (resource);
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_init (wl_resource_get_link (resource));
|
||||
}
|
||||
@ -442,7 +443,7 @@ tool_set_cursor (struct wl_client *client,
|
||||
|
||||
if (surface &&
|
||||
!meta_wayland_surface_assign_role (surface,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR))
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE_TABLET_CURSOR))
|
||||
{
|
||||
wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE,
|
||||
"wl_surface@%d already has a different role",
|
||||
@ -471,7 +472,7 @@ tool_destroy (struct wl_client *client,
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_tool_v1_interface tool_interface = {
|
||||
static const struct zwp_tablet_tool_v2_interface tool_interface = {
|
||||
tool_set_cursor,
|
||||
tool_destroy
|
||||
};
|
||||
@ -490,7 +491,7 @@ emit_proximity_in (MetaWaylandTabletTool *tool,
|
||||
tablet_resource = meta_wayland_tablet_lookup_resource (tool->current_tablet,
|
||||
client);
|
||||
|
||||
zwp_tablet_tool_v1_send_proximity_in (resource, tool->proximity_serial,
|
||||
zwp_tablet_tool_v2_send_proximity_in (resource, tool->proximity_serial,
|
||||
tablet_resource, tool->focus_surface->resource);
|
||||
}
|
||||
|
||||
@ -502,7 +503,7 @@ meta_wayland_tablet_tool_create_new_resource (MetaWaylandTabletTool *tool,
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_tool_v1_interface,
|
||||
resource = wl_resource_create (client, &zwp_tablet_tool_v2_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &tool_interface,
|
||||
tool, unbind_resource);
|
||||
@ -622,7 +623,7 @@ broadcast_motion (MetaWaylandTabletTool *tool,
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_motion (resource, sx, sy);
|
||||
zwp_tablet_tool_v2_send_motion (resource, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -636,7 +637,7 @@ broadcast_down (MetaWaylandTabletTool *tool,
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_down (resource, tool->down_serial);
|
||||
zwp_tablet_tool_v2_send_down (resource, tool->down_serial);
|
||||
}
|
||||
}
|
||||
|
||||
@ -648,7 +649,62 @@ broadcast_up (MetaWaylandTabletTool *tool,
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_up (resource);
|
||||
zwp_tablet_tool_v2_send_up (resource);
|
||||
}
|
||||
}
|
||||
|
||||
static guint32
|
||||
translate_button_action (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
GDesktopStylusButtonAction action;
|
||||
|
||||
input_settings = meta_input_settings_get ();
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
action = meta_input_settings_get_stylus_button_action (input_settings,
|
||||
tool->device_tool,
|
||||
device,
|
||||
event->button.button);
|
||||
}
|
||||
else
|
||||
{
|
||||
action = G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT;
|
||||
}
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE:
|
||||
return BTN_STYLUS;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT:
|
||||
return BTN_STYLUS2;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK:
|
||||
return BTN_BACK;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD:
|
||||
return BTN_FORWARD;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT:
|
||||
default:
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
return clutter_evdev_event_get_event_code (event);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* We can't do much better here, there's several
|
||||
* different BTN_ ranges to cover.
|
||||
*/
|
||||
return event->button.button;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,28 +715,15 @@ broadcast_button (MetaWaylandTabletTool *tool,
|
||||
struct wl_resource *resource;
|
||||
guint32 button;
|
||||
|
||||
button = translate_button_action (tool, event);
|
||||
tool->button_serial = wl_display_next_serial (tool->seat->manager->wl_display);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
button = clutter_evdev_event_get_event_code (event);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* We can't do much better here, there's several
|
||||
* different BTN_ ranges to cover.
|
||||
*/
|
||||
button = event->button.button;
|
||||
}
|
||||
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_button (resource, tool->button_serial, button,
|
||||
zwp_tablet_tool_v2_send_button (resource, tool->button_serial, button,
|
||||
event->type == CLUTTER_BUTTON_PRESS ?
|
||||
ZWP_TABLET_TOOL_V1_BUTTON_STATE_PRESSED :
|
||||
ZWP_TABLET_TOOL_V1_BUTTON_STATE_RELEASED);
|
||||
ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED :
|
||||
ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -699,6 +742,22 @@ broadcast_axis (MetaWaylandTabletTool *tool,
|
||||
if (!clutter_input_device_get_axis_value (source, event->motion.axes, axis, &val))
|
||||
return;
|
||||
|
||||
if (axis == CLUTTER_INPUT_AXIS_PRESSURE)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
input_settings = meta_input_settings_get ();
|
||||
device = clutter_event_get_source_device (event);
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
val = meta_input_settings_translate_tablet_tool_pressure (input_settings,
|
||||
tool->device_tool,
|
||||
device, val);
|
||||
}
|
||||
}
|
||||
|
||||
value = val * TABLET_AXIS_MAX;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
@ -706,13 +765,13 @@ broadcast_axis (MetaWaylandTabletTool *tool,
|
||||
switch (axis)
|
||||
{
|
||||
case CLUTTER_INPUT_AXIS_PRESSURE:
|
||||
zwp_tablet_tool_v1_send_pressure (resource, value);
|
||||
zwp_tablet_tool_v2_send_pressure (resource, value);
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_DISTANCE:
|
||||
zwp_tablet_tool_v1_send_distance (resource, value);
|
||||
zwp_tablet_tool_v2_send_distance (resource, value);
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_SLIDER:
|
||||
zwp_tablet_tool_v1_send_slider (resource, value);
|
||||
zwp_tablet_tool_v2_send_slider (resource, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -738,9 +797,9 @@ broadcast_tilt (MetaWaylandTabletTool *tool,
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_tilt (resource,
|
||||
(int32_t) (xtilt * DEGREES_PRECISION),
|
||||
(int32_t) (ytilt * DEGREES_PRECISION));
|
||||
zwp_tablet_tool_v2_send_tilt (resource,
|
||||
wl_fixed_from_double (xtilt),
|
||||
wl_fixed_from_double (ytilt));
|
||||
}
|
||||
}
|
||||
|
||||
@ -761,8 +820,8 @@ broadcast_rotation (MetaWaylandTabletTool *tool,
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_rotation (resource,
|
||||
(int32_t) rotation * DEGREES_PRECISION);
|
||||
zwp_tablet_tool_v2_send_rotation (resource,
|
||||
wl_fixed_from_double (rotation));
|
||||
}
|
||||
}
|
||||
|
||||
@ -779,15 +838,15 @@ broadcast_axes (MetaWaylandTabletTool *tool,
|
||||
device = clutter_event_get_source_device (event);
|
||||
capabilities = input_device_get_capabilities (device);
|
||||
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_PRESSURE))
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE))
|
||||
broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_PRESSURE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_DISTANCE))
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE))
|
||||
broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_DISTANCE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_TILT))
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_TILT))
|
||||
broadcast_tilt (tool, event);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_ROTATION))
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION))
|
||||
broadcast_rotation (tool, event);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_SLIDER))
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER))
|
||||
broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_SLIDER);
|
||||
|
||||
/* FIXME: Missing wp_tablet_tool.wheel */
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <glib.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v1-server-protocol.h"
|
||||
#include "tablet-unstable-v2-server-protocol.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
@ -61,7 +61,7 @@ meta_wayland_tablet_free (MetaWaylandTablet *tablet)
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &tablet->resource_list)
|
||||
{
|
||||
zwp_tablet_v1_send_removed (resource);
|
||||
zwp_tablet_v2_send_removed (resource);
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_init (wl_resource_get_link (resource));
|
||||
}
|
||||
@ -76,7 +76,7 @@ tablet_destroy (struct wl_client *client,
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_v1_interface tablet_interface = {
|
||||
static const struct zwp_tablet_v2_interface tablet_interface = {
|
||||
tablet_destroy
|
||||
};
|
||||
|
||||
@ -87,15 +87,14 @@ meta_wayland_tablet_notify (MetaWaylandTablet *tablet,
|
||||
ClutterInputDevice *device = tablet->device;
|
||||
guint vid, pid;
|
||||
|
||||
zwp_tablet_v1_send_name (resource, clutter_input_device_get_device_name (device));
|
||||
zwp_tablet_v2_send_name (resource, clutter_input_device_get_device_name (device));
|
||||
zwp_tablet_v2_send_path (resource, clutter_input_device_get_device_node (device));
|
||||
|
||||
if (sscanf (clutter_input_device_get_vendor_id (device), "%x", &vid) == 1 &&
|
||||
sscanf (clutter_input_device_get_product_id (device), "%x", &pid) == 1)
|
||||
zwp_tablet_v1_send_id (resource, vid, pid);
|
||||
zwp_tablet_v2_send_id (resource, vid, pid);
|
||||
|
||||
/* FIXME: zwp_tablet_v1.path missing */
|
||||
|
||||
zwp_tablet_v1_send_done (resource);
|
||||
zwp_tablet_v2_send_done (resource);
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
@ -106,7 +105,7 @@ meta_wayland_tablet_create_new_resource (MetaWaylandTablet *tablet,
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_v1_interface,
|
||||
resource = wl_resource_create (client, &zwp_tablet_v2_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &tablet_interface,
|
||||
tablet, unbind_resource);
|
||||
|
@ -41,6 +41,10 @@ typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager;
|
||||
typedef struct _MetaWaylandTabletSeat MetaWaylandTabletSeat;
|
||||
typedef struct _MetaWaylandTabletTool MetaWaylandTabletTool;
|
||||
typedef struct _MetaWaylandTablet MetaWaylandTablet;
|
||||
typedef struct _MetaWaylandTabletPad MetaWaylandTabletPad;
|
||||
typedef struct _MetaWaylandTabletPadGroup MetaWaylandTabletPadGroup;
|
||||
typedef struct _MetaWaylandTabletPadStrip MetaWaylandTabletPadStrip;
|
||||
typedef struct _MetaWaylandTabletPadRing MetaWaylandTabletPadRing;
|
||||
|
||||
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
|
||||
typedef struct _MetaWaylandRegion MetaWaylandRegion;
|
||||
|
Reference in New Issue
Block a user