[vlc-commits] [Git][videolan/vlc][master] 2 commits: win32: drawable: replace the internal HWND with a hook on the parent Window

Steve Lhomme (@robUx4) gitlab at videolan.org
Thu Nov 17 14:51:34 UTC 2022



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
e568b2fd by Steve Lhomme at 2022-11-17T14:39:26+00:00
win32: drawable: replace the internal HWND with a hook on the parent Window

Every time the parent receives a message, we check if the size has not changed.

The window hook only works if we have a DLL. This is the case in regular windows
builds. It won't work if it's very built statically.

We do not use an internal HWND anymore that was not always getting the WM_SIZE
events.

- - - - -
7c64a9d2 by Steve Lhomme at 2022-11-17T14:39:26+00:00
doc: win32: remove window flag that redraws the window

This trick worked to redraw/resize the VLC HWND when the parent changes. But
not all apps can do that.

- - - - -


2 changed files:

- doc/libvlc/win_player.c
- modules/video_output/win32/drawable.c


Changes:

=====================================
doc/libvlc/win_player.c
=====================================
@@ -124,7 +124,6 @@ int WINAPI WinMain(HINSTANCE hInstance,
     ZeroMemory(&wc, sizeof(WNDCLASSEX));
 
     wc.cbSize = sizeof(WNDCLASSEX);
-    wc.style = CS_HREDRAW | CS_VREDRAW;
     wc.lpfnWndProc = WindowProc;
     wc.hInstance = hInstance;
     wc.hCursor = LoadCursor(NULL, IDC_ARROW);


=====================================
modules/video_output/win32/drawable.c
=====================================
@@ -58,7 +58,8 @@ vlc_module_end ()
 /* Keep a list of busy drawables, so we don't overlap videos if there are
  * more than one video track in the stream. */
 static vlc_mutex_t serializer = VLC_STATIC_MUTEX;
-static HWND *used = NULL;
+static HHOOK hook = NULL;
+static struct drawable_sys *used = NULL;
 
 static const struct vlc_window_operations ops = {
     .destroy = Close,
@@ -67,120 +68,39 @@ static const struct vlc_window_operations ops = {
 #define RECTWidth(r)   (LONG)((r).right - (r).left)
 #define RECTHeight(r)  (LONG)((r).bottom - (r).top)
 
-static const TCHAR *EMBED_HWND_CLASS = TEXT("VLC embedded HWND");
-
 struct drawable_sys
 {
-    vlc_thread_t thread;
-    vlc_sem_t hwnd_set;
-
-    vlc_window_t *wnd;
-    HWND hWnd;
     HWND embed_hwnd;
     RECT rect_parent;
 
     vlc_wasync_resize_compressor_t compressor;
 };
 
-static LRESULT CALLBACK WinVoutEventProc(HWND hwnd, UINT message,
-                                         WPARAM wParam, LPARAM lParam )
+static LRESULT CALLBACK GetMsgProc(int nCode, 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;
-
-    vlc_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;
+    if (nCode < 0)
+        return CallNextHookEx(NULL, nCode, wParam, lParam);
 
-        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:
-        /* wait for all pending timers */
-        vlc_wasync_resize_compressor_dropOrWait(&sys->compressor);
-        vlc_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:
-        vlc_wasync_resize_compressor_reportSize(&sys->compressor, LOWORD(lParam), HIWORD(lParam));
-        return 0;
-    default:
-        break;
-    }
-
-    /* Let windows handle the message */
-    return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-static void *WindowLoopThread(void *lpParameter)
-{
-    struct drawable_sys *sys = lpParameter;
-
-    /* Get this module's instance */
-    HMODULE hInstance = GetModuleHandle(NULL);
-
-    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_sem_post(&sys->hwnd_set);
-
-    if (sys->hWnd == NULL)
-        return NULL;
-
-    /* Main loop */
-    /* GetMessage will sleep if there's no message in the queue */
-    MSG msg;
-    while( GetMessage( &msg, 0, 0, 0 ) )
+    MSG *pMsg = (void*)(intptr_t)lParam;
+    vlc_mutex_lock (&serializer);
+    for (struct drawable_sys *sys = used; sys->embed_hwnd != 0; sys++)
     {
-        TranslateMessage(&msg);
-        DispatchMessage(&msg);
+        if (pMsg->hwnd == sys->embed_hwnd)
+        {
+            RECT clientRect;
+            GetClientRect(pMsg->hwnd, &clientRect);
+            if (RECTWidth(sys->rect_parent)  != RECTWidth(clientRect) ||
+                RECTHeight(sys->rect_parent) != RECTHeight(clientRect))
+            {
+                sys->rect_parent = clientRect;
+                vlc_wasync_resize_compressor_reportSize(&sys->compressor, RECTWidth(sys->rect_parent),
+                                                                          RECTHeight(sys->rect_parent));
+            }
+            break;
+        }
     }
-    return NULL;
+    vlc_mutex_unlock (&serializer);
+    return 0;
 }
 
 static void RemoveDrawable(HWND val)
@@ -190,22 +110,25 @@ static void RemoveDrawable(HWND val)
     /* Remove this drawable from the list of busy ones */
     vlc_mutex_lock (&serializer);
     assert (used != NULL);
-    while (used[n] != val)
+    while (used[n].embed_hwnd != val)
     {
-        assert (used[n]);
+        assert (used[n].embed_hwnd);
         n++;
     }
+
+    vlc_wasync_resize_compressor_destroy(&used[n].compressor);
+
     do
         used[n] = used[n + 1];
-    while (used[++n] != 0);
+    while (used[++n].embed_hwnd != 0);
 
     if (n == 1)
     {
         free (used);
         used = NULL;
 
-        HINSTANCE hInstance = GetModuleHandle(NULL);
-        UnregisterClass( EMBED_HWND_CLASS, hInstance );
+        UnhookWindowsHookEx(hook);
+        hook = NULL;
     }
     vlc_mutex_unlock (&serializer);
 }
@@ -220,57 +143,58 @@ static int Open(vlc_window_t *wnd)
         return VLC_EGENERIC;
     HWND val = (HWND)drawable;
 
-    HWND *tab;
     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)
+        for (/*n = 0*/; used[n].embed_hwnd; n++)
+            if (used[n].embed_hwnd == val)
             {
                 msg_Warn (wnd, "HWND 0x%p is busy", val);
                 vlc_mutex_unlock (&serializer);
                 return VLC_EGENERIC;
             }
 
-    tab = realloc (used, sizeof (*used) * (n + 2));
+    if (hook == NULL)
+    {
+        assert(first_hwnd);
+        /* Get this DLL instance, it can't be a global module */
+        HMODULE hInstance = GetModuleHandle(TEXT("lib" MODULE_STRING "_plugin.dll"));
+        hook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hInstance, 0);
+        if (hook == NULL)
+        {
+            vlc_mutex_unlock (&serializer);
+
+            char msg[256];
+            int i_error = GetLastError();
+            FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                            NULL, i_error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                            msg, ARRAY_SIZE(msg), NULL );
+            msg_Err(wnd, "Failed to hook to the parent window: %s", msg);
+            return VLC_EGENERIC;
+        }
+    }
+
+    struct drawable_sys *tab = realloc (used, sizeof (*used) * (n + 2));
     if (unlikely(tab == NULL)) {
         vlc_mutex_unlock (&serializer);
+        if (first_hwnd)
+        {
+            UnhookWindowsHookEx(hook);
+            hook = NULL;
+        }
         return VLC_ENOMEM;
     }
     used = tab;
