Added patch to implement support for layered window regions.

This commit is contained in:
Sebastian Lackner 2017-05-29 07:44:06 +02:00
parent 5cc0023094
commit 5d31795ffc
4 changed files with 658 additions and 1 deletions

View File

@ -8000,12 +8000,18 @@ fi
# | * [#9512] Make sure popups don't block access to objects underneath in DVDPro
# |
# | Modified files:
# | * dlls/user32/message.c, dlls/user32/tests/input.c
# | * dlls/user32/message.c, dlls/user32/tests/input.c, dlls/winex11.drv/bitblt.c, server/protocol.def, server/window.c
# |
if test "$enable_user32_Mouse_Message_Hwnd" -eq 1; then
patch_apply user32-Mouse_Message_Hwnd/0001-user32-Try-harder-to-find-a-target-for-mouse-message.patch
patch_apply user32-Mouse_Message_Hwnd/0002-user32-tests-Add-tests-for-clicking-through-layered-.patch
patch_apply user32-Mouse_Message_Hwnd/0003-user32-tests-Add-tests-for-window-region-of-layered-.patch
patch_apply user32-Mouse_Message_Hwnd/0004-server-Add-support-for-a-layered-window-region.-v2.patch
(
printf '%s\n' '+ { "Dmitry Timoshkov", "user32: Try harder to find a target for mouse messages.", 1 },';
printf '%s\n' '+ { "Sebastian Lackner", "user32/tests: Add tests for clicking through layered window.", 1 },';
printf '%s\n' '+ { "Sebastian Lackner", "user32/tests: Add tests for window region of layered windows.", 1 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "server: Add support for a layered window region.", 2 },';
) >> "$patchlist"
fi

View File

