From 60078ca97581adb15f7b76dbc61fcae0b2736dff Mon Sep 17 00:00:00 2001 From: Pierre Lamot Date: Wed, 10 May 2023 18:23:44 +0200 Subject: [PATCH] libvlc: allow user to report mouse events when using libvlc_video_set_output_callbacks when using libvlc_video_set_output_callbacks, VLC has no native surface to intercept mouse events (unlike libvlc_media_player_set_xwindow/xid/...). This patch allows user to send these events manually to VLC. This is useful when dealing with interactive medias (DVD menus). --- doc/libvlc/d3d11_player.cpp | 7 ++- doc/libvlc/d3d9_player.c | 11 +++-- include/vlc/libvlc_media_player.h | 78 +++++++++++++++++++++++++++---- lib/media_player.c | 6 +-- modules/video_output/wextern.c | 35 +++++++++++--- 5 files changed, 113 insertions(+), 24 deletions(-) diff --git a/doc/libvlc/d3d11_player.cpp b/doc/libvlc/d3d11_player.cpp index 26be031fef..5fb9957db1 100644 --- a/doc/libvlc/d3d11_player.cpp +++ b/doc/libvlc/d3d11_player.cpp @@ -498,8 +498,11 @@ static void CleanupDevice_cb( void *opaque ) } // receive the libvlc callback to call when we want to change the libvlc output size -static void SetResize_cb( void *opaque, +static void SetReport_cb( void *opaque, libvlc_video_output_resize_cb report_size_change, + libvlc_video_output_mouse_move_cb report_mouse_move, + libvlc_video_output_mouse_press_cb report_mouse_press, + libvlc_video_output_mouse_release_cb report_mouse_release, void *report_opaque ) { struct render_context *ctx = static_cast( opaque ); @@ -681,7 +684,7 @@ int WINAPI WinMain(HINSTANCE hInstance, /* Tell VLC to render into our D3D11 environment */ libvlc_video_set_output_callbacks( Context.p_mp, libvlc_video_engine_d3d11, - SetupDevice_cb, CleanupDevice_cb, SetResize_cb, + SetupDevice_cb, CleanupDevice_cb, SetReport_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, nullptr, nullptr, SelectPlane_cb, &Context ); diff --git a/doc/libvlc/d3d9_player.c b/doc/libvlc/d3d9_player.c index 6bc430806b..562cfd2be9 100644 --- a/doc/libvlc/d3d9_player.c +++ b/doc/libvlc/d3d9_player.c @@ -222,9 +222,12 @@ static void CleanupDevice_cb( void *opaque ) } } -static void SetResize_cb( void *opaque, - libvlc_video_output_resize_cb report_size_change, - void *report_opaque ) +static void SetReport_cb( void *opaque, + libvlc_video_output_resize_cb report_size_change, + libvlc_video_output_mouse_move_cb report_mouse_move, + libvlc_video_output_mouse_press_cb report_mouse_press, + libvlc_video_output_mouse_release_cb report_mouse_release, + void *report_opaque ) { struct render_context *ctx = opaque; EnterCriticalSection(&ctx->sizeLock); @@ -416,7 +419,7 @@ int WINAPI WinMain(HINSTANCE hInstance, /* Tell VLC to render into our D3D9 environment */ libvlc_video_set_output_callbacks( Context.p_mp, libvlc_video_engine_d3d9, - SetupDevice_cb, CleanupDevice_cb, SetResize_cb, + SetupDevice_cb, CleanupDevice_cb, SetReport_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, NULL, NULL, NULL, &Context ); diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h index a8613e8373..8f92036905 100644 --- a/include/vlc/libvlc_media_player.h +++ b/include/vlc/libvlc_media_player.h @@ -717,32 +717,92 @@ typedef enum libvlc_video_engine_t { /** Callback type that can be called to request a render size changes. - * - * libvlc will provide a callback of this type when calling \ref libvlc_video_output_set_resize_cb. - * - * \param report_opaque parameter passed to \ref libvlc_video_output_set_resize_cb. [IN] + * + * libvlc will provide a callback of this type when calling \ref libvlc_video_output_set_window_cb. + * + * \param report_opaque parameter passed to \ref libvlc_video_output_set_window_cb. [IN] * \param width new rendering width requested. [IN] * \param height new rendering height requested. [IN] */ typedef void( *libvlc_video_output_resize_cb )( void *report_opaque, unsigned width, unsigned height ); +/** + * Enumeration of the different mouse buttons that can be reported for user interaction + * can be passed to \ref libvlc_video_output_mouse_press_cb and \ref libvlc_video_output_mouse_release_cb. + */ +typedef enum libvlc_video_output_mouse_button_t { + libvlc_video_output_mouse_button_left = 0, + libvlc_video_output_mouse_button_middle = 1, + libvlc_video_output_mouse_button_right = 2 +} libvlc_video_output_mouse_button_t; + + +/** Callback type that can be called to notify the mouse position when hovering the render surface. + * + * libvlc will provide a callback of this type when calling \ref libvlc_video_output_set_window_cb. + * + * The position (0,0) denotes the top left corner, bottom right corner position + * is (width,height) as reported by \ref libvlc_video_output_resize_cb. + * + * \param report_opaque parameter passed to \ref libvlc_video_output_set_window_cb. [IN] + * \param x horizontal mouse positon in \ref libvlc_video_output_resize_cb coordinates. [IN] + * \param y vertical mouse positon in \ref libvlc_video_output_resize_cb coordinates. [IN] + */ +typedef void (*libvlc_video_output_mouse_move_cb)(void *opaque, int x, int y); + +/** Callback type that can be called to notify when a mouse button is pressed in the rendering surface. + * + * libvlc will provide a callback of this type when calling \ref libvlc_video_output_set_window_cb. + * + * The button event will be reported at the last position provided by \ref libvlc_video_output_mouse_move_cb + * + * \param report_opaque parameter passed to \ref libvlc_video_output_set_window_cb. [IN] + * \param button represent the button pressed, see \ref libvlc_video_output_mouse_button_t for available buttons. [IN] + */ +typedef void (*libvlc_video_output_mouse_press_cb)(void *opaque, libvlc_video_output_mouse_button_t button); + +/** Callback type that can be called to notify when a mouse button is released in the rendering surface. + * + * libvlc will provide a callback of this type when calling \ref libvlc_video_output_set_window_cb. + * + * The button event will be reported at the last position provided by \ref libvlc_video_output_mouse_move_cb. + * + * \param report_opaque parameter passed to \ref libvlc_video_output_set_window_cb. [IN] + * \param button represent the button released, see \ref libvlc_video_output_mouse_button_t for available buttons. [IN] + */ +typedef void (*libvlc_video_output_mouse_release_cb)(void *opaque, libvlc_video_output_mouse_button_t button); + /** Set the callback to call when the host app resizes the rendering area. * * This allows text rendering and aspect ratio to be handled properly when the host - * rendering size changes. + * rendering size changes and to provide mouse. * * It may be called before the \ref libvlc_video_output_setup_cb callback. * + * \warning These callbacks cannot be called concurently, the caller is responsible for serialization + * * \param[in] opaque private pointer set on the opaque parameter of @a libvlc_video_output_setup_cb() * \param[in] report_size_change callback which must be called when the host size changes. * The callback is valid until another call to \ref libvlc_video_output_set_resize_cb * is done. This may be called from any thread. + * \param[in] report_mouse_move callback which must be called when the mouse position change on the video surface. + * The coordinates are relative to the size reported through the report_size_change. + * This may be called from any thread. + * \param[in] report_mouse_pressed callback which must be called when a mouse button is pressed on the video surface, + * The position of the event is the last position reported by the report_mouse_move callback. This may be + * called from any thread. + * \param[in] report_mouse_released callback which must be called when a mouse button is released on the video surface, + * The position of the event is the last position reported by the report_mouse_move callback. This may be + * called from any thread. * \param[in] report_opaque private pointer to pass to the \ref report_size_change callback. */ -typedef void( *libvlc_video_output_set_resize_cb )( void *opaque, - libvlc_video_output_resize_cb report_size_change, - void *report_opaque ); +typedef void( *libvlc_video_output_set_window_cb )( void *opaque, + libvlc_video_output_resize_cb report_size_change, + libvlc_video_output_mouse_move_cb report_mouse_move, + libvlc_video_output_mouse_press_cb report_mouse_pressed, + libvlc_video_output_mouse_release_cb report_mouse_released, + void *report_opaque ); /** Tell the host the rendering for the given plane is about to start * @@ -801,7 +861,7 @@ bool libvlc_video_set_output_callbacks( libvlc_media_player_t *mp, libvlc_video_engine_t engine, libvlc_video_output_setup_cb setup_cb, libvlc_video_output_cleanup_cb cleanup_cb, - libvlc_video_output_set_resize_cb resize_cb, + libvlc_video_output_set_window_cb window_cb, libvlc_video_update_output_cb update_output_cb, libvlc_video_swap_cb swap_cb, libvlc_video_makeCurrent_cb makeCurrent_cb, diff --git a/lib/media_player.c b/lib/media_player.c index f6a69ce4d7..f1e3571e98 100644 --- a/lib/media_player.c +++ b/lib/media_player.c @@ -634,7 +634,7 @@ libvlc_media_player_new( libvlc_instance_t *instance ) var_Create( mp, "vout-cb-opaque", VLC_VAR_ADDRESS ); var_Create( mp, "vout-cb-setup", VLC_VAR_ADDRESS ); var_Create( mp, "vout-cb-cleanup", VLC_VAR_ADDRESS ); - var_Create( mp, "vout-cb-resize-cb", VLC_VAR_ADDRESS ); + var_Create( mp, "vout-cb-window-cb", VLC_VAR_ADDRESS ); var_Create( mp, "vout-cb-update-output", VLC_VAR_ADDRESS ); var_Create( mp, "vout-cb-swap", VLC_VAR_ADDRESS ); var_Create( mp, "vout-cb-get-proc-address", VLC_VAR_ADDRESS ); @@ -1062,7 +1062,7 @@ bool libvlc_video_set_output_callbacks(libvlc_media_player_t *mp, libvlc_video_engine_t engine, libvlc_video_output_setup_cb setup_cb, libvlc_video_output_cleanup_cb cleanup_cb, - libvlc_video_output_set_resize_cb resize_cb, + libvlc_video_output_set_window_cb set_window_cb, libvlc_video_update_output_cb update_output_cb, libvlc_video_swap_cb swap_cb, libvlc_video_makeCurrent_cb makeCurrent_cb, @@ -1108,7 +1108,7 @@ bool libvlc_video_set_output_callbacks(libvlc_media_player_t *mp, var_SetAddress( mp, "vout-cb-opaque", opaque ); var_SetAddress( mp, "vout-cb-setup", setup_cb ); var_SetAddress( mp, "vout-cb-cleanup", cleanup_cb ); - var_SetAddress( mp, "vout-cb-resize-cb", resize_cb ); + var_SetAddress( mp, "vout-cb-window-cb", set_window_cb ); var_SetAddress( mp, "vout-cb-update-output", update_output_cb ); var_SetAddress( mp, "vout-cb-swap", swap_cb ); var_SetAddress( mp, "vout-cb-get-proc-address", getProcAddress_cb ); diff --git a/modules/video_output/wextern.c b/modules/video_output/wextern.c index d3c2a6f748..d1b6c8fcf0 100644 --- a/modules/video_output/wextern.c +++ b/modules/video_output/wextern.c @@ -48,7 +48,7 @@ vlc_module_end() typedef struct { void *opaque; - libvlc_video_output_set_resize_cb setResizeCb; + libvlc_video_output_set_window_cb setWindowCb; } wextern_t; static void WindowResize(void *opaque, unsigned width, unsigned height) @@ -57,13 +57,34 @@ static void WindowResize(void *opaque, unsigned width, unsigned height) vlc_window_ReportSize(window, width, height); } +static void WindowMouseMoved(void *opaque, int x, int y) +{ + vlc_window_t *window = opaque; + vlc_window_ReportMouseMoved(window, x, y); +} + +static void WindowMousePress(void *opaque, libvlc_video_output_mouse_button_t button) +{ + vlc_window_t *window = opaque; + vlc_window_ReportMousePressed(window, button); +} + +static void WindowMouseRelease(void *opaque, libvlc_video_output_mouse_button_t button) +{ + vlc_window_t *window = opaque; + vlc_window_ReportMouseReleased(window, button); +} + static int Enable(struct vlc_window *wnd, const vlc_window_cfg_t *wcfg) { wextern_t *sys = wnd->sys; - if ( sys->setResizeCb != NULL ) + if ( sys->setWindowCb != NULL ) /* bypass the size handling as the window doesn't handle the size */ - sys->setResizeCb( sys->opaque, WindowResize, wnd ); + sys->setWindowCb( sys->opaque, + WindowResize, + WindowMouseMoved, WindowMousePress, WindowMouseRelease, + wnd ); (void) wcfg; return VLC_SUCCESS; @@ -73,8 +94,8 @@ static void Disable(struct vlc_window *wnd) { wextern_t *sys = wnd->sys; - if ( sys->setResizeCb != NULL ) - sys->setResizeCb( sys->opaque, NULL, NULL ); + if ( sys->setWindowCb != NULL ) + sys->setWindowCb( sys->opaque, NULL, NULL, NULL, NULL, NULL ); } static const struct vlc_window_operations ops = { @@ -89,11 +110,13 @@ static int Open(vlc_window_t *wnd) wextern_t *sys = vlc_obj_malloc(VLC_OBJECT(wnd), sizeof(*sys)); if (unlikely(sys==NULL)) return VLC_ENOMEM; + sys->opaque = var_InheritAddress( wnd, "vout-cb-opaque" ); - sys->setResizeCb = var_InheritAddress( wnd, "vout-cb-resize-cb" ); + sys->setWindowCb = var_InheritAddress( wnd, "vout-cb-window-cb" ); wnd->sys = sys; wnd->type = VLC_WINDOW_TYPE_DUMMY; wnd->ops = &ops; + wnd->info.has_double_click = false; return VLC_SUCCESS; }