[vlc-commits] core: window: handle mouse events

Thomas Guillem git at videolan.org
Mon Nov 28 16:37:45 CET 2016


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Fri Nov 25 16:42:13 2016 +0100| [45740ca2e675eebca69aed9308a104121c67bdb5] | committer: Thomas Guillem

core: window: handle mouse events

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).

Ref #9787

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=45740ca2e675eebca69aed9308a104121c67bdb5
---

 include/vlc_vout_window.h       | 94 +++++++++++++++++++++++++++++++++++++++++
 src/video_output/control.h      |  4 ++
 src/video_output/video_output.c | 56 ++++++++++++++++++++++++
 src/video_output/vout_control.h |  5 +++
 src/video_output/window.c       |  8 ++++
 5 files changed, 167 insertions(+)

diff --git a/include/vlc_vout_window.h b/include/vlc_vout_window.h
index 63351ba..3564f2c 100644
--- a/include/vlc_vout_window.h
+++ b/include/vlc_vout_window.h
@@ -64,6 +64,28 @@ 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;
+
 typedef struct vout_window_cfg_t {
     /* Window handle type */
     unsigned type;
@@ -88,6 +110,7 @@ typedef struct vout_window_owner {
     void *sys;
     void (*resized)(vout_window_t *, unsigned width, unsigned height);
     void (*closed)(vout_window_t *);
+    void (*mouse_event)(vout_window_t *, const vout_window_mouse_event_t *mouse);
 } vout_window_owner_t;
 
 /**
@@ -211,5 +234,76 @@ static inline void vout_window_ReportClose(vout_window_t *window)
         window->owner.closed(window);
 }
 
+static inline void vout_window_SendMouseEvent(vout_window_t *window,
+                                              const vout_window_mouse_event_t *mouse)
+{
+    if (window->owner.mouse_event != NULL)
+        window->owner.mouse_event(window, mouse);
+}
+
+/**
+ * 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_SendMouseEvent(window, &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_SendMouseEvent(window, &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_SendMouseEvent(window, &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_SendMouseEvent(window, &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_SendMouseEvent(window, &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/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 2487668..01d9135 100644
--- a/src/video_output/window.c
+++ b/src/video_output/window.c
@@ -149,6 +149,13 @@ static void vout_display_window_CloseNotify(vout_window_t *window)
     vout_SendEventClose(vout);
 }
 
+static void vout_display_window_MouseEvent(vout_window_t *window,
+                                           const vout_window_mouse_event_t *mouse)
+{
+    vout_thread_t *vout = (vout_thread_t *)window->obj.parent;
+    vout_WindowMouseEvent(vout, mouse);
+}
+
 /**
  * Creates a video window, initially without any attached display.
  */
@@ -168,6 +175,7 @@ vout_window_t *vout_display_window_New(vout_thread_t *vout,
         .sys = state,
         .resized = vout_display_window_ResizeNotify,
         .closed = vout_display_window_CloseNotify,
+        .mouse_event = vout_display_window_MouseEvent,
     };
     vout_window_t *window;
 



More information about the vlc-commits mailing list