@ -0,0 +1,202 @@
From 9728ac1dc57f11b11d4467de7f1c58c59218978d Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 29 May 2017 05:30:44 +0200
Subject: user32/tests: Add tests for clicking through layered window.
FIXME:
* It seems like the color key channels are swapped between Windows and Wine.
This can be tested by replacing the (128, 128, 128) with something else.
* Add tests with WS_CHILD layered Windows. On Windows this is supported for
>= Win8, but only when a manifest is present.
---
dlls/user32/tests/input.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 157 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index 62cd5b38055..47c5fa8c932 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -53,6 +53,7 @@
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
+#include "wingdi.h"
#include "winnls.h"
#include "wine/test.h"
@@ -1927,7 +1928,9 @@ static void test_Input_mouse(void)
struct thread_data thread_data;
HANDLE thread;
DWORD thread_id;
+ WNDCLASSA wclass;
POINT pt, pt_org;
+ BOOL ret;
MSG msg;
GetCursorPos(&pt_org);
@@ -2131,6 +2134,160 @@ static void test_Input_mouse(void)
ok(got_button_up, "expected WM_LBUTTONUP message\n");
DestroyWindow(hwnd);
ok(ReleaseCapture(), "ReleaseCapture failed\n");
+
+ wclass.style = 0;
+ wclass.lpfnWndProc = WndProc;
+ wclass.cbClsExtra = 0;
+ wclass.cbWndExtra = 0;
+ wclass.hInstance = GetModuleHandleA(NULL);
+ wclass.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
+ wclass.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
+ wclass.hbrBackground = CreateSolidBrush(RGB(128, 128, 128));
+ wclass.lpszMenuName = NULL;
+ wclass.lpszClassName = "InputLayeredTestClass";
+ RegisterClassA( &wclass );
+
+ /* click through layered window with alpha channel / color key */
+ hwnd = CreateWindowA(wclass.lpszClassName, "InputLayeredTest",
+ WS_VISIBLE | WS_POPUP, 100, 100, 100, 100, button_win, NULL, NULL, NULL);
+ ok(hwnd != NULL, "CreateWindowEx failed\n");
+
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ ret = SetLayeredWindowAttributes(hwnd, 0, 255, LWA_ALPHA);
+ ok(ret, "SetLayeredWindowAttributes failed\n");
+ while (wait_for_message(&msg)) DispatchMessageA(&msg);
+ Sleep(100);
+
+ got_button_down = got_button_up = FALSE;
+ simulate_click(TRUE, 150, 150);
+ while (wait_for_message(&msg))
+ {
+ DispatchMessageA(&msg);
+
+ if (msg.message == WM_LBUTTONDOWN)
+ {
+ ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_down = TRUE;
+ }
+ else if (msg.message == WM_LBUTTONUP)
+ {
+ ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_up = TRUE;
+ break;
+ }
+ }
+ ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
+ ok(got_button_up, "expected WM_LBUTTONUP message\n");
+
+ ret = SetLayeredWindowAttributes(hwnd, 0, 0, LWA_ALPHA);
+ ok(ret, "SetLayeredWindowAttributes failed\n");
+ while (wait_for_message(&msg)) DispatchMessageA(&msg);
+ Sleep(100);
+
+ got_button_down = got_button_up = FALSE;
+ simulate_click(TRUE, 150, 150);
+ while (wait_for_message(&msg))
+ {
+ DispatchMessageA(&msg);
+
+ if (msg.message == WM_LBUTTONDOWN)
+ {
+ todo_wine
+ ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_down = TRUE;
+ }
+ else if (msg.message == WM_LBUTTONUP)
+ {
+ todo_wine
+ ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_up = TRUE;
+ break;
+ }
+ }
+ ok(got_button_down || broken(!got_button_down), "expected WM_LBUTTONDOWN message\n");
+ ok(got_button_up, "expected WM_LBUTTONUP message\n");
+
+ ret = SetLayeredWindowAttributes(hwnd, RGB(0, 255, 0), 255, LWA_ALPHA | LWA_COLORKEY);
+ ok(ret, "SetLayeredWindowAttributes failed\n");
+ while (wait_for_message(&msg)) DispatchMessageA(&msg);
+ Sleep(100);
+
+ got_button_down = got_button_up = FALSE;
+ simulate_click(TRUE, 150, 150);
+ while (wait_for_message(&msg))
+ {
+ DispatchMessageA(&msg);
+
+ if (msg.message == WM_LBUTTONDOWN)
+ {
+ ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_down = TRUE;
+ }
+ else if (msg.message == WM_LBUTTONUP)
+ {
+ ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_up = TRUE;
+ break;
+ }
+ }
+ ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
+ ok(got_button_up, "expected WM_LBUTTONUP message\n");
+
+ ret = SetLayeredWindowAttributes(hwnd, RGB(128, 128, 128), 0, LWA_COLORKEY);
+ ok(ret, "SetLayeredWindowAttributes failed\n");
+ while (wait_for_message(&msg)) DispatchMessageA(&msg);
+ Sleep(100);
+
+ got_button_down = got_button_up = FALSE;
+ simulate_click(TRUE, 150, 150);
+ while (wait_for_message(&msg))
+ {
+ DispatchMessageA(&msg);
+
+ if (msg.message == WM_LBUTTONDOWN)
+ {
+ todo_wine
+ ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_down = TRUE;
+ }
+ else if (msg.message == WM_LBUTTONUP)
+ {
+ todo_wine
+ ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_up = TRUE;
+ break;
+ }
+ }
+ ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
+ ok(got_button_up, "expected WM_LBUTTONUP message\n");
+
+ SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
+ while (wait_for_message(&msg)) DispatchMessageA(&msg);
+ Sleep(100);
+
+ got_button_down = got_button_up = FALSE;
+ simulate_click(TRUE, 150, 150);
+ while (wait_for_message(&msg))
+ {
+ DispatchMessageA(&msg);
+
+ if (msg.message == WM_LBUTTONDOWN)
+ {
+ ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_down = TRUE;
+ }
+ else if (msg.message == WM_LBUTTONUP)
+ {
+ ok(msg.hwnd == hwnd, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_up = TRUE;
+ break;
+ }
+ }
+ ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
+ ok(got_button_up, "expected WM_LBUTTONUP message\n");
+
+ DestroyWindow(hwnd);
SetCursorPos(pt_org.x, pt_org.y);
CloseHandle(thread_data.start_event);
--
2.12.2

View File

@ -0,0 +1,149 @@
From c5c370cded7281e5b24545123e2ce5f310f651e5 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 29 May 2017 06:04:18 +0200
Subject: user32/tests: Add tests for window region of layered windows.
---
dlls/user32/tests/input.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index 47c5fa8c932..08c4c5435c6 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -80,6 +80,7 @@ static struct {
static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
static UINT (WINAPI *pGetRawInputDeviceList) (PRAWINPUTDEVICELIST, PUINT, UINT);
+static int (WINAPI *pGetWindowRgnBox)(HWND, LPRECT);
#define MAXKEYEVENTS 12
#define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one
@@ -164,6 +165,7 @@ static void init_function_pointers(void)
GET_PROC(SendInput)
GET_PROC(GetMouseMovePointsEx)
GET_PROC(GetRawInputDeviceList)
+ GET_PROC(GetWindowRgnBox)
#undef GET_PROC
}
@@ -1930,6 +1932,9 @@ static void test_Input_mouse(void)
DWORD thread_id;
WNDCLASSA wclass;
POINT pt, pt_org;
+ int region_type;
+ HRGN hregion;
+ RECT region;
BOOL ret;
MSG msg;
@@ -2159,6 +2164,12 @@ static void test_Input_mouse(void)
while (wait_for_message(&msg)) DispatchMessageA(&msg);
Sleep(100);
+ if (pGetWindowRgnBox)
+ {
+ region_type = pGetWindowRgnBox(hwnd, &region);
+ ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
+ }
+
got_button_down = got_button_up = FALSE;
simulate_click(TRUE, 150, 150);
while (wait_for_message(&msg))
@@ -2185,6 +2196,12 @@ static void test_Input_mouse(void)
while (wait_for_message(&msg)) DispatchMessageA(&msg);
Sleep(100);
+ if (pGetWindowRgnBox)
+ {
+ region_type = pGetWindowRgnBox(hwnd, &region);
+ ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
+ }
+
got_button_down = got_button_up = FALSE;
simulate_click(TRUE, 150, 150);
while (wait_for_message(&msg))
@@ -2213,6 +2230,12 @@ static void test_Input_mouse(void)
while (wait_for_message(&msg)) DispatchMessageA(&msg);
Sleep(100);
+ if (pGetWindowRgnBox)
+ {
+ region_type = pGetWindowRgnBox(hwnd, &region);
+ ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
+ }
+
got_button_down = got_button_up = FALSE;
simulate_click(TRUE, 150, 150);
while (wait_for_message(&msg))
@@ -2239,6 +2262,12 @@ static void test_Input_mouse(void)
while (wait_for_message(&msg)) DispatchMessageA(&msg);
Sleep(100);
+ if (pGetWindowRgnBox)
+ {
+ region_type = pGetWindowRgnBox(hwnd, &region);
+ ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
+ }
+
got_button_down = got_button_up = FALSE;
simulate_click(TRUE, 150, 150);
while (wait_for_message(&msg))
@@ -2266,6 +2295,12 @@ static void test_Input_mouse(void)
while (wait_for_message(&msg)) DispatchMessageA(&msg);
Sleep(100);
+ if (pGetWindowRgnBox)
+ {
+ region_type = pGetWindowRgnBox(hwnd, &region);
+ ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
+ }
+
got_button_down = got_button_up = FALSE;
simulate_click(TRUE, 150, 150);
while (wait_for_message(&msg))
@@ -2287,6 +2322,41 @@ static void test_Input_mouse(void)
ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
ok(got_button_up, "expected WM_LBUTTONUP message\n");
+ hregion = CreateRectRgn(0, 0, 10, 10);
+ ok(hregion != NULL, "CreateRectRgn failed\n");
+ ret = SetWindowRgn(hwnd, hregion, TRUE);
+ ok(ret, "SetWindowRgn failed\n");
+ DeleteObject(hregion);
+ while (wait_for_message(&msg)) DispatchMessageA(&msg);
+ Sleep(1000);
+
+ if (pGetWindowRgnBox)
+ {
+ region_type = pGetWindowRgnBox(hwnd, &region);
+ ok(region_type == SIMPLEREGION, "expected SIMPLEREGION, got %d\n", region_type);
+ }
+
+ got_button_down = got_button_up = FALSE;
+ simulate_click(TRUE, 150, 150);
+ while (wait_for_message(&msg))
+ {
+ DispatchMessageA(&msg);
+
+ if (msg.message == WM_LBUTTONDOWN)
+ {
+ ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_down = TRUE;
+ }
+ else if (msg.message == WM_LBUTTONUP)
+ {
+ ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
+ got_button_up = TRUE;
+ break;
+ }
+ }
+ ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
+ ok(got_button_up, "expected WM_LBUTTONUP message\n");
+
DestroyWindow(hwnd);
SetCursorPos(pt_org.x, pt_org.y);
--
2.12.2

View File

@ -0,0 +1,300 @@
From ac68b0ca43fd70c641d4b84477858db8c38af20a Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 17 May 2017 23:55:55 +0800
Subject: server: Add support for a layered window region. (v2)
---
dlls/user32/tests/input.c | 2 --
dlls/winex11.drv/bitblt.c | 46 ++++++++++++++++++++++++++++++++++-
server/protocol.def | 7 ++++++
server/window.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 114 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index 08c4c5435c6..87c491657a9 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -2276,13 +2276,11 @@ static void test_Input_mouse(void)
if (msg.message == WM_LBUTTONDOWN)
{
- todo_wine
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
got_button_down = TRUE;
}
else if (msg.message == WM_LBUTTONUP)
{
- todo_wine
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
got_button_up = TRUE;
break;
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c
index 80256dce569..474131da741 100644
--- a/dlls/winex11.drv/bitblt.c
+++ b/dlls/winex11.drv/bitblt.c
@@ -48,6 +48,7 @@
#include "winuser.h"
#include "x11drv.h"
#include "winternl.h"
+#include "wine/server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
@@ -1609,6 +1610,48 @@ static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len )
flush_rgn_data( rgn, data );
}
+static void set_layer_region( struct x11drv_window_surface *surface, HRGN hrgn )
+{
+ static const RECT empty_rect;
+ RGNDATA *data;
+ DWORD size;
+ HWND hwnd;
+
+ if (XFindContext( thread_init_display(), surface->window, winContext, (char **)&hwnd ))
+ return;
+
+ if (hrgn)
+ {
+ if (!(size = GetRegionData( hrgn, 0, NULL ))) return;
+ if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
+ if (!GetRegionData( hrgn, size, data ))
+ {
+ HeapFree( GetProcessHeap(), 0, data );
+ return;
+ }
+ SERVER_START_REQ( set_layer_region )
+ {
+ req->window = wine_server_user_handle( hwnd );
+ if (data->rdh.nCount)
+ wine_server_add_data( req, data->Buffer, data->rdh.nCount * sizeof(RECT) );
+ else
+ wine_server_add_data( req, &empty_rect, sizeof(empty_rect) );
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ HeapFree( GetProcessHeap(), 0, data );
+ }
+ else /* clear existing region */
+ {
+ SERVER_START_REQ( set_layer_region )
+ {
+ req->window = wine_server_user_handle( hwnd );
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ }
+}
+
/***********************************************************************
* update_surface_region
*/
@@ -1627,7 +1670,7 @@ static void update_surface_region( struct x11drv_window_surface *surface )
if (!surface->is_argb && surface->color_key == CLR_INVALID)
{
XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet );
- return;
+ set_layer_region( surface, NULL );
}
data->rdh.dwSize = sizeof(data->rdh);
@@ -1737,6 +1780,7 @@ static void update_surface_region( struct x11drv_window_surface *surface )
HeapFree( GetProcessHeap(), 0, data );
}
+ set_layer_region( surface, rgn );
DeleteObject( rgn );
#endif
}
diff --git a/server/protocol.def b/server/protocol.def
index 7eaaec2b823..f2526c4836c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2682,6 +2682,13 @@ enum coords_relative
@END
+/* Set the layer region */
+@REQ(set_layer_region)
+ user_handle_t window; /* handle to the window */
+ VARARG(region,rectangles); /* list of rectangles for the region (in window coords) */
+@END
+
+
/* Get the window update region */
@REQ(get_update_region)
user_handle_t window; /* handle to the window */
diff --git a/server/window.c b/server/window.c
index f35d6f60a42..672512b3a43 100644
--- a/server/window.c
+++ b/server/window.c
@@ -72,6 +72,7 @@ struct window
rectangle_t visible_rect; /* visible part of window rect (relative to parent client area) */
rectangle_t client_rect; /* client rectangle (relative to parent client area) */
struct region *win_region; /* region for shaped windows (relative to window rect) */
+ struct region *layer_region; /* region for layered windows (relative to window rect) */
struct region *update_region; /* update region (relative to window rect) */
unsigned int style; /* window style */
unsigned int ex_style; /* window extended style */
@@ -477,6 +478,7 @@ static struct window *create_window( struct window *parent, struct window *owner
win->atom = atom;
win->last_active = win->handle;
win->win_region = NULL;
+ win->layer_region = NULL;
win->update_region = NULL;
win->style = 0;
win->ex_style = 0;
@@ -653,6 +655,9 @@ static inline int is_point_in_window( struct window *win, int x, int y )
if (win->win_region &&
!point_in_region( win->win_region, x - win->window_rect.left, y - win->window_rect.top ))
return 0; /* not in window region */
+ if (win->layer_region &&
+ !point_in_region( win->layer_region, x - win->window_rect.left, y - win->window_rect.top ))
+ return 0; /* not in layer mask region */
return 1;
}
@@ -875,6 +880,18 @@ static struct region *intersect_window_region( struct region *region, struct win
}
+/* intersect the layer region with the specified region, relative to the window parent */
+static struct region *intersect_layer_region( struct region *region, struct window *win )
+{
+ /* make region relative to window rect */
+ offset_region( region, -win->window_rect.left, -win->window_rect.top );
+ if (!intersect_region( region, region, win->layer_region )) return NULL;
+ /* make region relative to parent again */
+ offset_region( region, win->window_rect.left, win->window_rect.top );
+ return region;
+}
+
+
/* convert coordinates from client to screen coords */
static inline void client_to_screen( struct window *win, int *x, int *y )
{
@@ -929,6 +946,11 @@ static struct region *clip_children( struct window *parent, struct window *last,
free_region( tmp );
return NULL;
}
+ if (ptr->layer_region && !intersect_layer_region( tmp, ptr ))
+ {
+ free_region( tmp );
+ return NULL;
+ }
offset_region( tmp, offset_x, offset_y );
if (!(region = subtract_region( region, region, tmp ))) break;
if (is_region_empty( region )) break;
@@ -990,11 +1012,13 @@ static struct region *get_visible_region( struct window *win, unsigned int flags
{
set_region_rect( region, &win->visible_rect );
if (win->win_region && !intersect_window_region( region, win )) goto error;
+ if (win->layer_region && !intersect_layer_region( region, win )) goto error;
}
else
{
set_region_client_rect( region, win );
if (win->win_region && !intersect_window_region( region, win )) goto error;
+ if (win->layer_region && !intersect_layer_region( region, win )) goto error;
}
/* clip children */
@@ -1039,6 +1063,7 @@ static struct region *get_visible_region( struct window *win, unsigned int flags
}
set_region_client_rect( tmp, win );
if (win->win_region && !intersect_window_region( tmp, win )) goto error;
+ if (win->layer_region && !intersect_layer_region( tmp, win )) goto error;
if (!intersect_region( region, region, tmp )) goto error;
if (is_region_empty( region )) break;
}
@@ -1071,6 +1096,7 @@ static struct region *clip_pixel_format_children( struct window *parent, struct
/* add the visible rect */
set_region_rect( clip, &ptr->visible_rect );
if (ptr->win_region && !intersect_window_region( clip, ptr )) break;
+ if (ptr->layer_region && !intersect_layer_region( clip, ptr )) break;
offset_region( clip, offset_x, offset_y );
if (!intersect_region( clip, clip, parent_clip )) break;
if (!union_region( region, region, clip )) break;
@@ -1079,6 +1105,7 @@ static struct region *clip_pixel_format_children( struct window *parent, struct
/* subtract the client rect if it uses a custom pixel format */
set_region_rect( clip, &ptr->client_rect );
if (ptr->win_region && !intersect_window_region( clip, ptr )) break;
+ if (ptr->layer_region && !intersect_layer_region( clip, ptr )) break;
offset_region( clip, offset_x, offset_y );
if (!intersect_region( clip, clip, parent_clip )) break;
if ((ptr->paint_flags & PAINT_HAS_PIXEL_FORMAT) && !subtract_region( region, region, clip ))
@@ -1105,8 +1132,10 @@ static struct region *get_surface_region( struct window *win )
if (!(clip = create_empty_region())) goto error;
set_region_rect( region, &win->visible_rect );
if (win->win_region && !intersect_window_region( region, win )) goto error;
+ if (win->layer_region && !intersect_layer_region( region, win )) goto error;
set_region_rect( clip, &win->client_rect );
if (win->win_region && !intersect_window_region( clip, win )) goto error;
+ if (win->layer_region && !intersect_layer_region( clip, win )) goto error;
if ((win->paint_flags & PAINT_HAS_PIXEL_FORMAT) && !subtract_region( region, region, clip ))
goto error;
@@ -1825,6 +1854,14 @@ static void set_window_region( struct window *win, struct region *region, int re
}
+/* set the layer region */
+static void set_layer_region( struct window *win, struct region *region )
+{
+ if (win->layer_region) free_region( win->layer_region );
+ win->layer_region = region;
+}
+
+
/* destroy a window */
void destroy_window( struct window *win )
{
@@ -1873,6 +1910,7 @@ void destroy_window( struct window *win )
detach_window_thread( win );
if (win->win_region) free_region( win->win_region );
+ if (win->layer_region) free_region( win->layer_region );
if (win->update_region) free_region( win->update_region );
if (win->class) release_class( win->class );
free( win->text );
@@ -2537,6 +2575,24 @@ DECL_HANDLER(set_window_region)
}
+/* set the layer region */
+DECL_HANDLER(set_layer_region)
+{
+ struct region *region = NULL;
+ struct window *win = get_window( req->window );
+
+ if (!win) return;
+
+ if (get_req_data_size()) /* no data means remove the region completely */
+ {
+ if (!(region = create_region_from_req_data( get_req_data(), get_req_data_size() )))
+ return;
+ if (win->ex_style & WS_EX_LAYOUTRTL) mirror_region( &win->window_rect, region );
+ }
+ set_layer_region( win, region );
+}
+
+
/* get a window update region */
DECL_HANDLER(get_update_region)
{
@@ -2633,6 +2689,12 @@ DECL_HANDLER(update_window_zorder)
offset_rect( &tmp, -ptr->window_rect.left, -ptr->window_rect.top );
if (!rect_in_region( ptr->win_region, &tmp )) continue;
}
+ if (ptr->layer_region)
+ {
+ tmp = rect;
+ offset_rect( &tmp, -ptr->window_rect.left, -ptr->window_rect.top );
+ if (!rect_in_region( ptr->layer_region, &tmp )) continue;
+ }
/* found a window obscuring the rectangle, now move win above this one */
/* making sure to not violate the topmost rule */
if (!(ptr->ex_style & WS_EX_TOPMOST) || (win->ex_style & WS_EX_TOPMOST))
--
2.12.2