[vlc-devel] [PATCH 2/2] core: window: handle mouse events
Thomas Guillem
thomas at gllm.fr
Fri Nov 25 17:39:35 CET 2016
Mouse events can now be caught by "vout window" modules in addition to "vout
display" modules. Mouse events are propagated to the vout_thread_t via a new
vout_control. That way, window mouse coordinates can be translated to video
coordinates from ThreadControl (where it's safe to access vd->source and
vd->cfg).
Fix #9787
---
include/vlc_vout_window.h | 88 +++++++++++++++++++++++++++++++++++++++++
src/video_output/control.h | 4 ++
src/video_output/opengl.c | 1 +
src/video_output/video_output.c | 56 ++++++++++++++++++++++++++
src/video_output/vout_control.h | 5 +++
src/video_output/window.c | 7 ++++
6 files changed, 161 insertions(+)
diff --git a/include/vlc_vout_window.h b/include/vlc_vout_window.h
index c302e28..66f8347 100644
--- a/include/vlc_vout_window.h
+++ b/include/vlc_vout_window.h
@@ -64,9 +64,33 @@ enum {
VOUT_WINDOW_SET_FULLSCREEN, /* int b_fullscreen */
};
+/**
+ * Window mouse event type for vout_window_mouse_event_t
+ */
+enum vout_window_mouse_event_type {
+ VOUT_WINDOW_MOUSE_STATE,
+ VOUT_WINDOW_MOUSE_MOVED,
+ VOUT_WINDOW_MOUSE_PRESSED,
+ VOUT_WINDOW_MOUSE_RELEASED,
+ VOUT_WINDOW_MOUSE_DOUBLE_CLICK,
+};
+
+/**
+ * Window mouse event
+ */
+typedef struct vout_window_mouse_event_t
+{
+ enum vout_window_mouse_event_type type;
+ int x;
+ int y;
+ int button_mask;
+} vout_window_mouse_event_t;
+
enum {
VOUT_WINDOW_EVENT_RESIZED, /* unsigned width, unsigned height */
VOUT_WINDOW_EVENT_CLOSED, /* void */
+
+ VOUT_WINDOW_EVENT_MOUSE, /* const vout_window_mouse_event_t * */
};
typedef struct vout_window_cfg_t {
@@ -225,5 +249,69 @@ static inline void vout_window_ReportClose(vout_window_t *window)
vout_window_SendEvent(window, VOUT_WINDOW_EVENT_CLOSED);
}
+/**
+ * Send a full mouse state
+ *
+ * The mouse position must be expressed against window unit. You can use this
+ * function of others vout_window_ReportMouse*() functions.
+ */
+static inline void vout_window_ReportMouseState(vout_window_t *window,
+ int x, int y, int button_mask)
+{
+ const vout_window_mouse_event_t mouse = {
+ VOUT_WINDOW_MOUSE_STATE, x, y, button_mask,
+ };
+ vout_window_SendEvent(window, VOUT_WINDOW_EVENT_MOUSE, &mouse);
+}
+
+/**
+ * Send a mouse movement
+ *
+ * The mouse position must be expressed against window unit.
+ */
+static inline void vout_window_ReportMouseMoved(vout_window_t *window,
+ int x, int y)
+{
+ const vout_window_mouse_event_t mouse = {
+ VOUT_WINDOW_MOUSE_MOVED, x, y, 0
+ };
+ vout_window_SendEvent(window, VOUT_WINDOW_EVENT_MOUSE, &mouse);
+}
+
+/**
+ * Send a mouse pressed event
+ */
+static inline void vout_window_ReportMousePressed(vout_window_t *window,
+ int button)
+{
+ const vout_window_mouse_event_t mouse = {
+ VOUT_WINDOW_MOUSE_PRESSED, 0, 0, button,
+ };
+ vout_window_SendEvent(window, VOUT_WINDOW_EVENT_MOUSE, &mouse);
+}
+
+/**
+ * Send a mouse released event
+ */
+static inline void vout_window_ReportMouseReleased(vout_window_t *window,
+ int button)
+{
+ const vout_window_mouse_event_t mouse = {
+ VOUT_WINDOW_MOUSE_RELEASED, 0, 0, button,
+ };
+ vout_window_SendEvent(window, VOUT_WINDOW_EVENT_MOUSE, &mouse);
+}
+
+/**
+ * Send a mouse double click event
+ */
+static inline void vout_window_ReportMouseDoubleClick(vout_window_t *window)
+{
+ const vout_window_mouse_event_t mouse = {
+ VOUT_WINDOW_MOUSE_DOUBLE_CLICK, 0, 0, 0,
+ };
+ vout_window_SendEvent(window, VOUT_WINDOW_EVENT_MOUSE, &mouse);
+}
+
/** @} */
#endif /* VLC_VOUT_WINDOW_H */
diff --git a/src/video_output/control.h b/src/video_output/control.h
index 9fdfd85..6804742 100644
--- a/src/video_output/control.h
+++ b/src/video_output/control.h
@@ -24,6 +24,8 @@
#ifndef LIBVLC_VOUT_INTERNAL_CONTROL_H
#define LIBVLC_VOUT_INTERNAL_CONTROL_H
+#include <vlc_vout_window.h>
+
/* */
enum {
VOUT_CONTROL_INIT,
@@ -51,6 +53,7 @@ enum {
VOUT_CONTROL_FULLSCREEN, /* bool */
VOUT_CONTROL_WINDOW_STATE, /* unsigned */
+ VOUT_CONTROL_WINDOW_MOUSE, /* window_mouse */
VOUT_CONTROL_DISPLAY_FILLED, /* bool */
VOUT_CONTROL_ZOOM, /* pair */
@@ -94,6 +97,7 @@ typedef struct {
unsigned width;
unsigned height;
} window;
+ vout_window_mouse_event_t window_mouse;
const vout_configuration_t *cfg;
subpicture_t *subpicture;
vlc_viewpoint_t viewpoint;
diff --git a/src/video_output/opengl.c b/src/video_output/opengl.c
index 1a42253..a76f4d2 100644
--- a/src/video_output/opengl.c
+++ b/src/video_output/opengl.c
@@ -115,6 +115,7 @@ static void vlc_gl_surface_Event(vout_window_t *wnd, int type, va_list args)
va_arg(args, unsigned));
break;
case VOUT_WINDOW_EVENT_CLOSED:
+ case VOUT_WINDOW_EVENT_MOUSE:
/* TODO */
break;
default: vlc_assert_unreachable();
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index ef111ec..00036f7 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -363,6 +363,17 @@ void vout_DisplayTitle(vout_thread_t *vout, const char *title)
vout_control_PushString(&vout->p->control, VOUT_CONTROL_OSD_TITLE, title);
}
+void vout_WindowMouseEvent(vout_thread_t *vout,
+ const vout_window_mouse_event_t *mouse)
+{
+ assert(mouse);
+ vout_control_cmd_t cmd;
+ vout_control_cmd_Init(&cmd, VOUT_CONTROL_WINDOW_MOUSE);
+ cmd.u.window_mouse = *mouse;
+
+ vout_control_Push(&vout->p->control, &cmd);
+}
+
void vout_PutSubpicture( vout_thread_t *vout, subpicture_t *subpic )
{
vout_control_cmd_t cmd;
@@ -1261,6 +1272,48 @@ static void ThreadChangeWindowState(vout_thread_t *vout, unsigned state)
#endif
}
+static void ThreadChangeWindowMouse(vout_thread_t *vout,
+ const vout_window_mouse_event_t *mouse)
+{
+ vout_display_t *vd = vout->p->display.vd;
+ switch (mouse->type)
+ {
+ case VOUT_WINDOW_MOUSE_STATE:
+ case VOUT_WINDOW_MOUSE_MOVED:
+ {
+ vout_display_place_t place;
+ vout_display_PlacePicture(&place, &vd->source, vd->cfg, false);
+
+ if (place.width <= 0 || place.height <= 0)
+ return;
+
+ const int x = vd->source.i_x_offset +
+ (int64_t)(mouse->x - place.x) *
+ vd->source.i_visible_width / place.width;
+ const int y = vd->source.i_y_offset +
+ (int64_t)(mouse->y - place.y) *
+ vd->source.i_visible_height/ place.height;
+
+ if (mouse->type == VOUT_WINDOW_MOUSE_STATE)
+ vout_display_SendEventMouseState(vd, x, y, mouse->button_mask);
+ else
+ vout_display_SendEventMouseMoved(vd, x, y);
+ break;
+ }
+ case VOUT_WINDOW_MOUSE_PRESSED:
+ vout_display_SendEventMousePressed(vd, mouse->button_mask);
+ break;
+ case VOUT_WINDOW_MOUSE_RELEASED:
+ vout_display_SendEventMouseReleased(vd, mouse->button_mask);
+ break;
+ case VOUT_WINDOW_MOUSE_DOUBLE_CLICK:
+ vout_display_SendEventMouseDoubleClick(vd);
+ break;
+ default: vlc_assert_unreachable();
+ break;
+ }
+}
+
static void ThreadChangeDisplayFilled(vout_thread_t *vout, bool is_filled)
{
vout_SetDisplayFilled(vout->p->display.vd, is_filled);
@@ -1551,6 +1604,9 @@ static int ThreadControl(vout_thread_t *vout, vout_control_cmd_t cmd)
case VOUT_CONTROL_WINDOW_STATE:
ThreadChangeWindowState(vout, cmd.u.integer);
break;
+ case VOUT_CONTROL_WINDOW_MOUSE:
+ ThreadChangeWindowMouse(vout, &cmd.u.window_mouse);
+ break;
case VOUT_CONTROL_DISPLAY_FILLED:
ThreadChangeDisplayFilled(vout, cmd.u.boolean);
break;
diff --git a/src/video_output/vout_control.h b/src/video_output/vout_control.h
index 0be3313..e50c096 100644
--- a/src/video_output/vout_control.h
+++ b/src/video_output/vout_control.h
@@ -25,6 +25,8 @@
#ifndef LIBVLC_VOUT_CONTROL_H
#define LIBVLC_VOUT_CONTROL_H 1
+typedef struct vout_window_mouse_event_t vout_window_mouse_event_t;
+
/**
* This function will (un)pause the display of pictures.
* It is thread safe
@@ -69,6 +71,9 @@ void vout_NextPicture( vout_thread_t *p_vout, mtime_t *pi_duration );
*/
void vout_DisplayTitle( vout_thread_t *p_vout, const char *psz_title );
+void vout_WindowMouseEvent( vout_thread_t *p_vout,
+ const vout_window_mouse_event_t *mouse );
+
/**
* This function will return true if no more pictures are to be displayed.
*/
diff --git a/src/video_output/window.c b/src/video_output/window.c
index 11ed099..76d7e5a 100644
--- a/src/video_output/window.c
+++ b/src/video_output/window.c
@@ -164,6 +164,13 @@ static void vout_display_window_Event(vout_window_t *window, int type,
case VOUT_WINDOW_EVENT_CLOSED:
vout_display_window_CloseNotify(window);
break;
+ case VOUT_WINDOW_EVENT_MOUSE:
+ {
+ vout_thread_t *vout = (vout_thread_t *)window->obj.parent;
+ vout_WindowMouseEvent(vout,
+ va_arg(args, const vout_window_mouse_event_t*));
+ break;
+ }
default: vlc_assert_unreachable();
}
}
--
2.9.3
More information about the vlc-devel
mailing list