From 5067909587717bf2c6c35019ba6f6cc6fc3da115 Mon Sep 17 00:00:00 2001 From: Ulrich Czekalla Date: Mon, 7 Mar 2005 19:31:46 +0000 Subject: [PATCH] Create a thread-specific selection window to make sure we receive the selection events in the correct thread. --- dlls/x11drv/clipboard.c | 62 ++++++++++++++++++++++++++++-------------- dlls/x11drv/event.c | 17 ++++++++++++ dlls/x11drv/x11drv.h | 7 +++++ dlls/x11drv/x11drv.spec | 1 + dlls/x11drv/x11drv_main.c | 1 + include/wine/server_protocol.h | 3 +- server/clipboard.c | 6 +++- server/protocol.def | 1 + 8 files changed, 75 insertions(+), 23 deletions(-) diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c index 4263fad282f..ae76f3e3640 100644 --- a/dlls/x11drv/clipboard.c +++ b/dlls/x11drv/clipboard.c @@ -321,6 +321,26 @@ static UINT wSeqNo = 0; * Internal Clipboard implementation methods **************************************************************************/ +static Window thread_selection_wnd(void) +{ + Window w = x11drv_thread_data()->selection_wnd; + + if (!w) + { + wine_tsx11_lock(); + w = XCreateWindow(thread_display(), root_window, 0, 0, 1, 1, 0, screen_depth, + InputOutput, visual, 0, NULL); + wine_tsx11_unlock(); + + if (w) + x11drv_thread_data()->selection_wnd = w; + else + FIXME("Failed to create window. Fetching selection data will fail.\n"); + } + + return w; +} + /************************************************************************** * X11DRV_InitClipboard */ @@ -1603,7 +1623,6 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) unsigned long remain; Atom* targetList=NULL; Window w; - HWND hWndClipWindow; unsigned long cSelectionTargets = 0; if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD)) @@ -1613,21 +1632,13 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) return -1; /* Prevent self request */ } - if (lpcbinfo->flags & CB_OWNER) - hWndClipWindow = lpcbinfo->hWndOwner; - else if (lpcbinfo->flags & CB_OPEN) - hWndClipWindow = lpcbinfo->hWndOpen; - else - hWndClipWindow = GetActiveWindow(); - - if (!hWndClipWindow) + w = thread_selection_wnd(); + if (!w) { - WARN("No window available to retrieve selection!\n"); + ERR("No window available to retrieve selection!\n"); return -1; } - w = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT)); - /* * Query the selection owner for the TARGETS property */ @@ -1714,20 +1725,16 @@ static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat) Display *display = thread_display(); BOOL bRet = FALSE; Bool res; - - HWND hWndClipWindow = GetOpenClipboardWindow(); - HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow(); - LPWINE_CLIPFORMAT lpFormat; TRACE("%d\n", wFormat); if (!selectionAcquired) { - Window w = X11DRV_get_whole_window(GetAncestor(hWnd, GA_ROOT)); + Window w = thread_selection_wnd(); if(!w) { - FIXME("No parent win found %p %p\n", hWnd, hWndClipWindow); + ERR("No window available to read selection data!\n"); return FALSE; } @@ -1988,9 +1995,9 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd, Time t X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo); - if (cbinfo.flags & CB_OWNER) + if (cbinfo.flags & CB_PROCESS) { - /* Since we're still the owner, this wasn't initiated by + /* Since we're still the owner, this wasn't initiated by another Wine process */ if (OpenClipboard(hwnd)) { @@ -2130,7 +2137,20 @@ void X11DRV_AcquireClipboard(HWND hWndClipWindow) if (!hWndClipWindow) hWndClipWindow = GetActiveWindow(); - owner = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT)); + hWndClipWindow = GetAncestor(hWndClipWindow, GA_ROOT); + + if (GetCurrentThreadId() != GetWindowThreadProcessId(hWndClipWindow, NULL)) + { + TRACE("Thread %lx is acquiring selection with thread %lx's window %p\n", + GetCurrentThreadId(), + GetWindowThreadProcessId(hWndClipWindow, NULL), + hWndClipWindow); + if (!SendMessageW(hWndClipWindow, WM_X11DRV_ACQUIRE_SELECTION, 0, 0)) + ERR("Failed to acquire selection\n"); + return; + } + + owner = X11DRV_get_whole_window(hWndClipWindow); wine_tsx11_lock(); /* Grab PRIMARY selection if not owned */ diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c index c5f1801ae6f..93d903b7158 100644 --- a/dlls/x11drv/event.c +++ b/dlls/x11drv/event.c @@ -902,3 +902,20 @@ static void EVENT_ClientMessage( HWND hwnd, XEvent *xev ) } TRACE( "no handler found for %ld\n", event->message_type ); } + + +/********************************************************************** + * X11DRV_WindowMessage (X11DRV.@) + */ +LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) +{ + switch(msg) + { + case WM_X11DRV_ACQUIRE_SELECTION: + X11DRV_AcquireClipboard( hwnd ); + return 0; + default: + FIXME( "got window msg %x hwnd %p wp %x lp %lx\n", msg, hwnd, wp, lp ); + return 0; + } +} diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h index f28bacebac7..ce6a5be448f 100644 --- a/dlls/x11drv/x11drv.h +++ b/dlls/x11drv/x11drv.h @@ -376,6 +376,7 @@ struct x11drv_thread_data Window cursor_window; /* current window that contains the cursor */ HWND last_focus; /* last window that had focus */ XIM xim; /* input method */ + Window selection_wnd; /* window used for selection interactions */ }; extern struct x11drv_thread_data *x11drv_init_thread_data(void); @@ -482,6 +483,12 @@ extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XEvent *event ); extern DWORD EVENT_x11_time_to_win32_time(Time time); +/* X11 driver private messages, must be in the range 0x80001000..0x80001fff */ +enum x11drv_window_messages +{ + WM_X11DRV_ACQUIRE_SELECTION = 0x80001000 +}; + /* x11drv private window data */ struct x11drv_win_data { diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec index f97ec9436fb..00304fa1411 100644 --- a/dlls/x11drv/x11drv.spec +++ b/dlls/x11drv/x11drv.spec @@ -109,6 +109,7 @@ @ cdecl SetWindowText(long wstr) X11DRV_SetWindowText @ cdecl ShowWindow(long long) X11DRV_ShowWindow @ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove +@ cdecl WindowMessage(long long long long) X11DRV_WindowMessage # WinTab32 @ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet diff --git a/dlls/x11drv/x11drv_main.c b/dlls/x11drv/x11drv_main.c index 1aed7692900..bbfe2cfa1f7 100644 --- a/dlls/x11drv/x11drv_main.c +++ b/dlls/x11drv/x11drv_main.c @@ -487,6 +487,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) data->cursor = None; data->cursor_window = None; data->last_focus = 0; + data->selection_wnd = 0; NtCurrentTeb()->driver_data = data; if (desktop_tid) AttachThreadInput( GetCurrentThreadId(), desktop_tid, TRUE ); return data; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 445ee70bc41..1615763b9e1 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3130,6 +3130,7 @@ struct set_clipboard_info_reply #define SET_CB_CLOSE 0x020 #define CB_OPEN 0x040 #define CB_OWNER 0x080 +#define CB_PROCESS 0x100 @@ -3780,6 +3781,6 @@ union generic_reply struct duplicate_token_reply duplicate_token_reply; }; -#define SERVER_PROTOCOL_VERSION 157 +#define SERVER_PROTOCOL_VERSION 158 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/clipboard.c b/server/clipboard.c index 063fe8c9067..3f9db20e663 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -80,7 +80,7 @@ static int set_clipboard_window(user_handle_t win, int clear) static int set_clipboard_owner(user_handle_t win, int clear) { - if (cbthread && cbthread != current) + if (cbthread && cbthread->process != current->process) { set_error(STATUS_WAS_LOCKED); return 0; @@ -166,4 +166,8 @@ DECL_HANDLER(set_clipboard_info) if (cbowner == current) reply->flags |= CB_OWNER; + + if (cbowner && + cbowner->process == current->process) + reply->flags |= CB_PROCESS; } diff --git a/server/protocol.def b/server/protocol.def index 1de26074241..d7d2b53b329 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2200,6 +2200,7 @@ enum message_type #define SET_CB_CLOSE 0x020 #define CB_OPEN 0x040 #define CB_OWNER 0x080 +#define CB_PROCESS 0x100 /* Open a security token */ -- 2.11.4.GIT