Compare commits
	
		
			31 Commits
		
	
	
		
			3.21.90
			...
			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