Commit 50679095 authored by Ulrich Czekalla's avatar Ulrich Czekalla Committed by Alexandre Julliard

Create a thread-specific selection window to make sure we receive the

selection events in the correct thread.
parent 0ed059cd
...@@ -321,6 +321,26 @@ static UINT wSeqNo = 0; ...@@ -321,6 +321,26 @@ static UINT wSeqNo = 0;
* Internal Clipboard implementation methods * 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 * X11DRV_InitClipboard
*/ */
...@@ -1603,7 +1623,6 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) ...@@ -1603,7 +1623,6 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
unsigned long remain; unsigned long remain;
Atom* targetList=NULL; Atom* targetList=NULL;
Window w; Window w;
HWND hWndClipWindow;
unsigned long cSelectionTargets = 0; unsigned long cSelectionTargets = 0;
if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD)) if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD))
...@@ -1613,21 +1632,13 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) ...@@ -1613,21 +1632,13 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
return -1; /* Prevent self request */ return -1; /* Prevent self request */
} }
if (lpcbinfo->flags & CB_OWNER) w = thread_selection_wnd();
hWndClipWindow = lpcbinfo->hWndOwner; if (!w)
else if (lpcbinfo->flags & CB_OPEN)
hWndClipWindow = lpcbinfo->hWndOpen;
else
hWndClipWindow = GetActiveWindow();
if (!hWndClipWindow)
{ {
WARN("No window available to retrieve selection!\n"); ERR("No window available to retrieve selection!\n");
return -1; return -1;
} }
w = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
/* /*
* Query the selection owner for the TARGETS property * Query the selection owner for the TARGETS property
*/ */
...@@ -1714,20 +1725,16 @@ static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat) ...@@ -1714,20 +1725,16 @@ static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat)
Display *display = thread_display(); Display *display = thread_display();
BOOL bRet = FALSE; BOOL bRet = FALSE;
Bool res; Bool res;
HWND hWndClipWindow = GetOpenClipboardWindow();
HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
LPWINE_CLIPFORMAT lpFormat; LPWINE_CLIPFORMAT lpFormat;
TRACE("%d\n", wFormat); TRACE("%d\n", wFormat);
if (!selectionAcquired) if (!selectionAcquired)
{ {
Window w = X11DRV_get_whole_window(GetAncestor(hWnd, GA_ROOT)); Window w = thread_selection_wnd();
if(!w) if(!w)
{ {
FIXME("No parent win found %p %p\n", hWnd, hWndClipWindow); ERR("No window available to read selection data!\n");
return FALSE; return FALSE;
} }
...@@ -1988,9 +1995,9 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd, Time t ...@@ -1988,9 +1995,9 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd, Time t
X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo); 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 */ another Wine process */
if (OpenClipboard(hwnd)) if (OpenClipboard(hwnd))
{ {
...@@ -2130,7 +2137,20 @@ void X11DRV_AcquireClipboard(HWND hWndClipWindow) ...@@ -2130,7 +2137,20 @@ void X11DRV_AcquireClipboard(HWND hWndClipWindow)
if (!hWndClipWindow) if (!hWndClipWindow)
hWndClipWindow = GetActiveWindow(); 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(); wine_tsx11_lock();
/* Grab PRIMARY selection if not owned */ /* Grab PRIMARY selection if not owned */
......
...@@ -902,3 +902,20 @@ static void EVENT_ClientMessage( HWND hwnd, XEvent *xev ) ...@@ -902,3 +902,20 @@ static void EVENT_ClientMessage( HWND hwnd, XEvent *xev )
} }
TRACE( "no handler found for %ld\n", event->message_type ); 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;
}
}
...@@ -376,6 +376,7 @@ struct x11drv_thread_data ...@@ -376,6 +376,7 @@ struct x11drv_thread_data
Window cursor_window; /* current window that contains the cursor */ Window cursor_window; /* current window that contains the cursor */
HWND last_focus; /* last window that had focus */ HWND last_focus; /* last window that had focus */
XIM xim; /* input method */ XIM xim; /* input method */
Window selection_wnd; /* window used for selection interactions */
}; };
extern struct x11drv_thread_data *x11drv_init_thread_data(void); extern struct x11drv_thread_data *x11drv_init_thread_data(void);
...@@ -482,6 +483,12 @@ extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XEvent *event ); ...@@ -482,6 +483,12 @@ extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XEvent *event );
extern DWORD EVENT_x11_time_to_win32_time(Time time); 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 */ /* x11drv private window data */
struct x11drv_win_data struct x11drv_win_data
{ {
......
...@@ -109,6 +109,7 @@ ...@@ -109,6 +109,7 @@
@ cdecl SetWindowText(long wstr) X11DRV_SetWindowText @ cdecl SetWindowText(long wstr) X11DRV_SetWindowText
@ cdecl ShowWindow(long long) X11DRV_ShowWindow @ cdecl ShowWindow(long long) X11DRV_ShowWindow
@ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove @ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove
@ cdecl WindowMessage(long long long long) X11DRV_WindowMessage
# WinTab32 # WinTab32
@ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet @ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet
......
...@@ -487,6 +487,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) ...@@ -487,6 +487,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)
data->cursor = None; data->cursor = None;
data->cursor_window = None; data->cursor_window = None;
data->last_focus = 0; data->last_focus = 0;
data->selection_wnd = 0;
NtCurrentTeb()->driver_data = data; NtCurrentTeb()->driver_data = data;
if (desktop_tid) AttachThreadInput( GetCurrentThreadId(), desktop_tid, TRUE ); if (desktop_tid) AttachThreadInput( GetCurrentThreadId(), desktop_tid, TRUE );
return data; return data;
......
...@@ -3130,6 +3130,7 @@ struct set_clipboard_info_reply ...@@ -3130,6 +3130,7 @@ struct set_clipboard_info_reply
#define SET_CB_CLOSE 0x020 #define SET_CB_CLOSE 0x020
#define CB_OPEN 0x040 #define CB_OPEN 0x040
#define CB_OWNER 0x080 #define CB_OWNER 0x080
#define CB_PROCESS 0x100
...@@ -3780,6 +3781,6 @@ union generic_reply ...@@ -3780,6 +3781,6 @@ union generic_reply
struct duplicate_token_reply duplicate_token_reply; struct duplicate_token_reply duplicate_token_reply;
}; };
#define SERVER_PROTOCOL_VERSION 157 #define SERVER_PROTOCOL_VERSION 158
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -80,7 +80,7 @@ static int set_clipboard_window(user_handle_t win, int clear) ...@@ -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) 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); set_error(STATUS_WAS_LOCKED);
return 0; return 0;
...@@ -166,4 +166,8 @@ DECL_HANDLER(set_clipboard_info) ...@@ -166,4 +166,8 @@ DECL_HANDLER(set_clipboard_info)
if (cbowner == current) if (cbowner == current)
reply->flags |= CB_OWNER; reply->flags |= CB_OWNER;
if (cbowner &&
cbowner->process == current->process)
reply->flags |= CB_PROCESS;
} }
...@@ -2200,6 +2200,7 @@ enum message_type ...@@ -2200,6 +2200,7 @@ enum message_type
#define SET_CB_CLOSE 0x020 #define SET_CB_CLOSE 0x020
#define CB_OPEN 0x040 #define CB_OPEN 0x040
#define CB_OWNER 0x080 #define CB_OWNER 0x080
#define CB_PROCESS 0x100
/* Open a security token */ /* Open a security token */
......
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