From deddd33b2b81c91507b0ac68df47bb64e30132cd Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 15 Dec 2008 18:20:27 -0600 Subject: [PATCH] winex11: set X focus to reflect wine focus within virtual desktops --- dlls/winex11.drv/event.c | 11 ++++++++++- dlls/winex11.drv/window.c | 34 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 7 ++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index a5d2e85..18b5dc9 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -58,6 +58,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(event); extern BOOL ximInComposeMode; +Time takefocus_timestamp=0; + #define DndNotDnd -1 /* OffiX drag&drop */ #define DndUnknown 0 #define DndRawData 1 @@ -552,6 +554,13 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event ) hwnd, IsWindowEnabled(hwnd), IsWindowVisible(hwnd), GetWindowLongW(hwnd, GWL_STYLE), GetFocus(), GetActiveWindow(), GetForegroundWindow(), last_focus ); + if (hwnd == GetDesktopWindow()) + { + takefocus_timestamp = event_time; + + X11DRV_sync_focus_window(); + return; + } if (can_activate_window(hwnd)) { /* simulate a mouse click on the caption to find out @@ -682,7 +691,7 @@ static void X11DRV_FocusOut( HWND hwnd, XEvent *xev ) Foreground window, because in most cases the messages sent above must have already changed the foreground window, in which case we don't have to change the foreground window to 0 */ - if (hwnd == GetForegroundWindow()) + if (hwnd == GetForegroundWindow() && DefaultRootWindow(event->display) == root_window) { TRACE( "lost focus, setting fg to desktop\n" ); SetForegroundWindow( GetDesktopWindow() ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index dfbb210..bfc1120 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2024,10 +2024,41 @@ void CDECL X11DRV_SetFocus( HWND hwnd ) /* CurrentTime */ GetMessageTime() - EVENT_x11_time_to_win32_time(0)); } + else + { + PostMessageW( GetDesktopWindow(), WM_X11DRV_SYNC_FOCUS, 0, 0 ); + } wine_tsx11_unlock(); } +static int XSyncFocusErrorHandler( Display *dpy, XErrorEvent *event, void *arg ) +{ + return event->request_code == X_SetInputFocus && + (event->error_code == BadMatch || event->error_code == BadWindow); +} + +/********************************************************************** + * X11DRV_sync_focus_window + */ +void X11DRV_sync_focus_window( void ) +{ + HWND hwnd = GetForegroundWindow(); + Window win = X11DRV_get_whole_window(hwnd); + Display* display = thread_display(); + + if (win && takefocus_timestamp) + { + TRACE( "setting focus to %p (%lx) time=%ld\n", hwnd, win, takefocus_timestamp ); + /* The window may be unviewable or gone at any time so we expect errors. */ + X11DRV_expect_error( display, XSyncFocusErrorHandler, NULL); + XSetInputFocus( display, win, RevertToParent, takefocus_timestamp ); + XSync( display, False ); + X11DRV_check_error(); + } +} + + /*********************************************************************** * WindowPosChanging (X11DRV.@) */ @@ -2309,6 +2340,9 @@ LRESULT CDECL X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) case WM_X11DRV_RESIZE_DESKTOP: X11DRV_resize_desktop( LOWORD(lp), HIWORD(lp) ); return 0; + case WM_X11DRV_SYNC_FOCUS: + X11DRV_sync_focus_window(); + return 0; default: FIXME( "got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, wp, lp ); return 0; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 955a08c..47bc760 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -571,6 +571,9 @@ extern HMODULE x11drv_module; extern BYTE key_state_table[256]; extern POINT cursor_pos; +/* time of last WM_TAKE_FOCUS request on the virtual desktop */ +extern Time takefocus_timestamp; + /* atoms */ enum x11drv_atoms @@ -673,7 +676,8 @@ enum x11drv_window_messages WM_X11DRV_DELETE_WINDOW, WM_X11DRV_SET_WIN_FORMAT, WM_X11DRV_SET_WIN_REGION, - WM_X11DRV_RESIZE_DESKTOP + WM_X11DRV_RESIZE_DESKTOP, + WM_X11DRV_SYNC_FOCUS }; /* _NET_WM_STATE properties that we keep track of */ @@ -738,6 +742,7 @@ extern void X11DRV_InitClipboard(void); extern int CDECL X11DRV_AcquireClipboard(HWND hWndClipWindow); extern void X11DRV_ResetSelectionOwner(void); extern void CDECL X11DRV_SetFocus( HWND hwnd ); +extern void X11DRV_sync_focus_window( void ); extern Cursor X11DRV_GetCursor( Display *display, struct tagCURSORICONINFO *ptr ); extern void CDECL X11DRV_SetCursor( struct tagCURSORICONINFO *lpCursor ); extern BOOL CDECL X11DRV_ClipCursor( LPCRECT clip ); -- 1.5.6.3