[vlc-devel] [PATCH v3 5/5] vout: win32: drawable: use an internal HWND to detect size changes
Steve Lhomme
robux4 at ycbcr.xyz
Thu May 7 17:04:45 CEST 2020
On 2020-05-07 16:56, Rémi Denis-Courmont wrote:
> Le torstaina 7. toukokuuta 2020, 17.45.08 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 | 174 +++++++++++++++++++++++++++++++-
>> 1 file changed, 170 insertions(+), 4 deletions(-)
>>
>> diff --git a/modules/video_output/drawable.c
>> b/modules/video_output/drawable.c index ad82afadd9e9..901065588488 100644
>> --- a/modules/video_output/drawable.c
>> +++ b/modules/video_output/drawable.c
>> @@ -64,6 +64,121 @@ 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_sem_t hwnd_set;
>> +
>> + 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);
>> +
>> + 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 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 +199,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 +220,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 +241,58 @@ 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_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() );
>
> IIRC, Windows errors are conventionally printed in hex format?
HRESULT yes, DWORD no. It's just copy pasting code from other parts of
the code.
>> + 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_sem_wait(&sys->hwnd_set);
>> +
>> + 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;
>
> Seemingly useless cast.
>
>> return VLC_SUCCESS;
>> +
>> +error:
>> + RemoveDrawable(sys->embed_hwnd);
>> +
>> + return VLC_EGENERIC;
>> }
>>
>> /**
>> @@ -134,7 +300,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);
>> }
>
>
> --
> 雷米‧德尼-库尔蒙
> http://www.remlab.net/
>
>
>
> _______________________________________________
> 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