vlc | branch: master | Thomas Guillem <[email protected]> | 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; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
