[vlc-devel] [PATCH v2 5/5] vout: win32: drawable: use an internal HWND to detect size changes
Alexandre Janniaux
ajanni at videolabs.io
Thu May 7 16:26:03 CEST 2020
Hi,
hwnd_is_ready doesn't look initialized, but anyway you oculd
probably replace the lock, the cond and the boolean by
a semaphore to simplify instead.
Regards,
--
Alexandre Janniaux
Videolabs
On Thu, May 07, 2020 at 04:11:19PM +0200, Steve Lhomme wrote:
> In the past the display module was checking if the size of the host HWND
> changed via the Manage callback. Now this callback doesn't exist anymore and
> the window module is responsible for reporting its size.
>
> In the case of embedded-window we need to read the size of the parent as we
> don't get any events telling us it's resized, nor that we should be resized
> (since apps using set_hwnd have no way to know the HWND we use internally to
> resize it).
> ---
> modules/video_output/drawable.c | 182 +++++++++++++++++++++++++++++++-
> 1 file changed, 178 insertions(+), 4 deletions(-)
>
> diff --git a/modules/video_output/drawable.c b/modules/video_output/drawable.c
> index ad82afadd9e9..9e1d098d0576 100644
> --- a/modules/video_output/drawable.c
> +++ b/modules/video_output/drawable.c
> @@ -64,6 +64,125 @@ static const struct vout_window_operations ops = {
> .destroy = Close,
> };
>
> +#define RECTWidth(r) (LONG)((r).right - (r).left)
> +#define RECTHeight(r) (LONG)((r).bottom - (r).top)
> +
> +static const TCHAR *EMBED_HWND_CLASS = TEXT("VLC embeded HWND");
> +
> +struct drawable_sys
> +{
> + vlc_mutex_t hwnd_lock;
> + vlc_cond_t hwnd_ready;
> + bool hwnd_is_ready;
> +
> + vout_window_t *wnd;
> + HWND hWnd;
> + HWND embed_hwnd;
> + RECT rect_parent;
> +};
> +
> +static LRESULT CALLBACK WinVoutEventProc(HWND hwnd, UINT message,
> + WPARAM wParam, LPARAM lParam )
> +{
> + if( message == WM_CREATE /*WM_NCCREATE*/ )
> + {
> + /* Store our internal structure for future use */
> + CREATESTRUCT *c = (CREATESTRUCT *)lParam;
> + SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)c->lpCreateParams );
> + return 0;
> + }
> +
> + LONG_PTR p_user_data = GetWindowLongPtr( hwnd, GWLP_USERDATA );
> + if( unlikely(p_user_data == 0) )
> + return DefWindowProc(hwnd, message, wParam, lParam);
> + struct drawable_sys *sys = (struct drawable_sys *)p_user_data;
> +
> + vout_window_t *wnd = sys->wnd;
> +
> + RECT clientRect;
> + GetClientRect(sys->embed_hwnd, &clientRect);
> + if (RECTWidth(sys->rect_parent) != RECTWidth(clientRect) ||
> + RECTHeight(sys->rect_parent) != RECTHeight(clientRect)) {
> + sys->rect_parent = clientRect;
> +
> + SetWindowPos(hwnd, 0, 0, 0,
> + RECTWidth(sys->rect_parent),
> + RECTHeight(sys->rect_parent),
> + SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
> + }
> +
> + switch( message )
> + {
> + case WM_ERASEBKGND:
> + /* nothing to erase */
> + return 1;
> +
> + case WM_PAINT:
> + /* nothing to repaint */
> + ValidateRect(hwnd, NULL);
> + break;
> +
> + case WM_CLOSE:
> + vout_window_ReportClose(wnd);
> + return 0;
> +
> + /* the window has been closed so shut down everything now */
> + case WM_DESTROY:
> + /* just destroy the window */
> + PostQuitMessage( 0 );
> + return 0;
> +
> + case WM_SIZE:
> + vout_window_ReportSize(wnd, LOWORD(lParam), HIWORD(lParam));
> + return 0;
> +
> + default:
> + break;
> + }
> +
> + /* Let windows handle the message */
> + return DefWindowProc(hwnd, message, wParam, lParam);
> +}
> +
> +static DWORD WINAPI WindowLoopThread(LPVOID lpParameter)
> +{
> + struct drawable_sys *sys = lpParameter;
> +
> + /* Get this module's instance */
> + HMODULE hInstance = GetModuleHandle(NULL);
> +
> + vlc_mutex_lock(&sys->hwnd_lock);
> + sys->hWnd =
> + CreateWindowEx( 0,
> + EMBED_HWND_CLASS, /* name of window class */
> + TEXT("Embedded HWND"), /* window title */
> + WS_CHILD|WS_VISIBLE|WS_DISABLED, /* window style */
> + 0, /* default X coordinate */
> + 0, /* default Y coordinate */
> + RECTWidth(sys->rect_parent), /* window width */
> + RECTHeight(sys->rect_parent), /* window height */
> + sys->embed_hwnd, /* parent window */
> + NULL, /* no menu in this window */
> + hInstance, /* handle of this program instance */
> + sys ); /* send to WM_CREATE */
> + sys->hwnd_is_ready = true;
> + vlc_cond_signal(&sys->hwnd_ready);
> + vlc_mutex_unlock(&sys->hwnd_lock);
> +
> + if (sys->hWnd == NULL)
> + return 1;
> +
> + /* Main loop */
> + /* GetMessage will sleep if there's no message in the queue */
> + MSG msg;
> + while( GetMessage( &msg, 0, 0, 0 ) )
> + {
> + TranslateMessage(&msg);
> + DispatchMessage(&msg);
> + }
> + return 0;
> +}
> +
> static void RemoveDrawable(HWND val)
> {
> size_t n = 0;
> @@ -84,6 +203,9 @@ static void RemoveDrawable(HWND val)
> {
> free (used);
> used = NULL;
> +
> + HINSTANCE hInstance = GetModuleHandle(NULL);
> + UnregisterClass( EMBED_HWND_CLASS, hInstance );
> }
> vlc_mutex_unlock (&serializer);
> }
> @@ -102,6 +224,7 @@ static int Open(vout_window_t *wnd)
> size_t n = 0;
>
> vlc_mutex_lock (&serializer);
> + bool first_hwnd = used == NULL;
> if (used != NULL)
> for (/*n = 0*/; used[n]; n++)
> if (used[n] == val)
> @@ -122,11 +245,62 @@ static int Open(vout_window_t *wnd)
>
> vlc_mutex_unlock (&serializer);
>
> + struct drawable_sys *sys = vlc_obj_calloc(VLC_OBJECT(wnd), 1, sizeof(*sys));
> + if (unlikely(sys == NULL)) {
> + RemoveDrawable(val);
> + return VLC_ENOMEM;
> + }
> +
> + sys->embed_hwnd = (HWND)val;
> + sys->wnd = wnd;
> + GetClientRect(sys->embed_hwnd, &sys->rect_parent);
> + vlc_mutex_init(&sys->hwnd_lock);
> + vlc_cond_init(&sys->hwnd_ready);
> +
> + if (first_hwnd)
> + {
> + /* Get this module's instance */
> + HMODULE hInstance = GetModuleHandle(NULL);
> +
> + WNDCLASS wc = { 0 }; /* window class components */
> + wc.lpfnWndProc = WinVoutEventProc; /* event handler */
> + wc.hInstance = hInstance; /* instance */
> + wc.lpszClassName = EMBED_HWND_CLASS;
> + if( !RegisterClass(&wc) )
> + {
> + msg_Err( sys->wnd, "RegisterClass failed (err=%lu)", GetLastError() );
> + goto error;
> + }
> + }
> +
> + // Create a Thread for the window event loop
> + if (CreateThread(NULL, 0, WindowLoopThread, sys, 0, NULL) == NULL)
> + {
> + msg_Err( sys->wnd, "CreateThread failed (err=%lu)", GetLastError() );
> + goto error;
> + }
> +
> + vlc_mutex_lock(&sys->hwnd_lock);
> + while (!sys->hwnd_is_ready)
> + vlc_cond_wait(&sys->hwnd_ready, &sys->hwnd_lock);
> + vlc_mutex_unlock(&sys->hwnd_lock);
> +
> + if (sys->hWnd == NULL)
> + {
> + msg_Err( sys->wnd, "Failed to create a window (err=%lu)", GetLastError() );
> + goto error;
> + }
> +
> wnd->type = VOUT_WINDOW_TYPE_HWND;
> - wnd->handle.hwnd = (void *)val;
> + wnd->handle.hwnd = (void *)sys->hWnd;
> wnd->ops = &ops;
> - wnd->sys = (void *)val;
> + wnd->sys = (void *)sys;
> return VLC_SUCCESS;
> +
> +error:
> + RemoveDrawable(sys->embed_hwnd);
> +
> + return VLC_EGENERIC;
> }
>
> /**
> @@ -134,7 +308,7 @@ static int Open(vout_window_t *wnd)
> */
> static void Close (vout_window_t *wnd)
> {
> - HWND val = (HWND) wnd->handle.hwnd;
> + struct drawable_sys *sys = wnd->sys;
>
> - RemoveDrawable(val);
> + RemoveDrawable(sys->embed_hwnd);
> }
> --
> 2.17.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list