From 3f79805aa080a305f767ae6784b452ea4c2851fb Mon Sep 17 00:00:00 2001 From: Philippe Normand Date: Mon, 10 Feb 2020 18:17:42 +0000 Subject: [PATCH] gl/wayland: Mouse events handling --- ext/gl/gstglimagesink.c | 37 +++++++ .../gst/gl/wayland/gstglwindow_wayland_egl.c | 97 ++++++++++--------- 2 files changed, 88 insertions(+), 46 deletions(-) diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c index a5c75716a6..3e2f6178e3 100644 --- a/ext/gl/gstglimagesink.c +++ b/ext/gl/gstglimagesink.c @@ -444,6 +444,30 @@ _display_size_to_stream_size (GstGLImageSink * gl_sink, gdouble x, GST_TRACE ("transform %fx%f into %fx%f", x, y, *stream_x, *stream_y); } +static void +_display_scroll_value_to_stream_scroll_value (GstGLImageSink * gl_sink, + gdouble delta_x, gdouble delta_y, gdouble * stream_delta_x, + gdouble * stream_delta_y) +{ + gdouble stream_width, stream_height; + + stream_width = (gdouble) GST_VIDEO_INFO_WIDTH (&gl_sink->out_info); + stream_height = (gdouble) GST_VIDEO_INFO_HEIGHT (&gl_sink->out_info); + + if (delta_x != 0 && gl_sink->display_rect.w > 0) + *stream_delta_x = delta_x * (stream_width / gl_sink->display_rect.w); + else + *stream_delta_x = delta_x; + + if (delta_y != 0 && gl_sink->display_rect.h > 0) + *stream_delta_y = delta_y * (stream_height / gl_sink->display_rect.h); + else + *stream_delta_y = delta_y; + + GST_TRACE_OBJECT (gl_sink, "transform %fx%f into %fx%f", delta_x, delta_y, + *stream_delta_x, *stream_delta_y); +} + /* rotate 90 */ static const gfloat clockwise_matrix[] = { 0.0f, -1.0f, 0.0f, 0.0f, @@ -598,6 +622,19 @@ gst_glimage_sink_navigation_send_event (GstNavigation * navigation, GstStructure stream_x, "pointer_y", G_TYPE_DOUBLE, stream_y, NULL); } + /* Converting pointer scroll coordinates to the non scaled geometry */ + if (width != 0 && gst_structure_get_double (structure, "delta_pointer_x", &x) + && height != 0 + && gst_structure_get_double (structure, "delta_pointer_y", &y)) { + gdouble stream_x, stream_y; + + _display_scroll_value_to_stream_scroll_value (sink, x, y, &stream_x, + &stream_y); + + gst_structure_set (structure, "delta_pointer_x", G_TYPE_DOUBLE, + stream_x, "delta_pointer_y", G_TYPE_DOUBLE, stream_y, NULL); + } + event = gst_event_new_navigation (structure); if (event) { gst_event_ref (event); diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c index ef59b2f604..6b06632a74 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -25,7 +25,9 @@ #include "config.h" #endif -#include +#include +#include +#include #include "wayland_event_source.h" @@ -60,7 +62,6 @@ static gboolean gst_gl_window_wayland_egl_set_render_rectangle (GstGLWindow * static void gst_gl_window_wayland_egl_set_preferred_size (GstGLWindow * window, gint width, gint height); -#if 0 static void pointer_handle_enter (void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) @@ -71,6 +72,7 @@ pointer_handle_enter (void *data, struct wl_pointer *pointer, uint32_t serial, window_egl->display.serial = serial; + /* FIXME: Not sure how useful this is */ if (window_egl->display.default_cursor) { image = window_egl->display.default_cursor->images[0]; buffer = wl_cursor_image_get_buffer (image); @@ -96,62 +98,44 @@ pointer_handle_motion (void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { GstGLWindowWaylandEGL *window_egl = data; + GstGLWindow *window = GST_GL_WINDOW (window_egl); window_egl->display.pointer_x = wl_fixed_to_double (sx_w); window_egl->display.pointer_y = wl_fixed_to_double (sy_w); -} - -enum wl_edges -{ - WL_EDGE_NONE = 0, - WL_EDGE_TOP = 1, - WL_EDGE_BOTTOM = 2, - WL_EDGE_LEFT = 4, - WL_EDGE_RIGHT = 8, -}; - -static guint -_get_closest_pointer_corner (GstGLWindowWaylandEGL * window_egl) -{ - guint edges = 0; - gdouble win_width, win_height; - gdouble p_x, p_y; - - win_width = (gdouble) window_egl->window.window_width; - win_height = (gdouble) window_egl->window.window_height; - p_x = window_egl->display.pointer_x; - p_y = window_egl->display.pointer_y; - - if (win_width == 0.0 || win_height == 0.0) - return WL_EDGE_NONE; - - edges |= win_width / 2.0 - p_x < 0.0 ? WL_EDGE_RIGHT : WL_EDGE_LEFT; - edges |= win_height / 2.0 - p_y < 0.0 ? WL_EDGE_BOTTOM : WL_EDGE_TOP; - - return edges; + gst_gl_window_send_mouse_event (window, "mouse-move", 0, + window_egl->display.pointer_x, window_egl->display.pointer_y); } static void pointer_handle_button (void *data, struct wl_pointer *pointer, uint32_t serial, - uint32_t time, uint32_t button, uint32_t state_w) + uint32_t time, uint32_t button, uint32_t state) { GstGLWindowWaylandEGL *window_egl = data; - guint edges = _get_closest_pointer_corner (window_egl); - window_egl->display.serial = serial; + GstGLWindow *window = GST_GL_WINDOW (window_egl); + const char *event_type; - if (button == BTN_LEFT && state_w == WL_POINTER_BUTTON_STATE_PRESSED) - wl_shell_surface_move (window_egl->window.wl_shell_surface, - window_egl->display.seat, serial); - - if (button == BTN_RIGHT && state_w == WL_POINTER_BUTTON_STATE_PRESSED) - wl_shell_surface_resize (window_egl->window.wl_shell_surface, - window_egl->display.seat, serial, edges); + event_type = state == 1 ? "mouse-button-press" : "mouse-button-release"; + gst_gl_window_send_mouse_event (window, event_type, button, + window_egl->display.pointer_x, window_egl->display.pointer_y); } static void pointer_handle_axis (void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { + GstGLWindowWaylandEGL *window_egl = data; + GstGLWindow *window = GST_GL_WINDOW (window_egl); + gdouble delta_x, delta_y; + gdouble delta = -wl_fixed_to_double (value); + if (axis == 1) { + delta_x = delta; + delta_y = 0; + } else { + delta_x = 0; + delta_y = delta; + } + gst_gl_window_send_scroll_event (window, window_egl->display.pointer_x, + window_egl->display.pointer_y, delta_x, delta_y); } static const struct wl_pointer_listener pointer_listener = { @@ -189,10 +173,19 @@ seat_handle_capabilities (void *data, struct wl_seat *seat, #endif } +static void +seat_name (void *data, struct wl_seat *seat, const char *name) +{ + GstGLWindowWaylandEGL *window_egl = data; + + GST_TRACE_OBJECT (window_egl, "seat %p has name %s", seat, name); +} + static const struct wl_seat_listener seat_listener = { seat_handle_capabilities, + seat_name }; -#endif + static void handle_ping (void *data, struct wl_shell_surface *wl_shell_surface, uint32_t serial) @@ -461,11 +454,18 @@ gst_gl_window_wayland_egl_new (GstGLDisplay * display) } static void -gst_gl_window_wayland_egl_close (GstGLWindow * window) +gst_gl_window_wayland_egl_close (GstGLWindow * gl_window) { GstGLWindowWaylandEGL *window_egl; + struct display *display; - window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + window_egl = GST_GL_WINDOW_WAYLAND_EGL (gl_window); + display = &window_egl->display; + + if (display->pointer != NULL) { + wl_pointer_destroy (display->pointer); + display->pointer = NULL; + } destroy_surfaces (window_egl); @@ -473,7 +473,7 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window) g_source_unref (window_egl->wl_source); window_egl->wl_source = NULL; - GST_GL_WINDOW_CLASS (parent_class)->close (window); + GST_GL_WINDOW_CLASS (parent_class)->close (gl_window); } static void @@ -510,6 +510,11 @@ registry_handle_global (void *data, struct wl_registry *registry, } else if (g_strcmp0 (interface, "wl_shell") == 0) { window_wayland->display.shell = wl_registry_bind (registry, name, &wl_shell_interface, 1); + } else if (g_strcmp0 (interface, "wl_seat") == 0) { + window_wayland->display.seat = + wl_registry_bind (registry, name, &wl_seat_interface, 4); + wl_seat_add_listener (window_wayland->display.seat, &seat_listener, + window_wayland); } }