diff --git a/clients/eventdemo.c b/clients/eventdemo.c index bdad6fd6..e323aa50 100644 --- a/clients/eventdemo.c +++ b/clients/eventdemo.c @@ -259,6 +259,54 @@ axis_handler(struct widget *widget, struct input *input, uint32_t time, wl_fixed_to_double(value)); } +static void +pointer_frame_handler(struct widget *widget, struct input *input, void *data) +{ + printf("pointer frame\n"); +} + +static void +axis_source_handler(struct widget *widget, struct input *input, + uint32_t source, void *data) +{ + const char *axis_source; + + switch (source) { + case WL_POINTER_AXIS_SOURCE_WHEEL: + axis_source = "wheel"; + break; + case WL_POINTER_AXIS_SOURCE_FINGER: + axis_source = "finger"; + break; + case WL_POINTER_AXIS_SOURCE_CONTINUOUS: + axis_source = "continuous"; + break; + default: + axis_source = ""; + break; + } + + printf("axis source: %s\n", axis_source); +} + +static void +axis_stop_handler(struct widget *widget, struct input *input, + uint32_t time, uint32_t axis, + void *data) +{ + printf("axis stop time: %d, axis: %s\n", + time, + axis == WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical" : + "horizontal"); +} + +static void +axis_discrete_handler(struct widget *widget, struct input *input, + uint32_t axis, int32_t discrete, void *data) +{ + printf("axis discrete axis: %d value: %d\n", axis, discrete); +} + /** * \brief CALLBACK function, Waylands informs about pointer motion * \param widget widget @@ -347,8 +395,15 @@ eventdemo_create(struct display *d) /* Set the callback motion handler for the window */ widget_set_motion_handler(e->widget, motion_handler); + /* Set the callback pointer frame handler for the window */ + widget_set_pointer_frame_handler(e->widget, pointer_frame_handler); + /* Set the callback axis handler for the window */ - widget_set_axis_handler(e->widget, axis_handler); + widget_set_axis_handlers(e->widget, + axis_handler, + axis_source_handler, + axis_stop_handler, + axis_discrete_handler); /* Initial drawing of the window */ window_schedule_resize(e->window, width, height); diff --git a/clients/window.c b/clients/window.c index 5d69116e..7d45acd4 100644 --- a/clients/window.c +++ b/clients/window.c @@ -282,6 +282,10 @@ struct widget { widget_touch_frame_handler_t touch_frame_handler; widget_touch_cancel_handler_t touch_cancel_handler; widget_axis_handler_t axis_handler; + widget_pointer_frame_handler_t pointer_frame_handler; + widget_axis_source_handler_t axis_source_handler; + widget_axis_stop_handler_t axis_stop_handler; + widget_axis_discrete_handler_t axis_discrete_handler; void *user_data; int opaque; int tooltip_count; @@ -1930,6 +1934,26 @@ widget_set_axis_handler(struct widget *widget, widget->axis_handler = handler; } +void +widget_set_pointer_frame_handler(struct widget *widget, + widget_pointer_frame_handler_t handler) +{ + widget->pointer_frame_handler = handler; +} + +void +widget_set_axis_handlers(struct widget *widget, + widget_axis_handler_t axis_handler, + widget_axis_source_handler_t axis_source_handler, + widget_axis_stop_handler_t axis_stop_handler, + widget_axis_discrete_handler_t axis_discrete_handler) +{ + widget->axis_handler = axis_handler; + widget->axis_source_handler = axis_source_handler; + widget->axis_stop_handler = axis_stop_handler; + widget->axis_discrete_handler = axis_discrete_handler; +} + static void window_schedule_redraw_task(struct window *window); @@ -2780,12 +2804,83 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer, widget->user_data); } +static void +pointer_handle_frame(void *data, struct wl_pointer *pointer) +{ + struct input *input = data; + struct widget *widget; + + widget = input->focus_widget; + if (input->grab) + widget = input->grab; + if (widget && widget->pointer_frame_handler) + (*widget->pointer_frame_handler)(widget, + input, + widget->user_data); +} + +static void +pointer_handle_axis_source(void *data, struct wl_pointer *pointer, + uint32_t source) +{ + struct input *input = data; + struct widget *widget; + + widget = input->focus_widget; + if (input->grab) + widget = input->grab; + if (widget && widget->axis_source_handler) + (*widget->axis_source_handler)(widget, + input, + source, + widget->user_data); +} + +static void +pointer_handle_axis_stop(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis) +{ + struct input *input = data; + struct widget *widget; + + widget = input->focus_widget; + if (input->grab) + widget = input->grab; + if (widget && widget->axis_stop_handler) + (*widget->axis_stop_handler)(widget, + input, time, + axis, + widget->user_data); +} + +static void +pointer_handle_axis_discrete(void *data, struct wl_pointer *pointer, + uint32_t axis, int32_t discrete) +{ + struct input *input = data; + struct widget *widget; + + widget = input->focus_widget; + if (input->grab) + widget = input->grab; + if (widget && widget->axis_discrete_handler) + (*widget->axis_discrete_handler)(widget, + input, + axis, + discrete, + widget->user_data); +} + static const struct wl_pointer_listener pointer_listener = { pointer_handle_enter, pointer_handle_leave, pointer_handle_motion, pointer_handle_button, pointer_handle_axis, + pointer_handle_frame, + pointer_handle_axis_source, + pointer_handle_axis_stop, + pointer_handle_axis_discrete, }; static void @@ -5178,7 +5273,7 @@ static void display_add_input(struct display *d, uint32_t id, int display_seat_version) { struct input *input; - int seat_version = MIN(display_seat_version, 4); + int seat_version = MIN(display_seat_version, 5); input = xzalloc(sizeof *input); input->display = d; diff --git a/clients/window.h b/clients/window.h index b92d10ce..ba843cc1 100644 --- a/clients/window.h +++ b/clients/window.h @@ -267,6 +267,27 @@ typedef void (*widget_axis_handler_t)(struct widget *widget, wl_fixed_t value, void *data); +typedef void (*widget_pointer_frame_handler_t)(struct widget *widget, + struct input *input, + void *data); + +typedef void (*widget_axis_source_handler_t)(struct widget *widget, + struct input *input, + uint32_t source, + void *data); + +typedef void (*widget_axis_stop_handler_t)(struct widget *widget, + struct input *input, + uint32_t time, + uint32_t axis, + void *data); + +typedef void (*widget_axis_discrete_handler_t)(struct widget *widget, + struct input *input, + uint32_t axis, + int32_t discrete, + void *data); + struct window * window_create(struct display *display); struct window * @@ -516,6 +537,16 @@ void widget_set_axis_handler(struct widget *widget, widget_axis_handler_t handler); void +widget_set_pointer_frame_handler(struct widget *widget, + widget_pointer_frame_handler_t handler); +void +widget_set_axis_handlers(struct widget *widget, + widget_axis_handler_t axis_handler, + widget_axis_source_handler_t axis_source_handler, + widget_axis_stop_handler_t axis_stop_handler, + widget_axis_discrete_handler_t axis_discrete_handler); + +void widget_schedule_redraw(struct widget *widget); void widget_set_use_cairo(struct widget *widget, int use_cairo); diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c index f8378590..7aa7630f 100644 --- a/desktop-shell/exposay.c +++ b/desktop-shell/exposay.c @@ -391,6 +391,16 @@ exposay_axis(struct weston_pointer_grab *grab, { } +static void +exposay_axis_source(struct weston_pointer_grab *grab, uint32_t source) +{ +} + +static void +exposay_frame(struct weston_pointer_grab *grab) +{ +} + static void exposay_pointer_grab_cancel(struct weston_pointer_grab *grab) { @@ -405,6 +415,8 @@ static const struct weston_pointer_grab_interface exposay_ptr_grab = { exposay_motion, exposay_button, exposay_axis, + exposay_axis_source, + exposay_frame, exposay_pointer_grab_cancel, }; diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 6e746556..5ae83efd 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -1602,6 +1602,17 @@ noop_grab_axis(struct weston_pointer_grab *grab, { } +static void +noop_grab_axis_source(struct weston_pointer_grab *grab, + uint32_t source) +{ +} + +static void +noop_grab_frame(struct weston_pointer_grab *grab) +{ +} + static void constrain_position(struct weston_move_grab *move, int *cx, int *cy) { @@ -1686,6 +1697,8 @@ static const struct weston_pointer_grab_interface move_grab_interface = { move_grab_motion, move_grab_button, noop_grab_axis, + noop_grab_axis_source, + noop_grab_frame, move_grab_cancel, }; @@ -1851,6 +1864,8 @@ static const struct weston_pointer_grab_interface resize_grab_interface = { resize_grab_motion, resize_grab_button, noop_grab_axis, + noop_grab_axis_source, + noop_grab_frame, resize_grab_cancel, }; @@ -2016,6 +2031,8 @@ static const struct weston_pointer_grab_interface busy_cursor_grab_interface = { busy_cursor_grab_motion, busy_cursor_grab_button, noop_grab_axis, + noop_grab_axis_source, + noop_grab_frame, busy_cursor_grab_cancel, }; @@ -3213,6 +3230,18 @@ popup_grab_axis(struct weston_pointer_grab *grab, weston_pointer_send_axis(grab->pointer, time, event); } +static void +popup_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source) +{ + weston_pointer_send_axis_source(grab->pointer, source); +} + +static void +popup_grab_frame(struct weston_pointer_grab *grab) +{ + weston_pointer_send_frame(grab->pointer); +} + static void popup_grab_cancel(struct weston_pointer_grab *grab) { @@ -3224,6 +3253,8 @@ static const struct weston_pointer_grab_interface popup_grab_interface = { popup_grab_motion, popup_grab_button, popup_grab_axis, + popup_grab_axis_source, + popup_grab_frame, popup_grab_cancel, }; @@ -4923,6 +4954,8 @@ static const struct weston_pointer_grab_interface rotate_grab_interface = { rotate_grab_motion, rotate_grab_button, noop_grab_axis, + noop_grab_axis_source, + noop_grab_frame, rotate_grab_cancel, }; diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c index c21b9e0e..8da3d3c8 100644 --- a/ivi-shell/hmi-controller.c +++ b/ivi-shell/hmi-controller.c @@ -1517,6 +1517,19 @@ pointer_default_grab_axis(struct weston_pointer_grab *grab, weston_pointer_send_axis(grab->pointer, time, event); } +static void +pointer_default_grab_axis_source(struct weston_pointer_grab *grab, + uint32_t source) +{ + weston_pointer_send_axis_source(grab->pointer, source); +} + +static void +pointer_default_grab_frame(struct weston_pointer_grab *grab) +{ + weston_pointer_send_frame(grab->pointer); +} + static void move_grab_update(struct move_grab *move, wl_fixed_t pointer[2]) { @@ -1664,6 +1677,8 @@ static const struct weston_pointer_grab_interface pointer_move_grab_workspace_in pointer_move_grab_motion, pointer_move_workspace_grab_button, pointer_default_grab_axis, + pointer_default_grab_axis_source, + pointer_default_grab_frame, pointer_move_workspace_grab_cancel }; diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c index d6d2fa17..3526ad1b 100644 --- a/src/compositor-rdp.c +++ b/src/compositor-rdp.c @@ -70,7 +70,7 @@ #include "pixman-renderer.h" #define MAX_FREERDP_FDS 32 -#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10) +#define DEFAULT_AXIS_STEP_DISTANCE 10 #define RDP_MODE_FREQ 60 * 1000 struct rdp_backend_config { @@ -942,10 +942,11 @@ static BOOL xf_peer_post_connect(freerdp_peer *client) static FREERDP_CB_RET_TYPE xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) { - wl_fixed_t wl_x, wl_y, axis; + wl_fixed_t wl_x, wl_y; RdpPeerContext *peerContext = (RdpPeerContext *)input->context; struct rdp_output *output; uint32_t button = 0; + bool need_frame = false; if (flags & PTR_FLAGS_MOVE) { output = peerContext->rdpBackend->output; @@ -954,6 +955,7 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) wl_y = wl_fixed_from_int((int)y); notify_motion_absolute(&peerContext->item.seat, weston_compositor_get_time(), wl_x, wl_y); + need_frame = true; } } @@ -968,10 +970,12 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) notify_button(&peerContext->item.seat, weston_compositor_get_time(), button, (flags & PTR_FLAGS_DOWN) ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED ); + need_frame = true; } if (flags & PTR_FLAGS_WHEEL) { struct weston_pointer_axis_event weston_event; + double value; /* DEFAULT_AXIS_STEP_DISTANCE is stolen from compositor-x11.c * The RDP specs says the lower bits of flags contains the "the number of rotation @@ -979,17 +983,23 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) * * https://blogs.msdn.microsoft.com/oldnewthing/20130123-00/?p=5473 explains the 120 value */ - axis = (DEFAULT_AXIS_STEP_DISTANCE * (flags & 0xff)) / 120; + value = (flags & 0xff) / 120.0; if (flags & PTR_FLAGS_WHEEL_NEGATIVE) - axis = -axis; + value = -value; weston_event.axis = WL_POINTER_AXIS_VERTICAL_SCROLL; - weston_event.value = axis; + weston_event.value = wl_fixed_from_double(DEFAULT_AXIS_STEP_DISTANCE * value); + weston_event.discrete = (int)value; + weston_event.has_discrete = true; notify_axis(&peerContext->item.seat, weston_compositor_get_time(), &weston_event); + need_frame = true; } + if (need_frame) + notify_pointer_frame(&peerContext->item.seat); + FREERDP_CB_RETURN(TRUE); } diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 48636fe8..d1c020d8 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -185,6 +185,8 @@ struct wayland_input { struct wayland_output *output; struct wayland_output *touch_focus; struct wayland_output *keyboard_focus; + + struct weston_pointer_axis_event vert, horiz; }; struct gl_renderer_interface *gl_renderer; @@ -1340,6 +1342,7 @@ input_handle_motion(void *data, struct wl_pointer *pointer, struct wayland_input *input = data; int32_t fx, fy; enum theme_location location; + bool want_frame = false; if (!input->output) return; @@ -1364,16 +1367,23 @@ input_handle_motion(void *data, struct wl_pointer *pointer, input_set_cursor(input); notify_pointer_focus(&input->base, NULL, 0, 0); input->has_focus = false; + want_frame = true; } else if (!input->has_focus && location == THEME_LOCATION_CLIENT_AREA) { wl_pointer_set_cursor(input->parent.pointer, input->enter_serial, NULL, 0, 0); notify_pointer_focus(&input->base, &input->output->base, x, y); input->has_focus = true; + want_frame = true; } - if (location == THEME_LOCATION_CLIENT_AREA) + if (location == THEME_LOCATION_CLIENT_AREA) { notify_motion_absolute(&input->base, time, x, y); + want_frame = true; + } + + if (want_frame && input->seat_version < WL_POINTER_FRAME_SINCE_VERSION) + notify_pointer_frame(&input->base); } static void @@ -1422,8 +1432,11 @@ input_handle_button(void *data, struct wl_pointer *pointer, location = THEME_LOCATION_CLIENT_AREA; } - if (location == THEME_LOCATION_CLIENT_AREA) + if (location == THEME_LOCATION_CLIENT_AREA) { notify_button(&input->base, time, button, state); + if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION) + notify_pointer_frame(&input->base); + } } static void @@ -1436,7 +1449,67 @@ input_handle_axis(void *data, struct wl_pointer *pointer, weston_event.axis = axis; weston_event.value = value; + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL && + input->vert.has_discrete) { + weston_event.has_discrete = true; + weston_event.discrete = input->vert.discrete; + input->vert.has_discrete = false; + } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL && + input->horiz.has_discrete) { + weston_event.has_discrete = true; + weston_event.discrete = input->horiz.discrete; + input->horiz.has_discrete = false; + } + notify_axis(&input->base, time, &weston_event); + + if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION) + notify_pointer_frame(&input->base); +} + +static void +input_handle_frame(void *data, struct wl_pointer *pointer) +{ + struct wayland_input *input = data; + + notify_pointer_frame(&input->base); +} + +static void +input_handle_axis_source(void *data, struct wl_pointer *pointer, + uint32_t source) +{ + struct wayland_input *input = data; + + notify_axis_source(&input->base, source); +} + +static void +input_handle_axis_stop(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis) +{ + struct wayland_input *input = data; + struct weston_pointer_axis_event weston_event; + + weston_event.axis = axis; + weston_event.value = 0; + + notify_axis(&input->base, time, &weston_event); +} + +static void +input_handle_axis_discrete(void *data, struct wl_pointer *pointer, + uint32_t axis, int32_t discrete) +{ + struct wayland_input *input = data; + + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { + input->vert.has_discrete = true; + input->vert.discrete = discrete; + } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) { + input->horiz.has_discrete = true; + input->horiz.discrete = discrete; + } } static const struct wl_pointer_listener pointer_listener = { @@ -1445,6 +1518,10 @@ static const struct wl_pointer_listener pointer_listener = { input_handle_motion, input_handle_button, input_handle_axis, + input_handle_frame, + input_handle_axis_source, + input_handle_axis_stop, + input_handle_axis_discrete, }; static void @@ -1851,6 +1928,9 @@ display_add_seat(struct wayland_backend *b, uint32_t id, uint32_t available_vers input->parent.cursor.surface = wl_compositor_create_surface(b->parent.compositor); + + input->vert.axis = WL_POINTER_AXIS_VERTICAL_SCROLL; + input->horiz.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL; } static void diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 93018dad..b70c1190 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -1085,6 +1085,8 @@ x11_backend_deliver_button_event(struct x11_backend *b, * steps. Therefore move the axis by some pixels every step. */ if (state) { weston_event.value = -DEFAULT_AXIS_STEP_DISTANCE; + weston_event.discrete = -1; + weston_event.has_discrete = true; weston_event.axis = WL_POINTER_AXIS_VERTICAL_SCROLL; notify_axis(&b->core_seat, @@ -1095,6 +1097,8 @@ x11_backend_deliver_button_event(struct x11_backend *b, case 5: if (state) { weston_event.value = DEFAULT_AXIS_STEP_DISTANCE; + weston_event.discrete = 1; + weston_event.has_discrete = true; weston_event.axis = WL_POINTER_AXIS_VERTICAL_SCROLL; notify_axis(&b->core_seat, @@ -1105,6 +1109,8 @@ x11_backend_deliver_button_event(struct x11_backend *b, case 6: if (state) { weston_event.value = -DEFAULT_AXIS_STEP_DISTANCE; + weston_event.discrete = -1; + weston_event.has_discrete = true; weston_event.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL; notify_axis(&b->core_seat, @@ -1115,6 +1121,8 @@ x11_backend_deliver_button_event(struct x11_backend *b, case 7: if (state) { weston_event.value = DEFAULT_AXIS_STEP_DISTANCE; + weston_event.discrete = 1; + weston_event.has_discrete = true; weston_event.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL; notify_axis(&b->core_seat, @@ -1131,6 +1139,7 @@ x11_backend_deliver_button_event(struct x11_backend *b, weston_compositor_get_time(), button, state ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED); + notify_pointer_frame(&b->core_seat); } static void @@ -1162,6 +1171,7 @@ x11_backend_deliver_motion_event(struct x11_backend *b, notify_motion(&b->core_seat, weston_compositor_get_time(), &motion_event); + notify_pointer_frame(&b->core_seat); b->prev_x = x; b->prev_y = y; diff --git a/src/compositor.h b/src/compositor.h index ddcafc62..5970e572 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -254,6 +254,8 @@ struct weston_pointer_motion_event { struct weston_pointer_axis_event { uint32_t axis; wl_fixed_t value; + bool has_discrete; + int32_t discrete; }; struct weston_pointer_grab; @@ -266,6 +268,8 @@ struct weston_pointer_grab_interface { void (*axis)(struct weston_pointer_grab *grab, uint32_t time, struct weston_pointer_axis_event *event); + void (*axis_source)(struct weston_pointer_grab *grab, uint32_t source); + void (*frame)(struct weston_pointer_grab *grab); void (*cancel)(struct weston_pointer_grab *grab); }; @@ -403,6 +407,12 @@ void weston_pointer_send_axis(struct weston_pointer *pointer, uint32_t time, struct weston_pointer_axis_event *event); +void +weston_pointer_send_axis_source(struct weston_pointer *pointer, + uint32_t source); +void +weston_pointer_send_frame(struct weston_pointer *pointer); + void weston_pointer_set_focus(struct weston_pointer *pointer, struct weston_view *view, @@ -1142,6 +1152,12 @@ notify_button(struct weston_seat *seat, uint32_t time, int32_t button, void notify_axis(struct weston_seat *seat, uint32_t time, struct weston_pointer_axis_event *event); +void +notify_axis_source(struct weston_seat *seat, uint32_t source); + +void +notify_pointer_frame(struct weston_seat *seat); + void notify_key(struct weston_seat *seat, uint32_t time, uint32_t key, enum wl_keyboard_key_state state, diff --git a/src/data-device.c b/src/data-device.c index 4a1c1b85..545a895d 100644 --- a/src/data-device.c +++ b/src/data-device.c @@ -416,6 +416,16 @@ drag_grab_axis(struct weston_pointer_grab *grab, { } +static void +drag_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source) +{ +} + +static void +drag_grab_frame(struct weston_pointer_grab *grab) +{ +} + static void drag_grab_cancel(struct weston_pointer_grab *grab) { @@ -433,6 +443,8 @@ static const struct weston_pointer_grab_interface pointer_drag_grab_interface = drag_grab_motion, drag_grab_button, drag_grab_axis, + drag_grab_axis_source, + drag_grab_frame, drag_grab_cancel, }; diff --git a/src/input.c b/src/input.c index 9382bb19..91813ec2 100644 --- a/src/input.c +++ b/src/input.c @@ -342,10 +342,57 @@ weston_pointer_send_axis(struct weston_pointer *pointer, if (!pointer->focus_client) return; + resource_list = &pointer->focus_client->pointer_resources; + wl_resource_for_each(resource, resource_list) { + if (event->has_discrete && + wl_resource_get_version(resource) >= + WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) + wl_pointer_send_axis_discrete(resource, event->axis, + event->discrete); + + if (event->value) + wl_pointer_send_axis(resource, time, + event->axis, event->value); + else if (wl_resource_get_version(resource) >= + WL_POINTER_AXIS_STOP_SINCE_VERSION) + wl_pointer_send_axis_stop(resource, time, + event->axis); + } +} + +WL_EXPORT void +weston_pointer_send_axis_source(struct weston_pointer *pointer, uint32_t source) +{ + struct wl_resource *resource; + struct wl_list *resource_list; + + resource_list = &pointer->focus_client->pointer_resources; + wl_resource_for_each(resource, resource_list) { + if (wl_resource_get_version(resource) >= + WL_POINTER_AXIS_SOURCE_SINCE_VERSION) { + wl_pointer_send_axis_source(resource, source); + } + } +} + +static void +pointer_send_frame(struct wl_resource *resource) +{ + if (wl_resource_get_version(resource) >= + WL_POINTER_FRAME_SINCE_VERSION) { + wl_pointer_send_frame(resource); + } +} + +WL_EXPORT void +weston_pointer_send_frame(struct weston_pointer *pointer) +{ + struct wl_resource *resource; + struct wl_list *resource_list; + resource_list = &pointer->focus_client->pointer_resources; wl_resource_for_each(resource, resource_list) - wl_pointer_send_axis(resource, time, - event->axis, event->value); + pointer_send_frame(resource); } static void @@ -356,6 +403,19 @@ default_grab_pointer_axis(struct weston_pointer_grab *grab, weston_pointer_send_axis(grab->pointer, time, event); } +static void +default_grab_pointer_axis_source(struct weston_pointer_grab *grab, + uint32_t source) +{ + weston_pointer_send_axis_source(grab->pointer, source); +} + +static void +default_grab_pointer_frame(struct weston_pointer_grab *grab) +{ + weston_pointer_send_frame(grab->pointer); +} + static void default_grab_pointer_cancel(struct weston_pointer_grab *grab) { @@ -367,6 +427,8 @@ static const struct weston_pointer_grab_interface default_grab_pointer_motion, default_grab_pointer_button, default_grab_pointer_axis, + default_grab_pointer_axis_source, + default_grab_pointer_frame, default_grab_pointer_cancel, }; @@ -830,6 +892,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer, wl_resource_for_each(resource, focus_resource_list) { wl_pointer_send_leave(resource, serial, surface_resource); + pointer_send_frame(resource); } } @@ -856,6 +919,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer, serial, view->surface->resource, sx, sy); + pointer_send_frame(resource); } pointer->focus_serial = serial; @@ -1277,9 +1341,6 @@ notify_axis(struct weston_seat *seat, uint32_t time, weston_compositor_wake(compositor); - if (!event->value) - return; - if (weston_compositor_run_axis_binding(compositor, pointer, time, event)) return; @@ -1287,6 +1348,28 @@ notify_axis(struct weston_seat *seat, uint32_t time, pointer->grab->interface->axis(pointer->grab, time, event); } +WL_EXPORT void +notify_axis_source(struct weston_seat *seat, uint32_t source) +{ + struct weston_compositor *compositor = seat->compositor; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + weston_compositor_wake(compositor); + + pointer->grab->interface->axis_source(pointer->grab, source); +} + +WL_EXPORT void +notify_pointer_frame(struct weston_seat *seat) +{ + struct weston_compositor *compositor = seat->compositor; + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + + weston_compositor_wake(compositor); + + pointer->grab->interface->frame(pointer->grab); +} + WL_EXPORT int weston_keyboard_set_locks(struct weston_keyboard *keyboard, uint32_t mask, uint32_t value) @@ -1979,6 +2062,7 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource, pointer->focus_serial, pointer->focus->surface->resource, sx, sy); + pointer_send_frame(cr); } } @@ -2557,7 +2641,7 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec, wl_signal_init(&seat->destroy_signal); wl_signal_init(&seat->updated_caps_signal); - seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 4, + seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5, seat, bind_seat); seat->compositor = ec; diff --git a/src/libinput-device.c b/src/libinput-device.c index 9860d6e6..99b2916f 100644 --- a/src/libinput-device.c +++ b/src/libinput-device.c @@ -80,7 +80,7 @@ handle_keyboard_key(struct libinput_device *libinput_device, STATE_UPDATE_AUTOMATIC); } -static void +static bool handle_pointer_motion(struct libinput_device *libinput_device, struct libinput_event_pointer *pointer_event) { @@ -97,9 +97,11 @@ handle_pointer_motion(struct libinput_device *libinput_device, notify_motion(device->seat, libinput_event_pointer_get_time(pointer_event), &event); + + return true; } -static void +static bool handle_pointer_motion_absolute( struct libinput_device *libinput_device, struct libinput_event_pointer *pointer_event) @@ -112,7 +114,7 @@ handle_pointer_motion_absolute( uint32_t width, height; if (!output) - return; + return false; time = libinput_event_pointer_get_time(pointer_event); width = device->output->current_mode->width; @@ -127,9 +129,11 @@ handle_pointer_motion_absolute( weston_output_transform_coordinate(device->output, x, y, &x, &y); notify_motion_absolute(device->seat, time, x, y); + + return true; } -static void +static bool handle_pointer_button(struct libinput_device *libinput_device, struct libinput_event_pointer *pointer_event) { @@ -145,21 +149,21 @@ handle_pointer_button(struct libinput_device *libinput_device, seat_button_count != 1) || (button_state == LIBINPUT_BUTTON_STATE_RELEASED && seat_button_count != 0)) - return; + return false; notify_button(device->seat, libinput_event_pointer_get_time(pointer_event), libinput_event_pointer_get_button(pointer_event), libinput_event_pointer_get_button_state(pointer_event)); + return true; } static double normalize_scroll(struct libinput_event_pointer *pointer_event, enum libinput_pointer_axis axis) { - static int warned; enum libinput_pointer_axis_source source; - double value; + double value = 0.0; source = libinput_event_pointer_get_axis_source(pointer_event); /* libinput < 0.8 sent wheel click events with value 10. Since 0.8 @@ -178,48 +182,101 @@ normalize_scroll(struct libinput_event_pointer *pointer_event, value = libinput_event_pointer_get_axis_value(pointer_event, axis); break; - default: - value = 0; - if (warned < 5) { - weston_log("Unknown scroll source %d. Event discarded\n", - source); - warned++; - } - break; } return value; } -static void +static int32_t +get_axis_discrete(struct libinput_event_pointer *pointer_event, + enum libinput_pointer_axis axis) +{ + enum libinput_pointer_axis_source source; + + source = libinput_event_pointer_get_axis_source(pointer_event); + + if (source != LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) + return 0; + + return libinput_event_pointer_get_axis_value_discrete(pointer_event, + axis); +} + +static bool handle_pointer_axis(struct libinput_device *libinput_device, struct libinput_event_pointer *pointer_event) { + static int warned; struct evdev_device *device = libinput_device_get_user_data(libinput_device); - double value; + double vert, horiz; + int32_t vert_discrete, horiz_discrete; enum libinput_pointer_axis axis; struct weston_pointer_axis_event weston_event; + enum libinput_pointer_axis_source source; + uint32_t wl_axis_source; + bool has_vert, has_horiz; + + has_vert = libinput_event_pointer_has_axis(pointer_event, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + has_horiz = libinput_event_pointer_has_axis(pointer_event, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + + if (!has_vert && !has_horiz) + return false; + + source = libinput_event_pointer_get_axis_source(pointer_event); + switch (source) { + case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: + wl_axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; + break; + case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: + wl_axis_source = WL_POINTER_AXIS_SOURCE_FINGER; + break; + case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: + wl_axis_source = WL_POINTER_AXIS_SOURCE_CONTINUOUS; + break; + default: + if (warned < 5) { + weston_log("Unknown scroll source %d.\n", source); + warned++; + } + return false; + } + + notify_axis_source(device->seat, wl_axis_source); + + if (has_vert) { + axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; + vert_discrete = get_axis_discrete(pointer_event, axis); + vert = normalize_scroll(pointer_event, axis); - axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; - if (libinput_event_pointer_has_axis(pointer_event, axis)) { - value = normalize_scroll(pointer_event, axis); - weston_event.value = wl_fixed_from_double(value); weston_event.axis = WL_POINTER_AXIS_VERTICAL_SCROLL; + weston_event.value = wl_fixed_from_double(vert); + weston_event.discrete = vert_discrete; + weston_event.has_discrete = (vert_discrete != 0); + notify_axis(device->seat, libinput_event_pointer_get_time(pointer_event), &weston_event); } - axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; - if (libinput_event_pointer_has_axis(pointer_event, axis)) { - value = normalize_scroll(pointer_event, axis); - weston_event.value = wl_fixed_from_double(value); + if (has_horiz) { + axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; + horiz_discrete = get_axis_discrete(pointer_event, axis); + horiz = normalize_scroll(pointer_event, axis); + weston_event.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL; + weston_event.value = wl_fixed_from_double(horiz); + weston_event.discrete = horiz_discrete; + weston_event.has_discrete = (horiz_discrete != 0); + notify_axis(device->seat, libinput_event_pointer_get_time(pointer_event), &weston_event); } + + return true; } static void @@ -296,7 +353,10 @@ evdev_device_process_event(struct libinput_event *event) { struct libinput_device *libinput_device = libinput_event_get_device(event); + struct evdev_device *device = + libinput_device_get_user_data(libinput_device); int handled = 1; + bool need_frame = false; switch (libinput_event_get_type(event)) { case LIBINPUT_EVENT_KEYBOARD_KEY: @@ -304,21 +364,22 @@ evdev_device_process_event(struct libinput_event *event) libinput_event_get_keyboard_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION: - handle_pointer_motion(libinput_device, + need_frame = handle_pointer_motion(libinput_device, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - handle_pointer_motion_absolute( - libinput_device, - libinput_event_get_pointer_event(event)); + need_frame = handle_pointer_motion_absolute( + libinput_device, + libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_BUTTON: - handle_pointer_button(libinput_device, + need_frame = handle_pointer_button(libinput_device, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_AXIS: - handle_pointer_axis(libinput_device, - libinput_event_get_pointer_event(event)); + need_frame = handle_pointer_axis( + libinput_device, + libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_TOUCH_DOWN: handle_touch_down(libinput_device, @@ -342,6 +403,9 @@ evdev_device_process_event(struct libinput_event *event) libinput_event_get_type(event)); } + if (need_frame) + notify_pointer_frame(device->seat); + return handled; } diff --git a/src/screen-share.c b/src/screen-share.c index ab649e3b..9b5154b7 100644 --- a/src/screen-share.c +++ b/src/screen-share.c @@ -143,6 +143,7 @@ ss_seat_handle_motion(void *data, struct wl_pointer *pointer, * always receiving the input in the same coordinates as the output. */ notify_motion_absolute(&seat->base, time, x, y); + notify_pointer_frame(&seat->base); } static void @@ -153,6 +154,7 @@ ss_seat_handle_button(void *data, struct wl_pointer *pointer, struct ss_seat *seat = data; notify_button(&seat->base, time, button, state); + notify_pointer_frame(&seat->base); } static void @@ -164,8 +166,10 @@ ss_seat_handle_axis(void *data, struct wl_pointer *pointer, weston_event.axis = axis; weston_event.value = value; + weston_event.has_discrete = false; notify_axis(&seat->base, time, &weston_event); + notify_pointer_frame(&seat->base); } static const struct wl_pointer_listener ss_seat_pointer_listener = { diff --git a/tests/weston-test-client-helper.c b/tests/weston-test-client-helper.c index 16786d9b..97c4395a 100644 --- a/tests/weston-test-client-helper.c +++ b/tests/weston-test-client-helper.c @@ -197,12 +197,44 @@ pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, axis, wl_fixed_to_double(value)); } +static void +pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) +{ + fprintf(stderr, "test-client: got pointer frame\n"); +} + +static void +pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t source) +{ + fprintf(stderr, "test-client: got pointer axis source %u\n", source); +} + +static void +pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) +{ + fprintf(stderr, "test-client: got pointer axis stop\n"); +} + +static void +pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t value) +{ + fprintf(stderr, "test-client: got pointer axis discrete %u %d\n", + axis, value); +} + static const struct wl_pointer_listener pointer_listener = { pointer_handle_enter, pointer_handle_leave, pointer_handle_motion, pointer_handle_button, pointer_handle_axis, + pointer_handle_frame, + pointer_handle_axis_source, + pointer_handle_axis_stop, + pointer_handle_axis_discrete, }; static void