[vlc-devel] [PATCH v2 5/5] vout: win32: drawable: use an internal HWND to detect size changes
Steve Lhomme
robux4 at ycbcr.xyz
Thu May 7 16:46:04 CEST 2020
It turns out vlc_sem_t uses vlc_atomic_wait but in a cleaner way.
On 2020-05-07 16:31, Steve Lhomme wrote:
> My understanding is that semaphores are heavier that condition
> variables. On the other hand it would be a clean win32 API call...
>
> On 2020-05-07 16:26, Alexandre Janniaux wrote:
>> 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
>> _______________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
>>
> _______________________________________________
> 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