[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