gl/wayland: Mouse events handling
authorPhilippe Normand <philn@igalia.com>
Mon, 10 Feb 2020 18:17:42 +0000 (18:17 +0000)
committerPhilippe Normand <philn@igalia.com>
Thu, 19 Mar 2020 09:59:47 +0000 (09:59 +0000)
ext/gl/gstglimagesink.c
gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c

index a5c7571..3e2f617 100644 (file)
@@ -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);
index ef59b2f..6b06632 100644 (file)
@@ -25,7 +25,9 @@
 #include "config.h"
 #endif
 
-#include <linux/input.h>
+#include <locale.h>
+#include <sys/mman.h>
+#include <unistd.h>
 
 #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;
-
-  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);
+  GstGLWindow *window = GST_GL_WINDOW (window_egl);
+  const char *event_type;
 
-  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 (gl_window);
+  display = &window_egl->display;
 
-  window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
+  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);
   }
 }