This fixes black screen during DirectShow video playback in some VisualArts engines applications. The affected applications use `put_Owner()` and then `put_WindowStyle(WS_CHILD)` soon after making the graph run with AutoShow enabled, which removes `WS_VISIBLE` on wine. On native, using `put_WindowStyle()` without `WS_VISIBLE` after the window is made visible retains window visibility.
From: Attila Fidan dev@print0.net
--- dlls/quartz/tests/vmr7.c | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index ff15ad9c81d..9d5a3255389 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -2321,6 +2321,69 @@ static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *grap IMediaControl_Release(control); }
+static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *graph, HWND our_hwnd) +{ + IMediaControl *control; + HRESULT hr; + LONG l; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + hr = IVideoWindow_put_AutoShow(window, OATRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_Visible(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(l == OATRUE, "Got %ld.\n", l); + + hr = IVideoWindow_put_Visible(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_AutoShow(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_Visible(window, OATRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(l == OATRUE, "Got %ld.\n", l); + + hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + ShowWindow(our_hwnd, SW_HIDE); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(l == OAFALSE, "Got %ld.\n", l); + + ShowWindow(our_hwnd, SW_SHOW); + + hr = IVideoWindow_put_Owner(window, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + IMediaControl_Release(control); +} + static void test_video_window(void) { ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props; @@ -2453,6 +2516,7 @@ static void test_video_window(void) test_video_window_state(window, hwnd, our_hwnd); test_video_window_position(window, hwnd, our_hwnd); test_video_window_autoshow(window, graph, hwnd); + test_video_window_visibility(window, graph, our_hwnd); test_video_window_owner(window, hwnd, our_hwnd); test_video_window_messages(window, hwnd, our_hwnd);
From: Attila Fidan dev@print0.net
--- dlls/quartz/tests/vmr9.c | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index bdd3516da73..1ac50e13766 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -2532,6 +2532,69 @@ static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *grap IMediaControl_Release(control); }
+static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *graph, HWND our_hwnd) +{ + IMediaControl *control; + HRESULT hr; + LONG l; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + hr = IVideoWindow_put_AutoShow(window, OATRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_Visible(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(l == OATRUE, "Got %ld.\n", l); + + hr = IVideoWindow_put_Visible(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_AutoShow(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_Visible(window, OATRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(l == OATRUE, "Got %ld.\n", l); + + hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + ShowWindow(our_hwnd, SW_HIDE); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(l == OAFALSE, "Got %ld.\n", l); + + ShowWindow(our_hwnd, SW_SHOW); + + hr = IVideoWindow_put_Owner(window, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + IMediaControl_Release(control); +} + static void test_video_window(void) { ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props; @@ -2665,6 +2728,7 @@ static void test_video_window(void) test_video_window_state(window, hwnd, our_hwnd); test_video_window_position(window, hwnd, our_hwnd); test_video_window_autoshow(window, graph, hwnd); + test_video_window_visibility(window, graph, our_hwnd); test_video_window_owner(window, hwnd, our_hwnd); test_video_window_messages(window, hwnd, our_hwnd);
From: Attila Fidan dev@print0.net
--- dlls/quartz/tests/videorenderer.c | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index ea54ec87a8e..d4296de6226 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -2306,6 +2306,69 @@ static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *grap IMediaControl_Release(control); }
+static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *graph, HWND our_hwnd) +{ + IMediaControl *control; + HRESULT hr; + LONG l; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + hr = IVideoWindow_put_AutoShow(window, OATRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_Visible(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(l == OATRUE, "Got %ld.\n", l); + + hr = IVideoWindow_put_Visible(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_AutoShow(window, OAFALSE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_Visible(window, OATRUE); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(l == OATRUE, "Got %ld.\n", l); + + hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + ShowWindow(our_hwnd, SW_HIDE); + + hr = IVideoWindow_put_WindowStyle(window, WS_CAPTION); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVideoWindow_get_Visible(window, &l); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(l == OAFALSE, "Got %ld.\n", l); + + ShowWindow(our_hwnd, SW_SHOW); + + hr = IVideoWindow_put_Owner(window, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + IMediaControl_Release(control); +} + static void test_video_window(void) { VIDEOINFOHEADER vih = @@ -2422,6 +2485,7 @@ static void test_video_window(void) test_video_window_state(window, hwnd, our_hwnd); test_video_window_position(window, hwnd, our_hwnd); test_video_window_autoshow(window, graph, hwnd); + test_video_window_visibility(window, graph, our_hwnd); test_video_window_owner(window, hwnd, our_hwnd); test_video_window_messages(window, hwnd, our_hwnd);
From: Attila Fidan dev@print0.net
Some applications set the window style while the window is visible, such as after pausing or running the graph with AutoShow enabled. On native, the window remains visible even if WS_VISIBLE isn't included. --- dlls/quartz/tests/videorenderer.c | 4 ++-- dlls/quartz/tests/vmr7.c | 4 ++-- dlls/quartz/tests/vmr9.c | 4 ++-- dlls/quartz/window.c | 7 +++++-- 4 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index d4296de6226..42a1c6c6594 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -2328,7 +2328,7 @@ static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *gr
hr = IVideoWindow_get_Visible(window, &l); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(l == OATRUE, "Got %ld.\n", l); + ok(l == OATRUE, "Got %ld.\n", l);
hr = IVideoWindow_put_Visible(window, OAFALSE); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -2344,7 +2344,7 @@ static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *gr
hr = IVideoWindow_get_Visible(window, &l); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(l == OATRUE, "Got %ld.\n", l); + ok(l == OATRUE, "Got %ld.\n", l);
hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd); ok(hr == S_OK, "Got hr %#lx.\n", hr); diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index 9d5a3255389..75b3fd221fd 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -2343,7 +2343,7 @@ static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *gr
hr = IVideoWindow_get_Visible(window, &l); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(l == OATRUE, "Got %ld.\n", l); + ok(l == OATRUE, "Got %ld.\n", l);
hr = IVideoWindow_put_Visible(window, OAFALSE); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -2359,7 +2359,7 @@ static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *gr
hr = IVideoWindow_get_Visible(window, &l); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(l == OATRUE, "Got %ld.\n", l); + ok(l == OATRUE, "Got %ld.\n", l);
hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd); ok(hr == S_OK, "Got hr %#lx.\n", hr); diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index 1ac50e13766..db0d9d35796 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -2554,7 +2554,7 @@ static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *gr
hr = IVideoWindow_get_Visible(window, &l); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(l == OATRUE, "Got %ld.\n", l); + ok(l == OATRUE, "Got %ld.\n", l);
hr = IVideoWindow_put_Visible(window, OAFALSE); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -2570,7 +2570,7 @@ static void test_video_window_visibility(IVideoWindow *window, IFilterGraph2 *gr
hr = IVideoWindow_get_Visible(window, &l); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(l == OATRUE, "Got %ld.\n", l); + ok(l == OATRUE, "Got %ld.\n", l);
hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd); ok(hr == S_OK, "Got hr %#lx.\n", hr); diff --git a/dlls/quartz/window.c b/dlls/quartz/window.c index 02c6a826bb2..41777c0bb6e 100644 --- a/dlls/quartz/window.c +++ b/dlls/quartz/window.c @@ -226,6 +226,7 @@ HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *capt HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG style) { struct video_window *window = impl_from_IVideoWindow(iface); + UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED;
TRACE("window %p, style %#lx.\n", window, style);
@@ -234,9 +235,11 @@ HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG s if (!window->pPin->peer) return VFW_E_NOT_CONNECTED;
+ if (IsWindowVisible(window->hwnd)) + flags |= SWP_SHOWWINDOW; + SetWindowLongW(window->hwnd, GWL_STYLE, style); - SetWindowPos(window->hwnd, 0, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + SetWindowPos(window->hwnd, 0, 0, 0, 0, 0, flags); return S_OK; }
Thanks for the patch. I think we should avoid toggling WS_VISIBLE, so I've taken a slightly different approach in !8848. I also took the liberty of moving the tests to existing test functions, and adding a couple of other related tests.
This merge request was closed by Attila Fidan.