Compare commits
31 Commits
wip/garnac
...
wip/tablet
Author | SHA1 | Date | |
---|---|---|---|
25bbb4cc40 | |||
3a963d95db | |||
212a170ae2 | |||
17f2b4ea43 | |||
4ce4f4eac9 | |||
d7b8db3c96 | |||
754a4bf287 | |||
d46586e383 | |||
38bff73d30 | |||
aaa59ab6a7 | |||
dff045963a | |||
6bbd6d2948 | |||
2ea01aa428 | |||
1a31721e57 | |||
033c78a7a2 | |||
f1afc604d9 | |||
c89edb29f9 | |||
c28fc68df1 | |||
5774875ab9 | |||
422284e0cd | |||
c72ad23b84 | |||
d0d343352c | |||
feff353081 | |||
216298dfad | |||
efd90eb471 | |||
63b1a55283 | |||
aa0eea9814 | |||
fe5f12ddb5 | |||
8110197df4 | |||
8d290f182a | |||
9d06421c1f |
@ -87,6 +87,7 @@ source_h = \
|
||||
clutter-group.h \
|
||||
clutter-image.h \
|
||||
clutter-input-device.h \
|
||||
clutter-input-device-tool.h \
|
||||
clutter-interval.h \
|
||||
clutter-keyframe-transition.h \
|
||||
clutter-keysyms.h \
|
||||
@ -167,6 +168,7 @@ source_c = \
|
||||
clutter-grid-layout.c \
|
||||
clutter-image.c \
|
||||
clutter-input-device.c \
|
||||
clutter-input-device-tool.c \
|
||||
clutter-interval.c \
|
||||
clutter-keyframe-transition.c \
|
||||
clutter-keysyms-table.c \
|
||||
@ -459,10 +461,12 @@ evdev_c_priv = \
|
||||
evdev/clutter-device-manager-evdev.c \
|
||||
evdev/clutter-input-device-evdev.c \
|
||||
evdev/clutter-event-evdev.c \
|
||||
evdev/clutter-input-device-tool-evdev.c \
|
||||
$(NULL)
|
||||
evdev_h_priv = \
|
||||
evdev/clutter-device-manager-evdev.h \
|
||||
evdev/clutter-input-device-evdev.h \
|
||||
evdev/clutter-input-device-tool-evdev.h \
|
||||
$(NULL)
|
||||
evdev_h = evdev/clutter-evdev.h
|
||||
|
||||
|
@ -132,6 +132,8 @@ struct _ClutterInputDevice
|
||||
gchar *vendor_id;
|
||||
gchar *product_id;
|
||||
|
||||
GPtrArray *tools;
|
||||
|
||||
guint has_cursor : 1;
|
||||
guint is_enabled : 1;
|
||||
};
|
||||
@ -143,6 +145,8 @@ struct _ClutterInputDeviceClass
|
||||
gboolean (* keycode_to_evdev) (ClutterInputDevice *device,
|
||||
guint hardware_keycode,
|
||||
guint *evdev_keycode);
|
||||
void (* update_from_tool) (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
};
|
||||
|
||||
/* Platform-dependent interface */
|
||||
@ -235,6 +239,15 @@ gboolean _clutter_input_device_get_scroll_delta (ClutterInputDev
|
||||
ClutterScrollDirection *direction_p,
|
||||
gdouble *delta_p);
|
||||
|
||||
ClutterInputDeviceTool * clutter_input_device_lookup_tool (ClutterInputDevice *device,
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type);
|
||||
void clutter_input_device_add_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
void clutter_input_device_update_from_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ */
|
||||
|
@ -761,6 +761,10 @@ typedef enum { /*< flags prefix=CLUTTER_EVENT >*/
|
||||
* determined by its phase field; event added in 1.24
|
||||
* @CLUTTER_TOUCHPAD_SWIPE: A swipe gesture event, the current state is
|
||||
* determined by its phase field; event added in 1.24
|
||||
* @CLUTTER_PROXIMITY_IN: A tool entered in proximity to a tablet;
|
||||
* event added in 1.28
|
||||
* @CLUTTER_PROXIMITY_OUT: A tool left from the proximity area of a tablet;
|
||||
* event added in 1.28
|
||||
* @CLUTTER_EVENT_LAST: Marks the end of the #ClutterEventType enumeration;
|
||||
* added in 1.10
|
||||
*
|
||||
@ -788,6 +792,8 @@ typedef enum { /*< prefix=CLUTTER >*/
|
||||
CLUTTER_TOUCH_CANCEL,
|
||||
CLUTTER_TOUCHPAD_PINCH,
|
||||
CLUTTER_TOUCHPAD_SWIPE,
|
||||
CLUTTER_PROXIMITY_IN,
|
||||
CLUTTER_PROXIMITY_OUT,
|
||||
|
||||
CLUTTER_EVENT_LAST /* helper */
|
||||
} ClutterEventType;
|
||||
@ -946,6 +952,8 @@ typedef enum {
|
||||
* @CLUTTER_INPUT_AXIS_YTILT: The tile on the Y axis
|
||||
* @CLUTTER_INPUT_AXIS_WHEEL: A wheel
|
||||
* @CLUTTER_INPUT_AXIS_DISTANCE: Distance (Since 1.12)
|
||||
* @CLUTTER_INPUT_AXIS_ROTATION: Rotation along the z-axis (Since 1.28)
|
||||
* @CLUTTER_INPUT_AXIS_SLIDER: A slider (Since 1.28)
|
||||
* @CLUTTER_INPUT_AXIS_LAST: Last value of the enumeration; this value is
|
||||
* useful when iterating over the enumeration values (Since 1.12)
|
||||
*
|
||||
@ -963,6 +971,8 @@ typedef enum {
|
||||
CLUTTER_INPUT_AXIS_YTILT,
|
||||
CLUTTER_INPUT_AXIS_WHEEL,
|
||||
CLUTTER_INPUT_AXIS_DISTANCE,
|
||||
CLUTTER_INPUT_AXIS_ROTATION,
|
||||
CLUTTER_INPUT_AXIS_SLIDER,
|
||||
|
||||
CLUTTER_INPUT_AXIS_LAST
|
||||
} ClutterInputAxis;
|
||||
@ -1484,6 +1494,32 @@ typedef enum {
|
||||
CLUTTER_SCROLL_FINISHED_VERTICAL = 1 << 1
|
||||
} ClutterScrollFinishFlags;
|
||||
|
||||
/**
|
||||
* ClutterInputDeviceToolType:
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_NONE: No tool
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_PEN: The tool is a pen
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_ERASER: The tool is an eraser
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_BRUSH: The tool is a brush
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_PENCIL: The tool is a pencil
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH: The tool is an airbrush
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_MOUSE: The tool is a mouse
|
||||
* @CLUTTER_INPUT_DEVICE_TOOL_LENS: The tool is a lens
|
||||
*
|
||||
* Defines the type of tool that a #ClutterInputDeviceTool represents.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
typedef enum {
|
||||
CLUTTER_INPUT_DEVICE_TOOL_NONE,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_PEN,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_ERASER,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_BRUSH,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_PENCIL,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_MOUSE,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_LENS
|
||||
} ClutterInputDeviceToolType;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ENUMS_H__ */
|
||||
|
@ -54,6 +54,8 @@ typedef struct _ClutterEventPrivate {
|
||||
gdouble delta_x;
|
||||
gdouble delta_y;
|
||||
|
||||
ClutterInputDeviceTool *tool;
|
||||
|
||||
gpointer platform_data;
|
||||
|
||||
ClutterModifierType button_state;
|
||||
@ -409,6 +411,8 @@ clutter_event_get_position (const ClutterEvent *event,
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_DELETE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
clutter_point_init (position, 0.f, 0.f);
|
||||
break;
|
||||
|
||||
@ -477,6 +481,8 @@ clutter_event_set_coords (ClutterEvent *event,
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_DELETE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
@ -1122,6 +1128,11 @@ clutter_event_set_device (ClutterEvent *event,
|
||||
case CLUTTER_TOUCHPAD_SWIPE:
|
||||
/* Rely on priv data for these */
|
||||
break;
|
||||
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
event->proximity.device = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1201,11 +1212,64 @@ clutter_event_get_device (const ClutterEvent *event)
|
||||
case CLUTTER_TOUCHPAD_SWIPE:
|
||||
/* Rely on priv data for these */
|
||||
break;
|
||||
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
device = event->proximity.device;
|
||||
break;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_set_device_tool:
|
||||
* @event: a #ClutterEvent
|
||||
* @tool: (nullable): a #ClutterInputDeviceTool
|
||||
*
|
||||
* Sets the tool in use for this event
|
||||
*
|
||||
* Since: 1.28
|
||||
**/
|
||||
void
|
||||
clutter_event_set_device_tool (ClutterEvent *event,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
real_event->tool = tool;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_device_tool:
|
||||
* @event: a #ClutterEvent
|
||||
*
|
||||
* Returns the device tool that originated this event
|
||||
*
|
||||
* Returns: (transfer none): The tool of this event
|
||||
*
|
||||
* Since: 1.28
|
||||
**/
|
||||
ClutterInputDeviceTool *
|
||||
clutter_event_get_device_tool (const ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
return real_event->tool;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_new:
|
||||
* @type: The type of event.
|
||||
@ -1269,6 +1333,7 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
new_real_event->button_state = real_event->button_state;
|
||||
new_real_event->latched_state = real_event->latched_state;
|
||||
new_real_event->locked_state = real_event->locked_state;
|
||||
new_real_event->tool = real_event->tool;
|
||||
}
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
@ -1617,6 +1682,8 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL:
|
||||
|
@ -117,6 +117,7 @@ typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
|
||||
typedef struct _ClutterTouchEvent ClutterTouchEvent;
|
||||
typedef struct _ClutterTouchpadPinchEvent ClutterTouchpadPinchEvent;
|
||||
typedef struct _ClutterTouchpadSwipeEvent ClutterTouchpadSwipeEvent;
|
||||
typedef struct _ClutterProximityEvent ClutterProximityEvent;
|
||||
|
||||
/**
|
||||
* ClutterAnyEvent:
|
||||
@ -213,6 +214,30 @@ struct _ClutterButtonEvent
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterProximityEvent:
|
||||
* @type: event type
|
||||
* @time: event time
|
||||
* @flags: event flags
|
||||
* @stage: event source stage
|
||||
* @source: event source actor
|
||||
* @device: the device that originated the event. If you want the physical
|
||||
* device the event originated from, use clutter_event_get_source_device()
|
||||
*
|
||||
* Event for tool proximity in tablet devices
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
struct _ClutterProximityEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterCrossingEvent:
|
||||
* @type: event type
|
||||
@ -490,6 +515,7 @@ union _ClutterEvent
|
||||
ClutterTouchEvent touch;
|
||||
ClutterTouchpadPinchEvent touchpad_pinch;
|
||||
ClutterTouchpadSwipeEvent touchpad_swipe;
|
||||
ClutterProximityEvent proximity;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -575,6 +601,13 @@ void clutter_event_set_source_device (ClutterEvent
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_6
|
||||
ClutterInputDevice * clutter_event_get_source_device (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_event_set_device_tool (ClutterEvent *event,
|
||||
ClutterInputDeviceTool *tool);
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
ClutterInputDeviceTool *clutter_event_get_device_tool (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_8
|
||||
void clutter_event_set_source (ClutterEvent *event,
|
||||
ClutterActor *actor);
|
||||
|
172
clutter/clutter/clutter-input-device-tool.c
Normal file
172
clutter/clutter/clutter-input-device-tool.c
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright © 2009, 2010, 2011 Intel Corp.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-input-device-tool.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
typedef struct _ClutterInputDeviceToolPrivate ClutterInputDeviceToolPrivate;
|
||||
|
||||
struct _ClutterInputDeviceToolPrivate
|
||||
{
|
||||
ClutterInputDeviceToolType type;
|
||||
guint64 serial;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_TYPE,
|
||||
PROP_SERIAL,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *props[PROP_LAST] = { NULL, };
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputDeviceTool, clutter_input_device_tool, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterInputDeviceTool *tool = CLUTTER_INPUT_DEVICE_TOOL (object);
|
||||
ClutterInputDeviceToolPrivate *priv;
|
||||
|
||||
priv = clutter_input_device_tool_get_instance_private (tool);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TYPE:
|
||||
priv->type = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_SERIAL:
|
||||
priv->serial = g_value_get_uint64 (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterInputDeviceTool *tool = CLUTTER_INPUT_DEVICE_TOOL (object);
|
||||
ClutterInputDeviceToolPrivate *priv;
|
||||
|
||||
priv = clutter_input_device_tool_get_instance_private (tool);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TYPE:
|
||||
g_value_set_enum (value, priv->type);
|
||||
break;
|
||||
case PROP_SERIAL:
|
||||
g_value_set_uint64 (value, priv->serial);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_class_init (ClutterInputDeviceToolClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = clutter_input_device_tool_set_property;
|
||||
gobject_class->get_property = clutter_input_device_tool_get_property;
|
||||
|
||||
props[PROP_TYPE] =
|
||||
g_param_spec_enum ("type",
|
||||
P_("Tool type"),
|
||||
P_("Tool type"),
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_TYPE,
|
||||
CLUTTER_INPUT_DEVICE_TOOL_NONE,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
props[PROP_SERIAL] =
|
||||
g_param_spec_uint64 ("serial",
|
||||
P_("Tool serial"),
|
||||
P_("Tool serial"),
|
||||
0, G_MAXUINT64, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_init (ClutterInputDeviceTool *tool)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_tool_get_serial:
|
||||
* @tool: a #ClutterInputDeviceTool
|
||||
*
|
||||
* Gets the serial of this tool, this value can be used to identify a
|
||||
* physical tool (eg. a tablet pen) across program executions.
|
||||
*
|
||||
* Returns: The serial ID for this tool
|
||||
*
|
||||
* Since: 1.28
|
||||
**/
|
||||
guint
|
||||
clutter_input_device_tool_get_serial (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->serial;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* clutter_input_device_tool_get_tool_type:
|
||||
* @tool: a #ClutterInputDeviceTool
|
||||
*
|
||||
* Gets the tool type of this tool.
|
||||
*
|
||||
* Returns: The tool type of this tool
|
||||
*
|
||||
* Since: 1.28
|
||||
**/
|
||||
ClutterInputDeviceToolType
|
||||
clutter_input_device_tool_get_tool_type (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->type;
|
||||
}
|
66
clutter/clutter/clutter-input-device-tool.h
Normal file
66
clutter/clutter/clutter-input-device-tool.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright © 2009, 2010, 2011 Intel Corp.
|
||||
*
|
||||
* 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 __CLUTTER_INPUT_DEVICE_TOOL_H__
|
||||
#define __CLUTTER_INPUT_DEVICE_TOOL_H__
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <clutter/clutter-types.h>
|
||||
#include "clutter-enum-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_INPUT_DEVICE_TOOL (clutter_input_device_tool_get_type ())
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_TOOL, ClutterInputDeviceTool))
|
||||
#define CLUTTER_IS_INPUT_DEVICE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_TOOL))
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_INPUT_DEVICE_TOOL, ClutterInputDeviceToolClass))
|
||||
#define CLUTTER_IS_INPUT_DEVICE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_INPUT_DEVICE_TOOL))
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_INPUT_DEVICE_TOOL, ClutterInputDeviceToolClass))
|
||||
|
||||
typedef struct _ClutterInputDeviceToolClass ClutterInputDeviceToolClass;
|
||||
|
||||
struct _ClutterInputDeviceTool
|
||||
{
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _ClutterInputDeviceToolClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
ClutterInputDeviceToolType clutter_input_device_tool_get_tool_type (ClutterInputDeviceTool *tool);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_TOOL_H__ */
|
@ -45,6 +45,7 @@
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-input-device-tool.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@ -73,7 +74,11 @@ enum
|
||||
};
|
||||
|
||||
static void _clutter_input_device_free_touch_info (gpointer data);
|
||||
|
||||
static void on_cursor_actor_destroy (ClutterActor *actor,
|
||||
ClutterInputDevice *device);
|
||||
static void on_cursor_actor_reactive_changed (ClutterActor *actor,
|
||||
GParamSpec *pspec,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
|
||||
|
||||
@ -103,6 +108,18 @@ clutter_input_device_dispose (GObject *gobject)
|
||||
g_clear_pointer (&device->scroll_info, g_array_unref);
|
||||
g_clear_pointer (&device->touch_sequences_info, g_hash_table_unref);
|
||||
|
||||
if (device->cursor_actor)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (device->cursor_actor,
|
||||
G_CALLBACK (on_cursor_actor_destroy),
|
||||
device);
|
||||
g_signal_handlers_disconnect_by_func (device->cursor_actor,
|
||||
G_CALLBACK (on_cursor_actor_reactive_changed),
|
||||
device);
|
||||
_clutter_actor_set_has_pointer (device->cursor_actor, FALSE);
|
||||
device->cursor_actor = NULL;
|
||||
}
|
||||
|
||||
if (device->inv_touch_sequence_actors)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
@ -110,7 +127,16 @@ clutter_input_device_dispose (GObject *gobject)
|
||||
|
||||
g_hash_table_iter_init (&iter, device->inv_touch_sequence_actors);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
g_list_free (value);
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (key,
|
||||
G_CALLBACK (on_cursor_actor_destroy),
|
||||
device);
|
||||
g_signal_handlers_disconnect_by_func (device->cursor_actor,
|
||||
G_CALLBACK (on_cursor_actor_reactive_changed),
|
||||
device);
|
||||
_clutter_actor_set_has_pointer (key, FALSE);
|
||||
g_list_free (value);
|
||||
}
|
||||
|
||||
g_hash_table_unref (device->inv_touch_sequence_actors);
|
||||
device->inv_touch_sequence_actors = NULL;
|
||||
@ -598,12 +624,6 @@ _clutter_input_device_get_actor (ClutterInputDevice *device,
|
||||
return info->actor;
|
||||
}
|
||||
|
||||
static void on_cursor_actor_destroy (ClutterActor *actor,
|
||||
ClutterInputDevice *device);
|
||||
static void on_cursor_actor_reactive_changed (ClutterActor *actor,
|
||||
GParamSpec *pspec,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
static void
|
||||
_clutter_input_device_associate_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
@ -1992,3 +2012,57 @@ clutter_input_device_get_product_id (ClutterInputDevice *device)
|
||||
|
||||
return device->product_id;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_device_add_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
g_return_if_fail (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER);
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool));
|
||||
|
||||
if (!device->tools)
|
||||
device->tools = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
|
||||
g_ptr_array_add (device->tools, tool);
|
||||
}
|
||||
|
||||
ClutterInputDeviceTool *
|
||||
clutter_input_device_lookup_tool (ClutterInputDevice *device,
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type)
|
||||
{
|
||||
ClutterInputDeviceTool *tool;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER, NULL);
|
||||
|
||||
if (!device->tools)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < device->tools->len; i++)
|
||||
{
|
||||
tool = g_ptr_array_index (device->tools, i);
|
||||
|
||||
if (serial == clutter_input_device_tool_get_serial (tool) &&
|
||||
type == clutter_input_device_tool_get_tool_type (tool))
|
||||
return tool;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_device_update_from_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterInputDeviceClass *device_class;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
device_class = CLUTTER_INPUT_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (device_class->update_from_tool)
|
||||
device_class->update_from_tool (device, tool);
|
||||
}
|
||||
|
@ -2487,6 +2487,22 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
clutter_input_device_update_from_tool (clutter_event_get_source_device (event),
|
||||
clutter_event_get_device_tool (event));
|
||||
|
||||
if (_clutter_event_process_filters (event))
|
||||
break;
|
||||
|
||||
if (!clutter_actor_event (stage, event, TRUE))
|
||||
{
|
||||
/* and bubbling phase */
|
||||
clutter_actor_event (stage, event, FALSE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CLUTTER_STAGE_STATE:
|
||||
/* fullscreen / focus - forward to stage */
|
||||
event->any.source = stage;
|
||||
|
@ -930,7 +930,9 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
||||
* event processing function
|
||||
*/
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
if (device != NULL &&
|
||||
event->type != CLUTTER_PROXIMITY_IN &&
|
||||
event->type != CLUTTER_PROXIMITY_OUT)
|
||||
{
|
||||
ClutterModifierType event_state = clutter_event_get_state (event);
|
||||
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
|
||||
|
@ -92,6 +92,7 @@ typedef struct _ClutterAnimation ClutterAnimation;
|
||||
typedef struct _ClutterAnimator ClutterAnimator;
|
||||
typedef struct _ClutterState ClutterState;
|
||||
|
||||
typedef struct _ClutterInputDeviceTool ClutterInputDeviceTool;
|
||||
typedef struct _ClutterInputDevice ClutterInputDevice;
|
||||
|
||||
typedef CoglMatrix ClutterMatrix;
|
||||
|
@ -71,6 +71,7 @@
|
||||
#include "clutter-group.h"
|
||||
#include "clutter-image.h"
|
||||
#include "clutter-input-device.h"
|
||||
#include "clutter-input-device-tool.h"
|
||||
#include "clutter-interval.h"
|
||||
#include "clutter-keyframe-transition.h"
|
||||
#include "clutter-keysyms.h"
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "clutter-backend-private.h"
|
||||
#include "clutter-evdev.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-input-device-tool-evdev.h"
|
||||
|
||||
#include "clutter-device-manager-evdev.h"
|
||||
|
||||
@ -430,7 +431,8 @@ static ClutterEvent *
|
||||
new_absolute_motion_event (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
gfloat x,
|
||||
gfloat y)
|
||||
gfloat y,
|
||||
gdouble *axes)
|
||||
{
|
||||
gfloat stage_width, stage_height;
|
||||
ClutterDeviceManagerEvdev *manager_evdev;
|
||||
@ -449,7 +451,8 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
|
||||
|
||||
event = clutter_event_new (CLUTTER_MOTION);
|
||||
|
||||
if (manager_evdev->priv->constrain_callback)
|
||||
if (manager_evdev->priv->constrain_callback &&
|
||||
clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
manager_evdev->priv->constrain_callback (seat->core_pointer,
|
||||
us2ms (time_us),
|
||||
@ -471,13 +474,24 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
|
||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||
event->motion.x = x;
|
||||
event->motion.y = y;
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
event->motion.axes = axes;
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||
clutter_event_set_device (event, input_device);
|
||||
}
|
||||
else
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
seat->pointer_x = x;
|
||||
seat->pointer_y = y;
|
||||
if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
seat->pointer_x = x;
|
||||
seat->pointer_y = y;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
@ -485,12 +499,13 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
|
||||
static void
|
||||
notify_absolute_motion (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
gfloat x,
|
||||
gfloat y)
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gdouble *axes)
|
||||
{
|
||||
ClutterEvent *event;
|
||||
|
||||
event = new_absolute_motion_event (input_device, time_us, x, y);
|
||||
event = new_absolute_motion_event (input_device, time_us, x, y, axes);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
@ -523,7 +538,7 @@ notify_relative_motion (ClutterInputDevice *input_device,
|
||||
new_y = seat->pointer_y + dy;
|
||||
|
||||
time_us = libinput_event_pointer_get_time_usec (pointer_event);
|
||||
event = new_absolute_motion_event (input_device, time_us, new_x, new_y);
|
||||
event = new_absolute_motion_event (input_device, time_us, new_x, new_y, NULL);
|
||||
|
||||
dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event);
|
||||
dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event);
|
||||
@ -680,20 +695,26 @@ notify_button (ClutterInputDevice *input_device,
|
||||
switch (button)
|
||||
{
|
||||
case BTN_LEFT:
|
||||
case BTN_TOUCH:
|
||||
button_nr = CLUTTER_BUTTON_PRIMARY;
|
||||
break;
|
||||
|
||||
case BTN_RIGHT:
|
||||
case BTN_STYLUS:
|
||||
button_nr = CLUTTER_BUTTON_SECONDARY;
|
||||
break;
|
||||
|
||||
case BTN_MIDDLE:
|
||||
case BTN_STYLUS2:
|
||||
button_nr = CLUTTER_BUTTON_MIDDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
|
||||
button_nr = button - (BTN_LEFT - 1) + 4;
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
button_nr = button - BTN_TOOL_PEN + 4;
|
||||
else
|
||||
button_nr = button - (BTN_LEFT - 1) + 4;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -708,25 +729,47 @@ notify_button (ClutterInputDevice *input_device,
|
||||
else
|
||||
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
|
||||
|
||||
/* Update the modifiers */
|
||||
if (state)
|
||||
seat->button_state |= maskmap[button - BTN_LEFT];
|
||||
else
|
||||
seat->button_state &= ~maskmap[button - BTN_LEFT];
|
||||
if (button_nr < G_N_ELEMENTS (maskmap))
|
||||
{
|
||||
/* Update the modifiers */
|
||||
if (state)
|
||||
seat->button_state |= maskmap[button_nr - 1];
|
||||
else
|
||||
seat->button_state &= ~maskmap[button_nr - 1];
|
||||
}
|
||||
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
event->button.time = us2ms (time_us);
|
||||
event->button.stage = CLUTTER_STAGE (stage);
|
||||
event->button.device = seat->core_pointer;
|
||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||
event->button.button = button_nr;
|
||||
event->button.x = seat->pointer_x;
|
||||
event->button.y = seat->pointer_y;
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
ClutterPoint point;
|
||||
|
||||
clutter_input_device_get_coords (input_device, NULL, &point);
|
||||
event->button.x = point.x;
|
||||
event->button.y = point.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->button.x = seat->pointer_x;
|
||||
event->button.y = seat->pointer_y;
|
||||
}
|
||||
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
|
||||
_clutter_evdev_event_set_event_code (event, button);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||
clutter_event_set_device (event, input_device);
|
||||
}
|
||||
else
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
queue_event (event);
|
||||
@ -868,6 +911,44 @@ notify_swipe_gesture_event (ClutterInputDevice *input_device,
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_proximity (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
gboolean in)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event = NULL;
|
||||
|
||||
/* 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;
|
||||
|
||||
device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
if (in)
|
||||
event = clutter_event_new (CLUTTER_PROXIMITY_IN);
|
||||
else
|
||||
event = clutter_event_new (CLUTTER_PROXIMITY_OUT);
|
||||
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
|
||||
event->proximity.time = us2ms (time_us);
|
||||
event->proximity.stage = CLUTTER_STAGE (stage);
|
||||
event->proximity.device = seat->core_pointer;
|
||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_libinput (ClutterDeviceManagerEvdev *manager_evdev)
|
||||
{
|
||||
@ -1430,6 +1511,122 @@ translate_scroll_source (enum libinput_pointer_axis_source source)
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterInputDeviceToolType
|
||||
translate_tool_type (struct libinput_tablet_tool *libinput_tool)
|
||||
{
|
||||
enum libinput_tablet_tool_type tool;
|
||||
|
||||
tool = libinput_tablet_tool_get_type (libinput_tool);
|
||||
|
||||
switch (tool)
|
||||
{
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_PEN;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_ERASER;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_BRUSH;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_PENCIL;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_MOUSE;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_LENS;
|
||||
default:
|
||||
return CLUTTER_INPUT_DEVICE_TOOL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
input_device_update_tool (ClutterInputDevice *input_device,
|
||||
struct libinput_tablet_tool *libinput_tool)
|
||||
{
|
||||
ClutterInputDeviceEvdev *evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
ClutterInputDeviceTool *tool = NULL;
|
||||
ClutterInputDeviceToolType tool_type;
|
||||
guint64 tool_serial;
|
||||
|
||||
if (libinput_tool)
|
||||
{
|
||||
tool_serial = libinput_tablet_tool_get_serial (libinput_tool);
|
||||
tool_type = translate_tool_type (libinput_tool);
|
||||
tool = clutter_input_device_lookup_tool (input_device,
|
||||
tool_serial, tool_type);
|
||||
|
||||
if (!tool)
|
||||
{
|
||||
tool = clutter_input_device_tool_evdev_new (libinput_tool,
|
||||
tool_serial, tool_type);
|
||||
clutter_input_device_add_tool (input_device, tool);
|
||||
}
|
||||
}
|
||||
|
||||
evdev_device->last_tool = tool;
|
||||
}
|
||||
|
||||
static gdouble *
|
||||
translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event)
|
||||
{
|
||||
GArray *axes = g_array_new (FALSE, FALSE, sizeof (gdouble));
|
||||
struct libinput_tablet_tool *libinput_tool;
|
||||
gdouble value;
|
||||
|
||||
libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event);
|
||||
|
||||
value = libinput_event_tablet_tool_get_x (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
value = libinput_event_tablet_tool_get_y (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
|
||||
if (libinput_tablet_tool_has_distance (libinput_tool))
|
||||
{
|
||||
value = libinput_event_tablet_tool_get_distance (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
}
|
||||
|
||||
if (libinput_tablet_tool_has_pressure (libinput_tool))
|
||||
{
|
||||
value = libinput_event_tablet_tool_get_pressure (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
}
|
||||
|
||||
if (libinput_tablet_tool_has_tilt (libinput_tool))
|
||||
{
|
||||
value = libinput_event_tablet_tool_get_tilt_x (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
value = libinput_event_tablet_tool_get_tilt_y (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
}
|
||||
|
||||
if (libinput_tablet_tool_has_rotation (libinput_tool))
|
||||
{
|
||||
value = libinput_event_tablet_tool_get_rotation (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
}
|
||||
|
||||
if (libinput_tablet_tool_has_slider (libinput_tool))
|
||||
{
|
||||
value = libinput_event_tablet_tool_get_slider_position (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
}
|
||||
|
||||
if (libinput_tablet_tool_has_wheel (libinput_tool))
|
||||
{
|
||||
value = libinput_event_tablet_tool_get_wheel_delta (tablet_event);
|
||||
g_array_append_val (axes, value);
|
||||
}
|
||||
|
||||
if (axes->len == 0)
|
||||
{
|
||||
g_array_free (axes, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return (gdouble *) g_array_free (axes, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
struct libinput_event *event)
|
||||
@ -1500,7 +1697,7 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
stage_width);
|
||||
y = libinput_event_pointer_get_absolute_y_transformed (motion_event,
|
||||
stage_height);
|
||||
notify_absolute_motion (device, time_us, x, y);
|
||||
notify_absolute_motion (device, time_us, x, y, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1809,6 +2006,84 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
time_us, n_fingers, dx, dy);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||
{
|
||||
guint64 time;
|
||||
double x, y, *axes;
|
||||
gfloat stage_width, stage_height;
|
||||
ClutterStage *stage;
|
||||
struct libinput_event_tablet_tool *tablet_event =
|
||||
libinput_event_get_tablet_tool_event (event);
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
|
||||
stage = _clutter_input_device_get_stage (device);
|
||||
if (!stage)
|
||||
break;
|
||||
|
||||
axes = translate_tablet_axes (tablet_event);
|
||||
if (!axes)
|
||||
break;
|
||||
|
||||
stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
|
||||
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);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
|
||||
{
|
||||
guint64 time;
|
||||
struct libinput_event_tablet_tool *tablet_event =
|
||||
libinput_event_get_tablet_tool_event (event);
|
||||
struct libinput_tablet_tool *libinput_tool = NULL;
|
||||
enum libinput_tablet_tool_proximity_state state;
|
||||
|
||||
state = libinput_event_tablet_tool_get_proximity_state (tablet_event);
|
||||
time = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
|
||||
libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event);
|
||||
|
||||
input_device_update_tool (device, libinput_tool);
|
||||
notify_proximity (device, time, state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
{
|
||||
guint64 time;
|
||||
guint32 button_state;
|
||||
struct libinput_event_tablet_tool *tablet_event =
|
||||
libinput_event_get_tablet_tool_event (event);
|
||||
guint tablet_button;
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
tablet_button = libinput_event_tablet_tool_get_button (tablet_event);
|
||||
|
||||
button_state = libinput_event_tablet_tool_get_button_state (tablet_event) ==
|
||||
LIBINPUT_BUTTON_STATE_PRESSED;
|
||||
notify_button (device, time, tablet_button, button_state);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
|
||||
{
|
||||
guint64 time;
|
||||
guint32 button_state;
|
||||
struct libinput_event_tablet_tool *tablet_event =
|
||||
libinput_event_get_tablet_tool_event (event);
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
|
||||
button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) ==
|
||||
LIBINPUT_TABLET_TOOL_TIP_DOWN;
|
||||
notify_button (device, time, BTN_TOUCH, button_state);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
handled = FALSE;
|
||||
}
|
||||
@ -2604,5 +2879,5 @@ clutter_evdev_warp_pointer (ClutterInputDevice *pointer_device,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
notify_absolute_motion (pointer_device, ms2us(time_), x, y);
|
||||
notify_absolute_motion (pointer_device, ms2us(time_), x, y, NULL);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "clutter/clutter-device-manager-private.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-evdev.h"
|
||||
#include "clutter-input-device-tool-evdev.h"
|
||||
|
||||
#include "clutter-input-device-evdev.h"
|
||||
#include "clutter-device-manager-evdev.h"
|
||||
@ -71,6 +72,42 @@ clutter_input_device_evdev_keycode_to_evdev (ClutterInputDevice *device,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_evdev_update_from_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *evdev_tool;
|
||||
|
||||
evdev_tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (tool);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (device));
|
||||
|
||||
_clutter_input_device_reset_axes (device);
|
||||
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_X, 0, 0, 0);
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_Y, 0, 0, 0);
|
||||
|
||||
if (libinput_tablet_tool_has_distance (evdev_tool->tool))
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_DISTANCE, 0, 1, 0);
|
||||
|
||||
if (libinput_tablet_tool_has_pressure (evdev_tool->tool))
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_PRESSURE, 0, 1, 0);
|
||||
|
||||
if (libinput_tablet_tool_has_tilt (evdev_tool->tool))
|
||||
{
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_XTILT, -90, 90, 0);
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_YTILT, -90, 90, 0);
|
||||
}
|
||||
|
||||
if (libinput_tablet_tool_has_rotation (evdev_tool->tool))
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_ROTATION, 0, 360, 0);
|
||||
|
||||
if (libinput_tablet_tool_has_slider (evdev_tool->tool))
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_SLIDER, -1, 1, 0);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (device));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_evdev_class_init (ClutterInputDeviceEvdevClass *klass)
|
||||
{
|
||||
@ -78,6 +115,7 @@ clutter_input_device_evdev_class_init (ClutterInputDeviceEvdevClass *klass)
|
||||
|
||||
object_class->finalize = clutter_input_device_evdev_finalize;
|
||||
klass->keycode_to_evdev = clutter_input_device_evdev_keycode_to_evdev;
|
||||
klass->update_from_tool = clutter_input_device_evdev_update_from_tool;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -112,7 +150,7 @@ _clutter_input_device_evdev_new (ClutterDeviceManager *manager,
|
||||
device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev);
|
||||
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV,
|
||||
"id", device_id,
|
||||
"name", libinput_device_get_sysname (libinput_device),
|
||||
"name", libinput_device_get_name (libinput_device),
|
||||
"device-manager", manager,
|
||||
"device-type", type,
|
||||
"device-mode", CLUTTER_INPUT_MODE_SLAVE,
|
||||
@ -203,6 +241,8 @@ _clutter_input_device_evdev_determine_type (struct libinput_device *ldev)
|
||||
*/
|
||||
if (libinput_device_config_tap_get_finger_count (ldev) > 0)
|
||||
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_POINTER))
|
||||
return CLUTTER_POINTER_DEVICE;
|
||||
else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
|
@ -65,6 +65,7 @@ struct _ClutterInputDeviceEvdev
|
||||
|
||||
struct libinput_device *libinput_device;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterInputDeviceTool *last_tool;
|
||||
};
|
||||
|
||||
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;
|
||||
|
71
clutter/clutter/evdev/clutter-input-device-tool-evdev.c
Normal file
71
clutter/clutter/evdev/clutter-input-device-tool-evdev.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright © 2009, 2010, 2011 Intel Corp.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-input-device-tool-evdev.h"
|
||||
|
||||
G_DEFINE_TYPE (ClutterInputDeviceToolEvdev, clutter_input_device_tool_evdev,
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL)
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_evdev_finalize (GObject *object)
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (object);
|
||||
|
||||
libinput_tablet_tool_unref (tool->tool);
|
||||
|
||||
G_OBJECT_CLASS (clutter_input_device_tool_evdev_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_evdev_class_init (ClutterInputDeviceToolEvdevClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = clutter_input_device_tool_evdev_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_evdev_init (ClutterInputDeviceToolEvdev *tool)
|
||||
{
|
||||
}
|
||||
|
||||
ClutterInputDeviceTool *
|
||||
clutter_input_device_tool_evdev_new (struct libinput_tablet_tool *tool,
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type)
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *evdev_tool;
|
||||
|
||||
evdev_tool = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV,
|
||||
"type", type,
|
||||
"serial", serial,
|
||||
NULL);
|
||||
|
||||
evdev_tool->tool = libinput_tablet_tool_ref (tool);
|
||||
|
||||
return CLUTTER_INPUT_DEVICE_TOOL (evdev_tool);
|
||||
}
|
77
clutter/clutter/evdev/clutter-input-device-tool-evdev.h
Normal file
77
clutter/clutter/evdev/clutter-input-device-tool-evdev.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright © 2009, 2010, 2011 Intel Corp.
|
||||
*
|
||||
* 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 __CLUTTER_INPUT_DEVICE_EVDEV_TOOL_H__
|
||||
#define __CLUTTER_INPUT_DEVICE_EVDEV_TOOL_H__
|
||||
|
||||
#include <libinput.h>
|
||||
|
||||
#include <clutter/clutter-input-device-tool.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV (clutter_input_device_tool_evdev_get_type ())
|
||||
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_EVDEV(o) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((o), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV, ClutterInputDeviceToolEvdev))
|
||||
|
||||
#define CLUTTER_IS_INPUT_DEVICE_TOOL_EVDEV(o) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((o), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV))
|
||||
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_EVDEV_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((c), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV, ClutterInputDeviceToolEvdevClass))
|
||||
|
||||
#define CLUTTER_IS_INPUT_DEVICE_TOOL_EVDEV_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((c), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV))
|
||||
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_EVDEV_GET_CLASS(o) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((o), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_EVDEV, ClutterInputDeviceToolEvdevClass))
|
||||
|
||||
typedef struct _ClutterInputDeviceToolEvdev ClutterInputDeviceToolEvdev;
|
||||
typedef struct _ClutterInputDeviceToolEvdevClass ClutterInputDeviceToolEvdevClass;
|
||||
|
||||
struct _ClutterInputDeviceToolEvdev
|
||||
{
|
||||
ClutterInputDeviceTool parent_instance;
|
||||
struct libinput_tablet_tool *tool;
|
||||
};
|
||||
|
||||
struct _ClutterInputDeviceToolEvdevClass
|
||||
{
|
||||
ClutterInputDeviceToolClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_input_device_tool_evdev_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterInputDeviceTool * clutter_input_device_tool_evdev_new (struct libinput_tablet_tool *tool,
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_EVDEV_TOOL_H__ */
|
@ -62,6 +62,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 \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
@ -292,10 +294,20 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-popup.h \
|
||||
wayland/meta-wayland-seat.c \
|
||||
wayland/meta-wayland-seat.h \
|
||||
wayland/meta-wayland-tablet.c \
|
||||
wayland/meta-wayland-tablet.h \
|
||||
wayland/meta-wayland-tablet-manager.c \
|
||||
wayland/meta-wayland-tablet-manager.h \
|
||||
wayland/meta-wayland-tablet-seat.c \
|
||||
wayland/meta-wayland-tablet-seat.h \
|
||||
wayland/meta-wayland-tablet-tool.c \
|
||||
wayland/meta-wayland-tablet-tool.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-types.h \
|
||||
wayland/meta-wayland-versions.h \
|
||||
wayland/meta-wayland-outputs.c \
|
||||
|
@ -40,6 +40,7 @@ struct _MetaCursorRendererPrivate
|
||||
int current_x, current_y;
|
||||
|
||||
MetaCursorSprite *displayed_cursor;
|
||||
MetaOverlay *stage_overlay;
|
||||
gboolean handled_by_backend;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
@ -63,24 +64,48 @@ queue_redraw (MetaCursorRenderer *renderer,
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
if (!priv->stage_overlay)
|
||||
priv->stage_overlay = meta_stage_create_cursor_overlay (META_STAGE (stage));
|
||||
|
||||
if (cursor_sprite && !priv->handled_by_backend)
|
||||
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
meta_stage_set_cursor (META_STAGE (stage), texture, &rect);
|
||||
meta_stage_update_cursor_overlay (META_STAGE (stage), priv->stage_overlay,
|
||||
texture, &rect);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
{
|
||||
if (cursor_sprite)
|
||||
meta_cursor_sprite_realize_texture (cursor_sprite);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_finalize (GObject *object)
|
||||
{
|
||||
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
if (priv->stage_overlay)
|
||||
meta_stage_remove_cursor_overlay (META_STAGE (stage), priv->stage_overlay);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_cursor_renderer_finalize;
|
||||
klass->update_cursor = meta_cursor_renderer_real_update_cursor;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
typedef struct {
|
||||
struct _MetaOverlay {
|
||||
gboolean enabled;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
@ -36,22 +36,26 @@ typedef struct {
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
} MetaOverlay;
|
||||
};
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
MetaOverlay cursor_overlay;
|
||||
GList *overlays;
|
||||
gboolean is_active;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
|
||||
|
||||
static void
|
||||
meta_overlay_init (MetaOverlay *overlay)
|
||||
static MetaOverlay *
|
||||
meta_overlay_new ()
|
||||
{
|
||||
MetaOverlay *overlay;
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
overlay = g_slice_new0 (MetaOverlay);
|
||||
overlay->pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
return overlay;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -59,6 +63,8 @@ meta_overlay_free (MetaOverlay *overlay)
|
||||
{
|
||||
if (overlay->pipeline)
|
||||
cogl_object_unref (overlay->pipeline);
|
||||
|
||||
g_slice_free (MetaOverlay, overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -111,8 +117,15 @@ meta_stage_finalize (GObject *object)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
GList *l = priv->overlays;
|
||||
|
||||
meta_overlay_free (&priv->cursor_overlay);
|
||||
while (l)
|
||||
{
|
||||
meta_overlay_free (l->data);
|
||||
l = g_list_delete_link (l, l);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_stage_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -120,10 +133,12 @@ meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
GList *l;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
meta_overlay_paint (&priv->cursor_overlay);
|
||||
for (l = priv->overlays; l; l = l->next)
|
||||
meta_overlay_paint (l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -166,10 +181,6 @@ meta_stage_class_init (MetaStageClass *klass)
|
||||
static void
|
||||
meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_init (&priv->cursor_overlay);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
}
|
||||
|
||||
@ -209,17 +220,43 @@ queue_redraw_for_overlay (MetaStage *stage,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
MetaOverlay *
|
||||
meta_stage_create_cursor_overlay (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaOverlay *overlay;
|
||||
|
||||
overlay = meta_overlay_new ();
|
||||
priv->overlays = g_list_prepend (priv->overlays, overlay);
|
||||
|
||||
return overlay;
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_remove_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
GList *link;
|
||||
|
||||
link = g_list_find (priv->overlays, overlay);
|
||||
if (!link)
|
||||
return;
|
||||
|
||||
priv->overlays = g_list_delete_link (priv->overlays, link);
|
||||
meta_overlay_free (overlay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_update_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor () || texture == NULL);
|
||||
|
||||
meta_overlay_set (&priv->cursor_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
|
||||
meta_overlay_set (overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, overlay);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -36,6 +36,7 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _MetaStage MetaStage;
|
||||
typedef struct _MetaStageClass MetaStageClass;
|
||||
typedef struct _MetaOverlay MetaOverlay;
|
||||
|
||||
struct _MetaStageClass
|
||||
{
|
||||
@ -51,9 +52,14 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_stage_new (void);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
|
||||
void meta_stage_remove_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay);
|
||||
|
||||
void meta_stage_update_cursor_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
void meta_stage_set_active (MetaStage *stage,
|
||||
gboolean is_active);
|
||||
|
@ -221,8 +221,20 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
|
||||
if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
|
||||
{
|
||||
meta_cursor_tracker_update_position (meta_cursor_tracker_get_for_screen (NULL),
|
||||
event->motion.x, event->motion.y);
|
||||
MetaWaylandCompositor *compositor;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
if (meta_wayland_tablet_manager_consumes_event (compositor->tablet_manager, event))
|
||||
{
|
||||
meta_wayland_tablet_manager_update_cursor_position (compositor->tablet_manager, event);
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
|
||||
meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
|
||||
}
|
||||
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-buffer.h"
|
||||
#include "meta-wayland-surface-role-cursor.h"
|
||||
#include "meta-xwayland.h"
|
||||
#include "meta-cursor.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
@ -73,24 +74,6 @@
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
|
||||
|
||||
struct _MetaWaylandSurfaceRoleCursor
|
||||
{
|
||||
MetaWaylandSurfaceRole parent;
|
||||
|
||||
int hot_x;
|
||||
int hot_y;
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
|
||||
MetaWaylandBuffer *buffer;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
|
||||
meta_wayland_surface_role_cursor,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE);
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer);
|
||||
|
||||
static MetaWaylandPointerClient *
|
||||
meta_wayland_pointer_client_new (void)
|
||||
{
|
||||
@ -501,6 +484,12 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
||||
(gpointer) meta_wayland_pointer_on_cursor_changed,
|
||||
pointer);
|
||||
|
||||
if (pointer->cursor_surface && pointer->cursor_surface_destroy_id)
|
||||
{
|
||||
g_signal_handler_disconnect (pointer->cursor_surface,
|
||||
pointer->cursor_surface_destroy_id);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
|
||||
g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
|
||||
@ -934,7 +923,7 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
||||
*sy = wl_fixed_from_double (yf);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
|
||||
@ -948,7 +937,7 @@ meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (pointer->cursor_surface->role);
|
||||
|
||||
cursor_sprite = cursor_role->cursor_sprite;
|
||||
cursor_sprite = meta_wayland_surface_role_cursor_get_sprite (cursor_role);
|
||||
}
|
||||
|
||||
meta_cursor_tracker_set_window_cursor (cursor_tracker, cursor_sprite);
|
||||
@ -960,68 +949,14 @@ meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor_sprite_texture (MetaWaylandSurface *surface)
|
||||
ensure_update_cursor_surface (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (meta_get_backend ());
|
||||
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
|
||||
MetaCursorSprite *cursor_sprite = cursor_role->cursor_sprite;
|
||||
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
|
||||
if (pointer->cursor_surface != surface)
|
||||
return;
|
||||
|
||||
g_return_if_fail (!buffer || buffer->texture);
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
meta_cursor_sprite_set_texture (cursor_sprite,
|
||||
buffer->texture,
|
||||
cursor_role->hot_x * surface->scale,
|
||||
cursor_role->hot_y * surface->scale);
|
||||
|
||||
if (cursor_role->buffer)
|
||||
{
|
||||
struct wl_resource *buffer_resource;
|
||||
|
||||
g_assert (cursor_role->buffer == buffer);
|
||||
buffer_resource = buffer->resource;
|
||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (cursor_renderer,
|
||||
cursor_sprite,
|
||||
buffer_resource);
|
||||
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_cursor_sprite_set_texture (cursor_sprite, NULL, 0, 0);
|
||||
}
|
||||
|
||||
if (cursor_sprite == meta_cursor_tracker_get_displayed_cursor (cursor_tracker))
|
||||
meta_cursor_renderer_force_update (cursor_renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite,
|
||||
int x,
|
||||
int y,
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role)
|
||||
{
|
||||
MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_role);
|
||||
MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaScreen *screen = display->screen;
|
||||
const MetaMonitorInfo *monitor;
|
||||
|
||||
if (!meta_xwayland_is_xwayland_surface (surface))
|
||||
{
|
||||
monitor = meta_screen_get_monitor_for_point (screen, x, y);
|
||||
if (monitor)
|
||||
meta_cursor_sprite_set_texture_scale (cursor_sprite,
|
||||
(float)monitor->scale / surface->scale);
|
||||
}
|
||||
meta_wayland_surface_update_outputs (surface);
|
||||
pointer->cursor_surface = NULL;
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1031,14 +966,28 @@ meta_wayland_pointer_set_cursor_surface (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *prev_cursor_surface;
|
||||
|
||||
prev_cursor_surface = pointer->cursor_surface;
|
||||
|
||||
if (prev_cursor_surface == cursor_surface)
|
||||
return;
|
||||
|
||||
pointer->cursor_surface = cursor_surface;
|
||||
|
||||
if (prev_cursor_surface != cursor_surface)
|
||||
if (prev_cursor_surface)
|
||||
{
|
||||
if (prev_cursor_surface)
|
||||
meta_wayland_surface_update_outputs (prev_cursor_surface);
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
meta_wayland_surface_update_outputs (prev_cursor_surface);
|
||||
g_signal_handler_disconnect (prev_cursor_surface,
|
||||
pointer->cursor_surface_destroy_id);
|
||||
}
|
||||
|
||||
if (cursor_surface)
|
||||
{
|
||||
pointer->cursor_surface_destroy_id =
|
||||
g_signal_connect_swapped (cursor_surface, "destroy",
|
||||
G_CALLBACK (ensure_update_cursor_surface),
|
||||
pointer);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1072,23 +1021,15 @@ pointer_set_cursor (struct wl_client *client,
|
||||
|
||||
if (surface)
|
||||
{
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (meta_get_backend ());
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role;
|
||||
|
||||
cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
|
||||
if (!cursor_role->cursor_sprite)
|
||||
{
|
||||
cursor_role->cursor_sprite = meta_cursor_sprite_new ();
|
||||
g_signal_connect_object (cursor_role->cursor_sprite,
|
||||
"prepare-at",
|
||||
G_CALLBACK (cursor_sprite_prepare_at),
|
||||
cursor_role,
|
||||
0);
|
||||
}
|
||||
|
||||
cursor_role->hot_x = hot_x;
|
||||
cursor_role->hot_y = hot_y;
|
||||
|
||||
update_cursor_sprite_texture (surface);
|
||||
meta_wayland_surface_role_cursor_set_renderer (cursor_role,
|
||||
cursor_renderer);
|
||||
meta_wayland_surface_role_cursor_set_hotspot (cursor_role,
|
||||
hot_x, hot_y);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_set_cursor_surface (pointer, surface);
|
||||
@ -1261,136 +1202,3 @@ meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
|
||||
MetaWaylandSeat *seat = wl_container_of (pointer, seat, pointer);
|
||||
return seat;
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_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);
|
||||
meta_wayland_surface_ref_buffer_use_count (surface);
|
||||
}
|
||||
|
||||
meta_wayland_surface_queue_pending_frame_callbacks (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_pre_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
|
||||
if (pending->newly_attached && cursor_role->buffer)
|
||||
{
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_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)
|
||||
meta_wayland_surface_ref_buffer_use_count (surface);
|
||||
}
|
||||
|
||||
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
|
||||
|
||||
if (pending->newly_attached)
|
||||
update_cursor_sprite_texture (surface);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cursor_surface_role_is_on_output (MetaWaylandSurfaceRole *role,
|
||||
MetaMonitorInfo *monitor)
|
||||
{
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (role);
|
||||
MetaWaylandPointer *pointer = &surface->compositor->seat->pointer;
|
||||
MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (meta_get_backend ());
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
|
||||
MetaCursorSprite *displayed_cursor_sprite;
|
||||
MetaRectangle rect;
|
||||
|
||||
if (surface != pointer->cursor_surface)
|
||||
return FALSE;
|
||||
|
||||
displayed_cursor_sprite =
|
||||
meta_cursor_tracker_get_displayed_cursor (cursor_tracker);
|
||||
if (!displayed_cursor_sprite)
|
||||
return FALSE;
|
||||
|
||||
if (cursor_role->cursor_sprite != displayed_cursor_sprite)
|
||||
return FALSE;
|
||||
|
||||
rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
|
||||
cursor_role->cursor_sprite);
|
||||
return meta_rectangle_overlap (&rect, &monitor->rect);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_dispose (GObject *object)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (object);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object));
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandPointer *pointer = &compositor->seat->pointer;
|
||||
|
||||
if (pointer->cursor_surface == surface)
|
||||
pointer->cursor_surface = NULL;
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
|
||||
g_clear_object (&cursor_role->cursor_sprite);
|
||||
|
||||
if (cursor_role->buffer)
|
||||
{
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_surface_role_cursor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_cursor_init (MetaWaylandSurfaceRoleCursor *role)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *klass)
|
||||
{
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
surface_role_class->assigned = cursor_surface_role_assigned;
|
||||
surface_role_class->pre_commit = cursor_surface_role_pre_commit;
|
||||
surface_role_class->commit = cursor_surface_role_commit;
|
||||
surface_role_class->is_on_output = cursor_surface_role_is_on_output;
|
||||
|
||||
object_class->dispose = cursor_surface_role_dispose;
|
||||
}
|
||||
|
@ -32,12 +32,6 @@
|
||||
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#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);
|
||||
|
||||
struct _MetaWaylandPointerGrabInterface
|
||||
{
|
||||
void (*focus) (MetaWaylandPointerGrab *grab,
|
||||
@ -75,6 +69,7 @@ struct _MetaWaylandPointer
|
||||
guint32 click_serial;
|
||||
|
||||
MetaWaylandSurface *cursor_surface;
|
||||
guint cursor_surface_destroy_id;
|
||||
|
||||
MetaWaylandPointerGrab *grab;
|
||||
MetaWaylandPointerGrab default_grab;
|
||||
@ -151,4 +146,8 @@ void meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor);
|
||||
|
||||
MetaWaylandSeat *meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer);
|
||||
|
||||
void meta_wayland_surface_cursor_update (MetaWaylandSurface *cursor_surface);
|
||||
|
||||
void meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer);
|
||||
|
||||
#endif /* META_WAYLAND_POINTER_H */
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-pointer-gestures.h"
|
||||
#include "meta-wayland-tablet-manager.h"
|
||||
|
||||
typedef struct _MetaXWaylandSelection MetaXWaylandSelection;
|
||||
|
||||
@ -69,6 +70,7 @@ struct _MetaWaylandCompositor
|
||||
MetaXWaylandManager xwayland_manager;
|
||||
|
||||
MetaWaylandSeat *seat;
|
||||
MetaWaylandTabletManager *tablet_manager;
|
||||
};
|
||||
|
||||
#endif /* META_WAYLAND_PRIVATE_H */
|
||||
|
@ -205,7 +205,8 @@ meta_wayland_seat_devices_updated (ClutterDeviceManager *device_manager,
|
||||
}
|
||||
|
||||
static MetaWaylandSeat *
|
||||
meta_wayland_seat_new (struct wl_display *display)
|
||||
meta_wayland_seat_new (MetaWaylandCompositor *compositor,
|
||||
struct wl_display *display)
|
||||
{
|
||||
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
|
||||
ClutterDeviceManager *device_manager;
|
||||
@ -224,13 +225,16 @@ meta_wayland_seat_new (struct wl_display *display)
|
||||
|
||||
wl_global_create (display, &wl_seat_interface, META_WL_SEAT_VERSION, seat, bind_seat);
|
||||
|
||||
meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
|
||||
|
||||
return seat;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_seat_init (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
compositor->seat = meta_wayland_seat_new (compositor->wayland_display);
|
||||
compositor->seat = meta_wayland_seat_new (compositor,
|
||||
compositor->wayland_display);
|
||||
}
|
||||
|
||||
void
|
||||
|
281
src/wayland/meta-wayland-surface-role-cursor.c
Normal file
281
src/wayland/meta-wayland-surface-role-cursor.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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 <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include "meta-wayland-surface-role-cursor.h"
|
||||
#include "meta-wayland-buffer.h"
|
||||
#include "meta-xwayland.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
struct _MetaWaylandSurfaceRoleCursor
|
||||
{
|
||||
MetaWaylandSurfaceRole parent;
|
||||
|
||||
int hot_x;
|
||||
int hot_y;
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
MetaWaylandBuffer *buffer;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
|
||||
meta_wayland_surface_role_cursor,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE)
|
||||
|
||||
static void
|
||||
update_cursor_sprite_texture (MetaWaylandSurfaceRoleCursor *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;
|
||||
|
||||
g_return_if_fail (!buffer || buffer->texture);
|
||||
|
||||
if (!cursor_role->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);
|
||||
|
||||
if (cursor_role->buffer)
|
||||
{
|
||||
struct wl_resource *buffer_resource;
|
||||
|
||||
g_assert (cursor_role->buffer == buffer);
|
||||
buffer_resource = buffer->resource;
|
||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (cursor_role->cursor_renderer,
|
||||
cursor_sprite,
|
||||
buffer_resource);
|
||||
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_cursor_sprite_set_texture (cursor_sprite, NULL, 0, 0);
|
||||
}
|
||||
|
||||
meta_cursor_renderer_force_update (cursor_role->cursor_renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite,
|
||||
int x,
|
||||
int y,
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role)
|
||||
{
|
||||
MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_role);
|
||||
MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaScreen *screen = display->screen;
|
||||
const MetaMonitorInfo *monitor;
|
||||
|
||||
if (!meta_xwayland_is_xwayland_surface (surface))
|
||||
{
|
||||
monitor = meta_screen_get_monitor_for_point (screen, x, y);
|
||||
if (monitor)
|
||||
meta_cursor_sprite_set_texture_scale (cursor_sprite,
|
||||
(float) monitor->scale / surface->scale);
|
||||
}
|
||||
meta_wayland_surface_update_outputs (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_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);
|
||||
meta_wayland_surface_ref_buffer_use_count (surface);
|
||||
}
|
||||
|
||||
meta_wayland_surface_queue_pending_frame_callbacks (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_pre_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
|
||||
if (pending->newly_attached && cursor_role->buffer)
|
||||
{
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface_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)
|
||||
meta_wayland_surface_ref_buffer_use_count (surface);
|
||||
}
|
||||
|
||||
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
|
||||
|
||||
if (pending->newly_attached)
|
||||
update_cursor_sprite_texture (META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cursor_surface_role_is_on_output (MetaWaylandSurfaceRole *role,
|
||||
MetaMonitorInfo *monitor)
|
||||
{
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (role);
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
|
||||
MetaRectangle rect;
|
||||
|
||||
rect = meta_cursor_renderer_calculate_rect (cursor_role->cursor_renderer,
|
||||
cursor_role->cursor_sprite);
|
||||
return meta_rectangle_overlap (&rect, &monitor->rect);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_role_dispose (GObject *object)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (object);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (cursor_role->cursor_sprite,
|
||||
cursor_sprite_prepare_at, cursor_role);
|
||||
|
||||
g_clear_object (&cursor_role->cursor_renderer);
|
||||
g_clear_object (&cursor_role->cursor_sprite);
|
||||
|
||||
if (cursor_role->buffer)
|
||||
{
|
||||
meta_wayland_surface_unref_buffer_use_count (surface);
|
||||
g_clear_object (&cursor_role->buffer);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_surface_role_cursor_parent_class)->dispose (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,
|
||||
"prepare-at",
|
||||
G_CALLBACK (cursor_sprite_prepare_at),
|
||||
role,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *klass)
|
||||
{
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
surface_role_class->assigned = cursor_surface_role_assigned;
|
||||
surface_role_class->pre_commit = cursor_surface_role_pre_commit;
|
||||
surface_role_class->commit = cursor_surface_role_commit;
|
||||
surface_role_class->is_on_output = cursor_surface_role_is_on_output;
|
||||
|
||||
object_class->dispose = cursor_surface_role_dispose;
|
||||
}
|
||||
|
||||
MetaCursorSprite *
|
||||
meta_wayland_surface_role_cursor_get_sprite (MetaWaylandSurfaceRoleCursor *cursor_role)
|
||||
{
|
||||
return cursor_role->cursor_sprite;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_role_cursor_set_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role,
|
||||
gint hotspot_x,
|
||||
gint hotspot_y)
|
||||
{
|
||||
if (cursor_role->hot_x == hotspot_x &&
|
||||
cursor_role->hot_y == hotspot_y)
|
||||
return;
|
||||
|
||||
cursor_role->hot_x = hotspot_x;
|
||||
cursor_role->hot_y = hotspot_y;
|
||||
update_cursor_sprite_texture (cursor_role);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_role_cursor_get_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role,
|
||||
gint *hotspot_x,
|
||||
gint *hotspot_y)
|
||||
{
|
||||
if (hotspot_x)
|
||||
*hotspot_x = cursor_role->hot_x;
|
||||
if (hotspot_y)
|
||||
*hotspot_y = cursor_role->hot_y;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_role_cursor_set_renderer (MetaWaylandSurfaceRoleCursor *cursor_role,
|
||||
MetaCursorRenderer *renderer)
|
||||
{
|
||||
if (cursor_role->cursor_renderer == renderer)
|
||||
return;
|
||||
|
||||
if (renderer)
|
||||
g_object_ref (renderer);
|
||||
if (cursor_role->cursor_renderer)
|
||||
g_object_unref (cursor_role->cursor_renderer);
|
||||
|
||||
cursor_role->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;
|
||||
}
|
47
src/wayland/meta-wayland-surface-role-cursor.h
Normal file
47
src/wayland/meta-wayland-surface-role-cursor.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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_CURSOR_H
|
||||
#define META_WAYLAND_SURFACE_ROLE_CURSOR_H
|
||||
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "backends/meta-cursor-renderer.h"
|
||||
|
||||
#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);
|
||||
|
||||
MetaCursorSprite * meta_wayland_surface_role_cursor_get_sprite (MetaWaylandSurfaceRoleCursor *cursor_role);
|
||||
|
||||
void meta_wayland_surface_role_cursor_set_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role,
|
||||
gint hotspot_x,
|
||||
gint hotspot_y);
|
||||
void meta_wayland_surface_role_cursor_get_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role,
|
||||
gint *hotspot_x,
|
||||
gint *hotspot_y);
|
||||
void meta_wayland_surface_role_cursor_set_renderer (MetaWaylandSurfaceRoleCursor *cursor_role,
|
||||
MetaCursorRenderer *renderer);
|
||||
MetaCursorRenderer * meta_wayland_surface_role_cursor_get_renderer (MetaWaylandSurfaceRoleCursor *cursor_role);
|
||||
|
||||
|
||||
#endif /* META_WAYLAND_SURFACE_ROLE_CURSOR_H */
|
@ -137,6 +137,13 @@ G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND,
|
||||
meta_wayland_surface_role_dnd,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE);
|
||||
|
||||
enum {
|
||||
SURFACE_DESTROY,
|
||||
N_SURFACE_SIGNALS
|
||||
};
|
||||
|
||||
guint surface_signals[N_SURFACE_SIGNALS] = { 0 };
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role);
|
||||
|
||||
@ -2670,6 +2677,20 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
|
||||
*y = v.y;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_dispose (GObject *object)
|
||||
{
|
||||
MetaWaylandSurface *surface = META_WAYLAND_SURFACE (object);
|
||||
|
||||
if (!surface->destroying)
|
||||
{
|
||||
g_signal_emit (object, surface_signals[SURFACE_DESTROY], 0);
|
||||
surface->destroying = TRUE;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_surface_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_init (MetaWaylandSurface *surface)
|
||||
{
|
||||
@ -2679,6 +2700,17 @@ meta_wayland_surface_init (MetaWaylandSurface *surface)
|
||||
static void
|
||||
meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_wayland_surface_dispose;
|
||||
|
||||
surface_signals[SURFACE_DESTROY] =
|
||||
g_signal_new ("destroy",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -198,6 +198,7 @@ struct _MetaWaylandSurface
|
||||
MetaWaylandSerial acked_configure_serial;
|
||||
gboolean has_set_geometry;
|
||||
gboolean is_modal;
|
||||
gboolean destroying;
|
||||
|
||||
/* xdg_popup */
|
||||
struct {
|
||||
|
267
src/wayland/meta-wayland-tablet-manager.c
Normal file
267
src/wayland/meta-wayland-tablet-manager.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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-v1-server-protocol.h"
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-tablet-manager.h"
|
||||
#include "meta-wayland-tablet-seat.h"
|
||||
#include "meta-wayland-tablet-tool.h"
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_tablet_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_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE ||
|
||||
device_type == CLUTTER_CURSOR_DEVICE);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_manager_get_tablet_seat (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
guint32 id,
|
||||
struct wl_resource *seat_resource)
|
||||
{
|
||||
MetaWaylandTabletManager *tablet_manager = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
|
||||
tablet_seat = meta_wayland_tablet_manager_ensure_seat (tablet_manager, seat);
|
||||
meta_wayland_tablet_seat_create_new_resource (tablet_seat, client,
|
||||
resource, id);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_manager_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_manager_v1_interface tablet_manager_interface = {
|
||||
tablet_manager_get_tablet_seat,
|
||||
tablet_manager_destroy
|
||||
};
|
||||
|
||||
static void
|
||||
bind_tablet_manager (struct wl_client *client,
|
||||
void *data,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = data;
|
||||
MetaWaylandTabletManager *tablet_manager = compositor->tablet_manager;
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_manager_v1_interface,
|
||||
MIN (version, 1), id);
|
||||
wl_resource_set_implementation (resource, &tablet_manager_interface,
|
||||
tablet_manager, unbind_resource);
|
||||
wl_resource_set_user_data (resource, tablet_manager);
|
||||
wl_list_insert (&tablet_manager->resource_list,
|
||||
wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static MetaWaylandTabletManager *
|
||||
meta_wayland_tablet_manager_new (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
MetaWaylandTabletManager *tablet_manager;
|
||||
|
||||
tablet_manager = g_slice_new0 (MetaWaylandTabletManager);
|
||||
tablet_manager->compositor = compositor;
|
||||
tablet_manager->wl_display = compositor->wayland_display;
|
||||
tablet_manager->seats = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) meta_wayland_tablet_seat_free);
|
||||
wl_list_init (&tablet_manager->resource_list);
|
||||
|
||||
wl_global_create (tablet_manager->wl_display,
|
||||
&zwp_tablet_manager_v1_interface, 1,
|
||||
compositor, bind_tablet_manager);
|
||||
|
||||
return tablet_manager;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_manager_init (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
compositor->tablet_manager = meta_wayland_tablet_manager_new (compositor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_manager_free (MetaWaylandTabletManager *tablet_manager)
|
||||
{
|
||||
ClutterDeviceManager *device_manager;
|
||||
|
||||
device_manager = clutter_device_manager_get_default ();
|
||||
g_signal_handlers_disconnect_by_data (device_manager, tablet_manager);
|
||||
|
||||
g_hash_table_destroy (tablet_manager->seats);
|
||||
g_slice_free (MetaWaylandTabletManager, tablet_manager);
|
||||
}
|
||||
|
||||
static MetaWaylandTabletSeat *
|
||||
meta_wayland_tablet_manager_lookup_seat (MetaWaylandTabletManager *manager,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
MetaWaylandSeat *seat;
|
||||
GHashTableIter iter;
|
||||
|
||||
if (!is_tablet_device (device))
|
||||
return NULL;
|
||||
|
||||
g_hash_table_iter_init (&iter, manager->seats);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer*) &seat, (gpointer*) &tablet_seat))
|
||||
{
|
||||
if (meta_wayland_tablet_seat_lookup_tablet (tablet_seat, device))
|
||||
return tablet_seat;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_manager_consumes_event (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_source_device (event);
|
||||
|
||||
return meta_wayland_tablet_manager_lookup_seat (manager, device) != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_manager_update (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_source_device (event);
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
|
||||
tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device);
|
||||
|
||||
if (!tablet_seat)
|
||||
return;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
meta_wayland_tablet_seat_update (tablet_seat, event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_manager_handle_event (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_source_device (event);
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
|
||||
tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device);
|
||||
|
||||
if (!tablet_seat)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
return meta_wayland_tablet_seat_handle_event (tablet_seat, event);
|
||||
default:
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
}
|
||||
|
||||
MetaWaylandTabletSeat *
|
||||
meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager,
|
||||
MetaWaylandSeat *seat)
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
|
||||
tablet_seat = g_hash_table_lookup (manager->seats, seat);
|
||||
|
||||
if (!tablet_seat)
|
||||
{
|
||||
tablet_seat = meta_wayland_tablet_seat_new (manager);
|
||||
g_hash_table_insert (manager->seats, seat, tablet_seat);
|
||||
}
|
||||
|
||||
return tablet_seat;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_manager_update_cursor_position (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat = NULL;
|
||||
MetaWaylandTabletTool *tool = NULL;
|
||||
ClutterInputDeviceTool *device_tool;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
device_tool = clutter_event_get_device_tool (event);
|
||||
|
||||
if (device)
|
||||
tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device);
|
||||
|
||||
if (tablet_seat && device_tool)
|
||||
tool = meta_wayland_tablet_seat_lookup_tool (tablet_seat, device_tool);
|
||||
|
||||
if (tool)
|
||||
{
|
||||
gfloat new_x, new_y;
|
||||
|
||||
clutter_event_get_coords (event, &new_x, &new_y);
|
||||
meta_wayland_tablet_tool_set_cursor_position (tool, new_x, new_y);
|
||||
}
|
||||
}
|
57
src/wayland/meta-wayland-tablet-manager.h
Normal file
57
src/wayland/meta-wayland-tablet-manager.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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_MANAGER_H
|
||||
#define META_WAYLAND_TABLET_MANAGER_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
struct _MetaWaylandTabletManager
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
struct wl_display *wl_display;
|
||||
struct wl_list resource_list;
|
||||
|
||||
GHashTable *seats;
|
||||
};
|
||||
|
||||
void meta_wayland_tablet_manager_init (MetaWaylandCompositor *compositor);
|
||||
void meta_wayland_tablet_manager_free (MetaWaylandTabletManager *tablet_manager);
|
||||
|
||||
gboolean meta_wayland_tablet_manager_consumes_event (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event);
|
||||
void meta_wayland_tablet_manager_update (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_wayland_tablet_manager_handle_event (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event);
|
||||
|
||||
MetaWaylandTabletSeat *
|
||||
meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager,
|
||||
MetaWaylandSeat *seat);
|
||||
|
||||
void meta_wayland_tablet_manager_update_cursor_position (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_MANAGER_H */
|
334
src/wayland/meta-wayland-tablet-seat.c
Normal file
334
src/wayland/meta-wayland-tablet-seat.c
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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-v1-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"
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
notify_tool_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_resource *client_resource,
|
||||
MetaWaylandTabletTool *tool)
|
||||
{
|
||||
struct wl_resource *tool_resource;
|
||||
struct wl_client *client;
|
||||
|
||||
client = wl_resource_get_client (client_resource);
|
||||
tool_resource = meta_wayland_tablet_tool_lookup_resource (tool, client);
|
||||
|
||||
if (!tool_resource)
|
||||
return;
|
||||
|
||||
zwp_tablet_seat_v1_send_tool_added (client_resource, tool_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_tablet_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_resource *client_resource,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandTablet *tablet;
|
||||
struct wl_client *client;
|
||||
|
||||
tablet = g_hash_table_lookup (tablet_seat->tablets, device);
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
client = wl_resource_get_client (client_resource);
|
||||
|
||||
if (meta_wayland_tablet_lookup_resource (tablet, client))
|
||||
return;
|
||||
|
||||
resource = meta_wayland_tablet_create_new_resource (tablet, client,
|
||||
client_resource, 0);
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
zwp_tablet_seat_v1_send_tablet_added (client_resource, resource);
|
||||
meta_wayland_tablet_notify (tablet, resource);
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_tablet_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, &tablet_seat->resource_list)
|
||||
{
|
||||
notify_tablet_added (tablet_seat, resource, device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
notify_tablets (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_resource *client_resource)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, tablet_seat->tablets);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &device, NULL))
|
||||
notify_tablet_added (tablet_seat, client_resource, device);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_tablet_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_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE ||
|
||||
device_type == CLUTTER_CURSOR_DEVICE);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_seat_device_added (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaWaylandTablet *tablet;
|
||||
|
||||
if (!is_tablet_device (device))
|
||||
return;
|
||||
|
||||
tablet = meta_wayland_tablet_new (device, tablet_seat);
|
||||
g_hash_table_insert (tablet_seat->tablets, device, tablet);
|
||||
broadcast_tablet_added (tablet_seat, device);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_seat_device_removed (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
g_hash_table_remove (tablet_seat->tablets, device);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_seat_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_seat_v1_interface tablet_seat_interface = {
|
||||
tablet_seat_destroy
|
||||
};
|
||||
|
||||
MetaWaylandTabletSeat *
|
||||
meta_wayland_tablet_seat_new (MetaWaylandTabletManager *manager)
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
const GSList *devices, *l;
|
||||
|
||||
tablet_seat = g_slice_new0 (MetaWaylandTabletSeat);
|
||||
tablet_seat->manager = manager;
|
||||
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);
|
||||
wl_list_init (&tablet_seat->resource_list);
|
||||
|
||||
g_signal_connect_swapped (tablet_seat->device_manager, "device-added",
|
||||
G_CALLBACK (meta_wayland_tablet_seat_device_added),
|
||||
tablet_seat);
|
||||
g_signal_connect_swapped (tablet_seat->device_manager, "device-removed",
|
||||
G_CALLBACK (meta_wayland_tablet_seat_device_removed),
|
||||
tablet_seat);
|
||||
|
||||
devices = clutter_device_manager_peek_devices (tablet_seat->device_manager);
|
||||
|
||||
for (l = devices; l; l = l->next)
|
||||
meta_wayland_tablet_seat_device_added (tablet_seat, l->data);
|
||||
|
||||
return tablet_seat;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_seat_free (MetaWaylandTabletSeat *tablet_seat)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_data (tablet_seat->device_manager,
|
||||
tablet_seat);
|
||||
g_hash_table_destroy (tablet_seat->tablets);
|
||||
g_hash_table_destroy (tablet_seat->tools);
|
||||
g_slice_free (MetaWaylandTabletSeat, tablet_seat);
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_seat_create_new_resource (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *manager_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_seat_v1_interface,
|
||||
wl_resource_get_version (manager_resource),
|
||||
id);
|
||||
wl_resource_set_implementation (resource, &tablet_seat_interface,
|
||||
tablet_seat, unbind_resource);
|
||||
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_tablets (tablet_seat, resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_seat_lookup_resource (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_client *client)
|
||||
{
|
||||
return wl_resource_find_for_client (&tablet_seat->resource_list, client);
|
||||
}
|
||||
|
||||
MetaWaylandTablet *
|
||||
meta_wayland_tablet_seat_lookup_tablet (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
return g_hash_table_lookup (tablet_seat->tablets, device);
|
||||
}
|
||||
|
||||
MetaWaylandTabletTool *
|
||||
meta_wayland_tablet_seat_lookup_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
return g_hash_table_lookup (tablet_seat->tools, tool);
|
||||
}
|
||||
|
||||
static MetaWaylandTabletTool *
|
||||
meta_wayland_tablet_seat_ensure_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *device_tool)
|
||||
{
|
||||
MetaWaylandTabletTool *tool;
|
||||
|
||||
tool = g_hash_table_lookup (tablet_seat->tools, device_tool);
|
||||
|
||||
if (!tool)
|
||||
{
|
||||
tool = meta_wayland_tablet_tool_new (tablet_seat, device, device_tool);
|
||||
g_hash_table_insert (tablet_seat->tools, device_tool, tool);
|
||||
}
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_seat_update (MetaWaylandTabletSeat *tablet_seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDeviceTool *device_tool;
|
||||
MetaWaylandTabletTool *tool = 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)
|
||||
{
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
meta_wayland_tablet_tool_update (tool, event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_seat_handle_event (MetaWaylandTabletSeat *tablet_seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
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;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_MOTION:
|
||||
meta_wayland_tablet_tool_handle_event (tool, event);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
default:
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_seat_notify_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&tablet_seat->resource_list, client);
|
||||
|
||||
if (resource)
|
||||
notify_tool_added (tablet_seat, resource, tool);
|
||||
}
|
66
src/wayland/meta-wayland-tablet-seat.h
Normal file
66
src/wayland/meta-wayland-tablet-seat.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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_SEAT_H
|
||||
#define META_WAYLAND_TABLET_SEAT_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
struct _MetaWaylandTabletSeat
|
||||
{
|
||||
MetaWaylandTabletManager *manager;
|
||||
ClutterDeviceManager *device_manager;
|
||||
struct wl_list resource_list;
|
||||
|
||||
GHashTable *tablets;
|
||||
GHashTable *tools;
|
||||
};
|
||||
|
||||
MetaWaylandTabletSeat *meta_wayland_tablet_seat_new (MetaWaylandTabletManager *tablet_manager);
|
||||
void meta_wayland_tablet_seat_free (MetaWaylandTabletSeat *tablet_seat);
|
||||
|
||||
struct wl_resource *meta_wayland_tablet_seat_create_new_resource (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *meta_wayland_tablet_seat_lookup_resource (MetaWaylandTabletSeat *tablet_seat,
|
||||
struct wl_client *client);
|
||||
|
||||
MetaWaylandTablet *meta_wayland_tablet_seat_lookup_tablet (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
MetaWaylandTabletTool *meta_wayland_tablet_seat_lookup_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
void meta_wayland_tablet_seat_update (MetaWaylandTabletSeat *tablet_seat,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_wayland_tablet_seat_handle_event (MetaWaylandTabletSeat *tablet_seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_tablet_seat_notify_tool (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_SEAT_H */
|
890
src/wayland/meta-wayland-tablet-tool.c
Normal file
890
src/wayland/meta-wayland-tablet-tool.c
Normal file
@ -0,0 +1,890 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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 <clutter/evdev/clutter-evdev.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "tablet-unstable-v1-server-protocol.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-surface-role-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"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.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)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
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_tool_update_cursor_surface (MetaWaylandTabletTool *tool)
|
||||
{
|
||||
MetaCursorSprite *cursor = NULL;
|
||||
|
||||
if (tool->cursor_renderer == NULL)
|
||||
return;
|
||||
|
||||
if (tool->current && tool->current_tablet)
|
||||
{
|
||||
if (tool->cursor_surface &&
|
||||
meta_wayland_surface_get_buffer (tool->cursor_surface))
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role =
|
||||
META_WAYLAND_SURFACE_ROLE_CURSOR (tool->cursor_surface->role);
|
||||
|
||||
cursor = meta_wayland_surface_role_cursor_get_sprite (cursor_role);
|
||||
}
|
||||
else
|
||||
cursor = NULL;
|
||||
}
|
||||
else if (tool->current_tablet)
|
||||
cursor = meta_cursor_sprite_from_theme (META_CURSOR_CROSSHAIR);
|
||||
else
|
||||
cursor = NULL;
|
||||
|
||||
meta_cursor_renderer_set_cursor (tool->cursor_renderer, cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_set_cursor_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
if (tool->cursor_surface == surface)
|
||||
return;
|
||||
|
||||
if (tool->cursor_surface)
|
||||
wl_list_remove (&tool->cursor_surface_destroy_listener.link);
|
||||
|
||||
tool->cursor_surface = surface;
|
||||
|
||||
if (tool->cursor_surface)
|
||||
wl_resource_add_destroy_listener (tool->cursor_surface->resource,
|
||||
&tool->cursor_surface_destroy_listener);
|
||||
|
||||
meta_wayland_tablet_tool_update_cursor_surface (tool);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
input_device_get_capabilities (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputAxis axis;
|
||||
guint32 capabilities = 0, i;
|
||||
|
||||
for (i = 0; i < clutter_input_device_get_n_axes (device); i++)
|
||||
{
|
||||
axis = clutter_input_device_get_axis (device, i);
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case CLUTTER_INPUT_AXIS_PRESSURE:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_PRESSURE;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_DISTANCE:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_DISTANCE;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_XTILT:
|
||||
case CLUTTER_INPUT_AXIS_YTILT:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_TILT;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_ROTATION:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_ROTATION;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_WHEEL:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_WHEEL;
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_SLIDER:
|
||||
capabilities |= 1 << ZWP_TABLET_TOOL_V1_CAPABILITY_SLIDER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
static enum zwp_tablet_tool_v1_type
|
||||
input_device_tool_get_type (ClutterInputDeviceTool *device_tool)
|
||||
{
|
||||
ClutterInputDeviceToolType tool_type;
|
||||
|
||||
tool_type = clutter_input_device_tool_get_tool_type (device_tool);
|
||||
|
||||
switch (tool_type)
|
||||
{
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_NONE:
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_PEN:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_PEN;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_ERASER:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_ERASER;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_BRUSH:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_BRUSH;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_PENCIL:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_PENCIL;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_AIRBRUSH;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_MOUSE:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_MOUSE;
|
||||
case CLUTTER_INPUT_DEVICE_TOOL_LENS:
|
||||
return ZWP_TABLET_TOOL_V1_TYPE_LENS;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_notify_capabilities (MetaWaylandTabletTool *tool,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
uint32_t capabilities;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_notify_details (MetaWaylandTabletTool *tool,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
guint64 serial;
|
||||
|
||||
zwp_tablet_tool_v1_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),
|
||||
(uint32_t) (serial & 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);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_ensure_resource (MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *seat_resource, *tool_resource;
|
||||
|
||||
seat_resource = meta_wayland_tablet_seat_lookup_resource (tool->seat, client);
|
||||
|
||||
if (seat_resource &&
|
||||
!meta_wayland_tablet_tool_lookup_resource (tool, client))
|
||||
{
|
||||
tool_resource = meta_wayland_tablet_tool_create_new_resource (tool, client,
|
||||
seat_resource,
|
||||
0);
|
||||
|
||||
meta_wayland_tablet_seat_notify_tool (tool->seat, tool, client);
|
||||
meta_wayland_tablet_tool_notify_details (tool, tool_resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_proximity_in (MetaWaylandTabletTool *tool)
|
||||
{
|
||||
struct wl_resource *resource, *tablet_resource;
|
||||
struct wl_client *client;
|
||||
|
||||
client = wl_resource_get_client (tool->focus_surface->resource);
|
||||
tablet_resource = meta_wayland_tablet_lookup_resource (tool->current_tablet,
|
||||
client);
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_proximity_in (resource, tool->proximity_serial,
|
||||
tablet_resource,
|
||||
tool->focus_surface->resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_proximity_out (MetaWaylandTabletTool *tool)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_proximity_out (resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_frame (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
guint32 _time = event ? clutter_event_get_time (event) : CLUTTER_CURRENT_TIME;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_frame (resource, _time);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_set_focus (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
if (tool->focus_surface == surface)
|
||||
return;
|
||||
|
||||
if (tool->focus_surface != NULL)
|
||||
{
|
||||
struct wl_list *l;
|
||||
|
||||
l = &tool->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
broadcast_proximity_out (tool);
|
||||
broadcast_frame (tool, event);
|
||||
move_resources (&tool->resource_list, &tool->focus_resource_list);
|
||||
}
|
||||
|
||||
wl_list_remove (&tool->focus_surface_destroy_listener.link);
|
||||
tool->focus_surface = NULL;
|
||||
}
|
||||
|
||||
if (surface != NULL && tool->current_tablet)
|
||||
{
|
||||
struct wl_client *client;
|
||||
struct wl_list *l;
|
||||
|
||||
tool->focus_surface = surface;
|
||||
client = wl_resource_get_client (tool->focus_surface->resource);
|
||||
wl_resource_add_destroy_listener (tool->focus_surface->resource,
|
||||
&tool->focus_surface_destroy_listener);
|
||||
|
||||
move_resources_for_client (&tool->focus_resource_list,
|
||||
&tool->resource_list, client);
|
||||
meta_wayland_tablet_tool_ensure_resource (tool, client);
|
||||
|
||||
l = &tool->focus_resource_list;
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (tool->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
|
||||
tool->proximity_serial = wl_display_next_serial (display);
|
||||
|
||||
broadcast_proximity_in (tool);
|
||||
broadcast_frame (tool, event);
|
||||
}
|
||||
}
|
||||
|
||||
meta_wayland_tablet_tool_update_cursor_surface (tool);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_focus_surface_destroy (struct wl_listener *listener,
|
||||
void *data)
|
||||
{
|
||||
MetaWaylandTabletTool *tool;
|
||||
|
||||
tool = wl_container_of (listener, tool, focus_surface_destroy_listener);
|
||||
meta_wayland_tablet_tool_set_focus (tool, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_cursor_surface_destroy (struct wl_listener *listener,
|
||||
void *data)
|
||||
{
|
||||
MetaWaylandTabletTool *tool;
|
||||
|
||||
tool = wl_container_of (listener, tool, cursor_surface_destroy_listener);
|
||||
meta_wayland_tablet_tool_set_cursor_surface (tool, NULL);
|
||||
}
|
||||
|
||||
MetaWaylandTabletTool *
|
||||
meta_wayland_tablet_tool_new (MetaWaylandTabletSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *device_tool)
|
||||
{
|
||||
MetaWaylandTabletTool *tool;
|
||||
|
||||
tool = g_slice_new0 (MetaWaylandTabletTool);
|
||||
tool->seat = seat;
|
||||
tool->device = device;
|
||||
tool->device_tool = device_tool;
|
||||
wl_list_init (&tool->resource_list);
|
||||
wl_list_init (&tool->focus_resource_list);
|
||||
|
||||
tool->focus_surface_destroy_listener.notify = tablet_tool_handle_focus_surface_destroy;
|
||||
tool->cursor_surface_destroy_listener.notify = tablet_tool_handle_cursor_surface_destroy;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_tool_free (MetaWaylandTabletTool *tool)
|
||||
{
|
||||
struct wl_resource *resource, *next;
|
||||
|
||||
meta_wayland_tablet_tool_set_focus (tool, NULL, NULL);
|
||||
meta_wayland_tablet_tool_set_cursor_surface (tool, NULL);
|
||||
g_clear_object (&tool->cursor_renderer);
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &tool->resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_removed (resource);
|
||||
}
|
||||
|
||||
g_slice_free (MetaWaylandTabletTool, tool);
|
||||
}
|
||||
|
||||
static void
|
||||
tool_set_cursor (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t serial,
|
||||
struct wl_resource *surface_resource,
|
||||
int32_t hotspot_x,
|
||||
int32_t hotspot_y)
|
||||
{
|
||||
MetaWaylandTabletTool *tool = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface;
|
||||
|
||||
surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
|
||||
|
||||
if (tool->focus_surface == NULL)
|
||||
return;
|
||||
if (tool->cursor_renderer == NULL)
|
||||
return;
|
||||
if (wl_resource_get_client (tool->focus_surface->resource) != client)
|
||||
return;
|
||||
if (tool->proximity_serial - serial > G_MAXUINT32 / 2)
|
||||
return;
|
||||
|
||||
if (surface &&
|
||||
!meta_wayland_surface_assign_role (surface,
|
||||
META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR))
|
||||
{
|
||||
wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE,
|
||||
"wl_surface@%d already has a different role",
|
||||
wl_resource_get_id (surface_resource));
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface)
|
||||
{
|
||||
MetaWaylandSurfaceRoleCursor *cursor_role;
|
||||
|
||||
cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
|
||||
meta_wayland_surface_role_cursor_set_renderer (cursor_role,
|
||||
tool->cursor_renderer);
|
||||
meta_wayland_surface_role_cursor_set_hotspot (cursor_role,
|
||||
hotspot_x, hotspot_y);
|
||||
}
|
||||
|
||||
meta_wayland_tablet_tool_set_cursor_surface (tool, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
tool_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_tool_v1_interface tool_interface = {
|
||||
tool_set_cursor,
|
||||
tool_destroy
|
||||
};
|
||||
|
||||
static void
|
||||
emit_proximity_in (MetaWaylandTabletTool *tool,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
struct wl_resource *tablet_resource;
|
||||
struct wl_client *client;
|
||||
|
||||
if (!tool->focus_surface)
|
||||
return;
|
||||
|
||||
client = wl_resource_get_client (resource);
|
||||
tablet_resource = meta_wayland_tablet_lookup_resource (tool->current_tablet,
|
||||
client);
|
||||
|
||||
zwp_tablet_tool_v1_send_proximity_in (resource, tool->proximity_serial,
|
||||
tablet_resource, tool->focus_surface->resource);
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_tool_create_new_resource (MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_tool_v1_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &tool_interface,
|
||||
tool, unbind_resource);
|
||||
wl_resource_set_user_data (resource, tool);
|
||||
|
||||
if (tool->focus_surface &&
|
||||
wl_resource_get_client (tool->focus_surface->resource) == client)
|
||||
{
|
||||
wl_list_insert (&tool->focus_resource_list, wl_resource_get_link (resource));
|
||||
emit_proximity_in (tool, resource);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_list_insert (&tool->resource_list, wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_tool_lookup_resource (MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource = NULL;
|
||||
|
||||
if (!wl_list_empty (&tool->resource_list))
|
||||
resource = wl_resource_find_for_client (&tool->resource_list, client);
|
||||
|
||||
if (!wl_list_empty (&tool->focus_resource_list))
|
||||
resource = wl_resource_find_for_client (&tool->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_account_button (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
if (event->type == CLUTTER_BUTTON_PRESS)
|
||||
tool->pressed_buttons |= 1 << (event->button.button - 1);
|
||||
else if (event->type == CLUTTER_BUTTON_RELEASE)
|
||||
tool->pressed_buttons &= ~(1 << (event->button.button - 1));
|
||||
}
|
||||
|
||||
static void
|
||||
sync_focus_surface (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
switch (display->event_route)
|
||||
{
|
||||
case META_EVENT_ROUTE_WINDOW_OP:
|
||||
case META_EVENT_ROUTE_COMPOSITOR_GRAB:
|
||||
case META_EVENT_ROUTE_FRAME_BUTTON:
|
||||
/* The compositor has a grab, so remove our focus */
|
||||
meta_wayland_tablet_tool_set_focus (tool, NULL, event);
|
||||
break;
|
||||
|
||||
case META_EVENT_ROUTE_NORMAL:
|
||||
case META_EVENT_ROUTE_WAYLAND_POPUP:
|
||||
meta_wayland_tablet_tool_set_focus (tool, tool->current, event);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
repick_for_event (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *for_event)
|
||||
{
|
||||
ClutterActor *actor = NULL;
|
||||
|
||||
actor = clutter_event_get_source (for_event);
|
||||
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
|
||||
tool->current = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
else
|
||||
tool->current = NULL;
|
||||
|
||||
sync_focus_surface (tool, for_event);
|
||||
meta_wayland_tablet_tool_update_cursor_surface (tool);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_get_relative_coordinates (MetaWaylandTabletTool *tool,
|
||||
ClutterInputDevice *device,
|
||||
MetaWaylandSurface *surface,
|
||||
wl_fixed_t *sx,
|
||||
wl_fixed_t *sy)
|
||||
{
|
||||
float xf = 0.0f, yf = 0.0f;
|
||||
ClutterPoint pos;
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, &pos);
|
||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
pos.x, pos.y, &xf, &yf);
|
||||
|
||||
*sx = wl_fixed_from_double (xf) / surface->scale;
|
||||
*sy = wl_fixed_from_double (yf) / surface->scale;
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_motion (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
ClutterInputDevice *device;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
meta_wayland_tablet_tool_get_relative_coordinates (tool, device,
|
||||
tool->focus_surface,
|
||||
&sx, &sy);
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_motion (resource, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_down (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
tool->down_serial = wl_display_next_serial (tool->seat->manager->wl_display);
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_down (resource, tool->down_serial);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_up (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_up (resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_button (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
guint32 button;
|
||||
|
||||
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,
|
||||
event->type == CLUTTER_BUTTON_PRESS ?
|
||||
ZWP_TABLET_TOOL_V1_BUTTON_STATE_PRESSED :
|
||||
ZWP_TABLET_TOOL_V1_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_axis (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event,
|
||||
ClutterInputAxis axis)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
ClutterInputDevice *source;
|
||||
uint32_t value;
|
||||
gdouble val;
|
||||
|
||||
source = clutter_event_get_source_device (event);
|
||||
|
||||
if (!clutter_input_device_get_axis_value (source, event->motion.axes, axis, &val))
|
||||
return;
|
||||
|
||||
value = val * TABLET_AXIS_MAX;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case CLUTTER_INPUT_AXIS_PRESSURE:
|
||||
zwp_tablet_tool_v1_send_pressure (resource, value);
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_DISTANCE:
|
||||
zwp_tablet_tool_v1_send_distance (resource, value);
|
||||
break;
|
||||
case CLUTTER_INPUT_AXIS_SLIDER:
|
||||
zwp_tablet_tool_v1_send_slider (resource, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_tilt (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
ClutterInputDevice *source;
|
||||
gdouble xtilt, ytilt;
|
||||
|
||||
source = clutter_event_get_source_device (event);
|
||||
|
||||
if (!clutter_input_device_get_axis_value (source, event->motion.axes,
|
||||
CLUTTER_INPUT_AXIS_XTILT, &xtilt) ||
|
||||
!clutter_input_device_get_axis_value (source, event->motion.axes,
|
||||
CLUTTER_INPUT_AXIS_YTILT, &ytilt))
|
||||
return;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_rotation (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
ClutterInputDevice *source;
|
||||
gdouble rotation;
|
||||
|
||||
source = clutter_event_get_source_device (event);
|
||||
|
||||
if (!clutter_input_device_get_axis_value (source, event->motion.axes,
|
||||
CLUTTER_INPUT_AXIS_ROTATION,
|
||||
&rotation))
|
||||
return;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v1_send_rotation (resource,
|
||||
(int32_t) rotation * DEGREES_PRECISION);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_axes (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
guint32 capabilities;
|
||||
|
||||
if (!event->motion.axes)
|
||||
return;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
capabilities = input_device_get_capabilities (device);
|
||||
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_PRESSURE))
|
||||
broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_PRESSURE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_DISTANCE))
|
||||
broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_DISTANCE);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_TILT))
|
||||
broadcast_tilt (tool, event);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_ROTATION))
|
||||
broadcast_rotation (tool, event);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V1_CAPABILITY_SLIDER))
|
||||
broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_SLIDER);
|
||||
|
||||
/* FIXME: Missing wp_tablet_tool.wheel */
|
||||
}
|
||||
|
||||
static void
|
||||
handle_motion_event (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
if (!tool->focus_surface)
|
||||
return;
|
||||
|
||||
broadcast_motion (tool, event);
|
||||
broadcast_axes (tool, event);
|
||||
broadcast_frame (tool, event);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_button_event (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
if (!tool->focus_surface)
|
||||
return;
|
||||
|
||||
if (event->type == CLUTTER_BUTTON_PRESS && event->button.button == 1)
|
||||
broadcast_down (tool, event);
|
||||
else if (event->type == CLUTTER_BUTTON_RELEASE && event->button.button == 1)
|
||||
broadcast_up (tool, event);
|
||||
else
|
||||
broadcast_button (tool, event);
|
||||
|
||||
broadcast_frame (tool, event);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_tool_update (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
meta_wayland_tablet_tool_account_button (tool, event);
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
if (!tool->pressed_buttons)
|
||||
repick_for_event (tool, event);
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
if (!tool->cursor_renderer)
|
||||
tool->cursor_renderer = meta_cursor_renderer_new ();
|
||||
tool->current_tablet =
|
||||
meta_wayland_tablet_seat_lookup_tablet (tool->seat,
|
||||
clutter_event_get_source_device (event));
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
tool->current_tablet = NULL;
|
||||
meta_wayland_tablet_tool_update_cursor_surface (tool);
|
||||
g_clear_object (&tool->cursor_renderer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_tool_handle_event (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
/* We don't have much info here to make anything useful out of it,
|
||||
* wait until the first motion event so we have both coordinates
|
||||
* and tool.
|
||||
*/
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
meta_wayland_tablet_tool_set_focus (tool, NULL, event);
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
handle_motion_event (tool, event);
|
||||
break;
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
handle_button_event (tool, event);
|
||||
break;
|
||||
default:
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *tool,
|
||||
int new_x,
|
||||
int new_y)
|
||||
{
|
||||
if (tool->cursor_renderer)
|
||||
meta_cursor_renderer_set_position (tool->cursor_renderer, new_x, new_y);
|
||||
}
|
81
src/wayland/meta-wayland-tablet-tool.h
Normal file
81
src/wayland/meta-wayland-tablet-tool.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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_TOOL_H
|
||||
#define META_WAYLAND_TABLET_TOOL_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
struct _MetaWaylandTabletTool
|
||||
{
|
||||
MetaWaylandTabletSeat *seat;
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDeviceTool *device_tool;
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
|
||||
MetaWaylandSurface *focus_surface;
|
||||
struct wl_listener focus_surface_destroy_listener;
|
||||
|
||||
MetaWaylandSurface *cursor_surface;
|
||||
struct wl_listener cursor_surface_destroy_listener;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
|
||||
MetaWaylandSurface *current;
|
||||
guint32 pressed_buttons;
|
||||
|
||||
guint32 proximity_serial;
|
||||
guint32 down_serial;
|
||||
guint32 button_serial;
|
||||
|
||||
MetaWaylandTablet *current_tablet;
|
||||
};
|
||||
|
||||
MetaWaylandTabletTool * meta_wayland_tablet_tool_new (MetaWaylandTabletSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *device_tool);
|
||||
void meta_wayland_tablet_tool_free (MetaWaylandTabletTool *tool);
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_tool_create_new_resource (MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_tool_lookup_resource (MetaWaylandTabletTool *tool,
|
||||
struct wl_client *client);
|
||||
|
||||
void meta_wayland_tablet_tool_update (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_wayland_tablet_tool_handle_event (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *tool,
|
||||
int new_x,
|
||||
int new_y);
|
||||
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_TOOL_H */
|
130
src/wayland/meta-wayland-tablet.c
Normal file
130
src/wayland/meta-wayland-tablet.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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-v1-server-protocol.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-tablet.h"
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
MetaWaylandTablet *
|
||||
meta_wayland_tablet_new (ClutterInputDevice *device,
|
||||
MetaWaylandTabletSeat *tablet_seat)
|
||||
{
|
||||
MetaWaylandTablet *tablet;
|
||||
|
||||
tablet = g_slice_new0 (MetaWaylandTablet);
|
||||
wl_list_init (&tablet->resource_list);
|
||||
wl_list_init (&tablet->focus_resource_list);
|
||||
tablet->device = device;
|
||||
tablet->tablet_seat = tablet_seat;
|
||||
|
||||
return tablet;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_free (MetaWaylandTablet *tablet)
|
||||
{
|
||||
struct wl_resource *resource, *next;
|
||||
|
||||
wl_resource_for_each_safe (resource, next, &tablet->resource_list)
|
||||
{
|
||||
zwp_tablet_v1_send_removed (resource);
|
||||
}
|
||||
|
||||
g_slice_free (MetaWaylandTablet, tablet);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_v1_interface tablet_interface = {
|
||||
tablet_destroy
|
||||
};
|
||||
|
||||
void
|
||||
meta_wayland_tablet_notify (MetaWaylandTablet *tablet,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
ClutterInputDevice *device = tablet->device;
|
||||
guint vid, pid;
|
||||
|
||||
zwp_tablet_v1_send_name (resource, clutter_input_device_get_device_name (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);
|
||||
|
||||
/* FIXME: zwp_tablet_v1.path missing */
|
||||
|
||||
zwp_tablet_v1_send_done (resource);
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_create_new_resource (MetaWaylandTablet *tablet,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_v1_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &tablet_interface,
|
||||
tablet, unbind_resource);
|
||||
wl_resource_set_user_data (resource, tablet);
|
||||
wl_list_insert (&tablet->resource_list, wl_resource_get_link (resource));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_lookup_resource (MetaWaylandTablet *tablet,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&tablet->resource_list, client);
|
||||
|
||||
if (!resource)
|
||||
resource = wl_resource_find_for_client (&tablet->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
59
src/wayland/meta-wayland-tablet.h
Normal file
59
src/wayland/meta-wayland-tablet.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2015 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_H
|
||||
#define META_WAYLAND_TABLET_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
struct _MetaWaylandTablet
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
|
||||
MetaWaylandSurface *current;
|
||||
};
|
||||
|
||||
MetaWaylandTablet * meta_wayland_tablet_new (ClutterInputDevice *device,
|
||||
MetaWaylandTabletSeat *tablet_seat);
|
||||
void meta_wayland_tablet_free (MetaWaylandTablet *tablet);
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_create_new_resource (MetaWaylandTablet *tablet,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_lookup_resource (MetaWaylandTablet *tablet,
|
||||
struct wl_client *client);
|
||||
|
||||
void meta_wayland_tablet_notify (MetaWaylandTablet *tablet,
|
||||
struct wl_resource *resource);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_H */
|
@ -36,6 +36,11 @@ typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
|
||||
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
||||
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
|
||||
|
||||
typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager;
|
||||
typedef struct _MetaWaylandTabletSeat MetaWaylandTabletSeat;
|
||||
typedef struct _MetaWaylandTabletTool MetaWaylandTabletTool;
|
||||
typedef struct _MetaWaylandTablet MetaWaylandTablet;
|
||||
|
||||
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
|
||||
typedef struct _MetaWaylandRegion MetaWaylandRegion;
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-outputs.h"
|
||||
#include "meta-wayland-data-device.h"
|
||||
#include "meta-wayland-tablet-manager.h"
|
||||
|
||||
static MetaWaylandCompositor _meta_wayland_compositor;
|
||||
|
||||
@ -167,7 +168,10 @@ void
|
||||
meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
meta_wayland_seat_update (compositor->seat, event);
|
||||
if (meta_wayland_tablet_manager_consumes_event (compositor->tablet_manager, event))
|
||||
meta_wayland_tablet_manager_update (compositor->tablet_manager, event);
|
||||
else
|
||||
meta_wayland_seat_update (compositor->seat, event);
|
||||
}
|
||||
|
||||
void
|
||||
@ -196,6 +200,10 @@ gboolean
|
||||
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
if (meta_wayland_tablet_manager_handle_event (compositor->tablet_manager,
|
||||
event))
|
||||
return TRUE;
|
||||
|
||||
return meta_wayland_seat_handle_event (compositor->seat, event);
|
||||
}
|
||||
|
||||
@ -327,6 +335,7 @@ meta_wayland_init (void)
|
||||
meta_wayland_data_device_manager_init (compositor);
|
||||
meta_wayland_shell_init (compositor);
|
||||
meta_wayland_pointer_gestures_init (compositor);
|
||||
meta_wayland_tablet_manager_init (compositor);
|
||||
meta_wayland_seat_init (compositor);
|
||||
meta_wayland_relative_pointer_init (compositor);
|
||||
meta_wayland_pointer_constraints_init (compositor);
|
||||
|
Reference in New Issue
Block a user