From 0b71e0bf120f85001d35fc884ddbb592372807da Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 14 Oct 2013 14:20:08 +0200 Subject: [PATCH] winex11: Add helper functions for converting between root and virtual screen coords. --- dlls/winex11.drv/desktop.c | 6 +-- dlls/winex11.drv/event.c | 86 ++++++++++++++++++------------------- dlls/winex11.drv/mouse.c | 49 +++++++++++---------- dlls/winex11.drv/window.c | 32 ++++++++------ dlls/winex11.drv/x11drv.h | 2 + dlls/winex11.drv/xdnd.c | 5 +-- dlls/winex11.drv/xinerama.c | 16 +++++++ 7 files changed, 107 insertions(+), 89 deletions(-) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index 5fbb8607441..733aca819dc 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -188,10 +188,10 @@ static BOOL CALLBACK update_windows_on_desktop_resize( HWND hwnd, LPARAM lparam if (resize_data->old_virtual_rect.top != virtual_screen_rect.top) mask |= CWY; if (mask && data->whole_window) { + POINT pos = virtual_screen_to_root( data->whole_rect.left, data->whole_rect.top ); XWindowChanges changes; - - changes.x = data->whole_rect.left - virtual_screen_rect.left; - changes.y = data->whole_rect.top - virtual_screen_rect.top; + changes.x = pos.x; + changes.y = pos.y; XReconfigureWMWindow( data->display, data->whole_window, data->vis.screen, mask, &changes ); } release_win_data( data ); diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 5e5b19ec925..4218949e567 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -815,6 +815,7 @@ static void X11DRV_Expose( HWND hwnd, XEvent *xev ) { XExposeEvent *event = &xev->xexpose; RECT rect; + POINT pos; struct x11drv_win_data *data; HRGN surface_region = 0; UINT flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN; @@ -822,12 +823,19 @@ static void X11DRV_Expose( HWND hwnd, XEvent *xev ) TRACE( "win %p (%lx) %d,%d %dx%d\n", hwnd, event->window, event->x, event->y, event->width, event->height ); + if (event->window != root_window) + { + pos.x = event->x; + pos.y = event->y; + } + else pos = root_to_virtual_screen( event->x, event->y ); + if (!(data = get_win_data( hwnd ))) return; - rect.left = event->x; - rect.top = event->y; - rect.right = event->x + event->width; - rect.bottom = event->y + event->height; + rect.left = pos.x; + rect.top = pos.y; + rect.right = pos.x + event->width; + rect.bottom = pos.y + event->height; if (event->window != data->client_window) { @@ -861,11 +869,8 @@ static void X11DRV_Expose( HWND hwnd, XEvent *xev ) } SERVER_END_REQ; } - else - { - OffsetRect( &rect, virtual_screen_rect.left, virtual_screen_rect.top ); - flags &= ~RDW_ALLCHILDREN; - } + else flags &= ~RDW_ALLCHILDREN; + release_win_data( data ); if (flags) RedrawWindow( hwnd, &rect, surface_region, flags ); @@ -1002,6 +1007,7 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) XConfigureEvent *event = &xev->xconfigure; struct x11drv_win_data *data; RECT rect; + POINT pos; UINT flags; HWND parent; BOOL root_coords; @@ -1034,11 +1040,18 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) 0, 0, &x, &y, &child ); root_coords = TRUE; } - rect.left = x; - rect.top = y; - rect.right = x + event->width; - rect.bottom = y + event->height; - if (root_coords) OffsetRect( &rect, virtual_screen_rect.left, virtual_screen_rect.top ); + + if (!root_coords) + { + pos.x = x; + pos.y = y; + } + else pos = root_to_virtual_screen( x, y ); + + rect.left = pos.x; + rect.top = pos.y; + rect.right = pos.x + event->width; + rect.bottom = pos.y + event->height; TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n", hwnd, data->whole_window, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, event->x, event->y, event->width, event->height ); @@ -1384,12 +1397,12 @@ static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt ) static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event ) { struct x11drv_win_data *data; + POINT pt; unsigned long data_length; unsigned long aux_long; unsigned char* p_data = NULL; Atom atom_aux; int x, y, cx, cy, dummy; - BOOL bAccept; Window win, w_aux_root, w_aux_child; if (!(data = get_win_data( hWnd ))) return; @@ -1400,34 +1413,19 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event ) XQueryPointer( event->display, win, &w_aux_root, &w_aux_child, &x, &y, &dummy, &dummy, (unsigned int*)&aux_long); - x += virtual_screen_rect.left; - y += virtual_screen_rect.top; + pt = root_to_virtual_screen( x, y ); /* find out drop point and drop window */ - if (x < 0 || y < 0 || x > cx || y > cy) + if (pt.x < 0 || pt.y < 0 || pt.x > cx || pt.y > cy) { - bAccept = GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES; - x = 0; - y = 0; + if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return; + pt.x = pt.y = 0; } else { - POINT pt = { x, y }; - HWND hwndDrop = find_drop_window( hWnd, &pt ); - if (hwndDrop) - { - x = pt.x; - y = pt.y; - bAccept = TRUE; - } - else - { - bAccept = FALSE; - } + if (!find_drop_window( hWnd, &pt )) return; } - if (!bAccept) return; - XGetWindowProperty( event->display, DefaultRootWindow(event->display), x11drv_atom(DndSelection), 0, 65535, FALSE, AnyPropertyType, &atom_aux, &dummy, @@ -1457,8 +1455,7 @@ static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event ) if( lpDrop ) { lpDrop->pFiles = sizeof(DROPFILES); - lpDrop->pt.x = x; - lpDrop->pt.y = y; + lpDrop->pt = pt; lpDrop->fNC = FALSE; lpDrop->fWide = FALSE; p_drop = (char *)(lpDrop + 1); @@ -1494,6 +1491,7 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event ) char *p_drop = NULL; char *p, *next; int x, y; + POINT pos; DROPFILES *lpDrop; HDROP hDrop; union { @@ -1535,8 +1533,7 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event ) if( drop_len && drop_len < 65535 ) { XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux, &x, &y, &u.i, &u.i, &u.u); - x += virtual_screen_rect.left; - y += virtual_screen_rect.top; + pos = root_to_virtual_screen( x, y ); drop_len += sizeof(DROPFILES) + 1; hDrop = GlobalAlloc( GMEM_SHARE, drop_len ); @@ -1545,13 +1542,12 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event ) if( lpDrop && (win_data = get_win_data( hWnd ))) { lpDrop->pFiles = sizeof(DROPFILES); - lpDrop->pt.x = x; - lpDrop->pt.y = y; + lpDrop->pt = pos; lpDrop->fNC = - ( x < (win_data->client_rect.left - win_data->whole_rect.left) || - y < (win_data->client_rect.top - win_data->whole_rect.top) || - x > (win_data->client_rect.right - win_data->whole_rect.left) || - y > (win_data->client_rect.bottom - win_data->whole_rect.top) ); + (pos.x < (win_data->client_rect.left - win_data->whole_rect.left) || + pos.y < (win_data->client_rect.top - win_data->whole_rect.top) || + pos.x > (win_data->client_rect.right - win_data->whole_rect.left) || + pos.y > (win_data->client_rect.bottom - win_data->whole_rect.top) ); lpDrop->fWide = FALSE; p_drop = (char*)(lpDrop + 1); release_win_data( win_data ); diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index b33827bb9d9..c89f69b46bd 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -361,6 +361,7 @@ static BOOL grab_clipping_window( const RECT *clip ) struct x11drv_thread_data *data = x11drv_thread_data(); Window clip_window; HWND msg_hwnd = 0; + POINT pos; if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) return TRUE; /* don't clip in the desktop process */ @@ -386,8 +387,8 @@ static BOOL grab_clipping_window( const RECT *clip ) TRACE( "clipping to %s win %lx\n", wine_dbgstr_rect(clip), clip_window ); if (!data->clip_hwnd) XUnmapWindow( data->display, clip_window ); - XMoveResizeWindow( data->display, clip_window, - clip->left - virtual_screen_rect.left, clip->top - virtual_screen_rect.top, + pos = virtual_screen_to_root( clip->left, clip->top ); + XMoveResizeWindow( data->display, clip_window, pos.x, pos.y, max( 1, clip->right - clip->left ), max( 1, clip->bottom - clip->top ) ); XMapWindow( data->display, clip_window ); @@ -549,20 +550,21 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU return; } + if (window != root_window) + { + pt.x = input->u.mi.dx; + pt.y = input->u.mi.dy; + } + else pt = root_to_virtual_screen( input->u.mi.dx, input->u.mi.dy ); + if (!(data = get_win_data( hwnd ))) return; if (window == data->whole_window) { - input->u.mi.dx += data->whole_rect.left - data->client_rect.left; - input->u.mi.dy += data->whole_rect.top - data->client_rect.top; + pt.x += data->whole_rect.left - data->client_rect.left; + pt.y += data->whole_rect.top - data->client_rect.top; } - if (window == root_window) - { - input->u.mi.dx += virtual_screen_rect.left; - input->u.mi.dy += virtual_screen_rect.top; - } - pt.x = input->u.mi.dx; - pt.y = input->u.mi.dy; + if (GetWindowLongW( data->hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) pt.x = data->client_rect.right - data->client_rect.left - 1 - pt.x; MapWindowPoints( hwnd, 0, &pt, 1 ); @@ -1344,9 +1346,9 @@ void CDECL X11DRV_SetCursor( HCURSOR handle ) BOOL CDECL X11DRV_SetCursorPos( INT x, INT y ) { struct x11drv_thread_data *data = x11drv_init_thread_data(); + POINT pos = virtual_screen_to_root( x, y ); - XWarpPointer( data->display, root_window, root_window, 0, 0, 0, 0, - x - virtual_screen_rect.left, y - virtual_screen_rect.top ); + XWarpPointer( data->display, root_window, root_window, 0, 0, 0, 0, pos.x, pos.y ); data->warp_serial = NextRequest( data->display ); XNoOp( data->display ); XFlush( data->display ); /* avoids bad mouse lag in games that do their own mouse warping */ @@ -1369,8 +1371,7 @@ BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos) if (ret) { POINT old = *pos; - pos->x = winX + virtual_screen_rect.left; - pos->y = winY + virtual_screen_rect.top; + *pos = root_to_virtual_screen( winX, winY ); TRACE( "pointer at (%d,%d) server pos %d,%d\n", pos->x, pos->y, old.x, old.y ); } return ret; @@ -1424,7 +1425,8 @@ void move_resize_window( HWND hwnd, int dir ) { Display *display = thread_display(); DWORD pt; - int x, y, rootX, rootY, button = 0; + POINT pos; + int button = 0; XEvent xev; Window win, root, child; unsigned int xstate; @@ -1432,14 +1434,13 @@ void move_resize_window( HWND hwnd, int dir ) if (!(win = X11DRV_get_whole_window( hwnd ))) return; pt = GetMessagePos(); - x = (short)LOWORD( pt ); - y = (short)HIWORD( pt ); + pos = virtual_screen_to_root( (short)LOWORD( pt ), (short)HIWORD( pt ) ); if (GetKeyState( VK_LBUTTON ) & 0x8000) button = 1; else if (GetKeyState( VK_MBUTTON ) & 0x8000) button = 2; else if (GetKeyState( VK_RBUTTON ) & 0x8000) button = 3; - TRACE( "hwnd %p/%lx, x %d, y %d, dir %d, button %d\n", hwnd, win, x, y, dir, button ); + TRACE( "hwnd %p/%lx, x %d, y %d, dir %d, button %d\n", hwnd, win, pos.x, pos.y, dir, button ); xev.xclient.type = ClientMessage; xev.xclient.window = win; @@ -1448,8 +1449,8 @@ void move_resize_window( HWND hwnd, int dir ) xev.xclient.display = display; xev.xclient.send_event = True; xev.xclient.format = 32; - xev.xclient.data.l[0] = x - virtual_screen_rect.left; /* x coord */ - xev.xclient.data.l[1] = y - virtual_screen_rect.top; /* y coord */ + xev.xclient.data.l[0] = pos.x; /* x coord */ + xev.xclient.data.l[1] = pos.y; /* y coord */ xev.xclient.data.l[2] = dir; /* direction */ xev.xclient.data.l[3] = button; /* button */ xev.xclient.data.l[4] = 0; /* unused */ @@ -1469,15 +1470,17 @@ void move_resize_window( HWND hwnd, int dir ) { MSG msg; INPUT input; + int x, y, rootX, rootY; if (!XQueryPointer( display, root_window, &root, &child, &rootX, &rootY, &x, &y, &xstate )) break; if (!(xstate & (Button1Mask << (button - 1)))) { /* fake a button release event */ + pos = root_to_virtual_screen( x, y ); input.type = INPUT_MOUSE; - input.u.mi.dx = x + virtual_screen_rect.left; - input.u.mi.dy = y + virtual_screen_rect.top; + input.u.mi.dx = pos.x; + input.u.mi.dy = pos.y; input.u.mi.mouseData = button_up_data[button - 1]; input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; input.u.mi.time = GetTickCount(); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index d9265e32bc8..b7718225a77 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1218,8 +1218,9 @@ static void sync_window_position( struct x11drv_win_data *data, /* only the size is allowed to change for the desktop window */ if (data->whole_window != root_window) { - changes.x = data->whole_rect.left - virtual_screen_rect.left; - changes.y = data->whole_rect.top - virtual_screen_rect.top; + POINT pt = virtual_screen_to_root( data->whole_rect.left, data->whole_rect.top ); + changes.x = pt.x; + changes.y = pt.y; mask |= CWX | CWY; } @@ -1415,6 +1416,7 @@ static void create_whole_window( struct x11drv_win_data *data ) BYTE alpha; DWORD layered_flags; HRGN win_rgn; + POINT pos; if (!data->managed && is_window_managed( data->hwnd, SWP_NOACTIVATE, &data->window_rect )) { @@ -1441,9 +1443,8 @@ static void create_whole_window( struct x11drv_win_data *data ) if (!(cy = data->whole_rect.bottom - data->whole_rect.top)) cy = 1; else if (cy > 65535) cy = 65535; - data->whole_window = XCreateWindow( data->display, root_window, - data->whole_rect.left - virtual_screen_rect.left, - data->whole_rect.top - virtual_screen_rect.top, + pos = virtual_screen_to_root( data->whole_rect.left, data->whole_rect.top ); + data->whole_window = XCreateWindow( data->display, root_window, pos.y, pos.y, cx, cy, 0, data->vis.depth, InputOutput, data->vis.visual, mask, &attr ); if (!data->whole_window) goto done; @@ -1835,6 +1836,7 @@ HWND create_foreign_window( Display *display, Window xwin ) static BOOL class_registered; struct x11drv_win_data *data; HWND hwnd, parent; + POINT pos; Window xparent, xroot; Window *xchildren; unsigned int nchildren; @@ -1873,16 +1875,17 @@ HWND create_foreign_window( Display *display, Window xwin ) { parent = GetDesktopWindow(); style |= WS_POPUP; - attr.x += virtual_screen_rect.left; - attr.y += virtual_screen_rect.top; + pos = root_to_virtual_screen( attr.x, attr.y ); } else { parent = create_foreign_window( display, xparent ); style |= WS_CHILD; + pos.x = attr.x; + pos.y = attr.y; } - hwnd = CreateWindowW( classW, NULL, style, attr.x, attr.y, attr.width, attr.height, + hwnd = CreateWindowW( classW, NULL, style, pos.x, pos.y, attr.width, attr.height, parent, 0, 0, NULL ); if (!(data = alloc_win_data( display, hwnd ))) @@ -1890,7 +1893,7 @@ HWND create_foreign_window( Display *display, Window xwin ) DestroyWindow( hwnd ); return 0; } - SetRect( &data->window_rect, attr.x, attr.y, attr.x + attr.width, attr.y + attr.height ); + SetRect( &data->window_rect, pos.x, pos.y, pos.x + attr.width, pos.y + attr.height ); data->whole_rect = data->client_rect = data->window_rect; data->whole_window = data->client_window = 0; data->embedded = TRUE; @@ -2355,6 +2358,7 @@ UINT CDECL X11DRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) int x, y; unsigned int width, height, border, depth; Window root, top; + POINT pos; DWORD style = GetWindowLongW( hwnd, GWL_STYLE ); struct x11drv_thread_data *thread_data = x11drv_thread_data(); struct x11drv_win_data *data = get_win_data( hwnd ); @@ -2387,11 +2391,11 @@ UINT CDECL X11DRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) XGetGeometry( thread_data->display, data->whole_window, &root, &x, &y, &width, &height, &border, &depth ); XTranslateCoordinates( thread_data->display, data->whole_window, root, 0, 0, &x, &y, &top ); - rect->left = x; - rect->top = y; - rect->right = x + width; - rect->bottom = y + height; - OffsetRect( rect, virtual_screen_rect.left, virtual_screen_rect.top ); + pos = root_to_virtual_screen( x, y ); + rect->left = pos.x; + rect->top = pos.y; + rect->right = pos.x + width; + rect->bottom = pos.y + height; X11DRV_X_to_window_rect( data, rect ); swp &= ~(SWP_NOMOVE | SWP_NOCLIENTMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index bfcea89849d..b5621e2e0a6 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -640,6 +640,8 @@ typedef int (*x11drv_error_callback)( Display *display, XErrorEvent *event, void extern void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg ) DECLSPEC_HIDDEN; extern int X11DRV_check_error(void) DECLSPEC_HIDDEN; extern void X11DRV_X_to_window_rect( struct x11drv_win_data *data, RECT *rect ) DECLSPEC_HIDDEN; +extern POINT virtual_screen_to_root( INT x, INT y ) DECLSPEC_HIDDEN; +extern POINT root_to_virtual_screen( INT x, INT y ) DECLSPEC_HIDDEN; extern void xinerama_init( unsigned int width, unsigned int height ) DECLSPEC_HIDDEN; struct x11drv_mode_info diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c index e1b6f782190..637fc06386b 100644 --- a/dlls/winex11.drv/xdnd.c +++ b/dlls/winex11.drv/xdnd.c @@ -278,10 +278,7 @@ void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event ) HWND targetWindow; HRESULT hr; - XDNDxy.x = event->data.l[2] >> 16; - XDNDxy.y = event->data.l[2] & 0xFFFF; - XDNDxy.x += virtual_screen_rect.left; - XDNDxy.y += virtual_screen_rect.top; + XDNDxy = root_to_virtual_screen( event->data.l[2] >> 16, event->data.l[2] & 0xFFFF ); targetWindow = WindowFromPoint(XDNDxy); pointl.x = XDNDxy.x; diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index d88831e01c0..60b392d79db 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -157,6 +157,22 @@ static inline int query_screens(void) #endif /* SONAME_LIBXINERAMA */ +POINT virtual_screen_to_root( INT x, INT y ) +{ + POINT pt; + pt.x = x - virtual_screen_rect.left; + pt.y = y - virtual_screen_rect.top; + return pt; +} + +POINT root_to_virtual_screen( INT x, INT y ) +{ + POINT pt; + pt.x = x + virtual_screen_rect.left; + pt.y = y + virtual_screen_rect.top; + return pt; +} + void xinerama_init( unsigned int width, unsigned int height ) { MONITORINFOEXW *primary;