-    used[n] = val;
-    used[n + 1] = 0;
+    used[n].embed_hwnd = val;
+    used[n + 1].embed_hwnd = 0;
 
     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_sem_init(&sys->hwnd_set, 0);
 
-    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;
-        }
-    }
+    struct drawable_sys *sys = &used[n];
+    GetClientRect(val, &sys->rect_parent);
 
     if (vlc_wasync_resize_compressor_init(&sys->compressor, wnd))
     {
@@ -278,25 +202,13 @@ static int Open(vlc_window_t *wnd)
         goto error;
     }
 
-    // Create a Thread for the window event loop
-    if (vlc_clone(&sys->thread, WindowLoopThread, sys))
-    {
-        msg_Err( sys->wnd, "Failed to start WindowLoopThread");
-        goto error;
-    }
-
-    vlc_sem_wait(&sys->hwnd_set);
-
-    if (sys->hWnd == NULL)
-    {
-        msg_Err( sys->wnd, "Failed to create a window (err=%lu)", GetLastError() );
-        goto error;
-    }
+    vlc_wasync_resize_compressor_reportSize(&sys->compressor, RECTWidth(sys->rect_parent),
+                                                                 RECTHeight(sys->rect_parent));
 
     wnd->type = VLC_WINDOW_TYPE_HWND;
-    wnd->handle.hwnd = (void *)sys->hWnd;
+    wnd->handle.hwnd = (void *)val;
     wnd->ops = &ops;
-    wnd->sys = (void *)sys;
+    wnd->sys = val;
     return VLC_SUCCESS;
 
 error:
@@ -309,15 +221,5 @@ error:
  */
 static void Close (vlc_window_t *wnd)
 {
-    struct drawable_sys *sys = wnd->sys;
-
-    if (sys->hWnd)
-        PostMessage( sys->hWnd, WM_CLOSE, 0, 0 );
-
-    if (sys->thread != NULL)
-        vlc_join(sys->thread, NULL);
-
-    vlc_wasync_resize_compressor_destroy(&sys->compressor);
-
-    RemoveDrawable(sys->embed_hwnd);
+    RemoveDrawable(wnd->sys);
 }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/329cff0aeb9c75f46c57743e670273cf604d11c3...7c64a9d27a2245c311e643959d26a770e360edfb

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/329cff0aeb9c75f46c57743e670273cf604d11c3...7c64a9d27a2245c311e643959d26a770e360edfb
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list