diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c index 25d15ee5bca..c77418066dd 100644 --- a/dlls/x11drv/event.c +++ b/dlls/x11drv/event.c @@ -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; diff --git a/dlls/x11drv/mouse.c b/dlls/x11drv/mouse.c index 5b31211aba9..b8fd63d96d0 100644 --- a/dlls/x11drv/mouse.c +++ b/dlls/x11drv/mouse.c @@ -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, diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c index 088706829bf..c5f726e151d 100644 --- a/dlls/x11drv/window.c +++ b/dlls/x11drv/window.c @@ -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 ); diff --git a/dlls/x11drv/x11drv_main.c b/dlls/x11drv/x11drv_main.c index 694241262e7..18fcbec5187 100644 --- a/dlls/x11drv/x11drv_main.c +++ b/dlls/x11drv/x11drv_main.c @@ -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; } diff --git a/include/x11drv.h b/include/x11drv.h index a0af0b34965..470b3346ac8 100644 --- a/include/x11drv.h +++ b/include/x11drv.h @@ -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);