2013-05-03 13:51:22 -04:00
|
|
|
/*
|
|
|
|
* Wayland Support
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 Intel Corporation
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright © 2008 Kristian Høgsberg
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
* the above copyright notice appear in all copies and that both that copyright
|
|
|
|
* notice and this permission notice appear in supporting documentation, and
|
|
|
|
* that the name of the copyright holders not be used in advertising or
|
|
|
|
* publicity pertaining to distribution of the software without specific,
|
|
|
|
* written prior permission. The copyright holders make no representations
|
|
|
|
* about the suitability of this software for any purpose. It is provided "as
|
|
|
|
* is" without express or implied warranty.
|
|
|
|
*
|
|
|
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
|
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
|
|
* OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* The file is based on src/input.c from Weston */
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2013-08-23 07:57:58 -04:00
|
|
|
#include <clutter/clutter.h>
|
2013-09-11 08:06:05 -04:00
|
|
|
#include <linux/input.h>
|
2013-08-23 07:57:58 -04:00
|
|
|
|
2013-05-03 13:51:22 -04:00
|
|
|
#include "meta-wayland-pointer.h"
|
2015-02-11 04:34:15 -05:00
|
|
|
#include "meta-wayland-popup.h"
|
2013-08-30 12:03:30 -04:00
|
|
|
#include "meta-wayland-private.h"
|
2014-10-07 22:39:00 -04:00
|
|
|
#include "meta-wayland-buffer.h"
|
2014-04-17 16:54:30 -04:00
|
|
|
#include "meta-cursor.h"
|
|
|
|
#include "meta-cursor-tracker-private.h"
|
2014-04-17 18:16:49 -04:00
|
|
|
#include "meta-surface-actor-wayland.h"
|
2013-05-03 13:51:22 -04:00
|
|
|
|
2013-07-17 04:44:29 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
2014-04-17 18:16:49 -04:00
|
|
|
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
|
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
static MetaWaylandPointerClient *
|
|
|
|
meta_wayland_pointer_client_new (void)
|
|
|
|
{
|
|
|
|
MetaWaylandPointerClient *pointer_client;
|
|
|
|
|
|
|
|
pointer_client = g_slice_new0 (MetaWaylandPointerClient);
|
|
|
|
wl_list_init (&pointer_client->pointer_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));
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-04-17 17:16:17 -04:00
|
|
|
static void
|
2015-08-09 09:24:16 -04:00
|
|
|
meta_wayland_pointer_cleanup_pointer_client (MetaWaylandPointer *pointer,
|
|
|
|
MetaWaylandPointerClient *pointer_client,
|
|
|
|
struct wl_client *client)
|
2014-04-17 17:16:17 -04:00
|
|
|
{
|
2015-08-09 09:24:16 -04:00
|
|
|
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);
|
|
|
|
|
2014-04-17 17:16:17 -04:00
|
|
|
wl_list_remove (wl_resource_get_link (resource));
|
2015-08-09 09:24:16 -04:00
|
|
|
|
|
|
|
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);
|
2014-04-17 17:16:17 -04:00
|
|
|
}
|
|
|
|
|
2014-11-26 18:22:01 -05:00
|
|
|
static void
|
|
|
|
sync_focus_surface (MetaWaylandPointer *pointer)
|
|
|
|
{
|
|
|
|
MetaDisplay *display = meta_get_display ();
|
|
|
|
|
|
|
|
switch (display->event_route)
|
|
|
|
{
|
|
|
|
case META_EVENT_ROUTE_WINDOW_OP:
|
|
|
|
case META_EVENT_ROUTE_COMPOSITOR_GRAB:
|
2015-01-19 14:27:27 -05:00
|
|
|
case META_EVENT_ROUTE_FRAME_BUTTON:
|
2014-11-26 18:22:01 -05:00
|
|
|
/* The compositor has a grab, so remove our focus... */
|
|
|
|
meta_wayland_pointer_set_focus (pointer, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case META_EVENT_ROUTE_NORMAL:
|
|
|
|
case META_EVENT_ROUTE_WAYLAND_POPUP:
|
|
|
|
{
|
|
|
|
const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface;
|
|
|
|
interface->focus (pointer->grab, pointer->current);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-04-17 17:00:59 -04:00
|
|
|
static void
|
|
|
|
set_cursor_surface (MetaWaylandPointer *pointer,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
if (pointer->cursor_surface == surface)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pointer->cursor_surface)
|
|
|
|
wl_list_remove (&pointer->cursor_surface_destroy_listener.link);
|
|
|
|
|
|
|
|
pointer->cursor_surface = surface;
|
|
|
|
|
|
|
|
if (pointer->cursor_surface)
|
|
|
|
wl_resource_add_destroy_listener (pointer->cursor_surface->resource,
|
|
|
|
&pointer->cursor_surface_destroy_listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pointer_handle_cursor_surface_destroy (struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, cursor_surface_destroy_listener);
|
|
|
|
|
|
|
|
set_cursor_surface (pointer, NULL);
|
|
|
|
meta_wayland_pointer_update_cursor_surface (pointer);
|
|
|
|
}
|
|
|
|
|
2013-12-03 10:50:35 -05:00
|
|
|
static void
|
2014-02-17 19:13:16 -05:00
|
|
|
pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
2013-12-03 10:50:35 -05:00
|
|
|
{
|
2014-02-17 19:13:16 -05:00
|
|
|
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
2014-02-20 11:29:28 -05:00
|
|
|
|
2014-10-08 15:36:13 -04:00
|
|
|
meta_wayland_pointer_set_focus (pointer, NULL);
|
2013-12-03 10:50:35 -05:00
|
|
|
}
|
|
|
|
|
2015-02-11 04:34:15 -05:00
|
|
|
void
|
|
|
|
meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
|
|
|
struct wl_resource *resource;
|
2015-08-09 09:24:16 -04:00
|
|
|
uint32_t time;
|
|
|
|
wl_fixed_t sx, sy;
|
2013-05-03 13:51:22 -04:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
if (!pointer->focus_client)
|
|
|
|
return;
|
2013-09-11 08:06:05 -04:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
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_pointer_send_motion (resource, time, sx, sy);
|
2013-09-11 08:06:05 -04:00
|
|
|
}
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2015-02-11 04:34:15 -05:00
|
|
|
void
|
|
|
|
meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
|
|
|
struct wl_resource *resource;
|
2013-09-11 08:06:05 -04:00
|
|
|
ClutterEventType event_type;
|
|
|
|
|
|
|
|
event_type = clutter_event_type (event);
|
2013-05-03 13:51:22 -04:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
if (pointer->focus_client &&
|
|
|
|
!wl_list_empty (&pointer->focus_client->pointer_resources))
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
2014-04-16 15:29:59 -04:00
|
|
|
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
|
2013-05-03 13:51:22 -04:00
|
|
|
struct wl_display *display = wl_client_get_display (client);
|
2015-08-09 09:24:16 -04:00
|
|
|
uint32_t time;
|
2013-09-11 08:06:05 -04:00
|
|
|
uint32_t button;
|
|
|
|
uint32_t serial;
|
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
time = clutter_event_get_time (event);
|
|
|
|
|
2013-09-11 08:06:05 -04:00
|
|
|
button = clutter_event_get_button (event);
|
|
|
|
switch (button)
|
|
|
|
{
|
|
|
|
/* The evdev input right and middle button numbers are swapped
|
|
|
|
relative to how Clutter numbers them */
|
|
|
|
case 2:
|
|
|
|
button = BTN_MIDDLE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
button = BTN_RIGHT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
button = button + BTN_LEFT - 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-05-03 13:51:22 -04:00
|
|
|
serial = wl_display_next_serial (display);
|
2014-09-17 19:51:27 -04:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
|
2014-09-17 19:51:27 -04:00
|
|
|
{
|
|
|
|
wl_pointer_send_button (resource, serial,
|
2015-08-09 09:24:16 -04:00
|
|
|
time, button,
|
2014-09-17 19:51:27 -04:00
|
|
|
event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
|
|
|
|
}
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2013-09-11 08:06:05 -04:00
|
|
|
if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE)
|
2014-11-26 18:22:01 -05:00
|
|
|
sync_focus_surface (pointer);
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2015-02-11 04:34:15 -05:00
|
|
|
static void
|
|
|
|
default_grab_focus (MetaWaylandPointerGrab *grab,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
|
|
|
MetaWaylandPointer *pointer = grab->pointer;
|
|
|
|
|
|
|
|
if (pointer->button_count > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
meta_wayland_pointer_set_focus (pointer, surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
default_grab_motion (MetaWaylandPointerGrab *grab,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
MetaWaylandPointer *pointer = grab->pointer;
|
|
|
|
|
|
|
|
meta_wayland_pointer_send_motion (pointer, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
default_grab_button (MetaWaylandPointerGrab *grab,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
MetaWaylandPointer *pointer = grab->pointer;
|
|
|
|
|
|
|
|
meta_wayland_pointer_send_button (pointer, event);
|
|
|
|
}
|
|
|
|
|
2013-05-03 13:51:22 -04:00
|
|
|
static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
|
|
|
|
default_grab_focus,
|
|
|
|
default_grab_motion,
|
|
|
|
default_grab_button
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2014-04-17 18:12:23 -04:00
|
|
|
meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
|
|
|
struct wl_display *display)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
2013-08-23 07:57:58 -04:00
|
|
|
ClutterDeviceManager *manager;
|
|
|
|
|
2013-05-03 13:51:22 -04:00
|
|
|
memset (pointer, 0, sizeof *pointer);
|
2014-04-17 18:12:23 -04:00
|
|
|
|
|
|
|
pointer->display = display;
|
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
pointer->pointer_clients =
|
|
|
|
g_hash_table_new_full (NULL, NULL, NULL,
|
|
|
|
(GDestroyNotify) meta_wayland_pointer_client_free);
|
2014-02-18 18:00:26 -05:00
|
|
|
|
2014-02-17 19:13:16 -05:00
|
|
|
pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
|
2014-02-18 18:00:26 -05:00
|
|
|
|
2014-04-18 10:15:40 -04:00
|
|
|
pointer->cursor_surface = NULL;
|
|
|
|
pointer->cursor_surface_destroy_listener.notify = pointer_handle_cursor_surface_destroy;
|
|
|
|
|
2013-05-03 13:51:22 -04:00
|
|
|
pointer->default_grab.interface = &default_pointer_grab_interface;
|
|
|
|
pointer->default_grab.pointer = pointer;
|
|
|
|
pointer->grab = &pointer->default_grab;
|
|
|
|
|
2013-08-23 07:57:58 -04:00
|
|
|
manager = clutter_device_manager_get_default ();
|
2014-04-18 10:27:48 -04:00
|
|
|
pointer->device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
|
2014-07-22 11:09:12 -04:00
|
|
|
|
|
|
|
pointer->cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
|
|
|
{
|
2014-07-21 18:30:21 -04:00
|
|
|
meta_wayland_pointer_set_focus (pointer, NULL);
|
2014-04-17 17:00:59 -04:00
|
|
|
set_cursor_surface (pointer, NULL);
|
2014-09-05 21:00:09 -04:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
|
2014-09-05 21:00:09 -04:00
|
|
|
pointer->display = NULL;
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2014-04-17 17:52:11 -04:00
|
|
|
static int
|
|
|
|
count_buttons (const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
static gint maskmap[5] =
|
|
|
|
{
|
|
|
|
CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON2_MASK, CLUTTER_BUTTON3_MASK,
|
|
|
|
CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK
|
|
|
|
};
|
|
|
|
ClutterModifierType mod_mask;
|
|
|
|
int i, count;
|
|
|
|
|
|
|
|
mod_mask = clutter_event_get_state (event);
|
|
|
|
count = 0;
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
{
|
|
|
|
if (mod_mask & maskmap[i])
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2014-04-17 18:16:49 -04:00
|
|
|
static void
|
|
|
|
repick_for_event (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *for_event)
|
|
|
|
{
|
2015-02-06 12:44:08 -05:00
|
|
|
ClutterActor *actor;
|
2014-04-17 18:16:49 -04:00
|
|
|
|
|
|
|
if (for_event)
|
2015-02-06 12:44:08 -05:00
|
|
|
actor = clutter_event_get_source (for_event);
|
2014-04-17 18:16:49 -04:00
|
|
|
else
|
2015-02-06 12:44:08 -05:00
|
|
|
actor = clutter_input_device_get_pointer_actor (pointer->device);
|
2014-04-17 18:16:49 -04:00
|
|
|
|
2014-04-18 18:51:17 -04:00
|
|
|
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
|
2014-04-18 18:46:15 -04:00
|
|
|
pointer->current = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
|
|
|
|
else
|
|
|
|
pointer->current = NULL;
|
2014-04-18 18:38:20 -04:00
|
|
|
|
2014-04-18 18:53:38 -04:00
|
|
|
sync_focus_surface (pointer);
|
2014-11-22 20:06:21 -05:00
|
|
|
meta_wayland_pointer_update_cursor_surface (pointer);
|
2014-04-17 18:16:49 -04:00
|
|
|
}
|
|
|
|
|
2014-04-20 10:59:49 -04:00
|
|
|
void
|
|
|
|
meta_wayland_pointer_update (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
repick_for_event (pointer, event);
|
|
|
|
|
2014-05-15 13:56:53 -04:00
|
|
|
pointer->button_count = count_buttons (event);
|
2014-04-20 10:59:49 -04:00
|
|
|
}
|
|
|
|
|
2014-04-17 18:16:49 -04:00
|
|
|
static void
|
|
|
|
notify_motion (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
pointer->grab->interface->motion (pointer->grab, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_motion_event (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
notify_motion (pointer, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_button_event (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
gboolean implicit_grab;
|
|
|
|
|
|
|
|
implicit_grab = (event->type == CLUTTER_BUTTON_PRESS) && (pointer->button_count == 1);
|
|
|
|
if (implicit_grab)
|
|
|
|
{
|
|
|
|
pointer->grab_button = clutter_event_get_button (event);
|
|
|
|
pointer->grab_time = clutter_event_get_time (event);
|
2014-04-18 10:27:48 -04:00
|
|
|
clutter_event_get_coords (event, &pointer->grab_x, &pointer->grab_y);
|
2014-04-17 18:16:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pointer->grab->interface->button (pointer->grab, event);
|
|
|
|
|
|
|
|
if (implicit_grab)
|
|
|
|
pointer->grab_serial = wl_display_get_serial (pointer->display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_scroll_event (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
struct wl_resource *resource;
|
|
|
|
wl_fixed_t x_value = 0, y_value = 0;
|
|
|
|
|
|
|
|
if (clutter_event_is_pointer_emulated (event))
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (clutter_event_get_scroll_direction (event))
|
|
|
|
{
|
|
|
|
case CLUTTER_SCROLL_UP:
|
|
|
|
y_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CLUTTER_SCROLL_DOWN:
|
|
|
|
y_value = DEFAULT_AXIS_STEP_DISTANCE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CLUTTER_SCROLL_LEFT:
|
|
|
|
x_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CLUTTER_SCROLL_RIGHT:
|
|
|
|
x_value = DEFAULT_AXIS_STEP_DISTANCE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CLUTTER_SCROLL_SMOOTH:
|
|
|
|
{
|
|
|
|
double dx, dy;
|
2014-05-03 15:06:08 -04:00
|
|
|
/* Clutter smooth scroll events are in discrete steps (1 step = 1.0 long
|
|
|
|
* vector along one axis). To convert to smooth scroll events that are
|
|
|
|
* in pointer motion event space, multiply the vector with the 10. */
|
|
|
|
const double factor = 10.0;
|
2014-04-17 18:16:49 -04:00
|
|
|
clutter_event_get_scroll_delta (event, &dx, &dy);
|
2014-05-03 15:06:08 -04:00
|
|
|
x_value = wl_fixed_from_double (dx) * factor;
|
|
|
|
y_value = wl_fixed_from_double (dy) * factor;
|
2014-04-17 18:16:49 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
if (pointer->focus_client)
|
2014-04-17 18:16:49 -04:00
|
|
|
{
|
2015-08-09 09:24:16 -04:00
|
|
|
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);
|
|
|
|
}
|
2014-04-17 18:16:49 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case CLUTTER_MOTION:
|
|
|
|
handle_motion_event (pointer, event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CLUTTER_BUTTON_PRESS:
|
|
|
|
case CLUTTER_BUTTON_RELEASE:
|
|
|
|
handle_button_event (pointer, event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CLUTTER_SCROLL:
|
|
|
|
handle_scroll_event (pointer, event);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-09-05 19:29:24 -04:00
|
|
|
static void
|
|
|
|
broadcast_focus (MetaWaylandPointer *pointer,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_fixed_t sx, sy;
|
|
|
|
|
|
|
|
meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy);
|
|
|
|
wl_pointer_send_enter (resource, pointer->focus_serial, pointer->focus_surface->resource, sx, sy);
|
|
|
|
}
|
|
|
|
|
2013-05-03 13:51:22 -04:00
|
|
|
void
|
|
|
|
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
2013-09-11 08:06:05 -04:00
|
|
|
MetaWaylandSurface *surface)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
2014-09-05 21:00:09 -04:00
|
|
|
if (pointer->display == NULL)
|
|
|
|
return;
|
|
|
|
|
2014-09-05 19:29:24 -04:00
|
|
|
if (pointer->focus_surface == surface)
|
2013-11-19 20:20:13 -05:00
|
|
|
return;
|
|
|
|
|
2014-09-16 20:55:27 -04:00
|
|
|
if (pointer->focus_surface != NULL)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
2015-08-09 09:24:16 -04:00
|
|
|
struct wl_client *client =
|
|
|
|
wl_resource_get_client (pointer->focus_surface->resource);
|
|
|
|
struct wl_display *display = wl_client_get_display (client);
|
|
|
|
uint32_t serial;
|
2014-04-16 15:11:10 -04:00
|
|
|
struct wl_resource *resource;
|
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
serial = wl_display_next_serial (display);
|
2014-01-31 18:18:59 -05:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
if (pointer->focus_client)
|
|
|
|
{
|
|
|
|
wl_resource_for_each (resource,
|
|
|
|
&pointer->focus_client->pointer_resources)
|
2014-04-16 15:11:10 -04:00
|
|
|
{
|
|
|
|
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
|
|
|
|
}
|
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
pointer->focus_client = NULL;
|
2014-02-18 23:16:54 -05:00
|
|
|
}
|
2014-02-19 07:56:56 -05:00
|
|
|
|
|
|
|
wl_list_remove (&pointer->focus_surface_listener.link);
|
|
|
|
pointer->focus_surface = NULL;
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2014-02-18 23:16:54 -05:00
|
|
|
if (surface != NULL)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
2015-08-09 09:24:16 -04:00
|
|
|
struct wl_client *client = wl_resource_get_client (surface->resource);
|
|
|
|
struct wl_display *display = wl_client_get_display (client);
|
2014-04-16 15:11:10 -04:00
|
|
|
struct wl_resource *resource;
|
2014-04-18 10:27:48 -04:00
|
|
|
ClutterPoint pos;
|
2014-04-16 15:11:10 -04:00
|
|
|
|
2014-02-18 23:16:54 -05:00
|
|
|
pointer->focus_surface = surface;
|
|
|
|
wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener);
|
2013-09-11 08:06:05 -04:00
|
|
|
|
2014-04-18 10:27:48 -04:00
|
|
|
clutter_input_device_get_coords (pointer->device, NULL, &pos);
|
|
|
|
|
2014-10-20 12:41:22 -04:00
|
|
|
if (pointer->focus_surface->window)
|
|
|
|
meta_window_handle_enter (pointer->focus_surface->window,
|
|
|
|
/* XXX -- can we reliably get a timestamp for setting focus? */
|
|
|
|
clutter_get_current_event_time (),
|
|
|
|
pos.x, pos.y);
|
2014-04-16 14:47:06 -04:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
pointer->focus_client =
|
|
|
|
meta_wayland_pointer_get_pointer_client (pointer, client);
|
|
|
|
if (pointer->focus_client)
|
2013-05-03 13:51:22 -04:00
|
|
|
{
|
2014-09-05 19:29:24 -04:00
|
|
|
pointer->focus_serial = wl_display_next_serial (display);
|
2014-02-18 18:00:26 -05:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
wl_resource_for_each (resource,
|
|
|
|
&pointer->focus_client->pointer_resources)
|
2014-04-16 15:11:10 -04:00
|
|
|
{
|
2014-09-05 19:29:24 -04:00
|
|
|
broadcast_focus (pointer, resource);
|
2014-04-16 15:11:10 -04:00
|
|
|
}
|
2014-02-18 23:16:54 -05:00
|
|
|
}
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
2014-10-06 18:41:13 -04:00
|
|
|
|
|
|
|
meta_wayland_pointer_update_cursor_surface (pointer);
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
|
|
|
MetaWaylandPointerGrab *grab)
|
|
|
|
{
|
|
|
|
const MetaWaylandPointerGrabInterface *interface;
|
|
|
|
|
|
|
|
pointer->grab = grab;
|
|
|
|
interface = pointer->grab->interface;
|
|
|
|
grab->pointer = pointer;
|
|
|
|
|
|
|
|
if (pointer->current)
|
2014-03-16 11:50:38 -04:00
|
|
|
interface->focus (pointer->grab, pointer->current);
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
|
|
|
{
|
|
|
|
const MetaWaylandPointerGrabInterface *interface;
|
|
|
|
|
|
|
|
pointer->grab = &pointer->default_grab;
|
|
|
|
interface = pointer->grab->interface;
|
2014-03-16 11:50:38 -04:00
|
|
|
interface->focus (pointer->grab, pointer->current);
|
2014-10-06 19:19:19 -04:00
|
|
|
|
|
|
|
meta_wayland_pointer_update_cursor_surface (pointer);
|
2013-05-03 13:51:22 -04:00
|
|
|
}
|
|
|
|
|
2015-02-11 04:34:15 -05:00
|
|
|
void
|
2013-09-10 09:53:31 -04:00
|
|
|
meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
|
|
|
|
{
|
2015-02-11 04:34:15 -05:00
|
|
|
MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)pointer->grab;
|
2014-03-10 15:00:59 -04:00
|
|
|
|
2015-02-11 04:34:15 -05:00
|
|
|
meta_wayland_popup_grab_end (popup_grab);
|
|
|
|
meta_wayland_popup_grab_destroy (popup_grab);
|
2013-09-10 09:53:31 -04:00
|
|
|
}
|
|
|
|
|
2015-02-11 22:13:55 -05:00
|
|
|
MetaWaylandPopup *
|
2013-09-10 09:53:31 -04:00
|
|
|
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
|
|
|
MetaWaylandSurface *surface)
|
|
|
|
{
|
2013-09-11 08:06:05 -04:00
|
|
|
MetaWaylandPopupGrab *grab;
|
2013-09-10 09:53:31 -04:00
|
|
|
|
2015-02-11 04:34:15 -05:00
|
|
|
if (pointer->grab != &pointer->default_grab &&
|
|
|
|
!meta_wayland_pointer_grab_is_popup_grab (pointer->grab))
|
2015-02-11 22:13:55 -05:00
|
|
|
return NULL;
|
2013-09-11 08:53:48 -04:00
|
|
|
|
|
|
|
if (pointer->grab == &pointer->default_grab)
|
|
|
|
{
|
2015-02-11 04:34:15 -05:00
|
|
|
struct wl_client *client = wl_resource_get_client (surface->resource);
|
|
|
|
|
|
|
|
grab = meta_wayland_popup_grab_create (pointer, client);
|
|
|
|
meta_wayland_popup_grab_begin (grab, surface);
|
2013-09-11 08:53:48 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
2013-09-10 09:53:31 -04:00
|
|
|
|
2015-02-11 22:13:55 -05:00
|
|
|
return meta_wayland_popup_create (surface, grab);
|
2013-09-10 09:53:31 -04:00
|
|
|
}
|
2013-09-11 08:06:05 -04:00
|
|
|
|
2014-04-17 18:16:49 -04:00
|
|
|
void
|
|
|
|
meta_wayland_pointer_repick (MetaWaylandPointer *pointer)
|
|
|
|
{
|
|
|
|
repick_for_event (pointer, NULL);
|
|
|
|
}
|
|
|
|
|
2013-09-11 08:06:05 -04:00
|
|
|
void
|
|
|
|
meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
|
|
|
MetaWaylandSurface *surface,
|
|
|
|
wl_fixed_t *sx,
|
|
|
|
wl_fixed_t *sy)
|
|
|
|
{
|
|
|
|
float xf = 0.0f, yf = 0.0f;
|
2014-04-27 10:38:16 -04:00
|
|
|
ClutterPoint pos;
|
2013-09-11 08:06:05 -04:00
|
|
|
|
2014-04-27 10:38:16 -04:00
|
|
|
clutter_input_device_get_coords (pointer->device, NULL, &pos);
|
2014-04-26 06:55:54 -04:00
|
|
|
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
2014-04-27 10:38:16 -04:00
|
|
|
pos.x, pos.y, &xf, &yf);
|
2013-09-11 08:06:05 -04:00
|
|
|
|
2014-04-26 04:27:34 -04:00
|
|
|
*sx = wl_fixed_from_double (xf) / surface->scale;
|
|
|
|
*sy = wl_fixed_from_double (yf) / surface->scale;
|
2013-09-11 08:06:05 -04:00
|
|
|
}
|
2014-03-16 15:32:52 -04:00
|
|
|
|
2014-04-17 16:54:30 -04:00
|
|
|
void
|
|
|
|
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
|
|
|
|
{
|
|
|
|
if (pointer->cursor_tracker == NULL)
|
|
|
|
return;
|
|
|
|
|
2014-10-06 18:41:13 -04:00
|
|
|
if (pointer->current)
|
2014-04-17 16:54:30 -04:00
|
|
|
{
|
2014-10-06 18:41:13 -04:00
|
|
|
MetaCursorReference *cursor;
|
2014-04-17 16:54:30 -04:00
|
|
|
|
2014-10-06 18:41:13 -04:00
|
|
|
if (pointer->cursor_surface && pointer->cursor_surface->buffer)
|
|
|
|
{
|
|
|
|
struct wl_resource *buffer = pointer->cursor_surface->buffer->resource;
|
|
|
|
cursor = meta_cursor_reference_from_buffer (buffer,
|
|
|
|
pointer->hotspot_x,
|
|
|
|
pointer->hotspot_y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cursor = NULL;
|
2014-04-17 16:54:30 -04:00
|
|
|
|
2014-10-06 18:41:13 -04:00
|
|
|
meta_cursor_tracker_set_window_cursor (pointer->cursor_tracker, cursor);
|
|
|
|
|
|
|
|
if (cursor)
|
|
|
|
meta_cursor_reference_unref (cursor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_cursor_tracker_unset_window_cursor (pointer->cursor_tracker);
|
|
|
|
}
|
2014-04-17 16:54:30 -04:00
|
|
|
}
|
2014-04-17 17:00:59 -04:00
|
|
|
|
2014-04-17 17:16:17 -04:00
|
|
|
static void
|
2014-04-17 18:16:49 -04:00
|
|
|
pointer_set_cursor (struct wl_client *client,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t serial,
|
|
|
|
struct wl_resource *surface_resource,
|
|
|
|
int32_t x, int32_t y)
|
|
|
|
{
|
|
|
|
MetaWaylandPointer *pointer = wl_resource_get_user_data (resource);
|
|
|
|
MetaWaylandSurface *surface;
|
|
|
|
|
|
|
|
surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
|
|
|
|
|
|
|
|
if (pointer->focus_surface == NULL)
|
|
|
|
return;
|
|
|
|
if (wl_resource_get_client (pointer->focus_surface->resource) != client)
|
|
|
|
return;
|
|
|
|
if (pointer->focus_serial - serial > G_MAXUINT32 / 2)
|
|
|
|
return;
|
|
|
|
|
2015-02-06 03:12:21 -05:00
|
|
|
if (surface)
|
|
|
|
{
|
|
|
|
if (meta_wayland_surface_set_role (surface,
|
|
|
|
META_WAYLAND_SURFACE_ROLE_CURSOR,
|
|
|
|
resource,
|
|
|
|
WL_POINTER_ERROR_ROLE) != 0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-17 18:16:49 -04:00
|
|
|
pointer->hotspot_x = x;
|
|
|
|
pointer->hotspot_y = y;
|
|
|
|
set_cursor_surface (pointer, surface);
|
|
|
|
meta_wayland_pointer_update_cursor_surface (pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-04-17 17:16:17 -04:00
|
|
|
pointer_release (struct wl_client *client,
|
|
|
|
struct wl_resource *resource)
|
|
|
|
{
|
|
|
|
wl_resource_destroy (resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wl_pointer_interface pointer_interface = {
|
|
|
|
pointer_set_cursor,
|
|
|
|
pointer_release,
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer,
|
|
|
|
struct wl_client *client,
|
|
|
|
struct wl_resource *seat_resource,
|
|
|
|
uint32_t id)
|
|
|
|
{
|
|
|
|
struct wl_resource *cr;
|
2015-08-09 09:24:16 -04:00
|
|
|
MetaWaylandPointerClient *pointer_client;
|
2014-04-17 17:16:17 -04:00
|
|
|
|
2014-08-04 10:22:23 -04:00
|
|
|
cr = wl_resource_create (client, &wl_pointer_interface, wl_resource_get_version (seat_resource), id);
|
2015-08-09 09:24:16 -04:00
|
|
|
wl_resource_set_implementation (cr, &pointer_interface, pointer,
|
|
|
|
meta_wayland_pointer_unbind_pointer_client_resource);
|
2014-04-17 17:16:17 -04:00
|
|
|
|
2015-08-09 09:24:16 -04:00
|
|
|
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);
|
2014-04-17 17:00:59 -04:00
|
|
|
}
|
2014-05-22 10:57:02 -04:00
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer,
|
|
|
|
MetaWaylandSurface *surface,
|
|
|
|
uint32_t serial)
|
|
|
|
{
|
2014-06-26 07:36:46 -04:00
|
|
|
return (pointer->button_count > 0 &&
|
2014-05-22 10:57:02 -04:00
|
|
|
pointer->grab_serial == serial &&
|
|
|
|
pointer->focus_surface == surface);
|
|
|
|
}
|
2015-02-10 08:11:17 -05:00
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer, uint32_t serial)
|
|
|
|
{
|
|
|
|
return pointer->grab_serial == serial;
|
|
|
|
}
|
2015-02-11 22:20:52 -05:00
|
|
|
|
|
|
|
MetaWaylandSurface *
|
|
|
|
meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer)
|
|
|
|
{
|
|
|
|
MetaWaylandPopupGrab *grab;
|
|
|
|
|
|
|
|
if (!meta_wayland_pointer_grab_is_popup_grab (pointer->grab))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
|
|
|
return meta_wayland_popup_grab_get_top_popup(grab);
|
|
|
|
}
|