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

Steve Lhomme robux4 at ycbcr.xyz
Thu May 7 15:55:50 CEST 2020


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.


More information about the vlc-devel mailing list