winex11: Add helper functions for converting between root and virtual screen coords.

This commit is contained in:
Alexandre Julliard 2013-10-14 14:20:08 +02:00
parent bb45a93d71
commit 0b71e0bf12
7 changed files with 107 additions and 89 deletions

View File

@ -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 );

View File

@ -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 );

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;