@ -37,12 +37,21 @@ struct weston_drag {
struct weston_view * focus ;
struct wl_resource * focus_resource ;
struct wl_listener focus_listener ;
struct weston_pointer_grab grab ;
struct weston_view * icon ;
struct wl_listener icon_destroy_listener ;
int32_t dx , dy ;
} ;
struct weston_pointer_drag {
struct weston_drag base ;
struct weston_pointer_grab grab ;
} ;
struct weston_touch_drag {
struct weston_drag base ;
struct weston_touch_grab grab ;
} ;
static void
empty_region ( pixman_region32_t * region )
{
@ -172,17 +181,21 @@ static struct wl_data_source_interface data_source_interface = {
} ;
static void
drag_surface_configure ( struct weston_surface * es , int32_t sx , int32_t sy , int32_t width , int32_t height )
drag_surface_configure ( struct weston_drag * drag ,
struct weston_pointer * pointer ,
struct weston_touch * touch ,
struct weston_surface * es , int32_t sx , int32_t sy ,
int32_t width , int32_t height )
{
struct weston_drag * drag = es - > configure_private ;
struct weston_pointer * pointer = drag - > grab . pointer ;
struct wl_list * list ;
float fx , fy ;
assert ( es - > configure = = drag_surface_configure ) ;
assert ( ( pointer ! = NULL & & touch = = NULL ) | |
( pointer = = NULL & & touch ! = NULL ) ) ;
if ( ! weston_surface_is_mapped ( es ) & & es - > buffer_ref . buffer ) {
if ( pointer - > sprite & & weston_view_is_mapped ( pointer - > sprite ) )
if ( pointer & & pointer - > sprite & &
weston_view_is_mapped ( pointer - > sprite ) )
list = & pointer - > sprite - > layer_link ;
else
list = & es - > compositor - > cursor_layer . view_list ;
@ -196,11 +209,40 @@ drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_
drag - > dx + = sx ;
drag - > dy + = sy ;
/* init to 0 for avoiding a compile warning */
fx = fy = 0 ;
if ( pointer ) {
fx = wl_fixed_to_double ( pointer - > x ) + drag - > dx ;
fy = wl_fixed_to_double ( pointer - > y ) + drag - > dy ;
} else if ( touch ) {
fx = wl_fixed_to_double ( touch - > grab_x ) + drag - > dx ;
fy = wl_fixed_to_double ( touch - > grab_y ) + drag - > dy ;
}
weston_view_configure ( drag - > icon , fx , fy , width , height ) ;
}
static void
pointer_drag_surface_configure ( struct weston_surface * es , int32_t sx , int32_t sy , int32_t width , int32_t height )
{
struct weston_pointer_drag * drag = es - > configure_private ;
struct weston_pointer * pointer = drag - > grab . pointer ;
assert ( es - > configure = = pointer_drag_surface_configure ) ;
drag_surface_configure ( & drag - > base , pointer , NULL , es , sx , sy , width , height ) ;
}
static void
touch_drag_surface_configure ( struct weston_surface * es , int32_t sx , int32_t sy , int32_t width , int32_t height )
{
struct weston_touch_drag * drag = es - > configure_private ;
struct weston_touch * touch = drag - > grab . touch ;
assert ( es - > configure = = touch_drag_surface_configure ) ;
drag_surface_configure ( & drag - > base , NULL , touch , es , sx , sy , width , height ) ;
}
static void
destroy_drag_focus ( struct wl_listener * listener , void * data )
{
@ -211,12 +253,13 @@ destroy_drag_focus(struct wl_listener *listener, void *data)
}
static void
weston_drag_set_focus ( struct weston_drag * drag , struct weston_view * view ,
weston_drag_set_focus ( struct weston_drag * drag ,
struct weston_seat * seat ,
struct weston_view * view ,
wl_fixed_t sx , wl_fixed_t sy )
{
struct weston_pointer * pointer = drag - > grab . pointer ;
struct wl_resource * resource , * offer = NULL ;
struct wl_display * display = pointer - > seat - > compositor - > wl_display ;
struct wl_display * display = seat - > compositor - > wl_display ;
uint32_t serial ;
if ( drag - > focus & & view & & drag - > focus - > surface = = view - > surface ) {
@ -238,7 +281,7 @@ weston_drag_set_focus(struct weston_drag *drag, struct weston_view *view,
wl_resource_get_client ( view - > surface - > resource ) ! = drag - > client )
return ;
resource = wl_resource_find_for_client ( & pointer - > seat - > drag_resource_list ,
resource = wl_resource_find_for_client ( & seat - > drag_resource_list ,
wl_resource_get_client ( view - > surface - > resource ) ) ;
if ( ! resource )
return ;
@ -264,8 +307,8 @@ weston_drag_set_focus(struct weston_drag *drag, struct weston_view *view,
static void
drag_grab_focus ( struct weston_pointer_grab * grab )
{
struct weston_drag * drag =
container_of ( grab , struct weston_drag , grab ) ;
struct weston_pointer_ drag * drag =
container_of ( grab , struct weston_pointer_ drag , grab ) ;
struct weston_pointer * pointer = grab - > pointer ;
struct weston_view * view ;
wl_fixed_t sx , sy ;
@ -273,40 +316,41 @@ drag_grab_focus(struct weston_pointer_grab *grab)
view = weston_compositor_pick_view ( pointer - > seat - > compositor ,
pointer - > x , pointer - > y ,
& sx , & sy ) ;
if ( drag - > focus ! = view )
weston_drag_set_focus ( drag , view , sx , sy ) ;
if ( drag - > base . focus ! = view )
weston_drag_set_focus ( & drag - > base , pointer - > seat , view , sx , sy ) ;
}
static void
drag_grab_motion ( struct weston_pointer_grab * grab , uint32_t time ,
wl_fixed_t x , wl_fixed_t y )
{
struct weston_drag * drag =
container_of ( grab , struct weston_drag , grab ) ;
struct weston_pointer_ drag * drag =
container_of ( grab , struct weston_pointer_ drag , grab ) ;
struct weston_pointer * pointer = drag - > grab . pointer ;
float fx , fy ;
wl_fixed_t sx , sy ;
weston_pointer_move ( pointer , x , y ) ;
if ( drag - > icon ) {
fx = wl_fixed_to_double ( pointer - > x ) + drag - > dx ;
fy = wl_fixed_to_double ( pointer - > y ) + drag - > dy ;
weston_view_set_position ( drag - > icon , fx , fy ) ;
weston_view_schedule_repaint ( drag - > icon ) ;
if ( drag - > base . icon ) {
fx = wl_fixed_to_double ( pointer - > x ) + drag - > base . dx ;
fy = wl_fixed_to_double ( pointer - > y ) + drag - > base . dy ;
weston_view_set_position ( drag - > base . icon , fx , fy ) ;
weston_view_schedule_repaint ( drag - > base . icon ) ;
}
if ( drag - > focus_resource ) {
weston_view_from_global_fixed ( drag - > focus ,
if ( drag - > base . focus_resource ) {
weston_view_from_global_fixed ( drag - > base . focus ,
pointer - > x , pointer - > y ,
& sx , & sy ) ;
wl_data_device_send_motion ( drag - > focus_resource , time , sx , sy ) ;
wl_data_device_send_motion ( drag - > base . focus_resource , time , sx , sy ) ;
}
}
static void
data_device_end_drag_grab ( struct weston_drag * drag )
data_device_end_drag_grab ( struct weston_drag * drag ,
struct weston_seat * seat )
{
if ( drag - > icon ) {
if ( weston_view_is_mapped ( drag - > icon ) )
@ -318,10 +362,16 @@ data_device_end_drag_grab(struct weston_drag *drag)
weston_view_destroy ( drag - > icon ) ;
}
weston_drag_set_focus ( drag , NULL , 0 , 0 ) ;
weston_drag_set_focus ( drag , seat , NULL , 0 , 0 ) ;
}
weston_pointer_end_grab ( drag - > grab . pointer ) ;
static void
data_device_end_pointer_drag_grab ( struct weston_pointer_drag * drag )
{
struct weston_pointer * pointer = drag - > grab . pointer ;
data_device_end_drag_grab ( & drag - > base , pointer - > seat ) ;
weston_pointer_end_grab ( pointer ) ;
free ( drag ) ;
}
@ -329,37 +379,37 @@ static void
drag_grab_button ( struct weston_pointer_grab * grab ,
uint32_t time , uint32_t button , uint32_t state_w )
{
struct weston_drag * drag =
container_of ( grab , struct weston_drag , grab ) ;
struct weston_pointer_ drag * drag =
container_of ( grab , struct weston_pointer_ drag , grab ) ;
struct weston_pointer * pointer = drag - > grab . pointer ;
enum wl_pointer_button_state state = state_w ;
if ( drag - > focus_resource & &
if ( drag - > base . focus_resource & &
pointer - > grab_button = = button & &
state = = WL_POINTER_BUTTON_STATE_RELEASED )
wl_data_device_send_drop ( drag - > focus_resource ) ;
wl_data_device_send_drop ( drag - > base . focus_resource ) ;
if ( pointer - > button_count = = 0 & &
state = = WL_POINTER_BUTTON_STATE_RELEASED ) {
if ( drag - > data_source )
wl_list_remove ( & drag - > data_source_listener . link ) ;
data_device_end_drag_grab ( drag ) ;
if ( drag - > base . data_source )
wl_list_remove ( & drag - > base . data_source_listener . link ) ;
data_device_end_pointer_ drag_grab ( drag ) ;
}
}
static void
drag_grab_cancel ( struct weston_pointer_grab * grab )
{
struct weston_drag * drag =
container_of ( grab , struct weston_drag , grab ) ;
struct weston_pointer_ drag * drag =
container_of ( grab , struct weston_pointer_ drag , grab ) ;
if ( drag - > data_source )
wl_list_remove ( & drag - > data_source_listener . link ) ;
if ( drag - > base . data_source )
wl_list_remove ( & drag - > base . data_source_listener . link ) ;
data_device_end_drag_grab ( drag ) ;
data_device_end_pointer_ drag_grab ( drag ) ;
}
static const struct weston_pointer_grab_interface drag_grab_interface = {
static const struct weston_pointer_grab_interface pointer_ drag_grab_interface = {
drag_grab_focus ,
drag_grab_motion ,
drag_grab_button ,
@ -367,12 +417,109 @@ static const struct weston_pointer_grab_interface drag_grab_interface = {
} ;
static void
destroy_data_device_source ( struct wl_listener * listener , void * data )
drag_grab_touch_down ( struct weston_touch_grab * grab , uint32_t time ,
int touch_id , wl_fixed_t sx , wl_fixed_t sy )
{
struct weston_drag * drag = container_of ( listener , struct weston_drag ,
data_source_listener ) ;
}
static void
data_device_end_touch_drag_grab ( struct weston_touch_drag * drag )
{
struct weston_touch * touch = drag - > grab . touch ;
data_device_end_drag_grab ( & drag - > base , touch - > seat ) ;
weston_touch_end_grab ( touch ) ;
free ( drag ) ;
}
static void
drag_grab_touch_up ( struct weston_touch_grab * grab ,
uint32_t time , int touch_id )
{
struct weston_touch_drag * touch_drag =
container_of ( grab , struct weston_touch_drag , grab ) ;
struct weston_touch * touch = grab - > touch ;
if ( touch_id ! = touch - > grab_touch_id )
return ;
if ( touch_drag - > base . focus_resource )
wl_data_device_send_drop ( touch_drag - > base . focus_resource ) ;
if ( touch_drag - > base . data_source )
wl_list_remove ( & touch_drag - > base . data_source_listener . link ) ;
data_device_end_touch_drag_grab ( touch_drag ) ;
}
static void
drag_grab_touch_focus ( struct weston_touch_drag * drag )
{
struct weston_touch * touch = drag - > grab . touch ;
struct weston_view * view ;
wl_fixed_t view_x , view_y ;
data_device_end_drag_grab ( drag ) ;
view = weston_compositor_pick_view ( touch - > seat - > compositor ,
touch - > grab_x , touch - > grab_y ,
& view_x , & view_y ) ;
if ( drag - > base . focus ! = view )
weston_drag_set_focus ( & drag - > base , touch - > seat ,
view , view_x , view_y ) ;
}
static void
drag_grab_touch_motion ( struct weston_touch_grab * grab , uint32_t time ,
int touch_id , wl_fixed_t sx , wl_fixed_t sy )
{
struct weston_touch_drag * touch_drag =
container_of ( grab , struct weston_touch_drag , grab ) ;
struct weston_touch * touch = grab - > touch ;
wl_fixed_t view_x , view_y ;
float fx , fy ;
if ( touch_id ! = touch - > grab_touch_id )
return ;
drag_grab_touch_focus ( touch_drag ) ;
if ( touch_drag - > base . icon ) {
fx = wl_fixed_to_double ( touch - > grab_x ) + touch_drag - > base . dx ;
fy = wl_fixed_to_double ( touch - > grab_y ) + touch_drag - > base . dy ;
weston_view_set_position ( touch_drag - > base . icon , fx , fy ) ;
weston_view_schedule_repaint ( touch_drag - > base . icon ) ;
}
if ( touch_drag - > base . focus_resource ) {
weston_view_from_global_fixed ( touch_drag - > base . focus ,
touch - > grab_x , touch - > grab_y ,
& view_x , & view_y ) ;
wl_data_device_send_motion ( touch_drag - > base . focus_resource , time ,
view_x , view_y ) ;
}
}
static void
drag_grab_touch_cancel ( struct weston_touch_grab * grab )
{
struct weston_touch_drag * touch_drag =
container_of ( grab , struct weston_touch_drag , grab ) ;
if ( touch_drag - > base . data_source )
wl_list_remove ( & touch_drag - > base . data_source_listener . link ) ;
data_device_end_touch_drag_grab ( touch_drag ) ;
}
static const struct weston_touch_grab_interface touch_drag_grab_interface = {
drag_grab_touch_down ,
drag_grab_touch_up ,
drag_grab_touch_motion ,
drag_grab_touch_cancel
} ;
static void
destroy_pointer_data_device_source ( struct wl_listener * listener , void * data )
{
struct weston_pointer_drag * drag = container_of ( listener ,
struct weston_pointer_drag , base . data_source_listener ) ;
data_device_end_pointer_drag_grab ( drag ) ;
}
static void
@ -385,47 +532,102 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *data)
}
WL_EXPORT int
weston_seat_start_drag ( struct weston_seat * seat ,
weston_pointer_start_drag ( struct weston_pointer * pointer ,
struct weston_data_source * source ,
struct weston_surface * icon ,
struct wl_client * client )
{
struct weston_drag * drag ;
struct weston_pointer_ drag * drag ;
drag = zalloc ( sizeof * drag ) ;
if ( drag = = NULL )
return - 1 ;
drag - > grab . interface = & drag_grab_interface ;
drag - > client = client ;
drag - > data_source = source ;
drag - > grab . interface = & pointer_ drag_grab_interface;
drag - > base . client = client ;
drag - > base . data_source = source ;
if ( icon ) {
drag - > icon = weston_view_create ( icon ) ;
if ( drag - > icon = = NULL ) {
drag - > base . icon = weston_view_create ( icon ) ;
if ( drag - > base . icon = = NULL ) {
free ( drag ) ;
return - 1 ;
}
drag - > icon_destroy_listener . notify = handle_drag_icon_destroy ;
drag - > base . icon_destroy_listener . notify = handle_drag_icon_destroy ;
wl_signal_add ( & icon - > destroy_signal ,
& drag - > icon_destroy_listener ) ;
& drag - > base . icon_destroy_listener ) ;
icon - > configure = drag_surface_configure ;
icon - > configure = pointer_ drag_surface_configure;
icon - > configure_private = drag ;
} else {
drag - > icon = NULL ;
drag - > base . icon = NULL ;
}
if ( source ) {
drag - > data_source_listener . notify = destroy_data_device_source ;
drag - > base . data_source_listener . notify = destroy_pointer _data_device_source ;
wl_signal_add ( & source - > destroy_signal ,
& drag - > data_source_listener ) ;
& drag - > base . data_source_listener ) ;
}
weston_pointer_set_focus ( seat - > pointer , NULL ,
weston_pointer_set_focus ( pointer , NULL ,
wl_fixed_from_int ( 0 ) , wl_fixed_from_int ( 0 ) ) ;
weston_pointer_start_grab ( seat - > pointer , & drag - > grab ) ;
weston_pointer_start_grab ( pointer , & drag - > grab ) ;
return 0 ;
}
static void
destroy_touch_data_device_source ( struct wl_listener * listener , void * data )
{
struct weston_touch_drag * drag = container_of ( listener ,
struct weston_touch_drag , base . data_source_listener ) ;
data_device_end_touch_drag_grab ( drag ) ;
}
WL_EXPORT int
weston_touch_start_drag ( struct weston_touch * touch ,
struct weston_data_source * source ,
struct weston_surface * icon ,
struct wl_client * client )
{
struct weston_touch_drag * drag ;
drag = zalloc ( sizeof * drag ) ;
if ( drag = = NULL )
return - 1 ;
drag - > grab . interface = & touch_drag_grab_interface ;
drag - > base . client = client ;
drag - > base . data_source = source ;
if ( icon ) {
drag - > base . icon = weston_view_create ( icon ) ;
if ( drag - > base . icon = = NULL ) {
free ( drag ) ;
return - 1 ;
}
drag - > base . icon_destroy_listener . notify = handle_drag_icon_destroy ;
wl_signal_add ( & icon - > destroy_signal ,
& drag - > base . icon_destroy_listener ) ;
icon - > configure = touch_drag_surface_configure ;
icon - > configure_private = drag ;
} else {
drag - > base . icon = NULL ;
}
if ( source ) {
drag - > base . data_source_listener . notify = destroy_touch_data_device_source ;
wl_signal_add ( & source - > destroy_signal ,
& drag - > base . data_source_listener ) ;
}
weston_touch_start_grab ( touch , & drag - > grab ) ;
drag_grab_touch_focus ( drag ) ;
return 0 ;
}
@ -439,11 +641,15 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
struct weston_seat * seat = wl_resource_get_user_data ( resource ) ;
struct weston_data_source * source = NULL ;
struct weston_surface * icon = NULL ;
int32_t ret = 0 ;
if ( seat - > pointer - > button_count = = 0 | |
if ( ( seat - > pointer - > button_count = = 0 | |
seat - > pointer - > grab_serial ! = serial | |
! seat - > pointer - > focus | |
seat - > pointer - > focus - > surface ! = wl_resource_get_user_data ( origin_resource ) )
seat - > pointer - > focus - > surface ! = wl_resource_get_user_data ( origin_resource ) ) & &
( seat - > touch - > grab_serial ! = serial | |
! seat - > touch - > focus | |
seat - > touch - > focus - > surface ! = wl_resource_get_user_data ( origin_resource ) ) )
return ;
/* FIXME: Check that the data source type array isn't empty. */
@ -459,7 +665,17 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
return ;
}
if ( weston_seat_start_drag ( seat , source , icon , client ) < 0 )
if ( seat - > pointer - > button_count = = 1 & &
seat - > pointer - > grab_serial = = serial & &
seat - > pointer - > focus & &
seat - > pointer - > focus - > surface = = wl_resource_get_user_data ( origin_resource ) )
ret = weston_pointer_start_drag ( seat - > pointer , source , icon , client ) ;
else if ( seat - > touch - > grab_serial ! = serial | |
seat - > touch - > focus | |
seat - > touch - > focus - > surface ! = wl_resource_get_user_data ( origin_resource ) )
ret = weston_touch_start_drag ( seat - > touch , source , icon , client ) ;
if ( ret < 0 )
wl_resource_post_no_memory ( resource ) ;
}