From: Akihiro Sagawa sagawa.aki@gmail.com
Now the video renderer window by IVideoWindow always has WS_CHILD style regardless open parameters.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52448 Signed-off-by: Akihiro Sagawa sagawa.aki@gmail.com --- dlls/mciqtz32/mciqtz.c | 133 ++++++++++++++++++++++++--------- dlls/mciqtz32/mciqtz_private.h | 1 + dlls/winmm/tests/mci.c | 42 +++++------ 3 files changed, 117 insertions(+), 59 deletions(-)
diff --git a/dlls/mciqtz32/mciqtz.c b/dlls/mciqtz32/mciqtz.c index 05929d25680..2439bfeea62 100644 --- a/dlls/mciqtz32/mciqtz.c +++ b/dlls/mciqtz32/mciqtz.c @@ -19,6 +19,7 @@ */
#include <stdarg.h> +#include <stdbool.h> #include <math.h> #include "windef.h" #include "winbase.h" @@ -31,6 +32,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(mciqtz);
+static const WCHAR mciqtz_class[] = L"MCIQTZ_Window"; + static DWORD MCIQTZ_mciClose(UINT, DWORD, LPMCI_GENERIC_PARMS); static DWORD MCIQTZ_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
@@ -68,6 +71,24 @@ static WINE_MCIQTZ* MCIQTZ_mciGetOpenDev(UINT wDevID) return wma; }
+static void unregister_class(void) +{ + UnregisterClassW(mciqtz_class, MCIQTZ_hInstance); +} + +static bool register_class(void) +{ + WNDCLASSW class = {0}; + + class.lpfnWndProc = DefWindowProcW; + class.cbWndExtra = sizeof(MCIDEVICEID); + class.hInstance = MCIQTZ_hInstance; + class.hCursor = LoadCursorW(0, (const WCHAR *)IDC_ARROW); + class.lpszClassName = mciqtz_class; + + return RegisterClassW(&class) || GetLastError() == ERROR_CLASS_ALREADY_EXISTS; +} + /************************************************************************** * MCIQTZ_drvOpen [internal] */ @@ -81,6 +102,9 @@ static DWORD MCIQTZ_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp) if (!modp) return 0xFFFFFFFF;
+ if (!register_class()) + return 0; + wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIQTZ)); if (!wma) return 0; @@ -109,6 +133,7 @@ static DWORD MCIQTZ_drvClose(DWORD dwDevID) /* finish all outstanding things */ MCIQTZ_mciClose(dwDevID, MCI_WAIT, NULL);
+ unregister_class(); mciFreeCommandResource(wma->command_table); mciSetDriverData(dwDevID, 0); CloseHandle(wma->stop_event); @@ -139,6 +164,64 @@ static DWORD MCIQTZ_drvConfigure(DWORD dwDevID) return 1; }
+static bool create_window(WINE_MCIQTZ *wma, DWORD flags, const MCI_DGV_OPEN_PARMSW *params) +{ + DWORD style = (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN) & ~WS_MAXIMIZEBOX; + LONG width, height, min_width; + HWND parent = NULL; + HRESULT hr; + RECT rc; + + if (flags & MCI_DGV_OPEN_PARENT) + parent = params->hWndParent; + if (flags & MCI_DGV_OPEN_WS) + style = params->dwStyle; + + hr = IBasicVideo_GetVideoSize(wma->vidbasic, &width, &height); + if (hr == E_NOINTERFACE) + return true; /* audio file */ + else if (FAILED(hr)) + { + ERR("Failed to get video size, hr %#lx.\n", hr); + return false; + } + + /* Native always assumes an overlapped window + * when calculating default video window size. */ + SetRect(&rc, 0, 0, width, height); + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + min_width = GetSystemMetrics(SM_CXMIN); + width = max(rc.right - rc.left, min_width); + height = rc.bottom - rc.top; + + wma->window = CreateWindowW(mciqtz_class, params->lpstrElementName, style, + CW_USEDEFAULT, CW_USEDEFAULT, width, height, parent, NULL, MCIQTZ_hInstance, NULL); + + TRACE("device %#x, flags %#lx, style %#lx, parent %p, dimensions %ldx%ld, created window %p.\n", + wma->wDevID, flags, style, parent, width, height, wma->window); + + if (!wma->window) + { + ERR("Failed to create window, error %lu.\n", GetLastError()); + return false; + } + + IVideoWindow_put_AutoShow(wma->vidwin, OAFALSE); + IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)wma->window); + IVideoWindow_put_Owner(wma->vidwin, (OAHWND)wma->window); + IVideoWindow_put_WindowStyle(wma->vidwin, WS_CHILD); /* reset window style */ + + GetClientRect(wma->window, &rc); + width = rc.right; + height = rc.bottom; + + IVideoWindow_SetWindowPosition(wma->vidwin, 0, 0, width, height); + IVideoWindow_put_Visible(wma->vidwin, OATRUE); + wma->parent = wma->window; + + return true; +} + /************************************************************************** * MCIQTZ_mciNotify [internal] * @@ -161,8 +244,6 @@ static DWORD MCIQTZ_mciOpen(UINT wDevID, DWORD dwFlags, { WINE_MCIQTZ* wma; HRESULT hr; - DWORD style = 0; - RECT rc = { 0, 0, 0, 0 };
TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpOpenParms);
@@ -238,22 +319,8 @@ static DWORD MCIQTZ_mciOpen(UINT wDevID, DWORD dwFlags, goto err; }
- IVideoWindow_put_AutoShow(wma->vidwin, OAFALSE); - IVideoWindow_put_Visible(wma->vidwin, OAFALSE); - if (dwFlags & MCI_DGV_OPEN_WS) - style = lpOpenParms->dwStyle; - if (dwFlags & MCI_DGV_OPEN_PARENT) { - IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)lpOpenParms->hWndParent); - IVideoWindow_put_WindowState(wma->vidwin, SW_HIDE); - IVideoWindow_put_WindowStyle(wma->vidwin, style|WS_CHILD); - IVideoWindow_put_Owner(wma->vidwin, (OAHWND)lpOpenParms->hWndParent); - GetClientRect(lpOpenParms->hWndParent, &rc); - IVideoWindow_SetWindowPosition(wma->vidwin, rc.left, rc.top, rc.right - rc.top, rc.bottom - rc.top); - wma->parent = (HWND)lpOpenParms->hWndParent; - } - else if (style) - IVideoWindow_put_WindowStyle(wma->vidwin, style); - IBasicVideo_GetVideoSize(wma->vidbasic, &rc.right, &rc.bottom); + if (!create_window(wma, dwFlags, lpOpenParms)) + goto err; wma->opened = TRUE;
if (dwFlags & MCI_NOTIFY) @@ -307,6 +374,13 @@ static DWORD MCIQTZ_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpP MCIQTZ_mciStop(wDevID, MCI_WAIT, NULL);
if (wma->opened) { + if (wma->window) + { + IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)NULL); + IVideoWindow_put_Owner(wma->vidwin, (OAHWND)NULL); + DestroyWindow(wma->window); + wma->window = NULL; + } IVideoWindow_Release(wma->vidwin); IBasicVideo_Release(wma->vidbasic); IBasicAudio_Release(wma->audio); @@ -447,7 +521,8 @@ static DWORD MCIQTZ_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms return MCIERR_INTERNAL; }
- IVideoWindow_put_Visible(wma->vidwin, OATRUE); + if (wma->parent) + ShowWindow(wma->parent, SW_SHOW);
if (!wma->thread) { @@ -919,21 +994,11 @@ static DWORD MCIQTZ_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMS return 0;
if (dwFlags & MCI_DGV_WINDOW_HWND && (IsWindow(lpParms->hWnd) || !lpParms->hWnd)) { - LONG visible = OATRUE; - LONG style = 0; - TRACE("Setting hWnd to %p\n", lpParms->hWnd); - IVideoWindow_get_Visible(wma->vidwin, &visible); - IVideoWindow_put_Visible(wma->vidwin, OAFALSE); - IVideoWindow_get_WindowStyle(wma->vidwin, &style); - style &= ~WS_CHILD; - if (lpParms->hWnd) - IVideoWindow_put_WindowStyle(wma->vidwin, style|WS_CHILD); - else - IVideoWindow_put_WindowStyle(wma->vidwin, style); - IVideoWindow_put_Owner(wma->vidwin, (OAHWND)lpParms->hWnd); - IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)lpParms->hWnd); - IVideoWindow_put_Visible(wma->vidwin, visible); - wma->parent = lpParms->hWnd; + HWND hwnd = lpParms->hWnd ? lpParms->hWnd : wma->window; + TRACE("Setting parent window to %p.\n", hwnd); + IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)hwnd); + IVideoWindow_put_Owner(wma->vidwin, (OAHWND)hwnd); + wma->parent = hwnd; } if (dwFlags & MCI_DGV_WINDOW_STATE) { TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow); diff --git a/dlls/mciqtz32/mciqtz_private.h b/dlls/mciqtz32/mciqtz_private.h index aa6fad99326..9206a88b3fa 100644 --- a/dlls/mciqtz32/mciqtz_private.h +++ b/dlls/mciqtz32/mciqtz_private.h @@ -42,6 +42,7 @@ typedef struct { REFERENCE_TIME seek_stop; UINT command_table; HWND parent; + HWND window; MCIDEVICEID notify_devid; HANDLE callback; HANDLE thread; diff --git a/dlls/winmm/tests/mci.c b/dlls/winmm/tests/mci.c index a0989d542c5..ee75a05d9c2 100644 --- a/dlls/winmm/tests/mci.c +++ b/dlls/winmm/tests/mci.c @@ -1566,15 +1566,10 @@ static void test_video_window(void) { video_window = NULL; EnumWindows(my_visible_window_proc, (LPARAM)&video_window); - todo_wine_if (testcase[i].open_flags & MCI_DGV_OPEN_PARENT) - ok(video_window != NULL, "Video window should be shown.\n"); - - /* FIXME: Remove once Wine is fixed */ - if (!video_window) goto next; + ok(video_window != NULL, "Video window should be shown.\n");
hwnd = GetWindow(video_window, GW_OWNER); - todo_wine_if (testcase[i].open_flags & MCI_DGV_OPEN_PARENT) - ok(hwnd == parent_window, "Got owner %p, expected %p.\n", hwnd, parent_window); + ok(hwnd == parent_window, "Got owner %p, expected %p.\n", hwnd, parent_window); } else { @@ -1588,8 +1583,7 @@ static void test_video_window(void)
expected = testcase[i].expected_style | WS_VISIBLE; style = GetWindowLongW(video_window, GWL_STYLE); - todo_wine_if (i != 3) - ok(style == expected, "Got style %#lx for window %p, expected %#lx.\n", style, video_window, expected); + ok(style == expected, "Got style %#lx for window %p, expected %#lx.\n", style, video_window, expected);
/* Get the source video size. */ err = mciSendCommandW(id, MCI_WHERE, MCI_DGV_WHERE_SOURCE, (DWORD_PTR)&parm); @@ -1623,16 +1617,16 @@ static void test_video_window(void)
GetWindowRect(video_window, &win_rc); OffsetRect(&rc, win_rc.left, win_rc.top); - todo_wine_if (testcase[i].style & WS_CHILD) - ok(EqualRect(&rc, &win_rc), "Got window rect %s, expected %s.\n", - wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&rc)); + ok(EqualRect(&rc, &win_rc), "Got window rect %s, expected %s.\n", + wine_dbgstr_rect(&win_rc), wine_dbgstr_rect(&rc));
err = mciSendCommandW(id, MCI_WHERE, MCI_DGV_WHERE_WINDOW, (DWORD_PTR)&parm); ok(!err, "Got %s.\n", dbg_mcierr(err)); win_rc.right -= win_rc.left; win_rc.bottom -= win_rc.top; - ok(EqualRect(&win_rc, &parm.where.rc), "Got rect %s, expected %s.\n", - wine_dbgstr_rect(&parm.where.rc), wine_dbgstr_rect(&win_rc)); + todo_wine_if (!(style & WS_CHILD)) + ok(EqualRect(&win_rc, &parm.where.rc), "Got rect %s, expected %s.\n", + wine_dbgstr_rect(&parm.where.rc), wine_dbgstr_rect(&win_rc));
err = mciSendCommandW(id, MCI_STOP, 0, (DWORD_PTR)&parm); ok(!err, "Got %s.\n", dbg_mcierr(err)); @@ -1656,11 +1650,11 @@ static void test_video_window(void) ok(!IsWindowVisible(main_window), "Main window should be hidden.\n");
hwnd = GetWindow(main_window, GW_CHILD); - todo_wine ok(hwnd != video_window, - "Video window (%p) and child window (%p) should be different.\n", video_window, hwnd); + ok(hwnd != video_window, "Video window (%p) and child window (%p) should be different.\n", + video_window, hwnd); style = GetWindowLongW(hwnd, GWL_STYLE); expected = WS_CHILD | WS_VISIBLE; - todo_wine ok(style == expected, "Child window %p: got style %#lx, expected %#lx.\n", + ok(style == expected, "Child window %p: got style %#lx, expected %#lx.\n", hwnd, style, expected);
style = GetWindowLongW(video_window, GWL_STYLE); @@ -1687,30 +1681,28 @@ static void test_video_window(void)
err = mciSendCommandW(id, MCI_WHERE, MCI_DGV_WHERE_DESTINATION, (DWORD_PTR)&parm); ok(!err, "Got %s.\n", dbg_mcierr(err)); - todo_wine_if ((testcase[i].style & (WS_CHILD | WS_POPUP)) != WS_CHILD) - ok(EqualRect(&parm.where.rc, &rc), "Got destination rect %s, expected %s.\n", - wine_dbgstr_rect(&parm.where.rc), wine_dbgstr_rect(&rc)); + ok(EqualRect(&parm.where.rc, &rc), "Got destination rect %s, expected %s.\n", + wine_dbgstr_rect(&parm.where.rc), wine_dbgstr_rect(&rc));
/* MCI_PLAY shows current video window */ err = mciSendCommandW(id, MCI_PLAY, 0, (DWORD_PTR)&parm); ok(!err, "Got %s.\n", dbg_mcierr(err)); - todo_wine ok(IsWindowVisible(main_window), "Main window should be shown.\n"); + ok(IsWindowVisible(main_window), "Main window should be shown.\n"); ok(IsWindow(video_window), "Video window should exist.\n"); - ok(!IsWindowVisible(video_window), "Video window should be hidden.\n"); + todo_wine ok(!IsWindowVisible(video_window), "Video window should be hidden.\n");
/* video window is reset to the default window, which is visible again */ parm.win.hWnd = NULL; err = mciSendCommandW(id, MCI_WINDOW, MCI_DGV_WINDOW_HWND, (DWORD_PTR)&parm); ok(!err, "Got %s.\n", dbg_mcierr(err)); - todo_wine ok(IsWindowVisible(main_window), "Main window should be shown.\n"); - todo_wine ok(IsWindowVisible(video_window), "Video window should be shown.\n"); + ok(IsWindowVisible(main_window), "Main window should be shown.\n"); + ok(IsWindowVisible(video_window), "Video window should be shown.\n");
err = mciSendCommandW(id, MCI_WHERE, MCI_DGV_WHERE_DESTINATION, (DWORD_PTR)&parm); ok(!err, "Got %s.\n", dbg_mcierr(err)); todo_wine ok(EqualRect(&parm.where.rc, &src_rc), "Got destination rect %s, expected %s.\n", wine_dbgstr_rect(&parm.where.rc), wine_dbgstr_rect(&src_rc));
-next: err = mciSendCommandW(id, MCI_CLOSE, 0, 0); ok(!err, "Got %s.\n", dbg_mcierr(err));