From 768286bffb925759fba610d7d01354ce083242f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 11 Feb 2015 17:34:15 +0800 Subject: [PATCH] wayland: Move out popup logic to its own file We'll want to expose popup logic outside of meta-wayland-pointer.c and one day we'll also probably want to add touch support for popups, so lets move it to its own file. There are no significant semantical changes, only refactoring. https://bugzilla.gnome.org/show_bug.cgi?id=744452 --- src/Makefile.am | 2 + src/wayland/meta-wayland-pointer.c | 206 ++++++------------------- src/wayland/meta-wayland-pointer.h | 8 + src/wayland/meta-wayland-popup.c | 238 +++++++++++++++++++++++++++++ src/wayland/meta-wayland-popup.h | 49 ++++++ src/wayland/meta-wayland-surface.c | 1 + src/wayland/meta-wayland-types.h | 2 + 7 files changed, 350 insertions(+), 156 deletions(-) create mode 100644 src/wayland/meta-wayland-popup.c create mode 100644 src/wayland/meta-wayland-popup.h diff --git a/src/Makefile.am b/src/Makefile.am index 20ed3e28a..baadb4110 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -253,6 +253,8 @@ libmutter_la_SOURCES += \ wayland/meta-wayland-keyboard.h \ wayland/meta-wayland-pointer.c \ wayland/meta-wayland-pointer.h \ + wayland/meta-wayland-popup.c \ + wayland/meta-wayland-popup.h \ wayland/meta-wayland-seat.c \ wayland/meta-wayland-seat.h \ wayland/meta-wayland-touch.c \ diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index fcb77958e..b9d7f664f 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -47,6 +47,7 @@ #include #include "meta-wayland-pointer.h" +#include "meta-wayland-popup.h" #include "meta-wayland-private.h" #include "meta-wayland-buffer.h" #include "meta-cursor.h" @@ -57,8 +58,6 @@ #define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10) -static void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer); - static void unbind_resource (struct wl_resource *resource) { @@ -127,23 +126,10 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data) meta_wayland_pointer_set_focus (pointer, NULL); } -static void -default_grab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) +void +meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer, + const ClutterEvent *event) { - 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; struct wl_resource *resource; struct wl_list *l; @@ -159,18 +145,17 @@ default_grab_motion (MetaWaylandPointerGrab *grab, } } -static void -default_grab_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) +void +meta_wayland_pointer_send_button (MetaWaylandPointer *pointer, + const ClutterEvent *event) { - MetaWaylandPointer *pointer = grab->pointer; struct wl_resource *resource; struct wl_list *l; ClutterEventType event_type; event_type = clutter_event_type (event); - l = &grab->pointer->focus_resource_list; + l = &pointer->focus_resource_list; if (!wl_list_empty (l)) { struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource); @@ -210,6 +195,36 @@ default_grab_button (MetaWaylandPointerGrab *grab, sync_focus_surface (pointer); } +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); +} + static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = { default_grab_focus, default_grab_motion, @@ -557,102 +572,13 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer) meta_wayland_pointer_update_cursor_surface (pointer); } -typedef struct { - MetaWaylandPointerGrab generic; - - struct wl_client *grab_client; - struct wl_list all_popups; -} MetaWaylandPopupGrab; - -typedef struct { - MetaWaylandPopupGrab *grab; - MetaWaylandSurface *surface; - struct wl_listener surface_destroy_listener; - - struct wl_list link; -} MetaWaylandPopup; - -static void -popup_grab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ - MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab; - - /* Popup grabs are in owner-events mode (ie, events for the same client - are reported as normal) */ - if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client) - meta_wayland_pointer_set_focus (grab->pointer, surface); - else - meta_wayland_pointer_set_focus (grab->pointer, NULL); -} - -static void -popup_grab_motion (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - default_grab_motion (grab, event); -} - -static void -popup_grab_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandPointer *pointer = grab->pointer; - - if (pointer->focus_surface) - default_grab_button (grab, event); - else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE && - pointer->button_count == 0) - meta_wayland_pointer_end_popup_grab (grab->pointer); -} - -static MetaWaylandPointerGrabInterface popup_grab_interface = { - popup_grab_focus, - popup_grab_motion, - popup_grab_button -}; - -static void +void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer) { - MetaWaylandPopupGrab *popup_grab; - MetaWaylandPopup *popup, *tmp; + MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)pointer->grab; - popup_grab = (MetaWaylandPopupGrab*)pointer->grab; - - g_assert (popup_grab->generic.interface == &popup_grab_interface); - - wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link) - { - meta_wayland_surface_popup_done (popup->surface); - wl_list_remove (&popup->surface_destroy_listener.link); - wl_list_remove (&popup->link); - g_slice_free (MetaWaylandPopup, popup); - } - - { - MetaDisplay *display = meta_get_display (); - meta_display_end_grab_op (display, - meta_display_get_current_time_roundtrip (display)); - } - - meta_wayland_pointer_end_grab (pointer); - g_slice_free (MetaWaylandPopupGrab, popup_grab); -} - -static void -on_popup_surface_destroy (struct wl_listener *listener, - void *data) -{ - MetaWaylandPopup *popup = - wl_container_of (listener, popup, surface_destroy_listener); - MetaWaylandPopupGrab *popup_grab = popup->grab; - - wl_list_remove (&popup->link); - g_slice_free (MetaWaylandPopup, popup); - - if (wl_list_empty (&popup_grab->all_popups)) - meta_wayland_pointer_end_popup_grab (popup_grab->generic.pointer); + meta_wayland_popup_grab_end (popup_grab); + meta_wayland_popup_grab_destroy (popup_grab); } gboolean @@ -660,56 +586,24 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, MetaWaylandSurface *surface) { MetaWaylandPopupGrab *grab; - MetaWaylandPopup *popup; - if (pointer->grab != &pointer->default_grab) - { - if (pointer->grab->interface != &popup_grab_interface) - return FALSE; - - grab = (MetaWaylandPopupGrab*)pointer->grab; - - if (wl_resource_get_client (surface->resource) != grab->grab_client) - return FALSE; - } + if (pointer->grab != &pointer->default_grab && + !meta_wayland_pointer_grab_is_popup_grab (pointer->grab)) + return FALSE; if (pointer->grab == &pointer->default_grab) { - MetaWindow *window = surface->window; + struct wl_client *client = wl_resource_get_client (surface->resource); - grab = g_slice_new0 (MetaWaylandPopupGrab); - grab->generic.interface = &popup_grab_interface; - grab->generic.pointer = pointer; - grab->grab_client = wl_resource_get_client (surface->resource); - wl_list_init (&grab->all_popups); - - meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab); - - meta_display_begin_grab_op (window->display, - window->screen, - window, - META_GRAB_OP_WAYLAND_POPUP, - FALSE, /* pointer_already_grabbed */ - FALSE, /* frame_action */ - 1, /* button. XXX? */ - 0, /* modmask */ - meta_display_get_current_time_roundtrip (window->display), - pointer->grab_x, - pointer->grab_y); + grab = meta_wayland_popup_grab_create (pointer, client); + meta_wayland_popup_grab_begin (grab, surface); } else grab = (MetaWaylandPopupGrab*)pointer->grab; - popup = g_slice_new0 (MetaWaylandPopup); - popup->grab = grab; - popup->surface = surface; - popup->surface_destroy_listener.notify = on_popup_surface_destroy; - if (surface->xdg_popup) - wl_resource_add_destroy_listener (surface->xdg_popup, &popup->surface_destroy_listener); - else if (surface->wl_shell_surface) - wl_resource_add_destroy_listener (surface->wl_shell_surface, &popup->surface_destroy_listener); + if (meta_wayland_popup_create (surface, grab) == NULL) + return FALSE; - wl_list_insert (&grab->all_popups, &popup->link); return TRUE; } diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h index de5d8152f..5dadd5fa3 100644 --- a/src/wayland/meta-wayland-pointer.h +++ b/src/wayland/meta-wayland-pointer.h @@ -85,6 +85,12 @@ void meta_wayland_pointer_update (MetaWaylandPointer *pointer, gboolean meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer, const ClutterEvent *event); +void meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer, + const ClutterEvent *event); + +void meta_wayland_pointer_send_button (MetaWaylandPointer *pointer, + const ClutterEvent *event); + void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, MetaWaylandSurface *surface); @@ -96,6 +102,8 @@ void meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer); gboolean meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, MetaWaylandSurface *popup); +void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer); + void meta_wayland_pointer_repick (MetaWaylandPointer *pointer); void meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer, diff --git a/src/wayland/meta-wayland-popup.c b/src/wayland/meta-wayland-popup.c new file mode 100644 index 000000000..9a70ce3a2 --- /dev/null +++ b/src/wayland/meta-wayland-popup.c @@ -0,0 +1,238 @@ +/* + * Wayland Support + * + * Copyright (C) 2013 Intel Corporation + * Copyright (C) 2015 Red Hat, Inc. + * + * 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 . + */ + +/* + * 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. + */ + +#include "config.h" + +#include "meta-wayland-popup.h" + +#include "meta-wayland-pointer.h" +#include "meta-wayland-private.h" +#include "meta-wayland-surface.h" + +struct _MetaWaylandPopupGrab +{ + MetaWaylandPointerGrab generic; + + struct wl_client *grab_client; + struct wl_list all_popups; +}; + +struct _MetaWaylandPopup +{ + MetaWaylandPopupGrab *grab; + MetaWaylandSurface *surface; + struct wl_listener surface_destroy_listener; + + struct wl_list link; +}; + +static void +popup_grab_focus (MetaWaylandPointerGrab *grab, + MetaWaylandSurface *surface) +{ + MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab; + + /* Popup grabs are in owner-events mode (ie, events for the same client + are reported as normal) */ + if (surface && + wl_resource_get_client (surface->resource) == popup_grab->grab_client) + meta_wayland_pointer_set_focus (grab->pointer, surface); + else + meta_wayland_pointer_set_focus (grab->pointer, NULL); +} + +static void +popup_grab_motion (MetaWaylandPointerGrab *grab, + const ClutterEvent *event) +{ + meta_wayland_pointer_send_motion (grab->pointer, event); +} + +static void +popup_grab_button (MetaWaylandPointerGrab *grab, + const ClutterEvent *event) +{ + MetaWaylandPointer *pointer = grab->pointer; + + if (pointer->focus_surface) + meta_wayland_pointer_send_button (grab->pointer, event); + else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE && + pointer->button_count == 0) + meta_wayland_pointer_end_popup_grab (grab->pointer); +} + +static MetaWaylandPointerGrabInterface popup_grab_interface = { + popup_grab_focus, + popup_grab_motion, + popup_grab_button +}; + +MetaWaylandPopupGrab * +meta_wayland_popup_grab_create (MetaWaylandPointer *pointer, + struct wl_client *client) +{ + MetaWaylandPopupGrab *grab; + + grab = g_slice_new0 (MetaWaylandPopupGrab); + grab->generic.interface = &popup_grab_interface; + grab->generic.pointer = pointer; + grab->grab_client = client; + wl_list_init (&grab->all_popups); + + return grab; +} + +void +meta_wayland_popup_grab_destroy (MetaWaylandPopupGrab *grab) +{ + g_slice_free (MetaWaylandPopupGrab, grab); +} + +void +meta_wayland_popup_grab_begin (MetaWaylandPopupGrab *grab, + MetaWaylandSurface *surface) +{ + MetaWaylandPointer *pointer = grab->generic.pointer; + MetaWindow *window = surface->window; + + meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab); + meta_display_begin_grab_op (window->display, + window->screen, + window, + META_GRAB_OP_WAYLAND_POPUP, + FALSE, /* pointer_already_grabbed */ + FALSE, /* frame_action */ + 1, /* button. XXX? */ + 0, /* modmask */ + meta_display_get_current_time_roundtrip ( + window->display), + pointer->grab_x, + pointer->grab_y); +} + +void +meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab) +{ + MetaWaylandPopup *popup, *tmp; + + g_assert (grab->generic.interface == &popup_grab_interface); + + wl_list_for_each_safe (popup, tmp, &grab->all_popups, link) + { + meta_wayland_surface_popup_done (popup->surface); + meta_wayland_popup_destroy (popup); + } + + { + MetaDisplay *display = meta_get_display (); + meta_display_end_grab_op (display, + meta_display_get_current_time_roundtrip (display)); + } + + meta_wayland_pointer_end_grab (grab->generic.pointer); +} + +gboolean +meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab) +{ + return grab->interface == &popup_grab_interface; +} + +void +meta_wayland_popup_destroy (MetaWaylandPopup *popup) +{ + wl_list_remove (&popup->surface_destroy_listener.link); + wl_list_remove (&popup->link); + g_slice_free (MetaWaylandPopup, popup); +} + +void +meta_wayland_popup_dismiss (MetaWaylandPopup *popup) +{ + MetaWaylandPopupGrab *popup_grab = popup->grab; + + meta_wayland_popup_destroy (popup); + + if (wl_list_empty (&popup_grab->all_popups)) + meta_wayland_pointer_end_popup_grab (popup_grab->generic.pointer); +} + +static void +on_popup_surface_destroy (struct wl_listener *listener, + void *data) +{ + MetaWaylandPopup *popup = + wl_container_of (listener, popup, surface_destroy_listener); + + meta_wayland_popup_dismiss (popup); +} + +MetaWaylandPopup * +meta_wayland_popup_create (MetaWaylandSurface *surface, + MetaWaylandPopupGrab *grab) +{ + MetaWaylandPopup *popup; + + /* Don't allow creating popups if the grab has a different client. */ + if (grab->grab_client != wl_resource_get_client (surface->resource)) + return NULL; + + popup = g_slice_new0 (MetaWaylandPopup); + popup->grab = grab; + popup->surface = surface; + popup->surface_destroy_listener.notify = on_popup_surface_destroy; + + if (surface->xdg_popup) + { + wl_resource_add_destroy_listener (surface->xdg_popup, + &popup->surface_destroy_listener); + } + else if (surface->wl_shell_surface) + { + wl_resource_add_destroy_listener (surface->wl_shell_surface, + &popup->surface_destroy_listener); + } + + wl_list_insert (&grab->all_popups, &popup->link); + + return popup; +} diff --git a/src/wayland/meta-wayland-popup.h b/src/wayland/meta-wayland-popup.h new file mode 100644 index 000000000..bba6d56e6 --- /dev/null +++ b/src/wayland/meta-wayland-popup.h @@ -0,0 +1,49 @@ +/* + * Wayland Support + * + * Copyright (C) 2013 Intel Corporation + * Copyright (C) 2015 Red Hat, Inc. + * + * 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 . + */ + +#ifndef META_WAYLAND_POPUP_H +#define META_WAYLAND_POPUP_H + +#include +#include + +#include "meta-wayland-types.h" +#include "meta-wayland-pointer.h" + +MetaWaylandPopupGrab *meta_wayland_popup_grab_create (MetaWaylandPointer *pointer, + struct wl_client *client); + +void meta_wayland_popup_grab_destroy (MetaWaylandPopupGrab *grab); + +void meta_wayland_popup_grab_begin (MetaWaylandPopupGrab *grab, + MetaWaylandSurface *surface); + +void meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab); + +gboolean meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab); + +MetaWaylandPopup *meta_wayland_popup_create (MetaWaylandSurface *surface, + MetaWaylandPopupGrab *grab); + +void meta_wayland_popup_destroy (MetaWaylandPopup *popup); + +void meta_wayland_popup_dismiss (MetaWaylandPopup *popup); + +#endif /* META_WAYLAND_POPUP_H */ diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 7089cc409..b7c888d7e 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -40,6 +40,7 @@ #include "meta-wayland-seat.h" #include "meta-wayland-keyboard.h" #include "meta-wayland-pointer.h" +#include "meta-wayland-popup.h" #include "meta-wayland-data-device.h" #include "meta-cursor-tracker-private.h" diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h index f28a34df9..9713f1e39 100644 --- a/src/wayland/meta-wayland-types.h +++ b/src/wayland/meta-wayland-types.h @@ -26,6 +26,8 @@ typedef struct _MetaWaylandSeat MetaWaylandSeat; typedef struct _MetaWaylandPointer MetaWaylandPointer; typedef struct _MetaWaylandPointerGrab MetaWaylandPointerGrab; typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface; +typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab; +typedef struct _MetaWaylandPopup MetaWaylandPopup; typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard; typedef struct _MetaWaylandTouch MetaWaylandTouch; typedef struct _MetaWaylandDataSource MetaWaylandDataSource;