diff options
author | Florian Müllner <fmuellner@gnome.org> | 2021-07-19 00:01:24 +0200 |
---|---|---|
committer | Florian Müllner <fmuellner@gnome.org> | 2021-07-19 00:03:33 +0200 |
commit | 952865a86ebb08f97263cfdbfe38b7adc20e4560 (patch) | |
tree | 1f9347628656210b03ceee4fae83beb21491d1eb /src/wayland/meta-wayland-pointer.c | |
parent | 7862f143937e43dca0513af3a24dabfb4d0db4fc (diff) | |
download | mutter-master.tar.gz |
Replace contents with redirect messagemaster
The default development branch is now `main`. This commit only exists
on `master` to point people towards that.
See https://gitlab.gnome.org/GNOME/glib/-/issues/2348 for details.
Diffstat (limited to 'src/wayland/meta-wayland-pointer.c')
-rw-r--r-- | src/wayland/meta-wayland-pointer.c | 1370 |
1 files changed, 0 insertions, 1370 deletions
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c deleted file mode 100644 index 3132abfd2..000000000 --- a/src/wayland/meta-wayland-pointer.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * 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" - -#include <linux/input.h> -#include <string.h> - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-renderer.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-cursor.h" -#include "clutter/clutter.h" -#include "cogl/cogl-wayland-server.h" -#include "cogl/cogl.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "meta/meta-cursor-tracker.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-cursor-surface.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-popup.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-xwayland.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -#include "relative-pointer-unstable-v1-server-protocol.h" - -#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10) - -enum -{ - FOCUS_SURFACE_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE (MetaWaylandPointer, meta_wayland_pointer, - META_TYPE_WAYLAND_INPUT_DEVICE) - -static void -meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface); - -static void -meta_wayland_pointer_reset_grab (MetaWaylandPointer *pointer); - -static void -meta_wayland_pointer_cancel_grab (MetaWaylandPointer *pointer); - -static MetaWaylandPointerClient * -meta_wayland_pointer_client_new (void) -{ - MetaWaylandPointerClient *pointer_client; - - pointer_client = g_new0 (MetaWaylandPointerClient, 1); - wl_list_init (&pointer_client->pointer_resources); - wl_list_init (&pointer_client->swipe_gesture_resources); - wl_list_init (&pointer_client->pinch_gesture_resources); - wl_list_init (&pointer_client->relative_pointer_resources); - - return pointer_client; -} - -static void -meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client) -{ - struct wl_resource *resource, *next; - - /* 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_safe (resource, next, &pointer_client->pointer_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - wl_resource_for_each_safe (resource, next, &pointer_client->swipe_gesture_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - wl_resource_for_each_safe (resource, next, &pointer_client->pinch_gesture_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - wl_resource_for_each_safe (resource, next, &pointer_client->relative_pointer_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - - g_free (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) && - wl_list_empty (&pointer_client->relative_pointer_resources)); -} - -MetaWaylandPointerClient * -meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer, - struct wl_client *client) -{ - if (!pointer->pointer_clients) - return NULL; - 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); - - pointer = wl_resource_get_user_data (resource); - if (!pointer) - return; - - 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 -sync_focus_surface (MetaWaylandPointer *pointer) -{ - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) && - !clutter_seat_is_unfocus_inhibited (clutter_seat)) - { - meta_wayland_pointer_set_focus (pointer, NULL); - return; - } - - switch (display->event_route) - { - case META_EVENT_ROUTE_WINDOW_OP: - case META_EVENT_ROUTE_COMPOSITOR_GRAB: - case META_EVENT_ROUTE_FRAME_BUTTON: - /* 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 (); - } - -} - -static void -meta_wayland_pointer_send_frame (MetaWaylandPointer *pointer, - struct wl_resource *resource) -{ - if (wl_resource_get_version (resource) >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) - wl_pointer_send_frame (resource); -} - -void -meta_wayland_pointer_broadcast_frame (MetaWaylandPointer *pointer) -{ - struct wl_resource *resource; - - if (!pointer->focus_client) - return; - - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - meta_wayland_pointer_send_frame (pointer, resource); - } -} - -void -meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - double dx, dy; - double dx_unaccel, dy_unaccel; - uint64_t time_us; - uint32_t time_us_hi; - uint32_t time_us_lo; - wl_fixed_t dxf, dyf; - wl_fixed_t dx_unaccelf, dy_unaccelf; - - if (!pointer->focus_client) - return; - - if (!clutter_event_get_relative_motion (event, - &dx, &dy, - &dx_unaccel, &dy_unaccel)) - return; - - time_us = clutter_event_get_time_us (event); - if (time_us == 0) - time_us = clutter_event_get_time (event) * 1000ULL; - time_us_hi = (uint32_t) (time_us >> 32); - time_us_lo = (uint32_t) time_us; - dxf = wl_fixed_from_double (dx); - dyf = wl_fixed_from_double (dy); - dx_unaccelf = wl_fixed_from_double (dx_unaccel); - dy_unaccelf = wl_fixed_from_double (dy_unaccel); - - wl_resource_for_each (resource, - &pointer->focus_client->relative_pointer_resources) - { - zwp_relative_pointer_v1_send_relative_motion (resource, - time_us_hi, - time_us_lo, - dxf, - dyf, - dx_unaccelf, - dy_unaccelf); - } -} - -void -meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - uint32_t time; - float sx, sy; - - if (!pointer->focus_client) - return; - - time = clutter_event_get_time (event); - meta_wayland_surface_get_relative_coordinates (pointer->focus_surface, - event->motion.x, - event->motion.y, - &sx, &sy); - - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - wl_pointer_send_motion (resource, time, - wl_fixed_from_double (sx), - wl_fixed_from_double (sy)); - } - - meta_wayland_pointer_send_relative_motion (pointer, event); - - meta_wayland_pointer_broadcast_frame (pointer); -} - -void -meta_wayland_pointer_send_button (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - ClutterEventType event_type; - - event_type = clutter_event_type (event); - - if (pointer->focus_client && - !wl_list_empty (&pointer->focus_client->pointer_resources)) - { - MetaWaylandInputDevice *input_device = - META_WAYLAND_INPUT_DEVICE (pointer); - uint32_t time; - uint32_t button; - uint32_t serial; - - button = clutter_event_get_event_code (event); - time = clutter_event_get_time (event); - serial = meta_wayland_input_device_next_serial (input_device); - - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - wl_pointer_send_button (resource, serial, - time, button, - event_type == CLUTTER_BUTTON_PRESS ? 1 : 0); - } - - meta_wayland_pointer_broadcast_frame (pointer); - } - - if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE) - sync_focus_surface (pointer); -} - -static void -default_grab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ - MetaWaylandPointer *pointer = grab->pointer; - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - if (!meta_wayland_seat_has_pointer (seat)) - return; - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) && - !clutter_seat_is_unfocus_inhibited (clutter_seat)) - return; - - if (pointer->button_count > 0) - return; - - switch (display->event_route) - { - case META_EVENT_ROUTE_WINDOW_OP: - case META_EVENT_ROUTE_COMPOSITOR_GRAB: - case META_EVENT_ROUTE_FRAME_BUTTON: - return; - break; - - case META_EVENT_ROUTE_NORMAL: - case META_EVENT_ROUTE_WAYLAND_POPUP: - break; - } - - 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); -} - -static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = { - default_grab_focus, - default_grab_motion, - default_grab_button -}; - -static void -meta_wayland_pointer_on_cursor_changed (MetaCursorTracker *cursor_tracker, - MetaWaylandPointer *pointer) -{ - if (pointer->cursor_surface) - meta_wayland_surface_update_outputs (pointer->cursor_surface); -} - -void -meta_wayland_pointer_enable (MetaWaylandPointer *pointer) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterSeat *clutter_seat; - - pointer->pointer_clients = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_wayland_pointer_client_free); - - pointer->cursor_surface = NULL; - - clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - pointer->device = clutter_seat_get_pointer (clutter_seat); - - g_signal_connect (cursor_tracker, - "cursor-changed", - G_CALLBACK (meta_wayland_pointer_on_cursor_changed), - pointer); - - g_signal_connect_swapped (cursor_tracker, - "visibility-changed", - G_CALLBACK (sync_focus_surface), - pointer); - - g_signal_connect_swapped (clutter_seat, - "is-unfocus-inhibited-changed", - G_CALLBACK (sync_focus_surface), - pointer); -} - -void -meta_wayland_pointer_disable (MetaWaylandPointer *pointer) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - g_signal_handlers_disconnect_by_func (cursor_tracker, - (gpointer) meta_wayland_pointer_on_cursor_changed, - pointer); - - g_signal_handlers_disconnect_by_func (cursor_tracker, - sync_focus_surface, - pointer); - - g_signal_handlers_disconnect_by_func (clutter_seat, - sync_focus_surface, - pointer); - - if (pointer->cursor_surface) - { - g_clear_signal_handler (&pointer->cursor_surface_destroy_id, - pointer->cursor_surface); - } - - meta_wayland_pointer_cancel_grab (pointer); - meta_wayland_pointer_reset_grab (pointer); - meta_wayland_pointer_set_focus (pointer, NULL); - meta_wayland_pointer_set_current (pointer, NULL); - - g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref); - pointer->cursor_surface = NULL; -} - -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; -} - -static void -current_surface_destroyed (MetaWaylandSurface *surface, - MetaWaylandPointer *pointer) -{ - meta_wayland_pointer_set_current (pointer, NULL); -} - -static void -meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - if (pointer->current) - { - g_clear_signal_handler (&pointer->current_surface_destroyed_handler_id, - pointer->current); - pointer->current = NULL; - } - - if (surface) - { - pointer->current = surface; - pointer->current_surface_destroyed_handler_id = - g_signal_connect (surface, "destroy", - G_CALLBACK (current_surface_destroyed), - pointer); - } -} - -static void -repick_for_event (MetaWaylandPointer *pointer, - const ClutterEvent *for_event) -{ - ClutterActor *actor; - MetaWaylandSurface *surface; - - if (clutter_event_type (for_event) == CLUTTER_LEAVE) - actor = clutter_event_get_related (for_event); - else - actor = clutter_event_get_source (for_event); - - if (META_IS_SURFACE_ACTOR_WAYLAND (actor)) - { - MetaSurfaceActorWayland *actor_wayland = - META_SURFACE_ACTOR_WAYLAND (actor); - - surface = meta_surface_actor_wayland_get_surface (actor_wayland); - } - else - { - surface = NULL; - } - - meta_wayland_pointer_set_current (pointer, surface); - - sync_focus_surface (pointer); - meta_wayland_pointer_update_cursor_surface (pointer); -} - -void -meta_wayland_pointer_update (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - if ((event->type == CLUTTER_MOTION || - event->type == CLUTTER_ENTER || - event->type == CLUTTER_LEAVE) && - !clutter_event_get_event_sequence (event)) - repick_for_event (pointer, event); - - if (event->type == CLUTTER_MOTION || - event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_BUTTON_RELEASE) - { - pointer->button_count = count_buttons (event); - } -} - -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); - clutter_event_get_coords (event, &pointer->grab_x, &pointer->grab_y); - } - - pointer->grab->interface->button (pointer->grab, event); - - if (implicit_grab) - { - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - - pointer->grab_serial = wl_display_get_serial (seat->wl_display); - } -} - -static void -handle_scroll_event (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - wl_fixed_t x_value = 0, y_value = 0; - int x_discrete = 0, y_discrete = 0; - enum wl_pointer_axis_source source = -1; - - if (clutter_event_is_pointer_emulated (event)) - return; - - switch (event->scroll.scroll_source) - { - case CLUTTER_SCROLL_SOURCE_WHEEL: - source = WL_POINTER_AXIS_SOURCE_WHEEL; - break; - case CLUTTER_SCROLL_SOURCE_FINGER: - source = WL_POINTER_AXIS_SOURCE_FINGER; - break; - case CLUTTER_SCROLL_SOURCE_CONTINUOUS: - source = WL_POINTER_AXIS_SOURCE_CONTINUOUS; - break; - default: - source = WL_POINTER_AXIS_SOURCE_WHEEL; - break; - } - - switch (clutter_event_get_scroll_direction (event)) - { - case CLUTTER_SCROLL_UP: - y_value = -DEFAULT_AXIS_STEP_DISTANCE; - y_discrete = -1; - break; - - case CLUTTER_SCROLL_DOWN: - y_value = DEFAULT_AXIS_STEP_DISTANCE; - y_discrete = 1; - break; - - case CLUTTER_SCROLL_LEFT: - x_value = -DEFAULT_AXIS_STEP_DISTANCE; - x_discrete = -1; - break; - - case CLUTTER_SCROLL_RIGHT: - x_value = DEFAULT_AXIS_STEP_DISTANCE; - x_discrete = 1; - break; - - case CLUTTER_SCROLL_SMOOTH: - { - double dx, dy; - /* 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; - clutter_event_get_scroll_delta (event, &dx, &dy); - x_value = wl_fixed_from_double (dx) * factor; - y_value = wl_fixed_from_double (dy) * factor; - } - break; - - default: - return; - } - - if (pointer->focus_client) - { - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - if (wl_resource_get_version (resource) >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) - wl_pointer_send_axis_source (resource, source); - - /* X axis */ - if (x_discrete != 0 && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) - wl_pointer_send_axis_discrete (resource, - WL_POINTER_AXIS_HORIZONTAL_SCROLL, - x_discrete); - - if (x_value) - wl_pointer_send_axis (resource, clutter_event_get_time (event), - WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value); - - if ((event->scroll.finish_flags & CLUTTER_SCROLL_FINISHED_HORIZONTAL) && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_STOP_SINCE_VERSION) - wl_pointer_send_axis_stop (resource, - clutter_event_get_time (event), - WL_POINTER_AXIS_HORIZONTAL_SCROLL); - /* Y axis */ - if (y_discrete != 0 && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) - wl_pointer_send_axis_discrete (resource, - WL_POINTER_AXIS_VERTICAL_SCROLL, - y_discrete); - - if (y_value) - wl_pointer_send_axis (resource, clutter_event_get_time (event), - WL_POINTER_AXIS_VERTICAL_SCROLL, y_value); - - if ((event->scroll.finish_flags & CLUTTER_SCROLL_FINISHED_VERTICAL) && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_STOP_SINCE_VERSION) - wl_pointer_send_axis_stop (resource, - clutter_event_get_time (event), - WL_POINTER_AXIS_VERTICAL_SCROLL); - } - - meta_wayland_pointer_broadcast_frame (pointer); - } -} - -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; - - 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; - } - - return FALSE; -} - -static void -meta_wayland_pointer_send_enter (MetaWaylandPointer *pointer, - struct wl_resource *pointer_resource, - uint32_t serial, - MetaWaylandSurface *surface) -{ - wl_fixed_t sx, sy; - - meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy); - wl_pointer_send_enter (pointer_resource, - serial, - surface->resource, - sx, sy); -} - -static void -meta_wayland_pointer_send_leave (MetaWaylandPointer *pointer, - struct wl_resource *pointer_resource, - uint32_t serial, - MetaWaylandSurface *surface) -{ - wl_pointer_send_leave (pointer_resource, serial, surface->resource); -} - -static void -meta_wayland_pointer_broadcast_enter (MetaWaylandPointer *pointer, - uint32_t serial, - MetaWaylandSurface *surface) -{ - struct wl_resource *pointer_resource; - - wl_resource_for_each (pointer_resource, - &pointer->focus_client->pointer_resources) - meta_wayland_pointer_send_enter (pointer, pointer_resource, - serial, surface); - - meta_wayland_pointer_broadcast_frame (pointer); -} - -static void -meta_wayland_pointer_broadcast_leave (MetaWaylandPointer *pointer, - uint32_t serial, - MetaWaylandSurface *surface) -{ - struct wl_resource *pointer_resource; - - wl_resource_for_each (pointer_resource, - &pointer->focus_client->pointer_resources) - meta_wayland_pointer_send_leave (pointer, pointer_resource, - serial, surface); - - meta_wayland_pointer_broadcast_frame (pointer); -} - -static void -focus_surface_destroyed (MetaWaylandSurface *surface, - MetaWaylandPointer *pointer) -{ - meta_wayland_pointer_set_focus (pointer, NULL); -} - -void -meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (pointer); - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - g_return_if_fail (meta_cursor_tracker_get_pointer_visible (cursor_tracker) || - clutter_seat_is_unfocus_inhibited (clutter_seat) || - surface == NULL); - - if (pointer->focus_surface == surface) - return; - - if (pointer->focus_surface != NULL) - { - uint32_t serial; - - serial = meta_wayland_input_device_next_serial (input_device); - - if (pointer->focus_client) - { - meta_wayland_pointer_broadcast_leave (pointer, - serial, - pointer->focus_surface); - pointer->focus_client = NULL; - } - - g_clear_signal_handler (&pointer->focus_surface_destroyed_handler_id, - pointer->focus_surface); - pointer->focus_surface = NULL; - } - - if (surface != NULL) - { - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - struct wl_client *client = wl_resource_get_client (surface->resource); - graphene_point_t pos; - MetaWindow *focus_window; - - pointer->focus_surface = surface; - - pointer->focus_surface_destroyed_handler_id = - g_signal_connect_after (pointer->focus_surface, "destroy", - G_CALLBACK (focus_surface_destroyed), - pointer); - - clutter_stage_get_device_coords (stage, pointer->device, NULL, &pos); - - focus_window = meta_wayland_surface_get_window (pointer->focus_surface); - if (focus_window) - meta_window_handle_enter (focus_window, - /* XXX -- can we reliably get a timestamp for setting focus? */ - clutter_get_current_event_time (), - pos.x, pos.y); - - pointer->focus_client = - meta_wayland_pointer_get_pointer_client (pointer, client); - if (pointer->focus_client) - { - pointer->focus_serial = - meta_wayland_input_device_next_serial (input_device); - meta_wayland_pointer_broadcast_enter (pointer, - pointer->focus_serial, - pointer->focus_surface); - } - } - - meta_wayland_pointer_update_cursor_surface (pointer); - - g_signal_emit (pointer, signals[FOCUS_SURFACE_CHANGED], 0); -} - -void -meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer, - MetaWaylandPointerGrab *grab) -{ - const MetaWaylandPointerGrabInterface *interface; - - meta_wayland_pointer_cancel_grab (pointer); - - pointer->grab = grab; - interface = pointer->grab->interface; - grab->pointer = pointer; - - interface->focus (pointer->grab, pointer->current); -} - -static void -meta_wayland_pointer_reset_grab (MetaWaylandPointer *pointer) -{ - pointer->grab = &pointer->default_grab; -} - -void -meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer) -{ - const MetaWaylandPointerGrabInterface *interface; - - pointer->grab = &pointer->default_grab; - interface = pointer->grab->interface; - interface->focus (pointer->grab, pointer->current); - - meta_wayland_pointer_update_cursor_surface (pointer); -} - -static void -meta_wayland_pointer_cancel_grab (MetaWaylandPointer *pointer) -{ - if (pointer->grab->interface->cancel) - pointer->grab->interface->cancel (pointer->grab); -} - -void -meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer) -{ - MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)pointer->grab; - - meta_wayland_popup_grab_destroy (popup_grab); -} - -MetaWaylandPopup * -meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, - MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandPopupGrab *grab; - - if (pointer->grab != &pointer->default_grab && - !meta_wayland_pointer_grab_is_popup_grab (pointer->grab)) - return NULL; - - if (pointer->grab == &pointer->default_grab) - grab = meta_wayland_popup_grab_create (pointer, popup_surface); - else - grab = (MetaWaylandPopupGrab*)pointer->grab; - - return meta_wayland_popup_create (popup_surface, grab); -} - -void -meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface, - wl_fixed_t *sx, - wl_fixed_t *sy) -{ - MetaBackend *backend = meta_get_backend (); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - float xf = 0.0f, yf = 0.0f; - graphene_point_t pos; - - clutter_stage_get_device_coords (stage, pointer->device, NULL, &pos); - meta_wayland_surface_get_relative_coordinates (surface, pos.x, pos.y, &xf, &yf); - - *sx = wl_fixed_from_double (xf); - *sy = wl_fixed_from_double (yf); -} - -void -meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - - if (pointer->current) - { - MetaCursorSprite *cursor_sprite = NULL; - - if (pointer->cursor_surface) - { - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (pointer->cursor_surface->role); - - cursor_sprite = meta_wayland_cursor_surface_get_sprite (cursor_surface); - } - - meta_cursor_tracker_set_window_cursor (cursor_tracker, cursor_sprite); - } - else - { - meta_cursor_tracker_unset_window_cursor (cursor_tracker); - } -} - -static void -ensure_update_cursor_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - if (pointer->cursor_surface != surface) - return; - - pointer->cursor_surface = NULL; - meta_wayland_pointer_update_cursor_surface (pointer); -} - -static void -meta_wayland_pointer_set_cursor_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *cursor_surface) -{ - MetaWaylandSurface *prev_cursor_surface; - - prev_cursor_surface = pointer->cursor_surface; - - if (prev_cursor_surface == cursor_surface) - return; - - pointer->cursor_surface = cursor_surface; - - if (prev_cursor_surface) - { - meta_wayland_surface_update_outputs (prev_cursor_surface); - g_clear_signal_handler (&pointer->cursor_surface_destroy_id, - prev_cursor_surface); - } - - if (cursor_surface) - { - pointer->cursor_surface_destroy_id = - g_signal_connect_swapped (cursor_surface, "destroy", - G_CALLBACK (ensure_update_cursor_surface), - pointer); - } - - meta_wayland_pointer_update_cursor_surface (pointer); -} - -static void -pointer_set_cursor (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - struct wl_resource *surface_resource, - int32_t hot_x, int32_t hot_y) -{ - MetaWaylandPointer *pointer; - MetaWaylandSurface *surface; - - pointer = wl_resource_get_user_data (resource); - if (!pointer) - return; - - 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; - - if (surface && - !meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_CURSOR_SURFACE, - NULL)) - { - wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface_resource)); - return; - } - - if (surface) - { - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = - clutter_backend_get_default_seat (clutter_backend); - ClutterInputDevice *device = clutter_seat_get_pointer (clutter_seat); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer_for_device (meta_get_backend (), - device); - MetaWaylandCursorSurface *cursor_surface; - - cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); - meta_wayland_cursor_surface_set_renderer (cursor_surface, - cursor_renderer); - meta_wayland_cursor_surface_set_hotspot (cursor_surface, - hot_x, hot_y); - } - - meta_wayland_pointer_set_cursor_surface (pointer, surface); -} - -static void -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 *resource; - MetaWaylandPointerClient *pointer_client; - - resource = wl_resource_create (client, &wl_pointer_interface, - wl_resource_get_version (seat_resource), id); - wl_resource_set_implementation (resource, &pointer_interface, pointer, - meta_wayland_pointer_unbind_pointer_client_resource); - - pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client); - - wl_list_insert (&pointer_client->pointer_resources, - wl_resource_get_link (resource)); - - if (pointer->focus_client == pointer_client) - { - meta_wayland_pointer_send_enter (pointer, resource, - pointer->focus_serial, - pointer->focus_surface); - meta_wayland_pointer_send_frame (pointer, resource); - } -} - -static gboolean -pointer_can_grab_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - MetaWaylandSurface *subsurface; - - if (pointer->focus_surface == surface) - return TRUE; - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface) - { - if (pointer_can_grab_surface (pointer, subsurface)) - return TRUE; - } - - return FALSE; -} - -gboolean -meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface, - uint32_t serial) -{ - return (pointer->grab_serial == serial && - pointer_can_grab_surface (pointer, surface)); -} - -gboolean -meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer, uint32_t serial) -{ - return pointer->grab_serial == serial; -} - -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); -} - -static void -relative_pointer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = { - relative_pointer_destroy -}; - -static void -relative_pointer_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -relative_pointer_manager_get_relative_pointer (struct wl_client *client, - struct wl_resource *manager_resource, - uint32_t id, - struct wl_resource *pointer_resource) -{ - MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); - struct wl_resource *resource; - MetaWaylandPointerClient *pointer_client; - - resource = wl_resource_create (client, &zwp_relative_pointer_v1_interface, - wl_resource_get_version (manager_resource), - id); - if (!resource) - { - wl_client_post_no_memory (client); - return; - } - - wl_resource_set_implementation (resource, &relative_pointer_interface, - pointer, - meta_wayland_pointer_unbind_pointer_client_resource); - - pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client); - - wl_list_insert (&pointer_client->relative_pointer_resources, - wl_resource_get_link (resource)); -} - -static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = { - relative_pointer_manager_destroy, - relative_pointer_manager_get_relative_pointer, -}; - -static void -bind_relative_pointer_manager (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandCompositor *compositor = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zwp_relative_pointer_manager_v1_interface, - 1, id); - - if (version != 1) - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "bound invalid version %u of " - "wp_relative_pointer_manager", - version); - - wl_resource_set_implementation (resource, &relative_pointer_manager, - compositor, - NULL); -} - -void -meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor) -{ - /* Relative pointer events are currently only supported by the native backend - * so lets just advertise the extension when the native backend is used. - */ -#ifdef HAVE_NATIVE_BACKEND - if (!META_IS_BACKEND_NATIVE (meta_get_backend ())) - return; -#else - return; -#endif - - if (!wl_global_create (compositor->wayland_display, - &zwp_relative_pointer_manager_v1_interface, 1, - compositor, bind_relative_pointer_manager)) - g_error ("Could not create relative pointer manager global"); -} - -MetaWaylandSeat * -meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (pointer); - - return meta_wayland_input_device_get_seat (input_device); -} - -static void -meta_wayland_pointer_init (MetaWaylandPointer *pointer) -{ - pointer->default_grab.interface = &default_pointer_grab_interface; - pointer->default_grab.pointer = pointer; - pointer->grab = &pointer->default_grab; -} - -static void -meta_wayland_pointer_class_init (MetaWaylandPointerClass *klass) -{ - signals[FOCUS_SURFACE_CHANGED] = g_signal_new ("focus-surface-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} |