2018-05-17 13:45:06 +02:00
# ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200809L
# endif
# include "tablet-unstable-v2-protocol.h"
2018-07-07 17:56:37 +02:00
# include "util/array.h"
2018-05-17 13:45:06 +02:00
# include <assert.h>
# include <stdlib.h>
# include <types/wlr_tablet_v2.h>
# include <wayland-util.h>
# include <wlr/types/wlr_tablet_tool.h>
# include <wlr/types/wlr_tablet_v2.h>
# include <wlr/util/log.h>
2018-09-08 19:16:56 +02:00
static const struct wlr_tablet_tool_v2_grab_interface default_tool_grab_interface ;
2018-07-20 10:18:22 +02:00
2018-07-14 10:29:22 +02:00
static const struct wlr_surface_role tablet_tool_cursor_surface_role = {
. name = " wp_tablet_tool-cursor " ,
2018-05-17 13:45:06 +02:00
} ;
static void handle_tablet_tool_v2_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 ) {
struct wlr_tablet_tool_client_v2 * tool = tablet_tool_client_from_resource ( resource ) ;
if ( ! tool ) {
return ;
}
struct wlr_surface * surface = NULL ;
if ( surface_resource ! = NULL ) {
surface = wlr_surface_from_resource ( surface_resource ) ;
2018-07-14 10:29:22 +02:00
if ( ! wlr_surface_set_role ( surface , & tablet_tool_cursor_surface_role , NULL ,
2018-06-24 20:56:39 +02:00
surface_resource , ZWP_TABLET_TOOL_V2_ERROR_ROLE ) ) {
2018-05-17 13:45:06 +02:00
return ;
}
}
struct wlr_tablet_v2_event_cursor evt = {
. surface = surface ,
. serial = serial ,
. hotspot_x = hotspot_x ,
. hotspot_y = hotspot_y ,
2018-06-24 20:56:39 +02:00
. seat_client = tool - > seat - > seat_client ,
2018-05-17 13:45:06 +02:00
} ;
wl_signal_emit ( & tool - > tool - > events . set_cursor , & evt ) ;
}
static void handle_tablet_tool_v2_destroy ( struct wl_client * client ,
struct wl_resource * resource ) {
wl_resource_destroy ( resource ) ;
}
static struct zwp_tablet_tool_v2_interface tablet_tool_impl = {
. set_cursor = handle_tablet_tool_v2_set_cursor ,
. destroy = handle_tablet_tool_v2_destroy ,
} ;
static enum zwp_tablet_tool_v2_type tablet_type_from_wlr_type (
enum wlr_tablet_tool_type wlr_type ) {
switch ( wlr_type ) {
case WLR_TABLET_TOOL_TYPE_PEN :
return ZWP_TABLET_TOOL_V2_TYPE_PEN ;
case WLR_TABLET_TOOL_TYPE_ERASER :
return ZWP_TABLET_TOOL_V2_TYPE_ERASER ;
case WLR_TABLET_TOOL_TYPE_BRUSH :
return ZWP_TABLET_TOOL_V2_TYPE_BRUSH ;
case WLR_TABLET_TOOL_TYPE_PENCIL :
return ZWP_TABLET_TOOL_V2_TYPE_PENCIL ;
case WLR_TABLET_TOOL_TYPE_AIRBRUSH :
return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH ;
case WLR_TABLET_TOOL_TYPE_MOUSE :
return ZWP_TABLET_TOOL_V2_TYPE_MOUSE ;
case WLR_TABLET_TOOL_TYPE_LENS :
return ZWP_TABLET_TOOL_V2_TYPE_LENS ;
}
assert ( false & & " Unreachable " ) ;
}
void destroy_tablet_tool_v2 ( struct wl_resource * resource ) {
struct wlr_tablet_tool_client_v2 * client =
tablet_tool_client_from_resource ( resource ) ;
if ( ! client ) {
return ;
}
if ( client - > frame_source ) {
wl_event_source_remove ( client - > frame_source ) ;
}
if ( client - > tool & & client - > tool - > current_client = = client ) {
client - > tool - > current_client = NULL ;
}
wl_list_remove ( & client - > seat_link ) ;
wl_list_remove ( & client - > tool_link ) ;
free ( client ) ;
wl_resource_set_user_data ( resource , NULL ) ;
}
void add_tablet_tool_client ( struct wlr_tablet_seat_client_v2 * seat ,
struct wlr_tablet_v2_tablet_tool * tool ) {
struct wlr_tablet_tool_client_v2 * client =
calloc ( 1 , sizeof ( struct wlr_tablet_tool_client_v2 ) ) ;
if ( ! client ) {
return ;
}
client - > tool = tool ;
client - > seat = seat ;
client - > resource =
wl_resource_create ( seat - > wl_client , & zwp_tablet_tool_v2_interface , 1 , 0 ) ;
if ( ! client - > resource ) {
free ( client ) ;
return ;
}
wl_resource_set_implementation ( client - > resource , & tablet_tool_impl ,
client , destroy_tablet_tool_v2 ) ;
zwp_tablet_seat_v2_send_tool_added ( seat - > resource , client - > resource ) ;
// Send the expected events
if ( tool - > wlr_tool - > hardware_serial ) {
zwp_tablet_tool_v2_send_hardware_serial (
client - > resource ,
tool - > wlr_tool - > hardware_serial > > 32 ,
tool - > wlr_tool - > hardware_serial & 0xFFFFFFFF ) ;
}
if ( tool - > wlr_tool - > hardware_wacom ) {
zwp_tablet_tool_v2_send_hardware_id_wacom (
client - > resource ,
tool - > wlr_tool - > hardware_wacom > > 32 ,
tool - > wlr_tool - > hardware_wacom & 0xFFFFFFFF ) ;
}
zwp_tablet_tool_v2_send_type ( client - > resource ,
tablet_type_from_wlr_type ( tool - > wlr_tool - > type ) ) ;
if ( tool - > wlr_tool - > tilt ) {
zwp_tablet_tool_v2_send_capability ( client - > resource ,
ZWP_TABLET_TOOL_V2_CAPABILITY_TILT ) ;
}
if ( tool - > wlr_tool - > pressure ) {
zwp_tablet_tool_v2_send_capability ( client - > resource ,
ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE ) ;
}
if ( tool - > wlr_tool - > distance ) {
zwp_tablet_tool_v2_send_capability ( client - > resource ,
ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE ) ;
}
if ( tool - > wlr_tool - > rotation ) {
zwp_tablet_tool_v2_send_capability ( client - > resource ,
ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION ) ;
}
if ( tool - > wlr_tool - > slider ) {
zwp_tablet_tool_v2_send_capability ( client - > resource ,
ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER ) ;
}
if ( tool - > wlr_tool - > wheel ) {
zwp_tablet_tool_v2_send_capability ( client - > resource ,
ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL ) ;
}
zwp_tablet_tool_v2_send_done ( client - > resource ) ;
client - > client = seat - > wl_client ;
wl_list_insert ( & seat - > tools , & client - > seat_link ) ;
wl_list_insert ( & tool - > clients , & client - > tool_link ) ;
}
static void handle_wlr_tablet_tool_destroy ( struct wl_listener * listener , void * data ) {
struct wlr_tablet_v2_tablet_tool * tool =
wl_container_of ( listener , tool , tool_destroy ) ;
struct wlr_tablet_tool_client_v2 * pos ;
struct wlr_tablet_tool_client_v2 * tmp ;
wl_list_for_each_safe ( pos , tmp , & tool - > clients , tool_link ) {
zwp_tablet_tool_v2_send_removed ( pos - > resource ) ;
pos - > tool = NULL ;
}
wl_list_remove ( & tool - > clients ) ;
wl_list_remove ( & tool - > link ) ;
wl_list_remove ( & tool - > tool_destroy . link ) ;
wl_list_remove ( & tool - > events . set_cursor . listener_list ) ;
free ( tool ) ;
}
struct wlr_tablet_v2_tablet_tool * wlr_tablet_tool_create (
struct wlr_tablet_manager_v2 * manager ,
struct wlr_seat * wlr_seat ,
2018-06-16 11:19:48 +02:00
struct wlr_tablet_tool * wlr_tool ) {
2018-05-17 13:45:06 +02:00
struct wlr_tablet_seat_v2 * seat = get_or_create_tablet_seat ( manager , wlr_seat ) ;
if ( ! seat ) {
return NULL ;
}
struct wlr_tablet_v2_tablet_tool * tool =
calloc ( 1 , sizeof ( struct wlr_tablet_v2_tablet_tool ) ) ;
if ( ! tool ) {
return NULL ;
}
tool - > wlr_tool = wlr_tool ;
wl_list_init ( & tool - > clients ) ;
2018-07-20 10:18:22 +02:00
tool - > default_grab . tool = tool ;
2018-09-08 19:16:56 +02:00
tool - > default_grab . interface = & default_tool_grab_interface ;
2018-07-20 10:18:22 +02:00
tool - > grab = & tool - > default_grab ;
2018-05-17 13:45:06 +02:00
tool - > tool_destroy . notify = handle_wlr_tablet_tool_destroy ;
wl_signal_add ( & wlr_tool - > events . destroy , & tool - > tool_destroy ) ;
wl_list_insert ( & seat - > tools , & tool - > link ) ;
// We need to create a tablet client for all clients on the seat
struct wlr_tablet_seat_client_v2 * pos ;
wl_list_for_each ( pos , & seat - > clients , seat_link ) {
// Tell the clients about the new tool
add_tablet_tool_client ( pos , tool ) ;
}
wl_signal_init ( & tool - > events . set_cursor ) ;
return tool ;
}
struct wlr_tablet_tool_client_v2 * tablet_tool_client_from_resource ( struct wl_resource * resource ) {
assert ( wl_resource_instance_of ( resource , & zwp_tablet_tool_v2_interface ,
& tablet_tool_impl ) ) ;
return wl_resource_get_user_data ( resource ) ;
}
/* Actual protocol foo */
2018-07-07 17:56:37 +02:00
// Button 0 is KEY_RESERVED in input-event-codes on linux (and freebsd)
2018-05-17 14:23:17 +02:00
static ssize_t tablet_tool_button_update ( struct wlr_tablet_v2_tablet_tool * tool ,
2018-05-17 13:45:06 +02:00
uint32_t button , enum zwp_tablet_pad_v2_button_state state ) {
bool found = false ;
size_t i = 0 ;
for ( ; i < tool - > num_buttons ; + + i ) {
if ( tool - > pressed_buttons [ i ] = = button ) {
found = true ;
2018-07-14 10:29:22 +02:00
wlr_log ( WLR_DEBUG , " Found the button \\ o/: %u " , button ) ;
2018-05-17 13:45:06 +02:00
break ;
2018-07-14 10:29:22 +02:00
2018-05-17 13:45:06 +02:00
}
}
2018-07-14 10:29:22 +02:00
if ( state = = ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED & & found ) {
/* Already have the button saved, durr */
return - 1 ;
}
2018-07-07 17:56:37 +02:00
if ( state = = ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED & & ! found ) {
if ( tool - > num_buttons < WLR_TABLET_V2_TOOL_BUTTONS_CAP ) {
i = tool - > num_buttons + + ;
tool - > pressed_buttons [ i ] = button ;
tool - > pressed_serials [ i ] = - 1 ;
} else {
i = - 1 ;
wlr_log ( WLR_ERROR , " You pressed more than %d tablet tool buttons. This is currently not supporte by wlroots. Please report this with a description of your tablet, since this is either a bug, or fancy hardware " ,
WLR_TABLET_V2_TOOL_BUTTONS_CAP ) ;
}
2018-05-17 13:45:06 +02:00
}
2018-05-17 15:21:20 +02:00
if ( state = = ZWP_TABLET_PAD_V2_BUTTON_STATE_RELEASED & & found ) {
2018-07-14 10:29:22 +02:00
wlr_log ( WLR_DEBUG , " Removed the button \\ o/: %u " , button ) ;
2018-05-17 13:45:06 +02:00
tool - > pressed_buttons [ i ] = 0 ;
2018-05-17 14:23:17 +02:00
tool - > pressed_serials [ i ] = 0 ;
2018-05-17 15:21:20 +02:00
tool - > num_buttons = push_zeroes_to_end ( tool - > pressed_buttons , WLR_TABLET_V2_TOOL_BUTTONS_CAP ) ;
tool - > num_buttons = push_zeroes_to_end ( tool - > pressed_serials , WLR_TABLET_V2_TOOL_BUTTONS_CAP ) ;
2018-05-17 13:45:06 +02:00
}
2018-05-17 15:21:20 +02:00
assert ( tool - > num_buttons < = WLR_TABLET_V2_TOOL_BUTTONS_CAP ) ;
2018-05-17 14:23:17 +02:00
return i ;
}
static inline int64_t timespec_to_msec ( const struct timespec * a ) {
return ( int64_t ) a - > tv_sec * 1000 + a - > tv_nsec / 1000000 ;
2018-05-17 13:45:06 +02:00
}
static void send_tool_frame ( void * data ) {
struct wlr_tablet_tool_client_v2 * tool = data ;
2018-05-17 14:23:17 +02:00
struct timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
zwp_tablet_tool_v2_send_frame ( tool - > resource , timespec_to_msec ( & now ) ) ;
2018-05-17 13:45:06 +02:00
tool - > frame_source = NULL ;
}
static void queue_tool_frame ( struct wlr_tablet_tool_client_v2 * tool ) {
struct wl_display * display = wl_client_get_display ( tool - > client ) ;
struct wl_event_loop * loop = wl_display_get_event_loop ( display ) ;
if ( ! tool - > frame_source ) {
tool - > frame_source =
wl_event_loop_add_idle ( loop , send_tool_frame , tool ) ;
}
}
2018-05-17 14:23:17 +02:00
void wlr_send_tablet_v2_tablet_tool_proximity_in (
2018-05-17 13:45:06 +02:00
struct wlr_tablet_v2_tablet_tool * tool ,
struct wlr_tablet_v2_tablet * tablet ,
struct wlr_surface * surface ) {
struct wl_client * client = wl_resource_get_client ( surface - > resource ) ;
if ( tool - > focused_surface = = surface ) {
2018-05-17 14:23:17 +02:00
return ;
2018-05-17 13:45:06 +02:00
}
struct wlr_tablet_client_v2 * tablet_tmp ;
struct wlr_tablet_client_v2 * tablet_client = NULL ;
wl_list_for_each ( tablet_tmp , & tablet - > clients , tablet_link ) {
if ( tablet_tmp - > client = = client ) {
tablet_client = tablet_tmp ;
break ;
}
}
// Couldn't find the client binding for the surface's client. Either
// the client didn't bind tablet_v2 at all, or not for the relevant
// seat
if ( ! tablet_client ) {
2018-05-17 14:23:17 +02:00
return ;
2018-05-17 13:45:06 +02:00
}
struct wlr_tablet_tool_client_v2 * tool_tmp = NULL ;
struct wlr_tablet_tool_client_v2 * tool_client = NULL ;
wl_list_for_each ( tool_tmp , & tool - > clients , tool_link ) {
if ( tool_tmp - > client = = client ) {
tool_client = tool_tmp ;
break ;
}
}
// Couldn't find the client binding for the surface's client. Either
// the client didn't bind tablet_v2 at all, or not for the relevant
// seat
if ( ! tool_client ) {
2018-05-17 14:23:17 +02:00
return ;
2018-05-17 13:45:06 +02:00
}
tool - > current_client = tool_client ;
2018-05-17 14:23:17 +02:00
uint32_t serial = wl_display_next_serial ( wl_client_get_display ( client ) ) ;
tool - > focused_surface = surface ;
tool - > proximity_serial = serial ;
2018-05-17 13:45:06 +02:00
zwp_tablet_tool_v2_send_proximity_in ( tool_client - > resource , serial ,
tablet_client - > resource , surface - > resource ) ;
2018-05-17 14:23:17 +02:00
/* Send all the pressed buttons */
for ( size_t i = 0 ; i < tool - > num_buttons ; + + i ) {
2018-05-17 15:21:20 +02:00
wlr_send_tablet_v2_tablet_tool_button ( tool ,
2018-05-17 14:23:17 +02:00
tool - > pressed_buttons [ i ] ,
ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ) ;
}
if ( tool - > is_down ) {
wlr_send_tablet_v2_tablet_tool_down ( tool ) ;
}
2018-05-17 13:45:06 +02:00
2018-05-17 14:23:17 +02:00
queue_tool_frame ( tool_client ) ;
2018-05-17 13:45:06 +02:00
}
void wlr_send_tablet_v2_tablet_tool_motion (
struct wlr_tablet_v2_tablet_tool * tool , double x , double y ) {
if ( ! tool - > current_client ) {
return ;
}
zwp_tablet_tool_v2_send_motion ( tool - > current_client - > resource ,
wl_fixed_from_double ( x ) , wl_fixed_from_double ( y ) ) ;
queue_tool_frame ( tool - > current_client ) ;
}
void wlr_send_tablet_v2_tablet_tool_proximity_out (
struct wlr_tablet_v2_tablet_tool * tool ) {
if ( tool - > current_client ) {
2018-05-17 15:21:20 +02:00
for ( size_t i = 0 ; i < tool - > num_buttons ; + + i ) {
zwp_tablet_tool_v2_send_button ( tool - > current_client - > resource ,
tool - > pressed_serials [ i ] ,
tool - > pressed_buttons [ i ] ,
ZWP_TABLET_PAD_V2_BUTTON_STATE_RELEASED ) ;
}
if ( tool - > is_down ) {
zwp_tablet_tool_v2_send_up ( tool - > current_client - > resource ) ;
}
2018-05-17 13:45:06 +02:00
if ( tool - > current_client - > frame_source ) {
wl_event_source_remove ( tool - > current_client - > frame_source ) ;
send_tool_frame ( tool - > current_client ) ;
}
2018-07-23 10:10:00 +02:00
zwp_tablet_tool_v2_send_proximity_out ( tool - > current_client - > resource ) ;
2018-05-17 15:21:20 +02:00
2018-05-17 13:45:06 +02:00
tool - > current_client = NULL ;
2018-05-17 15:21:20 +02:00
tool - > focused_surface = NULL ;
2018-05-17 13:45:06 +02:00
}
}
void wlr_send_tablet_v2_tablet_tool_pressure (
2018-05-19 12:16:11 +02:00
struct wlr_tablet_v2_tablet_tool * tool , double pressure ) {
2018-05-17 13:45:06 +02:00
if ( tool - > current_client ) {
zwp_tablet_tool_v2_send_pressure ( tool - > current_client - > resource ,
2018-05-19 12:16:11 +02:00
pressure * 65535 ) ;
2018-05-17 13:45:06 +02:00
queue_tool_frame ( tool - > current_client ) ;
}
}
void wlr_send_tablet_v2_tablet_tool_distance (
2018-05-19 12:16:11 +02:00
struct wlr_tablet_v2_tablet_tool * tool , double distance ) {
2018-05-17 13:45:06 +02:00
if ( tool - > current_client ) {
zwp_tablet_tool_v2_send_distance ( tool - > current_client - > resource ,
2018-05-19 12:16:11 +02:00
distance * 65535 ) ;
2018-05-17 13:45:06 +02:00
queue_tool_frame ( tool - > current_client ) ;
}
}
void wlr_send_tablet_v2_tablet_tool_tilt (
struct wlr_tablet_v2_tablet_tool * tool , double x , double y ) {
if ( ! tool - > current_client ) {
return ;
}
zwp_tablet_tool_v2_send_tilt ( tool - > current_client - > resource ,
wl_fixed_from_double ( x ) , wl_fixed_from_double ( y ) ) ;
queue_tool_frame ( tool - > current_client ) ;
}
void wlr_send_tablet_v2_tablet_tool_rotation (
struct wlr_tablet_v2_tablet_tool * tool , double degrees ) {
if ( ! tool - > current_client ) {
return ;
}
zwp_tablet_tool_v2_send_rotation ( tool - > current_client - > resource ,
wl_fixed_from_double ( degrees ) ) ;
queue_tool_frame ( tool - > current_client ) ;
}
void wlr_send_tablet_v2_tablet_tool_slider (
2018-05-19 12:16:11 +02:00
struct wlr_tablet_v2_tablet_tool * tool , double position ) {
2018-05-17 13:45:06 +02:00
if ( ! tool - > current_client ) {
return ;
}
zwp_tablet_tool_v2_send_slider ( tool - > current_client - > resource ,
2018-05-19 12:16:11 +02:00
position * 65535 ) ;
2018-05-17 13:45:06 +02:00
queue_tool_frame ( tool - > current_client ) ;
}
2018-05-17 14:23:17 +02:00
void wlr_send_tablet_v2_tablet_tool_button (
2018-05-17 13:45:06 +02:00
struct wlr_tablet_v2_tablet_tool * tool , uint32_t button ,
enum zwp_tablet_pad_v2_button_state state ) {
2018-05-17 14:23:17 +02:00
ssize_t index = tablet_tool_button_update ( tool , button , state ) ;
2018-05-17 13:45:06 +02:00
if ( tool - > current_client ) {
2018-05-17 14:23:17 +02:00
struct wl_client * client =
wl_resource_get_client ( tool - > current_client - > resource ) ;
uint32_t serial = wl_display_next_serial ( wl_client_get_display ( client ) ) ;
if ( index > = 0 ) {
tool - > pressed_serials [ index ] = serial ;
}
2018-05-17 13:45:06 +02:00
zwp_tablet_tool_v2_send_button ( tool - > current_client - > resource ,
serial , button , state ) ;
queue_tool_frame ( tool - > current_client ) ;
}
}
void wlr_send_tablet_v2_tablet_tool_wheel (
2018-06-24 20:56:39 +02:00
struct wlr_tablet_v2_tablet_tool * tool , double degrees , int32_t clicks ) {
2018-05-17 13:45:06 +02:00
if ( tool - > current_client ) {
zwp_tablet_tool_v2_send_wheel ( tool - > current_client - > resource ,
2018-06-24 20:56:39 +02:00
clicks , degrees ) ;
2018-05-17 13:45:06 +02:00
queue_tool_frame ( tool - > current_client ) ;
}
}
2018-05-17 14:23:17 +02:00
void wlr_send_tablet_v2_tablet_tool_down ( struct wlr_tablet_v2_tablet_tool * tool ) {
2018-05-17 13:45:06 +02:00
if ( tool - > is_down ) {
2018-05-17 14:23:17 +02:00
return ;
2018-05-17 13:45:06 +02:00
}
tool - > is_down = true ;
if ( tool - > current_client ) {
2018-05-17 14:23:17 +02:00
struct wl_client * client =
wl_resource_get_client ( tool - > current_client - > resource ) ;
uint32_t serial = wl_display_next_serial ( wl_client_get_display ( client ) ) ;
2018-05-17 13:45:06 +02:00
zwp_tablet_tool_v2_send_down ( tool - > current_client - > resource ,
serial ) ;
queue_tool_frame ( tool - > current_client ) ;
2018-05-17 14:23:17 +02:00
tool - > down_serial = serial ;
2018-05-17 13:45:06 +02:00
}
}
void wlr_send_tablet_v2_tablet_tool_up ( struct wlr_tablet_v2_tablet_tool * tool ) {
if ( ! tool - > is_down ) {
return ;
}
tool - > is_down = false ;
2018-05-17 14:23:17 +02:00
tool - > down_serial = 0 ;
2018-05-17 13:45:06 +02:00
if ( tool - > current_client ) {
zwp_tablet_tool_v2_send_up ( tool - > current_client - > resource ) ;
queue_tool_frame ( tool - > current_client ) ;
}
}
2018-07-20 10:18:22 +02:00
void wlr_tablet_v2_tablet_tool_notify_proximity_in (
struct wlr_tablet_v2_tablet_tool * tool ,
struct wlr_tablet_v2_tablet * tablet ,
struct wlr_surface * surface ) {
if ( tool - > grab - > interface - > proximity_in ) {
tool - > grab - > interface - > proximity_in ( tool - > grab , tablet , surface ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_down ( struct wlr_tablet_v2_tablet_tool * tool ) {
if ( tool - > grab - > interface - > down ) {
tool - > grab - > interface - > down ( tool - > grab ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_up ( struct wlr_tablet_v2_tablet_tool * tool ) {
if ( tool - > grab - > interface - > up ) {
tool - > grab - > interface - > up ( tool - > grab ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_motion (
struct wlr_tablet_v2_tablet_tool * tool , double x , double y ) {
if ( tool - > grab - > interface - > motion ) {
tool - > grab - > interface - > motion ( tool - > grab , x , y ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_pressure (
struct wlr_tablet_v2_tablet_tool * tool , double pressure ) {
if ( tool - > grab - > interface - > pressure ) {
tool - > grab - > interface - > pressure ( tool - > grab , pressure ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_distance (
struct wlr_tablet_v2_tablet_tool * tool , double distance ) {
if ( tool - > grab - > interface - > distance ) {
tool - > grab - > interface - > distance ( tool - > grab , distance ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_tilt (
struct wlr_tablet_v2_tablet_tool * tool , double x , double y ) {
if ( tool - > grab - > interface - > tilt ) {
tool - > grab - > interface - > tilt ( tool - > grab , x , y ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_rotation (
struct wlr_tablet_v2_tablet_tool * tool , double degrees ) {
if ( tool - > grab - > interface - > rotation ) {
tool - > grab - > interface - > rotation ( tool - > grab , degrees ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_slider (
struct wlr_tablet_v2_tablet_tool * tool , double position ) {
if ( tool - > grab - > interface - > slider ) {
tool - > grab - > interface - > slider ( tool - > grab , position ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_wheel (
struct wlr_tablet_v2_tablet_tool * tool , double degrees , int32_t clicks ) {
if ( tool - > grab - > interface - > wheel ) {
tool - > grab - > interface - > wheel ( tool - > grab , degrees , clicks ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_proximity_out (
struct wlr_tablet_v2_tablet_tool * tool ) {
if ( tool - > grab - > interface - > proximity_out ) {
tool - > grab - > interface - > proximity_out ( tool - > grab ) ;
}
}
void wlr_tablet_v2_tablet_tool_notify_button (
struct wlr_tablet_v2_tablet_tool * tool , uint32_t button ,
enum zwp_tablet_pad_v2_button_state state ) {
if ( tool - > grab - > interface - > button ) {
tool - > grab - > interface - > button ( tool - > grab , button , state ) ;
}
}
2018-09-08 19:16:56 +02:00
void wlr_tablet_tool_v2_start_grab ( struct wlr_tablet_v2_tablet_tool * tool ,
struct wlr_tablet_tool_v2_grab * grab ) {
2018-07-20 10:18:22 +02:00
wlr_tablet_tool_v2_end_grab ( tool ) ;
tool - > grab = grab ;
}
void wlr_tablet_tool_v2_end_grab ( struct wlr_tablet_v2_tablet_tool * tool ) {
if ( tool - > grab - > interface - > cancel ) {
tool - > grab - > interface - > cancel ( tool - > grab ) ;
}
tool - > grab = & tool - > default_grab ;
}
static void default_tool_proximity_in (
struct wlr_tablet_tool_v2_grab * grab ,
struct wlr_tablet_v2_tablet * tablet ,
struct wlr_surface * surface ) {
wlr_send_tablet_v2_tablet_tool_proximity_in ( grab - > tool , tablet , surface ) ;
}
static void default_tool_down ( struct wlr_tablet_tool_v2_grab * grab ) {
wlr_send_tablet_v2_tablet_tool_down ( grab - > tool ) ;
}
static void default_tool_up ( struct wlr_tablet_tool_v2_grab * grab ) {
wlr_send_tablet_v2_tablet_tool_up ( grab - > tool ) ;
}
static void default_tool_motion (
2018-09-08 19:16:56 +02:00
struct wlr_tablet_tool_v2_grab * grab , double x , double y ) {
2018-07-20 10:18:22 +02:00
wlr_send_tablet_v2_tablet_tool_motion ( grab - > tool , x , y ) ;
}
static void default_tool_pressure (
struct wlr_tablet_tool_v2_grab * grab , double pressure ) {
wlr_send_tablet_v2_tablet_tool_pressure ( grab - > tool , pressure ) ;
}
static void default_tool_distance (
struct wlr_tablet_tool_v2_grab * grab , double distance ) {
wlr_send_tablet_v2_tablet_tool_distance ( grab - > tool , distance ) ;
}
static void default_tool_tilt (
struct wlr_tablet_tool_v2_grab * grab , double x , double y ) {
wlr_send_tablet_v2_tablet_tool_tilt ( grab - > tool , x , y ) ;
}
static void default_tool_rotation (
struct wlr_tablet_tool_v2_grab * grab , double degrees ) {
wlr_send_tablet_v2_tablet_tool_rotation ( grab - > tool , degrees ) ;
}
static void default_tool_slider (
struct wlr_tablet_tool_v2_grab * grab , double position ) {
wlr_send_tablet_v2_tablet_tool_slider ( grab - > tool , position ) ;
}
static void default_tool_wheel (
struct wlr_tablet_tool_v2_grab * grab , double degrees , int32_t clicks ) {
wlr_send_tablet_v2_tablet_tool_wheel ( grab - > tool , degrees , clicks ) ;
}
static void default_tool_proximity_out ( struct wlr_tablet_tool_v2_grab * grab ) {
wlr_send_tablet_v2_tablet_tool_proximity_out ( grab - > tool ) ;
}
static void default_tool_button (
struct wlr_tablet_tool_v2_grab * grab , uint32_t button ,
enum zwp_tablet_pad_v2_button_state state ) {
wlr_send_tablet_v2_tablet_tool_button ( grab - > tool , button , state ) ;
}
static void default_tool_cancel ( struct wlr_tablet_tool_v2_grab * grab ) {
/* Do nothing. Default grab can't be canceled */
}
2018-09-08 19:16:56 +02:00
static const struct wlr_tablet_tool_v2_grab_interface
default_tool_grab_interface = {
2018-07-20 10:18:22 +02:00
. proximity_in = default_tool_proximity_in ,
. down = default_tool_down ,
. up = default_tool_up ,
. motion = default_tool_motion ,
. pressure = default_tool_pressure ,
. distance = default_tool_distance ,
. tilt = default_tool_tilt ,
. rotation = default_tool_rotation ,
. slider = default_tool_slider ,
. wheel = default_tool_wheel ,
. proximity_out = default_tool_proximity_out ,
. button = default_tool_button ,
. cancel = default_tool_cancel ,
} ;
2018-07-23 10:08:43 +02:00
struct implicit_grab_state {
struct wlr_surface * original ;
bool released ;
struct wlr_surface * focused ;
struct wlr_tablet_v2_tablet * tablet ;
} ;
static void check_and_release_implicit_grab ( struct wlr_tablet_tool_v2_grab * grab ) {
struct implicit_grab_state * state = grab - > data ;
/* Still button or tip pressed. We should hold the grab */
if ( grab - > tool - > is_down | | grab - > tool - > num_buttons > 0 | | state - > released ) {
return ;
}
state - > released = true ;
/* We should still focus the same surface. Do nothing */
if ( state - > original = = state - > focused ) {
wlr_tablet_tool_v2_end_grab ( grab - > tool ) ;
return ;
}
wlr_send_tablet_v2_tablet_tool_proximity_out ( grab - > tool ) ;
if ( state - > focused ) {
wlr_send_tablet_v2_tablet_tool_proximity_in ( grab - > tool ,
state - > tablet , state - > focused ) ;
}
wlr_tablet_tool_v2_end_grab ( grab - > tool ) ;
}
static void implicit_tool_proximity_in (
struct wlr_tablet_tool_v2_grab * grab ,
struct wlr_tablet_v2_tablet * tablet ,
struct wlr_surface * surface ) {
/* As long as we got an implicit grab, proximity won't change
* But should track the currently focused surface to change to it when
* the grab is released .
*/
struct implicit_grab_state * state = grab - > data ;
state - > focused = surface ;
state - > tablet = tablet ;
}
static void implicit_tool_proximity_out ( struct wlr_tablet_tool_v2_grab * grab ) {
struct implicit_grab_state * state = grab - > data ;
state - > focused = NULL ;
}
static void implicit_tool_down ( struct wlr_tablet_tool_v2_grab * grab ) {
wlr_send_tablet_v2_tablet_tool_down ( grab - > tool ) ;
}
static void implicit_tool_up ( struct wlr_tablet_tool_v2_grab * grab ) {
wlr_send_tablet_v2_tablet_tool_up ( grab - > tool ) ;
check_and_release_implicit_grab ( grab ) ;
}
/* Only send the motion event, when we are over the surface for now */
static void implicit_tool_motion (
struct wlr_tablet_tool_v2_grab * grab , double x , double y ) {
struct implicit_grab_state * state = grab - > data ;
if ( state - > focused ! = state - > original ) {
return ;
}
wlr_send_tablet_v2_tablet_tool_motion ( grab - > tool , x , y ) ;
}
static void implicit_tool_button (
struct wlr_tablet_tool_v2_grab * grab , uint32_t button ,
enum zwp_tablet_pad_v2_button_state state ) {
wlr_send_tablet_v2_tablet_tool_button ( grab - > tool , button , state ) ;
check_and_release_implicit_grab ( grab ) ;
}
static void implicit_tool_cancel ( struct wlr_tablet_tool_v2_grab * grab ) {
check_and_release_implicit_grab ( grab ) ;
free ( grab - > data ) ;
free ( grab ) ;
}
2018-09-08 19:16:56 +02:00
static const struct wlr_tablet_tool_v2_grab_interface
implicit_tool_grab_interface = {
2018-07-23 10:08:43 +02:00
. proximity_in = implicit_tool_proximity_in ,
. down = implicit_tool_down ,
. up = implicit_tool_up ,
. motion = implicit_tool_motion ,
. pressure = default_tool_pressure ,
. distance = default_tool_distance ,
. tilt = default_tool_tilt ,
. rotation = default_tool_rotation ,
. slider = default_tool_slider ,
. wheel = default_tool_wheel ,
. proximity_out = implicit_tool_proximity_out ,
. button = implicit_tool_button ,
. cancel = implicit_tool_cancel ,
} ;
static bool tool_has_implicit_grab ( struct wlr_tablet_v2_tablet_tool * tool ) {
2018-09-08 19:16:56 +02:00
return tool - > grab - > interface = = & implicit_tool_grab_interface ;
2018-07-23 10:08:43 +02:00
}
2018-09-08 19:16:56 +02:00
void wlr_tablet_tool_v2_start_implicit_grab (
struct wlr_tablet_v2_tablet_tool * tool ) {
2018-07-23 10:08:43 +02:00
if ( tool_has_implicit_grab ( tool ) | | ! tool - > focused_surface ) {
return ;
}
/* No current implicit grab */
if ( ! ( tool - > is_down | | tool - > num_buttons > 0 ) ) {
return ;
}
struct wlr_tablet_tool_v2_grab * grab =
calloc ( 1 , sizeof ( struct wlr_tablet_tool_v2_grab ) ) ;
if ( ! grab ) {
return ;
}
2018-09-08 19:16:56 +02:00
grab - > interface = & implicit_tool_grab_interface ;
2018-07-23 10:08:43 +02:00
grab - > tool = tool ;
struct implicit_grab_state * state = calloc ( 1 , sizeof ( struct implicit_grab_state ) ) ;
if ( ! state ) {
free ( grab ) ;
return ;
}
state - > original = tool - > focused_surface ;
grab - > data = state ;
wlr_tablet_tool_v2_start_grab ( tool , grab ) ;
}