[PATCH weston] input: send wl_keyboard.repeat_info with rate and delay info

Pekka Paalanen ppaalanen at gmail.com
Mon Jun 2 00:43:39 PDT 2014


On Fri, 30 May 2014 11:32:24 +0200
Jonny Lamb <jonny.lamb at collabora.co.uk> wrote:

> The compositor reads the values out from weston.ini, the weston
> compositor passes on the values, the weston-info client prints out the
> values, and the values are respected in toytoolkit.
> ---
>  clients/weston-info.c    | 106 ++++++++++++++++++++++++++++++++++++++++++++---
>  clients/window.c         |  24 +++++++++--
>  src/compositor-wayland.c |  18 ++++++--
>  src/compositor.c         |   5 +++
>  src/compositor.h         |   3 ++
>  src/input.c              |  12 +++++-
>  6 files changed, 154 insertions(+), 14 deletions(-)
> 
> diff --git a/clients/weston-info.c b/clients/weston-info.c
> index df869e3..9e2307b 100644
> --- a/clients/weston-info.c
> +++ b/clients/weston-info.c
> @@ -32,6 +32,8 @@
>  
>  #include "../shared/os-compatibility.h"
>  
> +#define MIN(x,y) (((x) < (y)) ? (x) : (y))
> +
>  typedef void (*print_info_t)(void *info);
>  typedef void (*destroy_info_t)(void *info);
>  
> @@ -90,6 +92,9 @@ struct seat_info {
>  
>  	uint32_t capabilities;
>  	char *name;
> +
> +	int32_t repeat_rate;
> +	int32_t repeat_delay;
>  };
>  
>  struct weston_info {
> @@ -291,22 +296,105 @@ print_seat_info(void *data)
>  		printf(" touch");
>  
>  	printf("\n");
> +
> +	if (seat->repeat_rate > 0)
> +		printf("\tkeyboard repeat rate: %d\n", seat->repeat_rate);
> +	if (seat->repeat_delay > 0)
> +		printf("\tkeyboard repeat delay: %d\n", seat->repeat_delay);
> +}
> +
> +static void
> +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
> +		       uint32_t format, int fd, uint32_t size)
> +{
> +}
> +
> +static void
> +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
> +		      uint32_t serial, struct wl_surface *surface,
> +		      struct wl_array *keys)
> +{
>  }
>  
>  static void
> +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
> +		      uint32_t serial, struct wl_surface *surface)
> +{
> +}
> +
> +static void
> +keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
> +		    uint32_t serial, uint32_t time, uint32_t key,
> +		    uint32_t state)
> +{
> +}
> +
> +static void
> +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
> +			  uint32_t serial, uint32_t mods_depressed,
> +			  uint32_t mods_latched, uint32_t mods_locked,
> +			  uint32_t group)
> +{
> +}
> +
> +static void
> +keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
> +			    int32_t rate, int32_t delay)
> +{
> +	struct seat_info *seat = data;
> +
> +	seat->repeat_rate = rate;
> +	seat->repeat_delay = delay;
> +}
> +
> +static const struct wl_keyboard_listener keyboard_listener = {
> +	keyboard_handle_keymap,
> +	keyboard_handle_enter,
> +	keyboard_handle_leave,
> +	keyboard_handle_key,
> +	keyboard_handle_modifiers,
> +	keyboard_handle_repeat_info,
> +};
> +
> +/* This is a struct so we don't have to add a (circular) pointer in
> + * seat_info to weston_info just so roundtrip_needed can be set to
> + * true. */
> +struct seat_async_data {
> +	struct seat_info *seat;
> +	struct weston_info *info;
> +};
> +
> +static void
>  seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
>  			 enum wl_seat_capability caps)
>  {
> -	struct seat_info *seat = data;
> -	seat->capabilities = caps;
> +	struct seat_async_data *async_data = data;
> +
> +	async_data->seat->capabilities = caps;
> +
> +	/* we want listen for repeat_info from wl_keyboard, but only
> +	 * do so if the seat info is >= 4 and if we actually have a
> +	 * keyboard */
> +	if (async_data->seat->global.version < 4)
> +		return;
> +
> +	if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
> +		struct wl_keyboard *keyboard;
> +
> +		keyboard = wl_seat_get_keyboard(async_data->seat->seat);
> +		wl_keyboard_add_listener(keyboard, &keyboard_listener,
> +					 async_data->seat);
> +
> +		async_data->info->roundtrip_needed = true;
> +	}
>  }
>  
>  static void
>  seat_handle_name(void *data, struct wl_seat *wl_seat,
>  		 const char *name)
>  {
> -	struct seat_info *seat = data;
> -	seat->name = xstrdup(name);
> +	struct seat_async_data *async_data = data;
> +	async_data->seat->name = xstrdup(name);
>  }
>  
>  static const struct wl_seat_listener seat_listener = {
> @@ -329,14 +417,20 @@ static void
>  add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
>  {
>  	struct seat_info *seat = xzalloc(sizeof *seat);
> +	struct seat_async_data *async_data = xzalloc(sizeof *async_data);

Where is the free() corresponding to this xzalloc()? If weston-info is
just leaking stuff also before this, then I don't mind. If someone
cares, he can fix it all up in a separate patch.

> +
> +	async_data->seat = seat;
> +	async_data->info = info;
>  
>  	init_global_info(info, &seat->global, id, "wl_seat", version);
>  	seat->global.print = print_seat_info;
>  	seat->global.destroy = destroy_seat_info;
>  
>  	seat->seat = wl_registry_bind(info->registry,
> -				      id, &wl_seat_interface, 2);
> -	wl_seat_add_listener(seat->seat, &seat_listener, seat);
> +				      id, &wl_seat_interface, MIN(version, 4));
> +	wl_seat_add_listener(seat->seat, &seat_listener, async_data);
> +
> +	seat->repeat_rate = seat->repeat_delay = -1;
>  
>  	info->roundtrip_needed = true;
>  }
> diff --git a/clients/window.c b/clients/window.c
> index b82a93e..9ba21e4 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -334,6 +334,9 @@ struct input {
>  		xkb_mod_mask_t shift_mask;
>  	} xkb;
>  
> +	int32_t repeat_rate;
> +	int32_t repeat_delay;
> +
>  	struct task repeat_task;
>  	int repeat_timer_fd;
>  	uint32_t repeat_sym;
> @@ -2865,9 +2868,9 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
>  		input->repeat_key = key;
>  		input->repeat_time = time;
>  		its.it_interval.tv_sec = 0;
> -		its.it_interval.tv_nsec = 25 * 1000 * 1000;
> +		its.it_interval.tv_nsec = (1000 / input->repeat_rate) * 1000 * 1000;

