[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:27:42 CEST 2020


I forgot to look for 'calloc', but the simplification stands.

Sorry for this :)

On Thu, May 07, 2020 at 04:26:03PM +0200, 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


More information about the vlc-devel mailing list