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.
This commit is contained in:
Alexandre Julliard 2002-06-14 00:08:40 +00:00
parent c0d1ff5967
commit 9428f06993
5 changed files with 85 additions and 38 deletions

View file

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

View file

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

View file

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

View file

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

View file

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