From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
dlls/user32/tests/Makefile.in | 2 +-
dlls/user32/tests/win.c | 686 ++++++++++++++++++++++++++++++++++
2 files changed, 687 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/Makefile.in b/dlls/user32/tests/Makefile.in
index dd101d69f3c..5b058b7d914 100644
--- a/dlls/user32/tests/Makefile.in
+++ b/dlls/user32/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = user32.dll
-IMPORTS = user32 gdi32 advapi32 hid
+IMPORTS = user32 gdi32 advapi32 hid dwmapi
C_SRCS = \
broadcast.c \
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index a37afd2dc5e..6f9c566a651 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -31,6 +31,7 @@
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
+#include "dwmapi.h"
#include "wine/test.h"
@@ -12004,6 +12005,689 @@ static void test_cancel_mode(void)
DestroyWindow(hwnd2);
}
+/* The window manager is not willing to fully honor window position
+ requests. For instance, Mutter does not allow windows to overlap
+ the top bar. For such WMs, we cannot reliably do
+ check_screen_surface tests, because we captured a different
+ background to compare with. */
+BOOL composition_broken_wm = FALSE;
+
+#define capture_surface(hdc, x, y, width, height, surface, surface_size) capture_surface_(__LINE__, hdc, x, y, width, height, surface, surface_size)
+static SIZE_T capture_surface_(int line, HDC hdc, int x, int y, int width, int height, DWORD *surface, SIZE_T surface_size)
+{
+ BITMAPINFOHEADER info;
+ HBITMAP bmp_obj;
+ SIZE_T data_size;
+ BITMAP bmp;
+ DWORD count;
+ BOOL ret;
+ HDC hdc_dst;
+
+ hdc_dst = CreateCompatibleDC(hdc);
+ ok_(__FILE__, line)(hdc_dst != 0, "CreateCompatibleDC failed, last error %u\n", GetLastError());
+ bmp_obj = CreateCompatibleBitmap(hdc, width, height);
+ ok_(__FILE__, line)(bmp_obj != 0, "CreateCompatibleBitmap failed, last error %u\n", GetLastError());
+
+#ifndef CAPTUREBLT
+#define CAPTUREBLT 0x40000000
+#endif
+
+ SelectObject(hdc_dst, bmp_obj);
+ ret = BitBlt(hdc_dst, 0, 0, width, height, hdc, x, y, SRCCOPY | CAPTUREBLT);
+ ok_(__FILE__, line)(ret, "BitBlt failed, last error %u\n", GetLastError());
+ count = GetObjectW(bmp_obj, sizeof(BITMAP), &bmp);
+ ok_(__FILE__, line)(count == sizeof(BITMAP), "GetObjectW failed, last error %u\n", GetLastError());
+
+ info.biSize = sizeof(BITMAPINFOHEADER);
+ info.biWidth = bmp.bmWidth;
+ info.biHeight = bmp.bmHeight;
+ info.biPlanes = 1;
+ info.biBitCount = 32;
+ info.biCompression = BI_RGB;
+ info.biSizeImage = 0;
+ info.biXPelsPerMeter = 0;
+ info.biYPelsPerMeter = 0;
+ info.biClrUsed = 0;
+ info.biClrImportant = 0;
+
+ data_size = ((bmp.bmWidth * info.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
+ ok_(__FILE__, line)( data_size == surface_size, "Got %Iu bytes, expected %Iu\n", data_size, surface_size );
+ count = GetDIBits(hdc_dst, bmp_obj, 0, bmp.bmHeight, surface, (BITMAPINFO*)&info, DIB_RGB_COLORS);
+ ok_(__FILE__, line)(count == bmp.bmHeight, "GetDIBits failed, last error %u\n", GetLastError());
+
+ DeleteObject(bmp_obj);
+ DeleteDC(hdc_dst);
+
+#if 0
+ {
+ BITMAPFILEHEADER header;
+ HANDLE file;
+
+ header.bfType = 0x4d42;
+ header.bfSize = sizeof(header) + sizeof(info) + data_size;
+ header.bfOffBits = sizeof(header) + sizeof(info);
+
+ file = CreateFileW(L"surface.bmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %u\n", GetLastError());
+ ret = WriteFile(file, &header, sizeof(header), &count, NULL);
+ ok(ret && count == sizeof(header), "WriteFile failed, error %u\n", GetLastError());
+ ret = WriteFile(file, &info, sizeof(info), &count, NULL);
+ ok(ret && count == sizeof(info), "WriteFile failed, error %u\n", GetLastError());
+ ret = WriteFile(file, surface, data_size, &count, NULL);
+ ok(ret && count == data_size, "WriteFile failed, error %u\n", GetLastError());
+ CloseHandle(file);
+ }
+#endif
+
+ return data_size;
+}
+
+static void dump_surface(int line, const DWORD *surface, SIZE_T surface_size, const char *prefix)
+{
+ int i, pos;
+ char buf[1024];
+
+ if (surface_size / 4 > 16)
+ return;
+ pos = sprintf(buf, "%s", prefix);
+ for (i = 0; i < surface_size / 4; i++)
+ pos += sprintf(buf + pos, " %08x", surface[i]);
+ trace_(__FILE__, line)("%s\n", buf);
+}
+
+#define capture_screen_surface(hwnd, surface, surface_size) capture_screen_surface_(__LINE__, hwnd, surface, surface_size)
+static SIZE_T capture_screen_surface_(int line, HWND hwnd, DWORD *surface, SIZE_T surface_size)
+{
+ SIZE_T data_size, i;
+ RECT rect, rect_win;
+ HDC hdc;
+
+ GetWindowRect(hwnd, &rect_win);
+ GetClientRect(hwnd, &rect);
+ OffsetRect(&rect, -rect.left, -rect.top);
+
+ hdc = GetDC(NULL);
+ ok_(__FILE__, line)(hdc != 0, "GetDC failed, last error %u\n", GetLastError());
+ if (DwmFlush() == E_NOTIMPL) flush_events( TRUE );
+ data_size = capture_surface_(line, hdc, rect_win.left, rect_win.top, rect.right, rect.bottom, surface, surface_size);
+ ReleaseDC(NULL, hdc);
+
+ for (i = data_size / 4; i != 0; i--) surface[i - 1] &= 0xffffff;
+ return data_size;
+}
+
+#define check_screen_surface(hwnd, expect, expect_size, todo) check_screen_surface_(__LINE__, hwnd, expect, expect_size, todo)
+static void check_screen_surface_(int line, HWND hwnd, const DWORD *expect, SIZE_T expect_size, BOOL todo)
+{
+ SIZE_T data_size;
+ DWORD *data;
+
+ if (composition_broken_wm)
+ return;
+
+ data = malloc(expect_size);
+ ok_(__FILE__, line)(data != NULL, "Failed to allocate %Iu bytes\n", expect_size);
+ data_size = capture_screen_surface_(line, hwnd, data, expect_size);
+ if (data_size != expect_size)
+ {
+ todo_wine_if(todo)
+ ok_(__FILE__, line)(0, "Unexpected screen surface size %Iu, expected %Iu", data_size, expect_size);
+ }
+ else if (memcmp( data, expect, data_size ))
+ {
+ todo_wine_if(todo)
+ ok_(__FILE__, line)(0, "Unexpected screen surface data\n");
+ dump_surface(line, expect, expect_size, "expected:");
+ dump_surface(line, data, data_size, "got: ");
+ }
+ else if (todo)
+ trace_(__FILE__, line)("Got expected screen surface data\n");
+ free(data);
+}
+
+#define capture_client_surface(hwnd, surface, surface_size) capture_client_surface_(__LINE__, hwnd, surface, surface_size)
+static SIZE_T capture_client_surface_(int line, HWND hwnd, DWORD *surface, SIZE_T surface_size)
+{
+ SIZE_T data_size;
+ RECT rect;
+ HDC hdc;
+
+ GetClientRect(hwnd, &rect);
+ OffsetRect(&rect, -rect.left, -rect.top);
+
+ hdc = GetDC(hwnd);
+ ok_(__FILE__, line)(hdc != 0, "GetDC failed, last error %u\n", GetLastError());
+ data_size = capture_surface_(line, hdc, 0, 0, rect.right, rect.bottom, surface, surface_size);
+ ReleaseDC(hwnd, hdc);
+
+ return data_size;
+}
+
+#define check_client_surface(hwnd, expect, expect_size, todo) check_client_surface_(__LINE__, hwnd, expect, expect_size, todo)
+static void check_client_surface_(int line, HWND hwnd, const DWORD *expect, SIZE_T expect_size, BOOL todo)
+{
+ SIZE_T data_size;
+ DWORD *data;
+
+ data = malloc(expect_size);
+ ok_(__FILE__, line)(data != NULL, "Failed to allocate %Iu bytes\n", expect_size);
+ data_size = capture_client_surface_(line, hwnd, data, expect_size);
+ if (data_size != expect_size)
+ {
+ todo_wine_if(todo)
+ ok_(__FILE__, line)(0, "Unexpected client surface size %Iu, expected %Iu", data_size, expect_size);
+ }
+ else if (memcmp( data, expect, data_size ))
+ {
+ todo_wine_if(todo)
+ ok_(__FILE__, line)(0, "Unexpected client surface data\n");
+ dump_surface(line, expect, expect_size, "expected:");
+ dump_surface(line, data, data_size, "got: ");
+ }
+ else if (todo)
+ trace_(__FILE__, line)("Got expected client surface data\n");
+ free(data);
+}
+
+static void paint_client_rect(HWND hwnd, COLORREF color)
+{
+ HDC hdc = GetDC(hwnd);
+ HPEN pen = CreatePen(PS_SOLID, 0, color);
+ HBRUSH brush = CreateSolidBrush(color);
+ RECT rect;
+ GetClientRect(hwnd, &rect);
+
+ SelectObject(hdc, pen);
+ SelectObject(hdc, brush);
+ Rectangle(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ DeleteObject(brush);
+ DeleteObject(pen);
+ DeleteDC(hdc);
+}
+
+LRESULT WINAPI test_surface_composition_winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ switch (msg)
+ {
+ case WM_ERASEBKGND: return 0;
+ case WM_NCPAINT:
+ case WM_PAINT:
+ {
+ BeginPaint(hwnd, NULL);
+ EndPaint(hwnd, NULL);
+ return 0;
+ }
+ default:
+ return DefWindowProcW(hwnd, msg, wparam, lparam);
+ }
+}
+
+static void test_surface_composition(void)
+{
+#define COLOR1 0x00ff0000
+#define COLOR2 0x0000ffff
+#define BGRA2RGB(x) RGB((x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff)
+ static const DWORD minimized_surface[] =
+ {
+ 0x00000000
+ };
+ static const DWORD hidden_surface[] =
+ {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ };
+ static const DWORD partial_surface[] =
+ {
+ 0x00000000, 0x00000000, COLOR1, COLOR1,
+ 0x00000000, 0x00000000, COLOR1, COLOR1,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ };
+ static const DWORD painted_surface[] =
+ {
+ COLOR1, COLOR1, COLOR1, COLOR1,
+ COLOR1, COLOR1, COLOR1, COLOR1,
+ COLOR1, COLOR1, COLOR1, COLOR1,
+ COLOR1, COLOR1, COLOR1, COLOR1,
+ };
+ static const DWORD painted_child_surface[] = {
+ COLOR1, COLOR1, COLOR1, COLOR1,
+ COLOR1, COLOR2, COLOR2, COLOR1,
+ COLOR1, COLOR2, COLOR2, COLOR1,
+ COLOR1, COLOR1, COLOR1, COLOR1,
+ };
+
+ DWORD screen_surface[ARRAY_SIZE(painted_surface)];
+ DWORD layered_const_surface[ARRAY_SIZE(painted_surface)];
+ DWORD layered_child_surface[ARRAY_SIZE(painted_child_surface)];
+ DWORD layered_child_const_surface[ARRAY_SIZE(painted_child_surface)];
+ DWORD layered_child_alpha_surface[ARRAY_SIZE(painted_child_surface)];
+
+ BLENDFUNCTION blend_cst_alpha = { AC_SRC_OVER, 0, 0x7f, 0 };
+ BLENDFUNCTION blend_src_alpha = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA };
+ WNDCLASSEXW wc;
+ BITMAPINFO info;
+ HBITMAP bmp_obj;
+ HRESULT hres;
+ SIZE_T i;
+ DWORD *data;
+ HWND hwnd, hwnd_child;
+ RECT rect;
+ BOOL ret;
+ HDC hdc_dst, hdc_src;
+
+ wc.cbSize = sizeof(WNDCLASSEXW);
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = test_surface_composition_winproc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandleW(NULL);
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = L"surface";
+ wc.hIconSm = 0;
+ RegisterClassExW(&wc);
+
+
+ hres = DwmFlush();
+ todo_wine ok(hres == S_OK || broken(hres == DWM_E_COMPOSITIONDISABLED), "DwmFlush returned %#x\n", hres);
+ if (hres == DWM_E_COMPOSITIONDISABLED)
+ {
+ win_skip("Cannot reliably capture screen surfaces, skipping tests\n");
+ return;
+ }
+
+ hwnd = CreateWindowW(L"surface", L"", WS_POPUP, 0, 0, 4, 4, NULL, NULL, NULL, NULL);
+ ok(hwnd != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+ flush_events( TRUE );
+
+ capture_screen_surface(hwnd, screen_surface, sizeof(screen_surface));
+
+ for (i = 0; i < ARRAY_SIZE(painted_surface); i++)
+ {
+ BYTE sr = (screen_surface[i] >> 16) & 0xff, dr = (painted_surface[i] >> 16) & 0xff;
+ BYTE sg = (screen_surface[i] >> 8) & 0xff, dg = (painted_surface[i] >> 8) & 0xff;
+ BYTE sb = (screen_surface[i] >> 0) & 0xff, db = (painted_surface[i] >> 0) & 0xff;
+ BYTE da = 0x7f;
+ dr = min(max((sr * (0xff - da) + dr * da + 0x7f) / 0xff, 0), 0xff);
+ dg = min(max((sg * (0xff - da) + dg * da + 0x7f) / 0xff, 0), 0xff);
+ db = min(max((sb * (0xff - da) + db * da + 0x7f) / 0xff, 0), 0xff);
+ layered_const_surface[i] = BGRA2RGB(RGB(dr, dg, db));
+ }
+
+ memcpy(layered_child_surface, screen_surface, sizeof(screen_surface));
+ for (i = 0; i < ARRAY_SIZE(painted_child_surface); i++)
+ {
+ if (painted_child_surface[i] == painted_surface[i])
+ layered_child_surface[i] = painted_surface[i];
+ }
+
+ for (i = 0; i < ARRAY_SIZE(painted_child_surface); i++)
+ {
+ BYTE sr = (screen_surface[i] >> 16) & 0xff, dr = (painted_child_surface[i] >> 16) & 0xff;
+ BYTE sg = (screen_surface[i] >> 8) & 0xff, dg = (painted_child_surface[i] >> 8) & 0xff;
+ BYTE sb = (screen_surface[i] >> 0) & 0xff, db = (painted_child_surface[i] >> 0) & 0xff;
+ BYTE da = 0x7f;
+ dr = min(max((sr * (0xff - da) + dr * da + 0x7f) / 0xff, 0), 0xff);
+ dg = min(max((sg * (0xff - da) + dg * da + 0x7f) / 0xff, 0), 0xff);
+ db = min(max((sb * (0xff - da) + db * da + 0x7f) / 0xff, 0), 0xff);
+ layered_child_const_surface[i] = BGRA2RGB(RGB(dr, dg, db));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(painted_child_surface); i++)
+ {
+ BYTE sr = (screen_surface[i] >> 16) & 0xff, dr = (painted_child_surface[i] >> 16) & 0xff;
+ BYTE sg = (screen_surface[i] >> 8) & 0xff, dg = (painted_child_surface[i] >> 8) & 0xff;
+ BYTE sb = (screen_surface[i] >> 0) & 0xff, db = (painted_child_surface[i] >> 0) & 0xff;
+ BYTE sa = painted_child_surface[i] == COLOR2 ? 0xff : 0x00;
+ dr = min(max((sr * (0xff - sa) + dr * 0xff + 0x7f) / 0xff, 0), 0xff);
+ dg = min(max((sg * (0xff - sa) + dg * 0xff + 0x7f) / 0xff, 0), 0xff);
+ db = min(max((sb * (0xff - sa) + db * 0xff + 0x7f) / 0xff, 0), 0xff);
+ layered_child_alpha_surface[i] = BGRA2RGB(RGB(dr, dg, db));
+ }
+
+
+ ShowWindow(hwnd, SW_SHOW);
+ flush_events( TRUE );
+ GetWindowRect(hwnd, &rect);
+ if (rect.left != 0 || rect.top != 0)
+ {
+ skip("window manager does not honor requested position\n");
+ composition_broken_wm = TRUE;
+ }
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ ShowWindow(hwnd, SW_HIDE);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), FALSE);
+ check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
+
+ ShowWindow(hwnd, SW_SHOW);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, minimized_surface, sizeof(minimized_surface), FALSE);
+ check_screen_surface(hwnd, minimized_surface, sizeof(minimized_surface), FALSE);
+
+ ShowWindow(hwnd, SW_RESTORE);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ SetWindowPos(hwnd, 0, -100, -100, 0, 0, SWP_NOSIZE);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), TRUE);
+ check_screen_surface(hwnd, hidden_surface, sizeof(hidden_surface), FALSE);
+
+ SetWindowPos(hwnd, 0, -2, -2, 0, 0, SWP_NOSIZE);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, partial_surface, sizeof(partial_surface), TRUE);
+
+ SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ hwnd_child = CreateWindowW(L"surface", L"", WS_CHILD | WS_VISIBLE, 1, 1, 2, 2, hwnd, NULL, NULL, NULL);
+ ok(hwnd_child != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+
+ flush_events( TRUE );
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | WS_CLIPCHILDREN);
+
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+
+ DestroyWindow(hwnd_child);
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+
+ DestroyWindow(hwnd);
+
+
+ /* WS_EX_LAYERED */
+
+ hwnd = CreateWindowW(L"surface", L"", WS_POPUP | WS_VISIBLE, 0, 0, 4, 4, 0, NULL, NULL, NULL);
+ ok(hwnd != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+ flush_events( TRUE );
+
+ SetWindowLongW(hwnd, GWL_EXSTYLE, GetWindowLongW(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ ShowWindow(hwnd, SW_HIDE);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), TRUE);
+ check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
+
+ ShowWindow(hwnd, SW_SHOW);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), TRUE);
+
+ hwnd_child = CreateWindowW(L"surface", L"", WS_CHILD | WS_VISIBLE, 1, 1, 2, 2, hwnd, NULL, NULL, NULL);
+ ok(hwnd_child != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+
+ flush_events( TRUE );
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), TRUE);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), TRUE);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), TRUE);
+
+ SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | WS_CLIPCHILDREN);
+
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), TRUE);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), TRUE);
+
+ DestroyWindow(hwnd_child);
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), TRUE);
+
+ DestroyWindow(hwnd);
+
+
+ /* SetLayeredWindowAttributes / LWA_ALPHA */
+
+ hwnd = CreateWindowW(L"surface", L"", WS_POPUP, 0, 0, 4, 4, 0, NULL, NULL, NULL);
+ ok(hwnd != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+
+ SetWindowLongW(hwnd, GWL_EXSTYLE, GetWindowLongW(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
+
+ ShowWindow(hwnd, SW_SHOW);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
+
+ ret = SetLayeredWindowAttributes(hwnd, 0, 0x7f, LWA_ALPHA);
+ ok(ret, "SetLayeredWindowAttributes failed, last error %u\n", GetLastError());
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, layered_const_surface, sizeof(layered_const_surface), TRUE);
+
+ hwnd_child = CreateWindowW(L"surface", L"", WS_CHILD | WS_VISIBLE, 1, 1, 2, 2, hwnd, NULL, NULL, NULL);
+ ok(hwnd_child != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+
+ flush_events( TRUE );
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, layered_const_surface, sizeof(layered_const_surface), TRUE);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_const_surface, sizeof(layered_child_const_surface), TRUE);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, layered_const_surface, sizeof(layered_const_surface), TRUE);
+
+ SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | WS_CLIPCHILDREN);
+
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_const_surface, sizeof(layered_child_const_surface), TRUE);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_const_surface, sizeof(layered_child_const_surface), TRUE);
+
+ DestroyWindow(hwnd_child);
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_const_surface, sizeof(layered_child_const_surface), TRUE);
+
+ DestroyWindow(hwnd);
+
+
+ /* SetLayeredWindowAttributes / LWA_COLORKEY */
+
+ hwnd = CreateWindowW(L"surface", L"", WS_POPUP, 0, 0, 4, 4, 0, NULL, NULL, NULL);
+ ok(hwnd != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+
+ SetWindowLongW(hwnd, GWL_EXSTYLE, GetWindowLongW(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ ret = SetLayeredWindowAttributes(hwnd, BGRA2RGB(COLOR2), 0, LWA_COLORKEY);
+ ok(ret, "SetLayeredWindowAttributes failed, last error %u\n", GetLastError());
+ ShowWindow(hwnd, SW_SHOW);
+ flush_events( TRUE );
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ hwnd_child = CreateWindowW(L"surface", L"", WS_CHILD | WS_VISIBLE, 1, 1, 2, 2, hwnd, NULL, NULL, NULL);
+ ok(hwnd_child != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+ flush_events( TRUE );
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_surface, sizeof(layered_child_surface), FALSE);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+ check_screen_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
+
+ SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | WS_CLIPCHILDREN);
+
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_surface, sizeof(layered_child_surface), FALSE);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_surface, sizeof(layered_child_surface), FALSE);
+
+ DestroyWindow(hwnd_child);
+ check_client_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), FALSE);
+ check_screen_surface(hwnd, layered_child_surface, sizeof(layered_child_surface), FALSE);
+
+ GetClientRect(hwnd, &rect);
+ OffsetRect(&rect, -rect.left, -rect.top);
+
+ memset(&info, 0, sizeof(info));
+ info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ info.bmiHeader.biWidth = rect.right;
+ info.bmiHeader.biHeight = rect.bottom;
+ info.bmiHeader.biPlanes = 1;
+ info.bmiHeader.biBitCount = 32;
+ info.bmiHeader.biCompression = BI_RGB;
+ info.bmiHeader.biSizeImage = rect.right * rect.bottom * 4;
+
+ hdc_dst = GetDC(hwnd);
+ ok(hdc_dst != 0, "GetDC failed, last error %u\n", GetLastError());
+ hdc_src = CreateCompatibleDC(hdc_dst);
+ ok(hdc_src != 0, "CreateCompatibleDC failed, last error %u\n", GetLastError());
+ bmp_obj = CreateDIBSection(hdc_src, &info, DIB_RGB_COLORS, (void **)&data, NULL, 0x0);
+ ok(bmp_obj != 0, "CreateBitmap failed, last error %u\n", GetLastError());
+ SelectObject(hdc_src, bmp_obj);
+ ret = BitBlt(hdc_src, 0, 0, rect.right, rect.bottom, hdc_dst, 0, 0, SRCCOPY);
+ ok(ret, "BitBlt failed, last error %u\n", GetLastError());
+ ReleaseDC(hwnd, hdc_dst);
+
+ for (i = rect.bottom * rect.right; i != 0; i--)
+ if (data[i - 1] == COLOR2) data[i - 1] |= 0xff000000;
+
+ DestroyWindow(hwnd);
+
+
+ /* UpdateLayeredWindow */
+
+ hdc_dst = GetDC(NULL);
+ hwnd = CreateWindowW(L"surface", L"", WS_POPUP, 0, 0, 4, 4, 0, NULL, NULL, NULL);
+ ok(hwnd != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+
+ SetWindowLongW(hwnd, GWL_EXSTYLE, GetWindowLongW(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
+
+ ret = UpdateLayeredWindow(hwnd, hdc_dst, NULL, (SIZE *)&rect.right, hdc_src, (POINT *)&rect.left, 0, NULL, ULW_OPAQUE);
+ ok(ret, "UpdateLayeredWindow failed, last error %u\n", GetLastError());
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
+
+ ShowWindow(hwnd, SW_SHOW);
+ flush_events( TRUE );
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, painted_child_surface, sizeof(painted_child_surface), TRUE);
+
+ ret = UpdateLayeredWindow(hwnd, hdc_dst, NULL, (SIZE *)&rect.right, hdc_src, (POINT *)&rect.left, BGRA2RGB(COLOR2), NULL, ULW_COLORKEY);
+ ok(ret, "UpdateLayeredWindow failed, last error %u\n", GetLastError());
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, layered_child_surface, sizeof(layered_child_surface), TRUE);
+
+ ret = UpdateLayeredWindow(hwnd, hdc_dst, NULL, (SIZE *)&rect.right, hdc_src, (POINT *)&rect.left, 0, &blend_cst_alpha, ULW_ALPHA);
+ ok(ret, "UpdateLayeredWindow failed, last error %u\n", GetLastError());
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, layered_child_const_surface, sizeof(layered_child_const_surface), TRUE);
+
+ ret = UpdateLayeredWindow(hwnd, hdc_dst, NULL, (SIZE *)&rect.right, hdc_src, (POINT *)&rect.left, 0, &blend_src_alpha, ULW_ALPHA);
+ ok(ret, "UpdateLayeredWindow failed, last error %u\n", GetLastError());
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, layered_child_alpha_surface, sizeof(layered_child_alpha_surface), TRUE);
+
+ DeleteObject(bmp_obj);
+ DeleteDC(hdc_src);
+ ReleaseDC(NULL, hdc_dst);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, layered_child_alpha_surface, sizeof(layered_child_alpha_surface), TRUE);
+
+ hwnd_child = CreateWindowW(L"surface", L"", WS_CHILD | WS_VISIBLE, 1, 1, 2, 2, hwnd, NULL, NULL, NULL);
+ ok(hwnd_child != 0, "CreateWindowW failed, last error %u\n", GetLastError());
+ flush_events( TRUE );
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, layered_child_alpha_surface, sizeof(layered_child_alpha_surface), TRUE);
+
+ paint_client_rect(hwnd, BGRA2RGB(COLOR1));
+ paint_client_rect(hwnd_child, BGRA2RGB(COLOR2));
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_screen_surface(hwnd, layered_child_alpha_surface, sizeof(layered_child_alpha_surface), TRUE);
+
+ DestroyWindow(hwnd_child);
+ DestroyWindow(hwnd);
+
+
+ UnregisterClassW(L"surface", NULL);
+
+#undef BGRA2RGB
+#undef COLOR1
+#undef COLOR2
+}
+
START_TEST(win)
{
char **argv;
@@ -12178,6 +12862,8 @@ START_TEST(win)
DestroyWindow(hwndMain2);
DestroyWindow(hwndMain);
+ test_surface_composition();
+
/* Make sure that following tests are executed last, under Windows they
* tend to break the tests which are sensitive to z-order and activation
* state of hwndMain and hwndMain2 windows.
--
2.31.1