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

selection events in the correct thread.
This commit is contained in:
Ulrich Czekalla 2005-03-07 19:31:46 +00:00 committed by Alexandre Julliard
parent 0ed059cd77
commit 5067909587
8 changed files with 75 additions and 23 deletions

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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
{

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */