From 3681a68e7804e0398b3f15f16af4ae19ef2e5dba Mon Sep 17 00:00:00 2001 From: Akihiro Sagawa Date: Thu, 30 Nov 2023 23:00:09 +0900 Subject: [PATCH] dwmapi: Implement DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS). Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55968 --- dlls/dwmapi/dwmapi_main.c | 41 ++++++++++++++++++++++++++++++-- dlls/dwmapi/tests/dwmapi.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/dlls/dwmapi/dwmapi_main.c b/dlls/dwmapi/dwmapi_main.c index 9ec03185f36..adc02552ba7 100644 --- a/dlls/dwmapi/dwmapi_main.c +++ b/dlls/dwmapi/dwmapi_main.c @@ -196,9 +196,46 @@ BOOL WINAPI DwmDefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, */ HRESULT WINAPI DwmGetWindowAttribute(HWND hwnd, DWORD attribute, PVOID pv_attribute, DWORD size) { - FIXME("(%p %ld %p %ld) stub\n", hwnd, attribute, pv_attribute, size); + BOOL enabled = FALSE; + HRESULT hr; - return E_NOTIMPL; + TRACE("(%p %ld %p %ld)\n", hwnd, attribute, pv_attribute, size); + + if (DwmIsCompositionEnabled(&enabled) == S_OK && !enabled) + return E_HANDLE; + if (!IsWindow(hwnd)) + return E_HANDLE; + + switch (attribute) { + case DWMWA_EXTENDED_FRAME_BOUNDS: + { + RECT *rect = (RECT *)pv_attribute; + DPI_AWARENESS_CONTEXT context; + + if (!rect) + return E_INVALIDARG; + if (size < sizeof(*rect)) + return E_NOT_SUFFICIENT_BUFFER; + if (GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD) + return E_HANDLE; + + /* DWM frame bounds are always in physical coords */ + context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); + if (GetWindowRect(hwnd, rect)) + hr = S_OK; + else + hr = HRESULT_FROM_WIN32(GetLastError()); + + SetThreadDpiAwarenessContext(context); + break; + } + default: + FIXME("attribute %ld not implemented.\n", attribute); + hr = E_NOTIMPL; + break; + } + + return hr; } /********************************************************************** diff --git a/dlls/dwmapi/tests/dwmapi.c b/dlls/dwmapi/tests/dwmapi.c index 29dbcbe74bd..a89a1fd705b 100644 --- a/dlls/dwmapi/tests/dwmapi.c +++ b/dlls/dwmapi/tests/dwmapi.c @@ -83,8 +83,66 @@ static void test_DwmGetCompositionTimingInfo(void) "Got wrong monitor refresh period %s.\n", wine_dbgstr_longlong(timing_info.qpcRefreshPeriod)); } +static void test_DWMWA_EXTENDED_FRAME_BOUNDS(void) +{ + DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); + DPI_AWARENESS_CONTEXT old_context = NULL; + BOOL enabled; + HRESULT hr; + RECT rect, window_rect, intersection; + HWND hwnd, child; + + pSetThreadDpiAwarenessContext = (void *)GetProcAddress(GetModuleHandleA("user32.dll"), + "SetThreadDpiAwarenessContext"); + if (pSetThreadDpiAwarenessContext) + old_context = pSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); + + hwnd = CreateWindowW(L"static", L"static", WS_OVERLAPPEDWINDOW | WS_POPUP | WS_VISIBLE, 10, 10, 200, 200, NULL, NULL, NULL, NULL); + child = CreateWindowW(L"edit", L"edit", WS_CHILD | WS_VISIBLE, 0, 0, 50, 50, hwnd, NULL, NULL, NULL); + + DwmIsCompositionEnabled(&enabled); + hr = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(rect)); + if (!enabled) { + ok(hr == E_HANDLE, "Got hr %#lx.\n", hr); + skip("DWM is disabled.\n"); + goto cleanup; + } + + hr = DwmGetWindowAttribute(NULL, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(rect)); + ok(hr == E_HANDLE, "Got hr %#lx.\n", hr); + hr = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &enabled, sizeof(enabled)); + ok(hr == E_NOT_SUFFICIENT_BUFFER, "Got hr %#lx.\n", hr); + hr = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, NULL, 0); + ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr); + hr = DwmGetWindowAttribute(child, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(rect)); + ok(hr == E_HANDLE, "Got hr %#lx.\n", hr); + hr = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rect, sizeof(rect)); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + /* Window rectangle covers extended frame */ + GetWindowRect(hwnd, &window_rect); + IntersectRect(&intersection, &window_rect, &rect); + ok(EqualRect(&intersection, &rect), "Got wrong frame %s, window %s.\n", wine_dbgstr_rect(&rect), wine_dbgstr_rect(&window_rect)); + + /* Extended frame bounds aren't adjusted for DPI */ + if (pSetThreadDpiAwarenessContext) { + RECT unaware_rect; + pSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE); + hr = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &unaware_rect, sizeof(unaware_rect)); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(EqualRect(&rect, &unaware_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&rect), wine_dbgstr_rect(&unaware_rect)); + } + +cleanup: + if (pSetThreadDpiAwarenessContext) + pSetThreadDpiAwarenessContext(old_context); + DestroyWindow(child); + DestroyWindow(hwnd); +} + START_TEST(dwmapi) { test_DwmIsCompositionEnabled(); test_DwmGetCompositionTimingInfo(); + test_DWMWA_EXTENDED_FRAME_BOUNDS(); } -- 2.11.4.GIT