[vlc-devel] [PATCH 5/5] vout: win32: drawable: use an internal HWND to detect size changes

Marvin Scholz epirat07 at gmail.com
Thu May 7 16:04:00 CEST 2020



On 7 May 2020, at 15:55, Steve Lhomme wrote:

> On 2020-05-07 15:43, Rémi Denis-Courmont wrote:
>> Le torstaina 7. toukokuuta 2020, 15.39.12 EEST Steve Lhomme a écrit 
>> :
>>> 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 | 183 
>>> +++++++++++++++++++++++++++++++-
>>>   1 file changed, 179 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/modules/video_output/drawable.c
>>> b/modules/video_output/drawable.c index ad82afadd9e9..350be296687d 
>>> 100644
>>> --- a/modules/video_output/drawable.c
>>> +++ b/modules/video_output/drawable.c
>>> @@ -64,6 +64,127 @@ 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;
>>> +
>>> +    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 */ +
>>> +    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;
>>> +    for( ;; )
>>> +    {
>>> +        if( !GetMessage( &msg, 0, 0, 0 ) )
>>> +            break;
>>
>> while...
>
> OK
>
>>> +
>>> +        TranslateMessage(&msg);
>>> +        DispatchMessage(&msg);
>>> +    }
>>> +    return 0;
>>> +}
>>> +
>>>   static void RemoveDrawable(HWND val)
>>>   {
>>>       size_t n = 0;
>>> @@ -84,6 +205,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 +226,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 +247,61 @@ 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);
>>> +    vlc_cond_wait(&sys->hwnd_ready, &sys->hwnd_lock);
>>> +    vlc_mutex_unlock(&sys->hwnd_lock);
>>
>> This is wrong, as has been explained many Many MANY times.
>
> Define "this" because I have no idea what you are referring to.


I believe you need the actual condition you want to check in
some variable, check it in a while loop and do the cond wait
in the body of that, as it can wake even when the condition
is not signalled.

So you want something like:

vlc_mutex_lock(&sys->hwnd_lock);
while (!hwnd_is_ready)
     vlc_cond_wait(&sys->hwnd_ready, &sys->hwnd_lock);
vlc_mutex_unlock(&sys->hwnd_lock);

I think?

> _______________________________________________
> 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