Commit 9428f069 authored by Alexandre Julliard's avatar Alexandre Julliard

Update the cursor for each window on receiving an X11 event, don't

wait for the SetCursor call. Added EnterNotify handler to set the cursor on window map/unmap.
parent c0d1ff59
......@@ -102,6 +102,7 @@ static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
......@@ -298,6 +299,10 @@ static void EVENT_ProcessEvent( XEvent *event )
X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
break;
case EnterNotify:
X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
break;
case FocusIn:
EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
break;
......
......@@ -134,9 +134,31 @@ static void send_mouse_event( HWND hwnd, DWORD flags, DWORD posX, DWORD posY,
/***********************************************************************
* X11DRV_GetCursor
* update_cursor
*
* Update the cursor of a window on a mouse event.
*/
Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
static void update_cursor( HWND hwnd, Window win )
{
struct x11drv_thread_data *data = x11drv_thread_data();
if (win == X11DRV_get_client_window( hwnd ))
win = X11DRV_get_whole_window( hwnd ); /* always set cursor on whole window */
if (data->cursor_window != win)
{
data->cursor_window = win;
if (data->cursor) TSXDefineCursor( data->display, win, data->cursor );
}
}
/***********************************************************************
* create_cursor
*
* Create an X cursor from a Windows one.
*/
static Cursor create_cursor( Display *display, CURSORICONINFO *ptr )
{
Pixmap pixmapBits, pixmapMask, pixmapMaskInv, pixmapAll;
XColor fg, bg;
......@@ -420,13 +442,6 @@ Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
return cursor;
}
/* set the cursor of a window; helper for X11DRV_SetCursor */
static BOOL CALLBACK set_win_cursor( HWND hwnd, LPARAM cursor )
{
Window win = X11DRV_get_whole_window( hwnd );
if (win) TSXDefineCursor( thread_display(), win, (Cursor)cursor );
return TRUE;
}
/***********************************************************************
* SetCursor (X11DRV.@)
......@@ -440,27 +455,34 @@ void X11DRV_SetCursor( CURSORICONINFO *lpCursor )
/* If in desktop mode, set the cursor on the desktop window */
wine_tsx11_lock();
cursor = X11DRV_GetCursor( gdi_display, lpCursor );
cursor = create_cursor( gdi_display, lpCursor );
if (cursor)
{
XDefineCursor( gdi_display, root_window, cursor );
/* Make the change take effect immediately */
XFlush(gdi_display);
XFreeCursor( gdi_display, cursor );
}
wine_tsx11_unlock();
}
else /* set the same cursor for all top-level windows of the current thread */
{
Display *display = thread_display();
struct x11drv_thread_data *data = x11drv_thread_data();
wine_tsx11_lock();
cursor = X11DRV_GetCursor( display, lpCursor );
wine_tsx11_unlock();
cursor = create_cursor( data->display, lpCursor );
if (cursor)
{
/* EnumThreadWindows( GetCurrentThreadId(), set_win_cursor, (LPARAM)cursor );*/
EnumWindows( set_win_cursor, (LPARAM)cursor );
TSXFreeCursor( display, cursor );
if (data->cursor) XFreeCursor( data->display, data->cursor );
data->cursor = cursor;
if (data->cursor_window)
{
XDefineCursor( data->display, data->cursor_window, cursor );
/* Make the change take effect immediately */
XFlush( data->display );
}
}
wine_tsx11_unlock();
}
}
......@@ -493,6 +515,7 @@ void X11DRV_GetCursorPos(LPPOINT pos)
&rootX, &rootY, &winX, &winY, &xstate ))
return;
update_key_state( xstate );
TRACE("pointer at (%d,%d)\n", winX, winY );
pos->x = winX;
pos->y = winY;
......@@ -503,18 +526,7 @@ void X11DRV_GetCursorPos(LPPOINT pos)
*/
void X11DRV_InitMouse( BYTE *key_state_table )
{
Window root, child;
int root_x, root_y, child_x, child_y;
unsigned int KeyState;
pKeyStateTable = key_state_table;
/* Get the current mouse position and simulate an absolute mouse
movement to initialize the mouse global variables */
TSXQueryPointer( thread_display(), root_window, &root, &child,
&root_x, &root_y, &child_x, &child_y, &KeyState);
update_key_state( KeyState );
send_mouse_event( 0, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
root_x, root_y, 0, GetTickCount() + X11DRV_server_startticks );
}
......@@ -528,7 +540,9 @@ void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event )
POINT pt;
if (buttonNum >= NB_BUTTONS) return;
if (!hwnd) return;
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
switch (buttonNum)
......@@ -555,7 +569,9 @@ void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event )
POINT pt;
if (buttonNum >= NB_BUTTONS || !button_up_flags[buttonNum]) return;
if (!hwnd) return;
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, button_up_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE,
......@@ -570,6 +586,28 @@ void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event )
{
POINT pt;
if (!hwnd) return;
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, event->time );
}
/***********************************************************************
* X11DRV_EnterNotify
*/
void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event )
{
POINT pt;
if (event->detail == NotifyVirtual || event->detail == NotifyNonlinearVirtual) return;
if (!hwnd) return;
/* simulate a mouse motion event */
update_cursor( hwnd, event->window );
get_coords( &hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
......
......@@ -115,7 +115,6 @@ inline static BOOL is_client_window_mapped( WND *win )
* get_window_attributes
*
* Fill the window attributes structure for an X window.
* Returned cursor must be freed by caller.
*/
static int get_window_attributes( Display *display, WND *win, XSetWindowAttributes *attr )
{
......@@ -128,14 +127,13 @@ static int get_window_attributes( Display *display, WND *win, XSetWindowAttribut
attr->override_redirect = !managed;
attr->colormap = X11DRV_PALETTE_PaletteXColormap;
attr->save_under = ((win->clsStyle & CS_SAVEBITS) != 0);
attr->cursor = None;
attr->cursor = x11drv_thread_data()->cursor;
attr->event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask);
ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
if (is_window_top_level( win ))
{
attr->event_mask |= StructureNotifyMask | FocusChangeMask | KeymapStateMask;
attr->cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
}
return (CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap | CWCursor);
}
......@@ -153,7 +151,6 @@ static void sync_window_style( Display *display, WND *win )
wine_tsx11_lock();
mask = get_window_attributes( display, win, &attr );
XChangeWindowAttributes( display, get_whole_window(win), mask, &attr );
if (attr.cursor) XFreeCursor( display, attr.cursor );
wine_tsx11_unlock();
}
......@@ -200,7 +197,7 @@ static Window create_icon_window( Display *display, WND *win )
XSetWindowAttributes attr;
attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask);
ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
attr.bit_gravity = NorthWestGravity;
attr.backing_store = NotUseful/*WhenMapped*/;
attr.colormap = X11DRV_PALETTE_PaletteXColormap; /* Needed due to our visual */
......@@ -230,6 +227,8 @@ inline static void destroy_icon_window( Display *display, WND *win )
struct x11drv_win_data *data = win->pDriverData;
if (!data->icon_window) return;
if (x11drv_thread_data()->cursor_window == data->icon_window)
x11drv_thread_data()->cursor_window = None;
wine_tsx11_lock();
XDeleteContext( display, data->icon_window, winContext );
XDestroyWindow( display, data->icon_window );
......@@ -695,7 +694,6 @@ static Window create_whole_window( Display *display, WND *win )
data->whole_window = XCreateWindow( display, parent, rect.left, rect.top, cx, cy,
0, screen_depth, InputOutput, visual,
mask, &attr );
if (attr.cursor) XFreeCursor( display, attr.cursor );
if (!data->whole_window)
{
......@@ -734,7 +732,7 @@ static Window create_client_window( Display *display, WND *win )
data->client_rect = rect;
attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask);
ButtonPressMask | ButtonReleaseMask | EnterWindowMask);
attr.bit_gravity = (win->clsStyle & (CS_VREDRAW | CS_HREDRAW)) ?
ForgetGravity : NorthWestGravity;
attr.backing_store = NotUseful/*WhenMapped*/;
......@@ -827,7 +825,8 @@ BOOL X11DRV_SetWindowText( HWND hwnd, LPCWSTR text )
*/
BOOL X11DRV_DestroyWindow( HWND hwnd )
{
Display *display = thread_display();
struct x11drv_thread_data *thread_data = x11drv_thread_data();
Display *display = thread_data->display;
WND *wndPtr = WIN_GetPtr( hwnd );
X11DRV_WND_DATA *data = wndPtr->pDriverData;
......@@ -836,6 +835,7 @@ BOOL X11DRV_DestroyWindow( HWND hwnd )
if (data->whole_window)
{
TRACE( "win %x xwin %lx/%lx\n", hwnd, data->whole_window, data->client_window );
if (thread_data->cursor_window == data->whole_window) thread_data->cursor_window = None;
wine_tsx11_lock();
XSync( gdi_display, False ); /* flush any reference to this drawable in GDI queue */
XDeleteContext( display, data->whole_window, winContext );
......
......@@ -456,6 +456,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
ExitProcess(1);
}
data->process_event_count = 0;
data->cursor = None;
data->cursor_window = None;
NtCurrentTeb()->driver_data = data;
return data;
}
......
......@@ -324,6 +324,8 @@ struct x11drv_thread_data
Display *display;
HANDLE display_fd;
int process_event_count; /* recursion count for event processing */
Cursor cursor; /* current cursor */
Window cursor_window; /* current window that contains the cursor */
};
extern struct x11drv_thread_data *x11drv_init_thread_data(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment