Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/dwmapi/dwmapi_main.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/dlls/dwmapi/dwmapi_main.c b/dlls/dwmapi/dwmapi_main.c index 8408a2e..3f48691 100644 --- a/dlls/dwmapi/dwmapi_main.c +++ b/dlls/dwmapi/dwmapi_main.c @@ -208,9 +208,33 @@ 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 %d %p %d) stub\n", hwnd, attribute, pv_attribute, size); + TRACE("(%p %d %p %d)\n", hwnd, attribute, pv_attribute, size);
- return E_NOTIMPL; + if (!hwnd) return E_HANDLE; + if (!pv_attribute) return E_INVALIDARG; + + switch (attribute) + { + case DWMWA_NCRENDERING_ENABLED: + if (size < sizeof(BOOL)) return E_INVALIDARG; + + WARN("DWMWA_NCRENDERING_ENABLED: always returning FALSE.\n"); + *(BOOL*)(pv_attribute) = FALSE; + break; + + case DWMWA_CLOAKED: + if (size < sizeof(DWORD)) return E_INVALIDARG; + + FIXME("DWMWA_CLOAKED: always returning 0.\n"); + *(DWORD*)(pv_attribute) = 0; + break; + + default: + FIXME("unimplemented attribute %d, size %u, for hwnd %p.\n", attribute, size, hwnd); + return E_INVALIDARG; + } + + return S_OK; }
/**********************************************************************
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/dwmapi/tests/Makefile.in | 2 +- dlls/dwmapi/tests/dwmapi.c | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/dlls/dwmapi/tests/Makefile.in b/dlls/dwmapi/tests/Makefile.in index 6c61304..5a560ea 100644 --- a/dlls/dwmapi/tests/Makefile.in +++ b/dlls/dwmapi/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = dwmapi.dll -IMPORTS = dwmapi +IMPORTS = dwmapi gdi32 user32
C_SRCS = \ dwmapi.c diff --git a/dlls/dwmapi/tests/dwmapi.c b/dlls/dwmapi/tests/dwmapi.c index 1904e28..cebefa9 100644 --- a/dlls/dwmapi/tests/dwmapi.c +++ b/dlls/dwmapi/tests/dwmapi.c @@ -16,9 +16,37 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "windows.h" #include "dwmapi.h" #include "wine/test.h"
+static HWND test_wnd; +static LRESULT WINAPI test_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProcA(hwnd, message, wParam, lParam); +} + +static void test_DwmGetWindowAttribute(void) +{ + BOOL nc_rendering; + HRESULT hr; + + hr = DwmGetWindowAttribute(NULL, DWMWA_NCRENDERING_ENABLED, &nc_rendering, sizeof(nc_rendering)); + ok(hr == E_HANDLE || broken(hr == E_INVALIDARG) /* Vista */, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) returned 0x%08x.\n", hr); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_NCRENDERING_ENABLED, NULL, sizeof(nc_rendering)); + ok(hr == E_INVALIDARG, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) returned 0x%08x.\n", hr); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_NCRENDERING_ENABLED, &nc_rendering, 0); + ok(hr == E_INVALIDARG, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) returned 0x%08x.\n", hr); + nc_rendering = FALSE; + hr = DwmGetWindowAttribute(test_wnd, 0xdeadbeef, &nc_rendering, sizeof(nc_rendering)); + ok(hr == E_INVALIDARG, "DwmGetWindowAttribute(0xdeadbeef) returned 0x%08x.\n", hr); + + nc_rendering = 0xdeadbeef; + hr = DwmGetWindowAttribute(test_wnd, DWMWA_NCRENDERING_ENABLED, &nc_rendering, sizeof(nc_rendering)); + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) failed 0x%08x.\n", hr); + ok(nc_rendering == FALSE || nc_rendering == TRUE, "non-boolean value 0x%x.\n", nc_rendering); +} + static void test_DwmIsCompositionEnabled(void) { BOOL enabled; @@ -35,5 +63,28 @@ static void test_DwmIsCompositionEnabled(void)
START_TEST(dwmapi) { + HINSTANCE inst = GetModuleHandleA(NULL); + WNDCLASSA cls; + + cls.style = 0; + cls.lpfnWndProc = test_wndproc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = inst; + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "Test"; + RegisterClassA(&cls); + + test_wnd = CreateWindowExA(0, "Test", "Test Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(test_wnd != NULL, "Failed to create test window.\n"); + + test_DwmGetWindowAttribute(); test_DwmIsCompositionEnabled(); + + DestroyWindow(test_wnd); + UnregisterClassA("Test", inst); }
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
This stops Unity games like Variables (steam appid 1054800) from complaining when changing full-screen mode.
dlls/dwmapi/Makefile.in | 1 + dlls/dwmapi/dwmapi_main.c | 7 +++++++ dlls/dwmapi/tests/dwmapi.c | 8 ++++++++ 3 files changed, 16 insertions(+)
diff --git a/dlls/dwmapi/Makefile.in b/dlls/dwmapi/Makefile.in index 3a36913..d273a22 100644 --- a/dlls/dwmapi/Makefile.in +++ b/dlls/dwmapi/Makefile.in @@ -1,5 +1,6 @@ MODULE = dwmapi.dll IMPORTLIB = dwmapi +IMPORTS = user32
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/dwmapi/dwmapi_main.c b/dlls/dwmapi/dwmapi_main.c index 3f48691..bb585c5 100644 --- a/dlls/dwmapi/dwmapi_main.c +++ b/dlls/dwmapi/dwmapi_main.c @@ -222,6 +222,13 @@ HRESULT WINAPI DwmGetWindowAttribute(HWND hwnd, DWORD attribute, PVOID pv_attrib *(BOOL*)(pv_attribute) = FALSE; break;
+ case DWMWA_EXTENDED_FRAME_BOUNDS: + if (size < sizeof(RECT)) return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + WARN("DWMWA_EXTENDED_FRAME_BOUNDS: returning window rect.\n"); + GetWindowRect(hwnd, pv_attribute); + break; + case DWMWA_CLOAKED: if (size < sizeof(DWORD)) return E_INVALIDARG;
diff --git a/dlls/dwmapi/tests/dwmapi.c b/dlls/dwmapi/tests/dwmapi.c index cebefa9..e593c30 100644 --- a/dlls/dwmapi/tests/dwmapi.c +++ b/dlls/dwmapi/tests/dwmapi.c @@ -30,6 +30,7 @@ static void test_DwmGetWindowAttribute(void) { BOOL nc_rendering; HRESULT hr; + RECT rc;
hr = DwmGetWindowAttribute(NULL, DWMWA_NCRENDERING_ENABLED, &nc_rendering, sizeof(nc_rendering)); ok(hr == E_HANDLE || broken(hr == E_INVALIDARG) /* Vista */, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) returned 0x%08x.\n", hr); @@ -45,6 +46,13 @@ static void test_DwmGetWindowAttribute(void) hr = DwmGetWindowAttribute(test_wnd, DWMWA_NCRENDERING_ENABLED, &nc_rendering, sizeof(nc_rendering)); ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) failed 0x%08x.\n", hr); ok(nc_rendering == FALSE || nc_rendering == TRUE, "non-boolean value 0x%x.\n", nc_rendering); + + hr = DwmGetWindowAttribute(test_wnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(rc) - 1); + ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) || broken(hr == E_INVALIDARG) /* Vista */, + "DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS) returned 0x%08x.\n", hr); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(rc)); + if (hr != E_HANDLE && hr != DWM_E_COMPOSITIONDISABLED /* Vista */) /* composition is on */ + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS) failed 0x%08x.\n", hr); }
static void test_DwmIsCompositionEnabled(void)
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Most of the logic has been followed from user32.
dlls/dwmapi/dwmapi_main.c | 75 ++++++++++++++++++++++++++++++++++++++ dlls/dwmapi/tests/dwmapi.c | 58 ++++++++++++++++++++++++++++- 2 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/dlls/dwmapi/dwmapi_main.c b/dlls/dwmapi/dwmapi_main.c index bb585c5..a433437 100644 --- a/dlls/dwmapi/dwmapi_main.c +++ b/dlls/dwmapi/dwmapi_main.c @@ -32,6 +32,74 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwmapi);
+static void get_caption_buttons_rect(HWND hwnd, RECT *rc) +{ + DWORD style = GetWindowLongW(hwnd, GWL_STYLE); + DWORD ex_style = GetWindowLongW(hwnd, GWL_EXSTYLE); + LONG border_w = 0, border_h = 0; + + GetWindowRect(hwnd, rc); + OffsetRect(rc, -rc->left, -rc->top); + + if ((style & WS_THICKFRAME) && (style & (WS_DLGFRAME | WS_BORDER)) != WS_DLGFRAME) + { + border_w += GetSystemMetrics(SM_CXFRAME); + border_h += GetSystemMetrics(SM_CYFRAME); + } + else if ((!(style & WS_THICKFRAME) && (style & WS_DLGFRAME)) || (ex_style & WS_EX_DLGMODALFRAME)) + { + border_w += GetSystemMetrics(SM_CXDLGFRAME); + border_h += GetSystemMetrics(SM_CYDLGFRAME); + } + else if ((style & WS_BORDER) || !(style & (WS_CHILD | WS_POPUP))) + { + border_w += GetSystemMetrics(SM_CXBORDER); + border_h += GetSystemMetrics(SM_CYBORDER); + } + + /* There's additional border info if the window is a child (but not MDI) */ + if ((style & WS_CHILD) && !(ex_style & WS_EX_MDICHILD)) + { + if (ex_style & WS_EX_CLIENTEDGE) + { + border_w += GetSystemMetrics(SM_CXEDGE); + border_h += GetSystemMetrics(SM_CYEDGE); + } + if (ex_style & WS_EX_STATICEDGE) + { + border_w += GetSystemMetrics(SM_CXBORDER); + border_h += GetSystemMetrics(SM_CYBORDER); + } + } + + rc->right -= border_w; + rc->top += border_h; + rc->left = rc->right; + + /* The height is always reported even if there are no buttons */ + rc->bottom = rc->top + GetSystemMetrics((ex_style & WS_EX_TOOLWINDOW) ? SM_CYSMCAPTION : SM_CYCAPTION); + + if ((style & (WS_SYSMENU | WS_CAPTION)) == (WS_SYSMENU | WS_CAPTION)) + { + if (ex_style & WS_EX_TOOLWINDOW) + rc->left -= GetSystemMetrics(SM_CYSMCAPTION); + else + { + UINT num_buttons = 1; + + /* Minimize and Maximize buttons are always visible in pairs */ + if (style & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX)) + num_buttons += 2; + else if (ex_style & WS_EX_CONTEXTHELP) + num_buttons++; + + rc->left -= GetSystemMetrics(SM_CXSIZE) * num_buttons; + } + rc->left = max(rc->left, border_w); + } +} + + /* At process attach */ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) { @@ -222,6 +290,13 @@ HRESULT WINAPI DwmGetWindowAttribute(HWND hwnd, DWORD attribute, PVOID pv_attrib *(BOOL*)(pv_attribute) = FALSE; break;
+ case DWMWA_CAPTION_BUTTON_BOUNDS: + if (size < sizeof(RECT)) return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + WARN("DWMWA_CAPTION_BUTTON_BOUNDS: returning rect based on system metrics.\n"); + get_caption_buttons_rect(hwnd, pv_attribute); + break; + case DWMWA_EXTENDED_FRAME_BOUNDS: if (size < sizeof(RECT)) return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
diff --git a/dlls/dwmapi/tests/dwmapi.c b/dlls/dwmapi/tests/dwmapi.c index e593c30..8308477 100644 --- a/dlls/dwmapi/tests/dwmapi.c +++ b/dlls/dwmapi/tests/dwmapi.c @@ -29,8 +29,8 @@ static LRESULT WINAPI test_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARA static void test_DwmGetWindowAttribute(void) { BOOL nc_rendering; + RECT rc, rc2; HRESULT hr; - RECT rc;
hr = DwmGetWindowAttribute(NULL, DWMWA_NCRENDERING_ENABLED, &nc_rendering, sizeof(nc_rendering)); ok(hr == E_HANDLE || broken(hr == E_INVALIDARG) /* Vista */, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) returned 0x%08x.\n", hr); @@ -53,6 +53,62 @@ static void test_DwmGetWindowAttribute(void) hr = DwmGetWindowAttribute(test_wnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(rc)); if (hr != E_HANDLE && hr != DWM_E_COMPOSITIONDISABLED /* Vista */) /* composition is on */ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS) failed 0x%08x.\n", hr); + + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc, sizeof(rc) - 1); + ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) || broken(hr == E_INVALIDARG) /* Vista */, + "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) returned 0x%08x.\n", hr); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc, sizeof(rc)); + if (hr != E_HANDLE && hr != DWM_E_COMPOSITIONDISABLED /* Vista */) /* composition is on */ + { + DWORD style = GetWindowLongA(test_wnd, GWL_STYLE), ex_style = GetWindowLongA(test_wnd, GWL_EXSTYLE); + + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr); + ok(rc.left > 0 && rc.right > rc.left && rc.top >= 0 && rc.bottom > rc.top, + "unexpected caption rect %s.\n", wine_dbgstr_rect(&rc)); + + SetWindowLongA(test_wnd, GWL_STYLE, style & ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX)); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2)); + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr); + ok(rc2.left > rc.left && rc2.right == rc.right && rc2.top == rc.top && rc2.bottom == rc.bottom, + "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc)); + + SetWindowLongA(test_wnd, GWL_EXSTYLE, ex_style | WS_EX_CONTEXTHELP); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2)); + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr); + ok(rc2.left > rc.left && rc2.right == rc.right && rc2.top == rc.top && rc2.bottom == rc.bottom, + "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc)); + + SetWindowLongA(test_wnd, GWL_EXSTYLE, ex_style | WS_EX_TOOLWINDOW); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2)); + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr); + ok(rc2.left > rc.left && rc2.right <= rc.right && rc2.top >= rc.top && rc2.bottom <= rc.bottom, + "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc)); + SetWindowLongA(test_wnd, GWL_EXSTYLE, ex_style); + + SetWindowLongA(test_wnd, GWL_STYLE, style & ~WS_SYSMENU); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2)); + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr); + ok(rc2.left == rc.right && rc2.right == rc.right && rc2.top == rc.top && rc2.bottom == rc.bottom, + "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc)); + SetWindowLongA(test_wnd, GWL_STYLE, style); + + ShowWindow(test_wnd, SW_SHOWMINIMIZED); + ok(IsIconic(test_wnd), "window was not minimized.\n"); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2)); + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr); + ok(rc2.left - rc.left == rc2.right - rc.right && rc2.left <= rc.left && rc2.top == rc.top && rc2.bottom == rc.bottom, + "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc)); + ShowWindow(test_wnd, SW_RESTORE); + ok(!IsIconic(test_wnd), "window was not restored.\n"); + + ShowWindow(test_wnd, SW_HIDE); + ok(!IsWindowVisible(test_wnd), "window was not hidden.\n"); + hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2)); + ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr); + ok(EqualRect(&rc, &rc2), "unexpected caption rect %s (expected %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc)); + ShowWindow(test_wnd, SW_SHOW); + ok(IsWindowVisible(test_wnd), "window was not shown.\n"); + } }
static void test_DwmIsCompositionEnabled(void)