You'd reduce truncation error by writing it as 1000000000/repeat_rate.

>  		its.it_value.tv_sec = 0;
> -		its.it_value.tv_nsec = 400 * 1000 * 1000;
> +		its.it_value.tv_nsec = input->repeat_delay * 1000 * 1000;
>  		timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
>  	}
>  }
> @@ -2899,12 +2902,24 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
>  		input->modifiers |= MOD_SHIFT_MASK;
>  }
>  
> +static void
> +keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
> +			    int32_t rate, int32_t delay)
> +{
> +	struct input *input = data;
> +
> +	input->repeat_rate = rate;
> +	input->repeat_delay = delay;
> +}
> +
>  static const struct wl_keyboard_listener keyboard_listener = {
>  	keyboard_handle_keymap,
>  	keyboard_handle_enter,
>  	keyboard_handle_leave,
>  	keyboard_handle_key,
>  	keyboard_handle_modifiers,
> +	keyboard_handle_repeat_info
> +
>  };
>  
>  static void
> @@ -4944,7 +4959,7 @@ display_add_input(struct display *d, uint32_t id)
>  	input = xzalloc(sizeof *input);
>  	input->display = d;
>  	input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface,
> -				       MIN(d->seat_version, 3));
> +				       MIN(d->seat_version, 4));
>  	input->touch_focus = NULL;
>  	input->pointer_focus = NULL;
>  	input->keyboard_focus = NULL;
> @@ -4965,6 +4980,9 @@ display_add_input(struct display *d, uint32_t id)
>  
>  	input->pointer_surface = wl_compositor_create_surface(d->compositor);
>  
> +	input->repeat_rate = 40;
> +	input->repeat_delay = 400;
> +
>  	input->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC,
>  						TFD_CLOEXEC | TFD_NONBLOCK);
>  	input->repeat_task.run = keyboard_repeat_func;
> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
> index 76e5396..bdc6076 100644
> --- a/src/compositor-wayland.c
> +++ b/src/compositor-wayland.c
> @@ -1573,12 +1573,24 @@ input_handle_modifiers(void *data, struct wl_keyboard *keyboard,
>  	notify_modifiers(&input->base, serial_out);
>  }
>  
> +static void
> +input_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
> +			 int32_t rate, int32_t delay)
> +{
> +	struct wayland_input *input = data;
> +	struct wayland_compositor *c = input->compositor;
> +
> +	c->base.kb_repeat_rate = rate;
> +	c->base.kb_repeat_delay = delay;
> +}
> +
>  static const struct wl_keyboard_listener keyboard_listener = {
>  	input_handle_keymap,
>  	input_handle_keyboard_enter,
>  	input_handle_keyboard_leave,
>  	input_handle_key,
>  	input_handle_modifiers,
> +	input_handle_repeat_info,
>  };
>  
>  static void
> @@ -1614,7 +1626,7 @@ static const struct wl_seat_listener seat_listener = {
>  };
>  
>  static void
> -display_add_seat(struct wayland_compositor *c, uint32_t id)
> +display_add_seat(struct wayland_compositor *c, uint32_t id, uint32_t version)
>  {
>  	struct wayland_input *input;
>  
> @@ -1625,7 +1637,7 @@ display_add_seat(struct wayland_compositor *c, uint32_t id)
>  	weston_seat_init(&input->base, &c->base, "default");
>  	input->compositor = c;
>  	input->parent.seat = wl_registry_bind(c->parent.registry, id,
> -					      &wl_seat_interface, 1);
> +					      &wl_seat_interface, MIN(version, 4));
>  	wl_list_insert(c->input_list.prev, &input->link);
>  
>  	wl_seat_add_listener(input->parent.seat, &seat_listener, input);
> @@ -1781,7 +1793,7 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
>  			wl_registry_bind(registry, name,
>  					 &_wl_fullscreen_shell_interface, 1);
>  	} else if (strcmp(interface, "wl_seat") == 0) {
> -		display_add_seat(c, name);
> +		display_add_seat(c, name, version);
>  	} else if (strcmp(interface, "wl_output") == 0) {
>  		wayland_compositor_register_output(c, name);
>  	} else if (strcmp(interface, "wl_shm") == 0) {
> diff --git a/src/compositor.c b/src/compositor.c
> index 574db2d..758d0ce 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -3710,6 +3710,11 @@ weston_compositor_init(struct weston_compositor *ec,
>  	if (weston_compositor_xkb_init(ec, &xkb_names) < 0)
>  		return -1;
>  
> +	weston_config_section_get_int(s, "repeat-rate",
> +				      &ec->kb_repeat_rate, 40);
> +	weston_config_section_get_int(s, "repeat-delay",
> +				      &ec->kb_repeat_delay, 400);
> +
>  	text_backend_init(ec);
>  
>  	wl_data_device_manager_init(ec->wl_display);
> diff --git a/src/compositor.h b/src/compositor.h
> index 057f8be..bb4475c 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -643,6 +643,9 @@ struct weston_compositor {
>  
>  	/* Raw keyboard processing (no libxkbcommon initialization or handling) */
>  	int use_xkbcommon;
> +
> +	int32_t kb_repeat_rate;
> +	int32_t kb_repeat_delay;
>  };
>  
>  struct weston_buffer {
> diff --git a/src/input.c b/src/input.c
> index 2c799f4..ffa2626 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -1758,6 +1758,14 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
>  		    wl_resource_get_link(cr))
>  			wl_data_device_set_keyboard_focus(seat);
>  	}
> +
> +	/* if wl_seat's version is at least 4, the wl_keyboard's
> +	 * version must be 4, so we support repeat_info */
> +	if (wl_resource_get_version(resource) >= 4) {
> +		wl_keyboard_send_repeat_info(cr,
> +					     seat->compositor->kb_repeat_rate,
> +					     seat->compositor->kb_repeat_delay);
> +	}
>  }
>  
>  static void
> @@ -1813,7 +1821,7 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
>  	enum wl_seat_capability caps = 0;
>  
>  	resource = wl_resource_create(client,
> -				      &wl_seat_interface, MIN(version, 3), id);
> +				      &wl_seat_interface, MIN(version, 4), id);
>  	wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
>  	wl_resource_set_implementation(resource, &seat_interface, data,
>  				       unbind_resource);
> @@ -2207,7 +2215,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, 3,
> +	seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 4,
>  					seat, bind_seat);
>  
>  	seat->compositor = ec;

Looks good, only few comments there.

I wonder if Weston should generate a protocol error, if a client tries
to bind to an interaface with a version greater than what the
compositor advertised. Otherwise they will disagree on the version.
That's for another time, though.


Thanks,
pq


More information about the wayland-devel mailing list