Create a thread-specific selection window to make sure we receive the
selection events in the correct thread.
This commit is contained in:
parent
0ed059cd77
commit
5067909587
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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,7 +1995,7 @@ 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 */
|
||||||
|
@ -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 )
|
||||||
}
|
}
|
||||||
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
|
||||||
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 );
|
||||||
|
|
||||||
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 @@
|
||||||
@ 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)
|
||||||
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
|
||||||
#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
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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
|
||||||
#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 */
|
||||||
|
|
Loading…
Reference in New Issue