gl/wayland: Mouse events handling

This commit is contained in:
Philippe Normand 2020-02-10 18:17:42 +00:00
parent 5a4c5e9169
commit 3f79805aa0
2 changed files with 88 additions and 46 deletions

View 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);

View 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;
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);
}
}