mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Added patch to implement support for layered window regions.
This commit is contained in:
parent
5cc0023094
commit
5d31795ffc
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, ®ion);
|
||||
+ 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, ®ion);
|
||||
+ 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, ®ion);
|
||||
+ 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, ®ion);
|
||||
+ 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, ®ion);
|
||||
+ 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, ®ion);
|
||||
+ 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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user