[PATCH 2/6] compositor: emulates button touches and notifies surfaces accordingly

Kristian Høgsberg krh at bitplanet.net
Tue Dec 20 11:33:42 PST 2011


On Fri, Dec 16, 2011 at 10:59 AM, Tiago Vignatti
<vignatti at freedesktop.org> wrote:
> From: Tiago Vignatti <tiago.vignatti at intel.com>

As I mentioned earlier, I'd like to not do the pointer emulation for
the first round of patches here.  Initially, I'd like this code to
only send out the touch down/motion/up events, so a lot of the code in
this patch wont be necessary.  In fact, there'll be very little left
and as such I think it makes more sense to just merge it with the 1/6
patch.  Also, we'll need a touch_focus wlsc_surface pointer in
wlsc_input_device to track which surface is receiving events.  The
first touch down event picks the surface, and all further events go to
that surface for the remainder of the touch session (ie until all
touch points are up again).

> Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
> ---
>  compositor/compositor.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 97 insertions(+), 0 deletions(-)
>
> diff --git a/compositor/compositor.c b/compositor/compositor.c
> index 2c461d8..f9b4575 100644
> --- a/compositor/compositor.c
> +++ b/compositor/compositor.c
> @@ -1178,6 +1178,48 @@ idle_handler(void *data)
>        return 1;
>  }
>
> +static void
> +wlsc_output_get_constrains(struct wlsc_compositor *ec, int *x, int *y)
> +{
> +       struct wlsc_output *output;
> +       int x_valid = 0, y_valid = 0;
> +       int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
> +
> +       wl_list_for_each(output, &ec->output_list, link) {
> +               if (output->x <= *x && *x <= output->x +
> +                   output->current->width)
> +                       x_valid = 1;
> +
> +               if (output->y <= *y && *y <= output->y +
> +                   output->current->height)
> +                       y_valid = 1;
> +
> +               /* FIXME: calculate this only on output addition/deletion */
> +               if (output->x < min_x)
> +                       min_x = output->x;
> +               if (output->y < min_y)
> +                       min_y = output->y;
> +
> +               if (output->x + output->current->width > max_x)
> +                       max_x = output->x + output->current->width;
> +               if (output->y + output->current->height > max_y)
> +                       max_y = output->y + output->current->height;
> +       }
> +
> +       if (!x_valid) {
> +               if (*x < min_x)
> +                       *x = min_x;
> +               else if (*x >= max_x)
> +                       *x = max_x;
> +       }
> +       if (!y_valid) {
> +               if (*y < min_y)
> +                       *y = min_y;
> +               else  if (*y >= max_y)
> +                       *y = max_y;
> +       }
> +}

We don't need to constrain the touch events, they're always scaled and
translated to the associated output.

>  WL_EXPORT void
>  notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
>  {
> @@ -1499,11 +1541,66 @@ notify_keyboard_focus(struct wl_input_device *device,
>  * It assumes always the correct cycle sequence until it gets here: touch_down
>  * → touch_update → ... → touch_update → touch_end. The driver is responsible
>  * for sending along such order.
> + *
> + * TODO: We'll have to keep touchpoint information for detect simple gestures
> + * on indirect devices.
>  */
>  WL_EXPORT void
>  notify_touch(struct wl_input_device *device, uint32_t time, int touch_id,
>              int x, int y, int touch_type)
>  {
> +       struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
> +       struct wlsc_compositor *ec = wd->compositor;
> +       struct wlsc_surface *es;
> +       int32_t sx, sy;
> +
> +       wlsc_compositor_activity(ec);

We'll need idle_inhibit on touch down and idle_release on touch up
instead.  Of course as long as a finger is down, we'll receive a
stream of events keeping the compositor active, so it won't make a big
difference in the end.

> +       if (touch_type == WL_INPUT_DEVICE_TOUCH_DOWN) {

Use a switch(touch_type) instead

> +               /* TODO: should TOUCH_DOWN send x and y? The driver is not
> +                * sending yet; Qt wants it, and XI 2.2 implements in such way
> +                * where the driver queues the events instead accumulate, so
> +                * it's slightly easier I guess. */

Yes, otherwise touch down is not a very useful event.  It should be
easy enough to do as I described in my comments on patch 1/6.

> +               es = pick_surface(device, &sx, &sy);

We'll need a touch point counter that tracks number of touch points
down and only picks the touch focus when the first touch down comes
in.  Then store the touch_focus in the device and transform
(wlsc_surface_transform) and deliver all further events with respect
to that surface.

> +               wl_input_device_set_pointer_focus(device, &es->surface, time,
> +                               0, 0, sx, sy);
> +
> +               /* TODO: we will want to send touch_id information and do the
> +                * grab according the finger so multiple clients can work
> +                * accordingly. Anyway, for now just emulates a button touch */
> +               notify_button(device, time, BTN_LEFT, 1);

Drop the pointer emulation for now.

> +               if (device->grab)
> +                       wl_resource_post_event(device->pointer_focus_resource,
> +                                       touch_type, time, touch_id,
> +                                       0, 0);

This one should just send to device->touch_focus instead.

> +       } else if (touch_type == WL_INPUT_DEVICE_TOUCH_MOTION) {
> +               /* TODO: at this point a wheel movement, scroll or any gesture
> +                * has to be identified, sent to the surface and any grab will
> +                * be ignored (?). We want this kinda of global gesture
> +                * probably only for pointer devices, i.e. touchpad, trackpad,
> +                * etc. For now we could just detect if tp > 1 and device ==
> +                * indirect ts, and return. */
> +
> +               /* TODO: we can avoid one screen constrains calculation here
> +                * if we move the code out from notify_motion.. */
> +               notify_motion(device, time, x, y);
> +
> +               if (!device->grab) {
> +                       wlsc_output_get_constrains(ec, &x, &y);
> +                       es = pick_surface(device, &sx, &sy);
> +                       wl_input_device_set_pointer_focus(device,
> +                                       &es->surface, time,
> +                                       x, y, sx, sy);
> +               }
> +               if (device->pointer_focus_resource)
> +                       wl_resource_post_event(device->pointer_focus_resource,
> +                                       touch_type, time, touch_id,
> +                                       device->x, device->y);

Again, we only need the last event for now, sent to the touch_focus.

> +       } else if (touch_type == WL_INPUT_DEVICE_TOUCH_UP) {
> +               notify_button(device, time, BTN_LEFT, 0);
> +               wl_resource_post_event(device->pointer_focus_resource,
> +                               touch_type, time, touch_id);

and drop the notify_button() call here, but update the touch point
count and reset touch_focus if we hit 0.

> +       }
>  }
>
>  static void
> --
> 1.7.5.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list