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
|
||||
**************************************************************************/
|
||||
|
||||
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,7 +1995,7 @@ 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
|
||||
another Wine process */
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue