Compare commits

...

5 Commits

Author SHA1 Message Date
3b17f67b97 wayland: Implement wl_pointer_gestures
The global wl_pointer_gestures object is now created, effectively
bridging pinch/swipe gestures with clients, so they're now
accessible to clients implementing the protocol.
2015-08-10 16:48:31 +02:00
0db347d642 wayland: Implement the wl_pointer_gesture_pinch interface
The pinch gesture resources are part of the MetaWaylandPointerClient, which
will be used during the propagation of CLUTTER_TOUCHPAD_PINCH events.
2015-08-10 16:45:23 +02:00
6963dbef16 wayland: Implement the wl_pointer_gesture_swipe interface
The swipe gesture resources are part of the MetaWaylandPointerClient, which
will be used during the emission of CLUTTER_TOUCHPAD_SWIPE events.
2015-08-10 16:45:23 +02:00
2b96fc7d0c wayland: Add gestures protocol XML 2015-08-10 16:45:23 +02:00
109389acf0 MetaWaylandPointer: Put client resources in its own struct
Instead of moving around all the bound pointer resources for a client
when changing focus, keep all the resources bound by a client in a per
client struct, and track the focus by having a pointer to the current
active pointer client struct instance.

This will simplify having wl_pointer extensinos sharing the pointer
focus of the wl_pointer by only having to add them to the pointer
client.

https://bugzilla.gnome.org/show_bug.cgi?id=744104
2015-08-10 16:44:01 +02:00
16 changed files with 894 additions and 81 deletions

2
.gitignore vendored
View File

@ -66,6 +66,8 @@ src/gtk-shell-protocol.c
src/gtk-shell-server-protocol.h
src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h
src/pointer-gestures-protocol.c
src/pointer-gestures-server-protocol.h
src/xserver-protocol.c
src/xserver-server-protocol.h
src/meta/meta-version.h

View File

@ -45,6 +45,8 @@ mutter_built_sources = \
if HAVE_WAYLAND
mutter_built_sources += \
pointer-gestures-protocol.c \
pointer-gestures-server-protocol.h \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
@ -53,6 +55,7 @@ mutter_built_sources += \
endif
wayland_protocols = \
wayland/protocol/pointer-gestures.xml \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml \
$(NULL)
@ -252,6 +255,12 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-data-device-private.h \
wayland/meta-wayland-pointer-gestures.c \
wayland/meta-wayland-pointer-gestures.h \
wayland/meta-wayland-pointer-gesture-swipe.c \
wayland/meta-wayland-pointer-gesture-swipe.h \
wayland/meta-wayland-pointer-gesture-pinch.c \
wayland/meta-wayland-pointer-gesture-pinch.h \
wayland/meta-wayland-keyboard.c \
wayland/meta-wayland-keyboard.h \
wayland/meta-wayland-pointer.c \

View File

@ -0,0 +1,160 @@
/*
* Wayland Support
*
* Copyright (C) 2015 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#define _GNU_SOURCE
#include "config.h"
#include <glib.h>
#include "meta-wayland-pointer-gesture-pinch.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-surface.h"
#include "pointer-gestures-server-protocol.h"
static void
handle_pinch_begin (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *resource;
uint32_t serial;
pointer_client = pointer->focus_client;
serial = wl_display_next_serial (pointer->display);
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
{
_wl_pointer_gesture_pinch_send_begin (resource, serial,
clutter_event_get_time (event),
pointer->focus_surface->resource,
2);
}
}
static void
handle_pinch_update (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *resource;
gdouble dx, dy, scale, rotation;
pointer_client = pointer->focus_client;
clutter_event_get_gesture_motion_delta (event, &dx, &dy);
rotation = clutter_event_get_gesture_pinch_angle_delta (event);
scale = clutter_event_get_gesture_pinch_scale (event);
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
{
_wl_pointer_gesture_pinch_send_update (resource,
clutter_event_get_time (event),
wl_fixed_from_double (dx),
wl_fixed_from_double (dy),
wl_fixed_from_double (scale),
wl_fixed_from_double (rotation));
}
}
static void
handle_pinch_end (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *resource;
gboolean cancelled = FALSE;
uint32_t serial;
pointer_client = pointer->focus_client;
serial = wl_display_next_serial (pointer->display);
if (event->touchpad_pinch.phase == CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL)
cancelled = TRUE;
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
{
_wl_pointer_gesture_pinch_send_end (resource, serial,
clutter_event_get_time (event),
cancelled);
}
}
gboolean
meta_wayland_pointer_gesture_pinch_handle_event (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
if (event->type != CLUTTER_TOUCHPAD_PINCH)
return FALSE;
if (!pointer->focus_client)
return FALSE;
switch (event->touchpad_pinch.phase)
{
case CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN:
handle_pinch_begin (pointer, event);
break;
case CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE:
handle_pinch_update (pointer, event);
break;
case CLUTTER_TOUCHPAD_GESTURE_PHASE_END:
case CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL:
handle_pinch_end (pointer, event);
break;
default:
return FALSE;
}
return TRUE;
}
static void
pointer_gesture_pinch_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct _wl_pointer_gesture_pinch_interface pointer_gesture_pinch_interface = {
pointer_gesture_pinch_destroy
};
void
meta_wayland_pointer_gesture_pinch_create_new_resource (MetaWaylandPointer *pointer,
struct wl_client *client,
struct wl_resource *gestures_resource,
uint32_t id)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *res;
pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
g_return_if_fail (pointer_client != NULL);
res = wl_resource_create (client, &_wl_pointer_gesture_pinch_interface,
wl_resource_get_version (gestures_resource), id);
wl_resource_set_implementation (res, &pointer_gesture_pinch_interface, pointer,
meta_wayland_pointer_unbind_pointer_client_resource);
wl_list_insert (&pointer_client->pinch_gesture_resources,
wl_resource_get_link (res));
}

View File

@ -0,0 +1,39 @@
/*
* Wayland Support
*
* Copyright (C) 2015 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_POINTER_GESTURE_PINCH_H
#define META_WAYLAND_POINTER_GESTURE_PINCH_H
#include <wayland-server.h>
#include <clutter/clutter.h>
#include <glib.h>
#include "meta-wayland-types.h"
gboolean meta_wayland_pointer_gesture_pinch_handle_event (MetaWaylandPointer *pointer,
const ClutterEvent *event);
void meta_wayland_pointer_gesture_pinch_create_new_resource (MetaWaylandPointer *pointer,
struct wl_client *client,
struct wl_resource *gestures_resource,
uint32_t id);
#endif /* META_WAYLAND_POINTER_GESTURE_PINCH_H */

View File

@ -0,0 +1,156 @@
/*
* Wayland Support
*
* Copyright (C) 2015 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#define _GNU_SOURCE
#include "config.h"
#include <glib.h>
#include "meta-wayland-pointer-gesture-swipe.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-surface.h"
#include "pointer-gestures-server-protocol.h"
static void
handle_swipe_begin (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *resource;
uint32_t serial, fingers;
pointer_client = pointer->focus_client;
serial = wl_display_next_serial (pointer->display);
fingers = clutter_event_get_gesture_swipe_finger_count (event);
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
{
_wl_pointer_gesture_swipe_send_begin (resource, serial,
clutter_event_get_time (event),
pointer->focus_surface->resource,
fingers);
}
}
static void
handle_swipe_update (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *resource;
gdouble dx, dy;
pointer_client = pointer->focus_client;
clutter_event_get_gesture_motion_delta (event, &dx, &dy);
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
{
_wl_pointer_gesture_swipe_send_update (resource,
clutter_event_get_time (event),
wl_fixed_from_double (dx),
wl_fixed_from_double (dy));
}
}
static void
handle_swipe_end (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *resource;
gboolean cancelled = FALSE;
uint32_t serial;
pointer_client = pointer->focus_client;
serial = wl_display_next_serial (pointer->display);
if (event->touchpad_swipe.phase == CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL)
cancelled = TRUE;
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
{
_wl_pointer_gesture_swipe_send_end (resource, serial,
clutter_event_get_time (event),
cancelled);
}
}
gboolean
meta_wayland_pointer_gesture_swipe_handle_event (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
if (event->type != CLUTTER_TOUCHPAD_SWIPE)
return FALSE;
if (!pointer->focus_client)
return FALSE;
switch (event->touchpad_swipe.phase)
{
case CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN:
handle_swipe_begin (pointer, event);
break;
case CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE:
handle_swipe_update (pointer, event);
break;
case CLUTTER_TOUCHPAD_GESTURE_PHASE_END:
handle_swipe_end (pointer, event);
break;
default:
return FALSE;
}
return TRUE;
}
static void
pointer_gesture_swipe_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct _wl_pointer_gesture_swipe_interface pointer_gesture_swipe_interface = {
pointer_gesture_swipe_release
};
void
meta_wayland_pointer_gesture_swipe_create_new_resource (MetaWaylandPointer *pointer,
struct wl_client *client,
struct wl_resource *pointer_resource,
uint32_t id)
{
MetaWaylandPointerClient *pointer_client;
struct wl_resource *res;
pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
g_return_if_fail (pointer_client != NULL);
res = wl_resource_create (client, &_wl_pointer_gesture_swipe_interface,
wl_resource_get_version (pointer_resource), id);
wl_resource_set_implementation (res, &pointer_gesture_swipe_interface, pointer,
meta_wayland_pointer_unbind_pointer_client_resource);
wl_list_insert (&pointer_client->swipe_gesture_resources,
wl_resource_get_link (res));
}

View File

@ -0,0 +1,39 @@
/*
* Wayland Support
*
* Copyright (C) 2015 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_POINTER_GESTURE_SWIPE_H
#define META_WAYLAND_POINTER_GESTURE_SWIPE_H
#include <wayland-server.h>
#include <clutter/clutter.h>
#include <glib.h>
#include "meta-wayland-types.h"
gboolean meta_wayland_pointer_gesture_swipe_handle_event (MetaWaylandPointer *pointer,
const ClutterEvent *event);
void meta_wayland_pointer_gesture_swipe_create_new_resource (MetaWaylandPointer *pointer,
struct wl_client *client,
struct wl_resource *pointer_resource,
uint32_t id);
#endif /* META_WAYLAND_POINTER_GESTURE_SWIPE_H */

View File

@ -0,0 +1,82 @@
/*
* Wayland Support
*
* Copyright (C) 2015 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#define _GNU_SOURCE
#include "config.h"
#include <glib.h>
#include "meta-wayland-pointer-gestures.h"
#include "pointer-gestures-server-protocol.h"
#include "meta-wayland-versions.h"
#include "meta-wayland-private.h"
static void
gestures_get_swipe (struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
struct wl_resource *pointer_resource)
{
MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
meta_wayland_pointer_gesture_swipe_create_new_resource (pointer, client, resource, id);
}
static void
gestures_get_pinch (struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
struct wl_resource *pointer_resource)
{
MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
meta_wayland_pointer_gesture_pinch_create_new_resource (pointer, client, resource, id);
}
static const struct _wl_pointer_gestures_interface pointer_gestures_interface = {
gestures_get_swipe,
gestures_get_pinch
};
static void
bind_pointer_gestures (struct wl_client *client,
void *data,
guint32 version,
guint32 id)
{
MetaWaylandPointerGestures *gestures = data;
struct wl_resource *resource;
resource = wl_resource_create (client, &_wl_pointer_gestures_interface, version, id);
wl_resource_set_implementation (resource, &pointer_gestures_interface,
gestures, NULL);
}
void
meta_wayland_pointer_gestures_init (MetaWaylandCompositor *compositor)
{
wl_global_create (compositor->wayland_display,
&_wl_pointer_gestures_interface,
META_WL_POINTER_GESTURES_VERSION,
gestures, bind_pointer_gestures);
}

View File

@ -0,0 +1,32 @@
/*
* Wayland Support
*
* Copyright (C) 2015 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_POINTER_GESTURES_H
#define META_WAYLAND_POINTER_GESTURES_H
#include <wayland-server.h>
#include <glib.h>
#include "meta-wayland-types.h"
void meta_wayland_pointer_gestures_init (MetaWaylandCompositor *compositor);
#endif /* META_WAYLAND_POINTER_GESTURES_H */

View File

@ -58,10 +58,121 @@
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
static void
unbind_resource (struct wl_resource *resource)
static MetaWaylandPointerClient *
meta_wayland_pointer_client_new (void)
{
MetaWaylandPointerClient *pointer_client;
pointer_client = g_slice_new0 (MetaWaylandPointerClient);
wl_list_init (&pointer_client->pointer_resources);
wl_list_init (&pointer_client->swipe_gesture_resources);
wl_list_init (&pointer_client->pinch_gesture_resources);
return pointer_client;
}
static void
meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
{
struct wl_resource *resource;
/* Since we make every wl_pointer resource defunct when we stop advertising
* the pointer capability on the wl_seat, we need to make sure all the
* resources in the pointer client instance gets removed.
*/
wl_resource_for_each (resource, &pointer_client->pointer_resources)
{
wl_list_remove (wl_resource_get_link (resource));
wl_list_init (wl_resource_get_link (resource));
}
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
{
wl_list_remove (wl_resource_get_link (resource));
wl_list_init (wl_resource_get_link (resource));
}
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
{
wl_list_remove (wl_resource_get_link (resource));
wl_list_init (wl_resource_get_link (resource));
}
g_slice_free (MetaWaylandPointerClient, pointer_client);
}
static gboolean
meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client)
{
return (wl_list_empty (&pointer_client->pointer_resources) &&
wl_list_empty (&pointer_client->swipe_gesture_resources) &&
wl_list_empty (&pointer_client->pinch_gesture_resources));
}
MetaWaylandPointerClient *
meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer,
struct wl_client *client)
{
return g_hash_table_lookup (pointer->pointer_clients, client);
}
static MetaWaylandPointerClient *
meta_wayland_pointer_ensure_pointer_client (MetaWaylandPointer *pointer,
struct wl_client *client)
{
MetaWaylandPointerClient *pointer_client;
pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
if (pointer_client)
return pointer_client;
pointer_client = meta_wayland_pointer_client_new ();
g_hash_table_insert (pointer->pointer_clients, client, pointer_client);
if (!pointer->focus_client &&
pointer->focus_surface &&
wl_resource_get_client (pointer->focus_surface->resource) == client)
pointer->focus_client = pointer_client;
return pointer_client;
}
static void
meta_wayland_pointer_cleanup_pointer_client (MetaWaylandPointer *pointer,
MetaWaylandPointerClient *pointer_client,
struct wl_client *client)
{
if (meta_wayland_pointer_client_is_empty (pointer_client))
{
if (pointer->focus_client == pointer_client)
pointer->focus_client = NULL;
g_hash_table_remove (pointer->pointer_clients, client);
}
}
void
meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource)
{
MetaWaylandPointer *pointer = wl_resource_get_user_data (resource);
MetaWaylandPointerClient *pointer_client;
struct wl_client *client = wl_resource_get_client (resource);
wl_list_remove (wl_resource_get_link (resource));
pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
if (!pointer_client)
{
/* This happens if all pointer devices were unplugged and no new resources
* were created by the client.
*
* If this is a resource that was previously made defunct, pointer_client
* be non-NULL but it is harmless since the below cleanup call will be
* prevented from removing the pointer client because of valid resources.
*/
return;
}
meta_wayland_pointer_cleanup_pointer_client (pointer,
pointer_client,
client);
}
static void
@ -131,17 +242,20 @@ meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
struct wl_resource *resource;
struct wl_list *l;
uint32_t time;
wl_fixed_t sx, sy;
l = &pointer->focus_resource_list;
wl_resource_for_each(resource, l)
if (!pointer->focus_client)
return;
time = clutter_event_get_time (event);
meta_wayland_pointer_get_relative_coordinates (pointer,
pointer->focus_surface,
&sx, &sy);
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
{
wl_fixed_t sx, sy;
meta_wayland_pointer_get_relative_coordinates (pointer,
pointer->focus_surface,
&sx, &sy);
wl_pointer_send_motion (resource, clutter_event_get_time (event), sx, sy);
wl_pointer_send_motion (resource, time, sx, sy);
}
}
@ -150,19 +264,21 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
struct wl_resource *resource;
struct wl_list *l;
ClutterEventType event_type;
event_type = clutter_event_type (event);
l = &pointer->focus_resource_list;
if (!wl_list_empty (l))
if (pointer->focus_client &&
!wl_list_empty (&pointer->focus_client->pointer_resources))
{
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
uint32_t time;
uint32_t button;
uint32_t serial;
time = clutter_event_get_time (event);
button = clutter_event_get_button (event);
switch (button)
{
@ -183,10 +299,10 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
serial = wl_display_next_serial (display);
wl_resource_for_each(resource, l)
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
{
wl_pointer_send_button (resource, serial,
clutter_event_get_time (event), button,
time, button,
event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
}
}
@ -241,8 +357,9 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
pointer->display = display;
wl_list_init (&pointer->resource_list);
wl_list_init (&pointer->focus_resource_list);
pointer->pointer_clients =
g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) meta_wayland_pointer_client_free);
pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
@ -265,6 +382,7 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer)
meta_wayland_pointer_set_focus (pointer, NULL);
set_cursor_surface (pointer, NULL);
g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
pointer->display = NULL;
}
@ -358,7 +476,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
struct wl_resource *resource;
struct wl_list *l;
wl_fixed_t x_value = 0, y_value = 0;
if (clutter_event_is_pointer_emulated (event))
@ -399,15 +516,17 @@ handle_scroll_event (MetaWaylandPointer *pointer,
return;
}
l = &pointer->focus_resource_list;
wl_resource_for_each (resource, l)
if (pointer->focus_client)
{
if (x_value)
wl_pointer_send_axis (resource, clutter_event_get_time (event),
WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
if (y_value)
wl_pointer_send_axis (resource, clutter_event_get_time (event),
WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
{
if (x_value)
wl_pointer_send_axis (resource, clutter_event_get_time (event),
WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
if (y_value)
wl_pointer_send_axis (resource, clutter_event_get_time (event),
WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
}
}
}
@ -430,6 +549,14 @@ meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
handle_scroll_event (pointer, event);
break;
case CLUTTER_TOUCHPAD_SWIPE:
meta_wayland_pointer_gesture_swipe_handle_event (pointer, event);
break;
case CLUTTER_TOUCHPAD_PINCH:
meta_wayland_pointer_gesture_pinch_handle_event (pointer, event);
break;
default:
break;
}
@ -437,29 +564,6 @@ meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
return FALSE;
}
static void
move_resources (struct wl_list *destination, struct wl_list *source)
{
wl_list_insert_list (destination, source);
wl_list_init (source);
}
static void
move_resources_for_client (struct wl_list *destination,
struct wl_list *source,
struct wl_client *client)
{
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe (resource, tmp, source)
{
if (wl_resource_get_client (resource) == client)
{
wl_list_remove (wl_resource_get_link (resource));
wl_list_insert (destination, wl_resource_get_link (resource));
}
}
}
static void
broadcast_focus (MetaWaylandPointer *pointer,
struct wl_resource *resource)
@ -482,22 +586,23 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
if (pointer->focus_surface != NULL)
{
struct wl_client *client =
wl_resource_get_client (pointer->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
uint32_t serial;
struct wl_resource *resource;
struct wl_list *l;
l = &pointer->focus_resource_list;
if (!wl_list_empty (l))
serial = wl_display_next_serial (display);
if (pointer->focus_client)
{
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display);
wl_resource_for_each (resource, l)
wl_resource_for_each (resource,
&pointer->focus_client->pointer_resources)
{
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
}
move_resources (&pointer->resource_list, &pointer->focus_resource_list);
pointer->focus_client = NULL;
}
wl_list_remove (&pointer->focus_surface_listener.link);
@ -506,8 +611,9 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
if (surface != NULL)
{
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_display *display = wl_client_get_display (client);
struct wl_resource *resource;
struct wl_list *l;
ClutterPoint pos;
pointer->focus_surface = surface;
@ -521,18 +627,14 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
clutter_get_current_event_time (),
pos.x, pos.y);
move_resources_for_client (&pointer->focus_resource_list,
&pointer->resource_list,
wl_resource_get_client (pointer->focus_surface->resource));
l = &pointer->focus_resource_list;
if (!wl_list_empty (l))
pointer->focus_client =
meta_wayland_pointer_get_pointer_client (pointer, client);
if (pointer->focus_client)
{
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
pointer->focus_serial = wl_display_next_serial (display);
wl_resource_for_each (resource, l)
wl_resource_for_each (resource,
&pointer->focus_client->pointer_resources)
{
broadcast_focus (pointer, resource);
}
@ -707,19 +809,19 @@ meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer,
uint32_t id)
{
struct wl_resource *cr;
MetaWaylandPointerClient *pointer_client;
cr = wl_resource_create (client, &wl_pointer_interface, wl_resource_get_version (seat_resource), id);
wl_resource_set_implementation (cr, &pointer_interface, pointer, unbind_resource);
wl_resource_set_implementation (cr, &pointer_interface, pointer,
meta_wayland_pointer_unbind_pointer_client_resource);
if (pointer->focus_surface && wl_resource_get_client (pointer->focus_surface->resource) == client)
{
wl_list_insert (&pointer->focus_resource_list, wl_resource_get_link (cr));
broadcast_focus (pointer, cr);
}
else
{
wl_list_insert (&pointer->resource_list, wl_resource_get_link (cr));
}
pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client);
wl_list_insert (&pointer_client->pointer_resources,
wl_resource_get_link (cr));
if (pointer->focus_client == pointer_client)
broadcast_focus (pointer, cr);
}
gboolean

View File

@ -25,6 +25,8 @@
#include <glib.h>
#include "meta-wayland-types.h"
#include "meta-wayland-pointer-gesture-swipe.h"
#include "meta-wayland-pointer-gesture-pinch.h"
#include <meta/meta-cursor-tracker.h>
@ -44,12 +46,19 @@ struct _MetaWaylandPointerGrab
MetaWaylandPointer *pointer;
};
struct _MetaWaylandPointerClient
{
struct wl_list pointer_resources;
struct wl_list swipe_gesture_resources;
struct wl_list pinch_gesture_resources;
};
struct _MetaWaylandPointer
{
struct wl_display *display;
struct wl_list resource_list;
struct wl_list focus_resource_list;
MetaWaylandPointerClient *focus_client;
GHashTable *pointer_clients;
MetaWaylandSurface *focus_surface;
struct wl_listener focus_surface_listener;
@ -127,4 +136,8 @@ gboolean meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer,
MetaWaylandSurface *meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer);
MetaWaylandPointerClient * meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer,
struct wl_client *client);
void meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource);
#endif /* META_WAYLAND_POINTER_H */

View File

@ -32,6 +32,7 @@
#include "meta-wayland-versions.h"
#include "meta-wayland-surface.h"
#include "meta-wayland-seat.h"
#include "meta-wayland-pointer-gestures.h"
typedef struct _MetaXWaylandSelection MetaXWaylandSelection;

View File

@ -332,6 +332,8 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_SCROLL:
case CLUTTER_TOUCHPAD_SWIPE:
case CLUTTER_TOUCHPAD_PINCH:
return meta_wayland_pointer_handle_event (&seat->pointer, event);
case CLUTTER_KEY_PRESS:

View File

@ -43,4 +43,6 @@ typedef struct _MetaWaylandOutput MetaWaylandOutput;
typedef struct _MetaWaylandSerial MetaWaylandSerial;
typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient;
#endif

View File

@ -44,5 +44,6 @@
#define META_XSERVER_VERSION 1
#define META_GTK_SHELL_VERSION 2
#define META_WL_SUBCOMPOSITOR_VERSION 1
#define META_WL_POINTER_GESTURES_VERSION 1
#endif

View File

@ -310,6 +310,7 @@ meta_wayland_init (void)
meta_wayland_outputs_init (compositor);
meta_wayland_data_device_manager_init (compositor);
meta_wayland_shell_init (compositor);
meta_wayland_pointer_gestures_init (compositor);
meta_wayland_seat_init (compositor);
compositor->display_name = wl_display_add_socket_auto (compositor->wayland_display);

View File

@ -0,0 +1,172 @@
<protocol name="pointer_gestures">
<interface name="_wl_pointer_gestures" version="1">
<description summary="touchpad gestures">
A global interface to provide semantic touchpad gestures for a given
pointer.
Two gestures are currently supported: swipe and zoom/rotate.
All gestures follow a three-stage cycle: begin, update, end and
are identified by a unique id.
Warning! The protocol described in this file is experimental. Each
version of this protocol should be considered incompatible with any
other version, and a client binding to a version different to the one
advertised will be terminated. Once the protocol is declared stable,
compatibility is guaranteed, the '_' prefix will be removed from the
name and the version will be reset to 1.
</description>
<request name="get_swipe_gesture">
<description summary="get swipe gesture">
Create a swipe gesture object. See the
wl_pointer_gesture_swipe interface for details.
</description>
<arg name="id" type="new_id" interface="_wl_pointer_gesture_swipe"/>
<arg name="pointer" type="object" interface="wl_pointer"/>
</request>
<request name="get_pinch_gesture">
<description summary="get pinch gesture">
Create a pinch gesture object. See the
wl_pointer_gesture_pinch interface for details.
</description>
<arg name="id" type="new_id" interface="_wl_pointer_gesture_pinch"/>
<arg name="pointer" type="object" interface="wl_pointer"/>
</request>
</interface>
<interface name="_wl_pointer_gesture_swipe" version="1">
<description summary="a swipe gesture object">
A swipe gesture object notifies a client about a multi-finger swipe
gesture detected on an indirect input device such as a touchpad.
The gesture is usually initiated by multiple fingers moving in the
same direction but once initiated the direction may change.
The precise conditions of when such a gesture is detected are
implementation-dependent.
A gesture consists of three stages: begin, update (optional) and end.
There cannot be multiple simultaneous pinch or swipe gestures on a
same pointer/seat, how compositors prevent these situations is
implementation-dependent.
A gesture may be cancelled by the compositor or the hardware.
Clients should not consider performing permanent or irreversible
actions until the end of a gesture has been received.
</description>
<request name="destroy" type="destructor">
<description summary="destroy the pointer swipe gesture object"/>
</request>
<event name="begin">
<description summary="multi-finger swipe begin">
This event is sent when a multi-finger swipe gesture is detected
on the device.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="fingers" type="uint" summary="number of fingers"/>
</event>
<event name="update">
<description summary="multi-finger swipe motion">
This event is sent when a multi-finger swipe gesture changes the
position of the logical center.
The dx and dy coordinates are relative coordinates of the logical
center of the gesture compared to the previous event.
</description>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
</event>
<event name="end">
<description summary="multi-finger swipe end">
This event is sent when a multi-finger swipe gesture ceases to
be valid. This may happen when one or more finger is lifted or
the gesture is cancelled.
When a gesture is cancelled, the client should undo state changes
caused by this gesture. What causes a gesture to be cancelled is
implementation-dependent.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
</event>
</interface>
<interface name="_wl_pointer_gesture_pinch" version="1">
<description summary="a pinch gesture object">
A pinch gesture object notifies a client about a multi-finger pinch
gesture detected on an indirect input device such as a touchpad.
The gesture is usually initiated by multiple fingers moving towards
each other or away from each other, or by two or more fingers rotating
around a logical center of gravity. The precise conditions of when
such a gesture is detected are implementation-dependent.
A gesture consists of three stages: begin, update (optional) and end.
There cannot be multiple simultaneous pinch or swipe gestures on a
same pointer/seat, how compositors prevent these situations is
implementation-dependent.
A gesture may be cancelled by the compositor or the hardware.
Clients should not consider performing permanent or irreversible
actions until the end of a gesture has been received.
</description>
<request name="destroy" type="destructor">
<description summary="destroy the pinch gesture object"/>
</request>
<event name="begin">
<description summary="multi-finger pinch begin">
This event is sent when a multi-finger pinch gesture is detected
on the device.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="fingers" type="uint" summary="number of fingers"/>
</event>
<event name="update">
<description summary="multi-finger pinch motion">
This event is sent when a multi-finger pinch gesture changes the
position of the logical center, the rotation or the relative scale.
The dx and dy coordinates are relative coordinates in the
surface coordinate space of the logical center of the gesture.
The scale factor is an absolute scale compared to the
pointer_gesture_pinch.begin event, e.g. a scale of 2 means the fingers
are now twice as far apart as on pointer_gesture_pinch.begin.
The rotation is the relative angle in degrees clockwise compared to the previous
pointer_gesture_pinch.begin or pointer_gesture_pinch.update event.
</description>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
<arg name="scale" type="fixed" summary="scale relative to the initial finger position"/>
<arg name="rotation" type="fixed" summary="angle in degrees cw relative to the previous event"/>
</event>
<event name="end">
<description summary="multi-finger pinch end">
This event is sent when a multi-finger pinch gesture ceases to
be valid. This may happen when one or more finger is lifted or
the gesture is cancelled.
When a gesture is cancelled, the client should undo state changes
caused by this gesture. What causes a gesture to be cancelled is
implementation-dependent.
</description>
<arg name="serial" type="uint"/>
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
</event>
</interface>
</protocol>