[vlc-commits] [Git][videolan/vlc][master] win32/drawable: use GWLP_WNDPROC to receive the parent WM_SIZE

Steve Lhomme (@robUx4) gitlab at videolan.org
Thu Mar 9 13:22:03 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
a4ac04bf by Steve Lhomme at 2023-03-09T13:07:15+00:00
win32/drawable: use GWLP_WNDPROC to receive the parent WM_SIZE

This is cleaner than SetWindowsHookEx which doesn't receive events in some
case and is supposed to be used only for debugging things.

In the end we don't need a custom UI thread nor a custom HWND.

- - - - -


1 changed file:

- modules/video_output/win32/drawable.c


Changes:

=====================================
modules/video_output/win32/drawable.c
=====================================
@@ -58,8 +58,7 @@ 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 HHOOK hook = NULL;
-static struct drawable_sys *used = NULL;
+static HWND *used = NULL;
 
 static const struct vlc_window_operations ops = {
     .destroy = Close,
@@ -68,39 +67,43 @@ 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
 {
     HWND embed_hwnd;
     RECT rect_parent;
 
+    WNDPROC prev_proc;
+
     vlc_wasync_resize_compressor_t compressor;
 };
 
-static LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
+static LRESULT CALLBACK WinVoutEventProc(HWND hwnd, UINT message,
+                                         WPARAM wParam, LPARAM lParam )
 {
-    if (nCode < 0)
-        return CallNextHookEx(NULL, nCode, wParam, lParam);
-
-    MSG *pMsg = (void*)(intptr_t)lParam;
-    vlc_mutex_lock (&serializer);
-    for (struct drawable_sys *sys = used; sys->embed_hwnd != 0; sys++)
+    HANDLE p_user_data = GetProp(hwnd, EMBED_HWND_CLASS);
+    struct drawable_sys *sys = (struct drawable_sys *)p_user_data;
+    LRESULT res = CallWindowProc(sys->prev_proc, hwnd, message, wParam, lParam);
+    switch(message)
     {
-        if (pMsg->hwnd == sys->embed_hwnd)
+        case WM_SIZE:
         {
             RECT clientRect;
-            GetClientRect(pMsg->hwnd, &clientRect);
+            GetClientRect(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));
+
+                vlc_wasync_resize_compressor_reportSize(&sys->compressor,
+                                                        RECTWidth(sys->rect_parent),
+                                                        RECTHeight(sys->rect_parent));
             }
-            break;
         }
+        break;
     }
-    vlc_mutex_unlock (&serializer);
-    return 0;
+    return res;
 }
 
 static void RemoveDrawable(HWND val)
@@ -110,25 +113,19 @@ static void RemoveDrawable(HWND val)
     /* Remove this drawable from the list of busy ones */
     vlc_mutex_lock (&serializer);
     assert (used != NULL);
-    while (used[n].embed_hwnd != val)
+    while (used[n] != val)
     {
-        assert (used[n].embed_hwnd);
+        assert (used[n]);
         n++;
     }
-
-    vlc_wasync_resize_compressor_destroy(&used[n].compressor);
-
     do
         used[n] = used[n + 1];
-    while (used[++n].embed_hwnd != 0);
+    while (used[++n] != 0);
 
     if (n == 1)
     {
         free (used);
         used = NULL;
-
-        UnhookWindowsHookEx(hook);
-        hook = NULL;
     }
     vlc_mutex_unlock (&serializer);
 }
@@ -143,77 +140,59 @@ 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].embed_hwnd; n++)
-            if (used[n].embed_hwnd == val)
+        for (/*n = 0*/; used[n]; n++)
+            if (used[n] == val)
             {
                 msg_Warn (wnd, "HWND 0x%p is busy", val);
                 vlc_mutex_unlock (&serializer);
                 return VLC_EGENERIC;
             }
 
-    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));
+    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].embed_hwnd = val;
-    used[n + 1].embed_hwnd = 0;
+    used[n] = val;
+    used[n + 1] = 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;
+    }
 
-    struct drawable_sys *sys = &used[n];
-    GetClientRect(val, &sys->rect_parent);
+    sys->embed_hwnd = val;
 
     if (vlc_wasync_resize_compressor_init(&sys->compressor, wnd))
     {
         msg_Err(wnd, "Failed to init async resize compressor");
-        goto error;
+        RemoveDrawable(val);
+        return VLC_EGENERIC;
     }
 
-    vlc_wasync_resize_compressor_reportSize(&sys->compressor, RECTWidth(sys->rect_parent),
-                                                                 RECTHeight(sys->rect_parent));
+    GetClientRect(val, &sys->rect_parent);
+    vlc_wasync_resize_compressor_reportSize(&sys->compressor,
+                                            RECTWidth(sys->rect_parent),
+                                            RECTHeight(sys->rect_parent));
+
+    sys->prev_proc = (WNDPROC)(uintptr_t) GetWindowLongPtr(val, GWLP_WNDPROC);
+    SetProp(val, EMBED_HWND_CLASS, sys);
+    SetWindowLongPtr(val, GWLP_WNDPROC, (LONG_PTR) WinVoutEventProc);
 
     wnd->type = VLC_WINDOW_TYPE_HWND;
     wnd->handle.hwnd = (void *)val;
     wnd->ops = &ops;
-    wnd->sys = val;
+    wnd->sys = sys;
     return VLC_SUCCESS;
-
-error:
-    Close(wnd);
-    return VLC_EGENERIC;
 }
 
 /**
@@ -221,5 +200,13 @@ error:
  */
 static void Close (vlc_window_t *wnd)
 {
-    RemoveDrawable(wnd->sys);
+    struct drawable_sys *sys = wnd->sys;
+
+    // do not use our callback anymore
+    SetWindowLongPtr(sys->embed_hwnd, GWLP_WNDPROC, (LONG_PTR) sys->prev_proc);
+    RemoveProp(sys->embed_hwnd, EMBED_HWND_CLASS);
+
+    vlc_wasync_resize_compressor_destroy(&sys->compressor);
+
+    RemoveDrawable(sys->embed_hwnd);
 }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/a4ac04bf17064f9a21bcc6e651e8892f09f0ca81

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/a4ac04bf17064f9a21bcc6e651e8892f09f0ca81
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