From: Zhiyi Zhang Subject: [PATCH v2 5/5] wined3d: Fix cursor clipping after changing display mode. Message-Id: <2e1c51a8-b104-efe1-b3d1-10cebdf2a684@codeweavers.com> Date: Wed, 8 Apr 2020 18:01:50 +0800 DirectDraw should clip the cursor to the primary screen only when the cooperative level is DDSCL_EXCLUSIVE. For Direct3D 8, 9 and DXGI, changing display mode shouldn't clip the cursor as tests showed. Signed-off-by: Zhiyi Zhang --- dlls/d3d8/tests/device.c | 2 -- dlls/d3d9/tests/device.c | 2 -- dlls/ddraw/ddraw.c | 31 +++++++++++++++++++++++++++---- dlls/ddraw/tests/ddraw7.c | 3 --- dlls/dxgi/tests/dxgi.c | 2 -- dlls/wined3d/directx.c | 5 ----- dlls/wined3d/swapchain.c | 1 - 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index ead5f47bf14..b9d838e5cd4 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -10152,7 +10152,6 @@ static void test_cursor_clipping(void) get_virtual_rect(&virtual_rect); ok(GetClipCursor(&clip_rect), "Adapter %u: GetClipCursor failed, error %#x.\n", adapter_idx, GetLastError()); - todo_wine_if(!EqualRect(&clip_rect, &virtual_rect)) ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u: Expect clip rect %s, got %s.\n", adapter_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect)); @@ -10161,7 +10160,6 @@ static void test_cursor_clipping(void) get_virtual_rect(&virtual_rect); ok(GetClipCursor(&clip_rect), "Adapter %u: GetClipCursor failed, error %#x.\n", adapter_idx, GetLastError()); - todo_wine_if(!EqualRect(&clip_rect, &virtual_rect)) ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u: Expect clip rect %s, got %s.\n", adapter_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect)); } diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index b84a35714cd..c65f0cd04da 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -13893,7 +13893,6 @@ static void test_cursor_clipping(void) get_virtual_rect(&virtual_rect); ok(GetClipCursor(&clip_rect), "Adapter %u: GetClipCursor failed, error %#x.\n", adapter_idx, GetLastError()); - todo_wine_if(!EqualRect(&clip_rect, &virtual_rect)) ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u: Expect clip rect %s, got %s.\n", adapter_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect)); @@ -13902,7 +13901,6 @@ static void test_cursor_clipping(void) get_virtual_rect(&virtual_rect); ok(GetClipCursor(&clip_rect), "Adapter %u: GetClipCursor failed, error %#x.\n", adapter_idx, GetLastError()); - todo_wine_if(!EqualRect(&clip_rect, &virtual_rect)) ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u: Expect clip rect %s, got %s.\n", adapter_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect)); } diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index db7fc2c9486..95e9fba9011 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -665,6 +665,8 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface) { struct ddraw *ddraw = impl_from_IDirectDraw7(iface); + struct wined3d_display_mode mode; + RECT clip_rect; HRESULT hr; TRACE("iface %p.\n", iface); @@ -684,7 +686,15 @@ static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface) } if (SUCCEEDED(hr = wined3d_output_set_display_mode(ddraw->wined3d_output, NULL))) + { ddraw->flags &= ~DDRAW_RESTORE_MODE; + if (ddraw->cooperative_level & DDSCL_EXCLUSIVE && + SUCCEEDED(hr = wined3d_output_get_display_mode(ddraw->wined3d_output, &mode, NULL))) + { + SetRect(&clip_rect, 0, 0, mode.width, mode.height); + ClipCursor(&clip_rect); + } + } InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK); @@ -768,6 +778,7 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, struct wined3d_rendertarget_view *rtv = NULL, *dsv = NULL; struct wined3d_stateblock *stateblock; BOOL restore_state = FALSE; + RECT clip_rect; HRESULT hr; TRACE("ddraw %p, window %p, flags %#x, restore_mode_on_normal %x.\n", ddraw, window, cooplevel, @@ -942,12 +953,11 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, wined3d_stateblock_decref(stateblock); } - if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE) - && restore_mode_on_normal) + if (!(cooplevel & DDSCL_EXCLUSIVE) && (ddraw->cooperative_level & DDSCL_EXCLUSIVE)) { - hr = ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface); - if (FAILED(hr)) + if (restore_mode_on_normal && FAILED(ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface))) ERR("RestoreDisplayMode failed\n"); + ClipCursor(NULL); } if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE) @@ -965,6 +975,12 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window, } } + if (cooplevel & DDSCL_EXCLUSIVE) + { + SetRect(&clip_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + ClipCursor(&clip_rect); + } + /* Unhandled flags */ if (cooplevel & DDSCL_ALLOWREBOOT) WARN("Unhandled flag DDSCL_ALLOWREBOOT, harmless\n"); @@ -1059,6 +1075,7 @@ static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD width, DW struct ddraw *ddraw = impl_from_IDirectDraw7(iface); struct wined3d_display_mode mode; enum wined3d_format_id format; + RECT clip_rect; HRESULT hr; TRACE("iface %p, width %u, height %u, bpp %u, refresh_rate %u, flags %#x.\n", @@ -1117,6 +1134,12 @@ static HRESULT WINAPI ddraw7_SetDisplayMode(IDirectDraw7 *iface, DWORD width, DW ddrawformat_from_wined3dformat(&ddraw->primary->surface_desc.u4.ddpfPixelFormat, mode.format_id); } ddraw->flags |= DDRAW_RESTORE_MODE; + + if (ddraw->cooperative_level & DDSCL_EXCLUSIVE) + { + SetRect(&clip_rect, 0, 0, width, height); + ClipCursor(&clip_rect); + } } InterlockedCompareExchange(&ddraw->device_state, DDRAW_DEVICE_STATE_NOT_RESTORED, DDRAW_DEVICE_STATE_OK); diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index a90fe51a508..2edb3ae229c 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -17409,7 +17409,6 @@ static void test_cursor_clipping(void) flush_events(); get_virtual_rect(&rect); ok(GetClipCursor(&clip_rect), "GetClipCursor failed, error %#x.\n", GetLastError()); - todo_wine_if(!EqualRect(&clip_rect, &rect)) ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect), wine_dbgstr_rect(&clip_rect)); @@ -17418,7 +17417,6 @@ static void test_cursor_clipping(void) flush_events(); get_virtual_rect(&rect); ok(GetClipCursor(&clip_rect), "GetClipCursor failed, error %#x.\n", GetLastError()); - todo_wine_if(GetSystemMetrics(SM_CMONITORS) > 1) ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect), wine_dbgstr_rect(&clip_rect)); @@ -17460,7 +17458,6 @@ static void test_cursor_clipping(void) flush_events(); get_virtual_rect(&rect); ok(GetClipCursor(&clip_rect), "GetClipCursor failed, error %#x.\n", GetLastError()); - todo_wine_if(GetSystemMetrics(SM_CMONITORS) > 1) ok(EqualRect(&clip_rect, &rect), "Expect clip rect %s, got %s.\n", wine_dbgstr_rect(&rect), wine_dbgstr_rect(&clip_rect)); diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 1565cbeb928..bbeaaa537b5 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -6118,7 +6118,6 @@ static void test_cursor_clipping(IUnknown *device, BOOL is_d3d12) ok(GetClipCursor(&clip_rect), "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx, output_idx, GetLastError()); - todo_wine_if(!EqualRect(&clip_rect, &virtual_rect)) ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx, output_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect)); @@ -6139,7 +6138,6 @@ static void test_cursor_clipping(IUnknown *device, BOOL is_d3d12) ok(GetClipCursor(&clip_rect), "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx, output_idx, GetLastError()); - todo_wine_if(!EqualRect(&clip_rect, &virtual_rect)) ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx, output_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect)); diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index cb3e0dd1041..42e1578561f 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1260,7 +1260,6 @@ HRESULT CDECL wined3d_output_set_display_mode(struct wined3d_output *output, const struct wined3d_display_mode *mode) { DEVMODEW new_mode, current_mode; - RECT clip_rc; LONG ret; enum wined3d_format_id new_format_id; @@ -1341,10 +1340,6 @@ HRESULT CDECL wined3d_output_set_display_mode(struct wined3d_output *output, /* Store the new values. */ output->screen_format = new_format_id; - /* And finally clip mouse to our screen. */ - SetRect(&clip_rc, 0, 0, new_mode.dmPelsWidth, new_mode.dmPelsHeight); - ClipCursor(&clip_rc); - return WINED3D_OK; } diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index e4cb5a27469..86f8277a27d 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -1067,7 +1067,6 @@ err: if (!output || FAILED(wined3d_output_set_display_mode(output, &swapchain->state.original_mode))) ERR("Failed to restore display mode.\n"); - ClipCursor(NULL); } if (swapchain->back_buffers) -- 2.20.1