- use global atoms for the format ids

- add timeout when calling XCheckTypedWindowEvent
- fix broken IsClipboardFormatAvailable; it tried to do a trick with
  EnumClipboardFormats by making incorrect assumptions
- in X11DRV_IsClipboardFormatAvailable do a quick exit if no one owns
  the selection
- add 1 second *minimum* time lapse between XSelectionOwner calls
- sync clipboard ownership between different wine processes
- prevents apps from getting into wierd state where they thought they
  didn't own the selection but they did and as a result queried
  themselves for available selection data
This commit is contained in:
Ulrich Czekalla 2003-06-23 23:02:02 +00:00 committed by Alexandre Julliard
parent a3c10cf1e0
commit b2df5f9f19
19 changed files with 2760 additions and 2541 deletions

View File

@ -715,12 +715,6 @@
################################################################
# Wine dll separation hacks, these will go away, don't use them
#
@ cdecl CLIPBOARD_DeleteRecord(ptr long)
@ cdecl CLIPBOARD_EmptyCache(long)
@ cdecl CLIPBOARD_GetFormatName(long ptr long)
@ cdecl CLIPBOARD_IsPresent(long)
@ cdecl CLIPBOARD_LookupFormat(long)
@ cdecl CLIPBOARD_ReleaseOwner()
@ cdecl DCE_InvalidateDCE(long ptr)
@ cdecl HOOK_CallHooks(long long long long long)
@ cdecl NC_GetInsideRect(long ptr)

View File

@ -89,13 +89,15 @@ static BOOL load_driver(void)
GET_USER_FUNC(GetScreenSaveActive);
GET_USER_FUNC(SetScreenSaveActive);
GET_USER_FUNC(AcquireClipboard);
GET_USER_FUNC(ReleaseClipboard);
GET_USER_FUNC(EmptyClipboard);
GET_USER_FUNC(SetClipboardData);
GET_USER_FUNC(GetClipboardData);
GET_USER_FUNC(CountClipboardFormats);
GET_USER_FUNC(EnumClipboardFormats);
GET_USER_FUNC(IsClipboardFormatAvailable);
GET_USER_FUNC(RegisterClipboardFormat);
GET_USER_FUNC(GetClipboardFormatName);
GET_USER_FUNC(IsSelectionOwner);
GET_USER_FUNC(EndClipboardUpdate);
GET_USER_FUNC(ResetSelectionOwner);
GET_USER_FUNC(ChangeDisplaySettingsExW);
GET_USER_FUNC(EnumDisplaySettingsExW);

File diff suppressed because it is too large Load Diff

View File

@ -47,6 +47,7 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(event);
WINE_DECLARE_DEBUG_CHANNEL(clipboard);
/* X context to associate a hwnd to an X window */
extern XContext winContext;
@ -272,10 +273,9 @@ static void EVENT_ProcessEvent( XEvent *event )
if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
hWnd = 0; /* Not for a registered window */
wine_tsx11_unlock();
if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
if ( !hWnd && event->xany.window != root_window
&& event->type != PropertyNotify
&& event->type != MappingNotify)
if (!hWnd && event->type != PropertyNotify && event->type != MappingNotify)
WARN( "Got event %s for unknown Window %08lx\n",
event_names[event->type], event->xany.window );
else
@ -574,6 +574,30 @@ static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
}
/***********************************************************************
* EVENT_SelectionRequest_AddTARGETS
* Utility function for EVENT_SelectionRequest_TARGETS.
*/
static void EVENT_SelectionRequest_AddTARGETS(Atom* targets, unsigned long* cTargets, Atom prop)
{
int i;
BOOL bExists;
/* Scan through what we have so far to avoid duplicates */
for (i = 0, bExists = FALSE; i < *cTargets; i++)
{
if (targets[i] == prop)
{
bExists = TRUE;
break;
}
}
if (!bExists)
targets[(*cTargets)++] = prop;
}
/***********************************************************************
* EVENT_SelectionRequest_TARGETS
* Service a TARGETS selection request event
@ -581,62 +605,46 @@ static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
Atom target, Atom rprop )
{
Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
Atom* targets;
Atom prop;
UINT wFormat;
unsigned long cTargets;
BOOL bHavePixmap;
int xRc;
TRACE("Request for %s\n", TSXGetAtomName(display, target));
UINT alias;
ULONG cTargets;
/*
* Count the number of items we wish to expose as selection targets.
* We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
* We include the TARGETS item, and propery aliases
*/
cTargets = CountClipboardFormats() + 1;
if ( CLIPBOARD_IsPresent(CF_DIB) || CLIPBOARD_IsPresent(CF_BITMAP) )
cTargets++;
cTargets = X11DRV_CountClipboardFormats() + 1;
for (wFormat = 0; (wFormat = X11DRV_EnumClipboardFormats(wFormat));)
{
LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
if (lpFormat && X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData))
cTargets++;
}
TRACE_(clipboard)(" found %ld formats\n", cTargets);
/* Allocate temp buffer */
targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
if(targets == NULL) return None;
if(targets == NULL)
return None;
/* Create TARGETS property list (First item in list is TARGETS itself) */
for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
(wFormat = EnumClipboardFormats( wFormat )); )
for (targets[0] = xaTargets, cTargets = 1, wFormat = 0;
(wFormat = X11DRV_EnumClipboardFormats(wFormat));)
{
if ( (prop = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat)) != None )
{
/* Scan through what we have so far to avoid duplicates */
int i;
BOOL bExists;
for (i = 0, bExists = FALSE; i < cTargets; i++)
{
if (targets[i] == prop)
{
bExists = TRUE;
break;
}
}
if (!bExists)
{
targets[cTargets++] = prop;
LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
/* Add PIXMAP prop for bitmaps additionally */
if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
&& !bHavePixmap )
{
targets[cTargets++] = XA_PIXMAP;
bHavePixmap = TRUE;
}
}
}
EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, lpFormat->drvData);
/* Check if any alias should be listed */
alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData);
if (alias)
EVENT_SelectionRequest_AddTARGETS(targets, &cTargets, alias);
}
if (TRACE_ON(event))
if (TRACE_ON(clipboard))
{
int i;
for ( i = 0; i < cTargets; i++)
@ -644,260 +652,18 @@ static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
if (targets[i])
{
char *itemFmtName = TSXGetAtomName(display, targets[i]);
TRACE("\tAtom# %d: Type %s\n", i, itemFmtName);
TRACE_(clipboard)("\tAtom# %d: Property %ld Type %s\n", i, targets[i], itemFmtName);
TSXFree(itemFmtName);
}
}
}
/* Update the X property */
TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
/* We may want to consider setting the type to xaTargets instead,
* in case some apps expect this instead of XA_ATOM */
xRc = TSXChangeProperty(display, requestor, rprop,
XA_ATOM, 32, PropModeReplace,
(unsigned char *)targets, cTargets);
TRACE("(Rc=%d)\n", xRc);
TSXChangeProperty(display, requestor, rprop, XA_ATOM, 32,
PropModeReplace, (unsigned char *)targets, cTargets);
HeapFree( GetProcessHeap(), 0, targets );
return rprop;
}
/***********************************************************************
* EVENT_SelectionRequest_STRING
* Service a STRING selection request event
*/
static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
Atom target, Atom rprop )
{
static UINT text_cp = (UINT)-1;
HANDLE hUnicodeText;
LPWSTR uni_text;
LPSTR text;
int size,i,j;
char* lpstr = 0;
char *itemFmtName;
int xRc;
if(text_cp == (UINT)-1)
{
HKEY hkey;
/* default value */
text_cp = CP_ACP;
if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
{
char buf[20];
DWORD type, count = sizeof(buf);
if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buf, &count))
text_cp = atoi(buf);
RegCloseKey(hkey);
}
}
/*
* Map the requested X selection property type atom name to a
* windows clipboard format ID.
*/
itemFmtName = TSXGetAtomName(display, target);
TRACE("Request for %s (wFormat=%x %s)\n",
itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT, NULL, 0));
TSXFree(itemFmtName);
hUnicodeText = GetClipboardData(CF_UNICODETEXT);
if(!hUnicodeText)
return None;
uni_text = GlobalLock(hUnicodeText);
if(!uni_text)
return None;
size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
text = HeapAlloc(GetProcessHeap(), 0, size);
if (!text)
return None;
WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
/* remove carriage returns */
lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
if(lpstr == NULL) return None;
for(i=0,j=0; i < size && text[i]; i++ )
{
if( text[i] == '\r' &&
(text[i+1] == '\n' || text[i+1] == '\0') ) continue;
lpstr[j++] = text[i];
}
lpstr[j]='\0';
/* Update the X property */
TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
xRc = TSXChangeProperty(display, requestor, rprop,
XA_STRING, 8, PropModeReplace,
lpstr, j);
TRACE("(Rc=%d)\n", xRc);
GlobalUnlock(hUnicodeText);
HeapFree(GetProcessHeap(), 0, text);
HeapFree( GetProcessHeap(), 0, lpstr );
return rprop;
}
/***********************************************************************
* EVENT_SelectionRequest_PIXMAP
* Service a PIXMAP selection request event
*/
static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
Atom target, Atom rprop )
{
HANDLE hClipData = 0;
Pixmap pixmap = 0;
UINT wFormat;
char * itemFmtName;
int xRc;
#if(0)
XSetWindowAttributes win_attr;
XWindowAttributes win_attr_src;
#endif
/*
* Map the requested X selection property type atom name to a
* windows clipboard format ID.
*/
itemFmtName = TSXGetAtomName(display, target);
wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
TRACE("Request for %s (wFormat=%x %s)\n",
itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0 ));
TSXFree(itemFmtName);
hClipData = GetClipboardData(wFormat);
if ( !hClipData )
{
TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
rprop = None; /* Fail the request */
goto END;
}
if (wFormat == CF_DIB)
{
HWND hwnd = GetOpenClipboardWindow();
HDC hdc = GetDC(hwnd);
/* For convert from packed DIB to Pixmap */
pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
ReleaseDC(hwnd, hdc);
}
else if (wFormat == CF_BITMAP)
{
HWND hwnd = GetOpenClipboardWindow();
HDC hdc = GetDC(hwnd);
pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
ReleaseDC(hwnd, hdc);
}
else
{
FIXME("%s to PIXMAP conversion not yet implemented!\n",
CLIPBOARD_GetFormatName(wFormat, NULL, 0));
rprop = None;
goto END;
}
TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
TSXGetAtomName(display, rprop), (long)requestor,
TSXGetAtomName(display, target), pixmap);
/* Store the Pixmap handle in the property */
xRc = TSXChangeProperty(display, requestor, rprop, target,
32, PropModeReplace,
(unsigned char *)&pixmap, 1);
TRACE("(Rc=%d)\n", xRc);
/* Enable the code below if you want to handle destroying Pixmap resources
* in response to property notify events. Clients like XPaint don't
* appear to be duplicating Pixmaps so they don't like us deleting,
* the resource in response to the property being deleted.
*/
#if(0)
/* Express interest in property notify events so that we can delete the
* pixmap when the client deletes the property atom.
*/
xRc = TSXGetWindowAttributes(display, requestor, &win_attr_src);
TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
(long)requestor);
win_attr.event_mask = win_attr_src.your_event_mask | PropertyChangeMask;
TSXChangeWindowAttributes(display, requestor, CWEventMask, &win_attr);
/* Register the Pixmap we created with the request property Atom.
* When this property is destroyed we also destroy the Pixmap in
* response to the PropertyNotify event.
*/
X11DRV_CLIPBOARD_RegisterPixmapResource( rprop, pixmap );
#endif
END:
return rprop;
}
/***********************************************************************
* EVENT_SelectionRequest_WCF
* Service a Wine Clipboard Format selection request event.
* For <WCF>* data types we simply copy the data to X without conversion.
*/
static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
Atom target, Atom rprop )
{
HANDLE hClipData = 0;
void* lpClipData;
UINT wFormat;
char * itemFmtName;
int cBytes;
int xRc;
int bemf;
/*
* Map the requested X selection property type atom name to a
* windows clipboard format ID.
*/
itemFmtName = TSXGetAtomName(display, target);
wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
TRACE("Request for %s (wFormat=%x %s)\n",
itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0));
TSXFree(itemFmtName);
hClipData = GetClipboardData(wFormat);
bemf = wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE;
if (bemf)
hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, hClipData, sizeof(hClipData), TRUE);
if( hClipData && (lpClipData = GlobalLock(hClipData)) )
{
cBytes = GlobalSize(hClipData);
TRACE("\tUpdating property %s, %d bytes...\n",
TSXGetAtomName(display, rprop), cBytes);
xRc = TSXChangeProperty(display, requestor, rprop,
target, 8, PropModeReplace,
(unsigned char *)lpClipData, cBytes);
TRACE("(Rc=%d)\n", xRc);
GlobalUnlock(hClipData);
}
else
{
TRACE("\tCould not retrieve native format!\n");
rprop = None; /* Fail the request */
}
if (bemf) /* We must free serialized metafile data */
GlobalFree(hClipData);
HeapFree(GetProcessHeap(), 0, targets);
return rprop;
}
@ -1016,10 +782,8 @@ static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BO
XSelectionEvent result;
Atom rprop = None;
Window request = event->requestor;
BOOL couldOpen = FALSE;
Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
Atom xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
TRACE_(clipboard)("\n");
/*
* We can only handle the selection request if :
@ -1029,8 +793,7 @@ static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BO
*/
if ( !bIsMultiple )
{
if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
|| !(couldOpen = OpenClipboard(hWnd)) )
if (((event->selection != XA_PRIMARY) && (event->selection != xaClipboard)))
goto END;
}
@ -1051,36 +814,48 @@ static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BO
/* MULTIPLE selection request */
rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
}
else if(event->target == XA_STRING) /* treat CF_TEXT as Unix text */
{
/* XA_STRING selection request */
rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
}
else if(event->target == XA_PIXMAP) /* Convert DIB's to Pixmaps */
{
/* XA_PIXMAP selection request */
rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
}
else if(event->target == XA_BITMAP) /* Convert DIB's to 1-bit Pixmaps */
{
/* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
}
else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
{
/* All <WCF> selection requests */
rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
}
else
rprop = None; /* Don't support this format */
{
LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(event->target);
if (!lpFormat)
lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(event->target);
if (lpFormat)
{
LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
if (lpData)
{
unsigned char* lpClipData;
DWORD cBytes;
HANDLE hClipData = lpFormat->lpDrvExportFunc(lpData, &cBytes);
if (hClipData && (lpClipData = GlobalLock(hClipData)))
{
TRACE_(clipboard)("\tUpdating property %s, %ld bytes\n",
lpFormat->Name, cBytes);
TSXChangeProperty(display, request, rprop, event->target,
8, PropModeReplace, (unsigned char *)lpClipData, cBytes);
GlobalUnlock(hClipData);
GlobalFree(hClipData);
}
}
}
else
{
if (TRACE_ON(clipboard))
{
TRACE_(clipboard)("Request for property %s (%ld) failed\n",
TSXGetAtomName(display, event->target), event->target);
}
}
}
END:
/* close clipboard only if we opened before */
if(couldOpen) CloseClipboard();
if( rprop == None)
TRACE("\tRequest ignored\n");
/* reply to sender
* SelectionNotify should be sent only at the end of a MULTIPLE request
*/
@ -1103,8 +878,6 @@ END:
*/
static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
{
Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
}
@ -1125,9 +898,6 @@ static void EVENT_PropertyNotify( XPropertyEvent *event )
{
TRACE("\tPropertyDelete for atom %s on window %ld\n",
TSXGetAtomName(event->display, event->atom), (long)event->window);
if (X11DRV_IsSelectionOwner())
X11DRV_CLIPBOARD_FreeResources( event->atom );
break;
}

View File

@ -373,15 +373,59 @@ extern Atom _kde_net_wm_system_tray_window_for;
/* X11 clipboard driver */
extern void X11DRV_CLIPBOARD_FreeResources( Atom property );
extern BOOL X11DRV_CLIPBOARD_RegisterPixmapResource( Atom property, Pixmap pixmap );
extern BOOL X11DRV_CLIPBOARD_IsNativeProperty(Atom prop);
extern UINT X11DRV_CLIPBOARD_MapPropertyToFormat(char *itemFmtName);
extern Atom X11DRV_CLIPBOARD_MapFormatToProperty(UINT id);
typedef struct tagPROPERTYFORMATMAP
{
LPCSTR lpszProperty;
LPCSTR lpszFormat;
} PROPERTYFORMATMAP;
typedef struct tagPROPERTYALIASMAP
{
LPCSTR lpszProperty;
UINT drvDataProperty;
LPCSTR lpszAlias;
UINT drvDataAlias;
} PROPERTYALIASMAP;
typedef struct tagWINE_CLIPDATA {
UINT wFormatID;
HANDLE16 hData16;
HANDLE hData32;
UINT wFlags;
struct tagWINE_CLIPDATA *PrevData;
struct tagWINE_CLIPDATA *NextData;
} WINE_CLIPDATA, *LPWINE_CLIPDATA;
typedef HANDLE (*DRVEXPORTFUNC)(LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
typedef HANDLE (*DRVIMPORTFUNC)(LPBYTE hData, UINT cBytes);
typedef struct tagWINE_CLIPFORMAT {
UINT wFormatID;
LPSTR Name;
UINT drvData;
UINT wFlags;
DRVIMPORTFUNC lpDrvImportFunc;
DRVEXPORTFUNC lpDrvExportFunc;
struct tagWINE_CLIPFORMAT *PrevFormat;
struct tagWINE_CLIPFORMAT *NextFormat;
} WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
#define CF_FLAG_BUILTINFMT 1 /* Built-in windows format */
#define CF_FLAG_SYNTHESIZED 8 /* Implicitly converted data */
extern Atom xaClipboard;
extern Atom xaTargets;
extern Atom xaMultiple;
extern BOOL X11DRV_InitClipboard(Display *display);
extern void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd);
extern BOOL X11DRV_IsSelectionOwner(void);
extern BOOL X11DRV_GetClipboardData(UINT wFormat);
extern HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, INT cbytes, BOOL out);
extern INT X11DRV_CountClipboardFormats(void);
extern UINT X11DRV_EnumClipboardFormats(UINT wFormat);
extern LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID);
extern LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData);
extern LPWINE_CLIPDATA X11DRV_CLIPBOARD_LookupData(DWORD wID);
extern UINT X11DRV_CLIPBOARD_LookupPropertyAlias(UINT drvDataProperty);
extern LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupAliasProperty(UINT drvDataAlias);
/* X11 event driver */

View File

@ -74,32 +74,34 @@
@ cdecl SetScreenSaveActive(long) X11DRV_SetScreenSaveActive
@ cdecl ChangeDisplaySettingsExW (ptr ptr long long long) X11DRV_ChangeDisplaySettingsExW
@ cdecl EnumDisplaySettingsExW (ptr long ptr long) X11DRV_EnumDisplaySettingsExW
@ cdecl AcquireClipboard() X11DRV_AcquireClipboard
@ cdecl CountClipboardFormats() X11DRV_CountClipboardFormats
@ cdecl CreateWindow(long ptr long) X11DRV_CreateWindow
@ cdecl DestroyWindow(long) X11DRV_DestroyWindow
@ cdecl GetDC(long long long long) X11DRV_GetDC
@ cdecl EmptyClipboard() X11DRV_EmptyClipboard
@ cdecl EndClipboardUpdate(long) X11DRV_EndClipboardUpdate
@ cdecl EnumClipboardFormats(long) X11DRV_EnumClipboardFormats
@ cdecl ForceWindowRaise(long) X11DRV_ForceWindowRaise
@ cdecl GetClipboardData(long ptr ptr) X11DRV_GetClipboardData
@ cdecl GetClipboardFormatName(long str long) X11DRV_GetClipboardFormatName
@ cdecl GetDC(long long long long) X11DRV_GetDC
@ cdecl IsClipboardFormatAvailable(long) X11DRV_IsClipboardFormatAvailable
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx
@ cdecl RegisterClipboardFormat(str) X11DRV_RegisterClipboardFormat
@ cdecl ReleaseDC(long long) X11DRV_ReleaseDC
@ cdecl ResetSelectionOwner(long long) X11DRV_ResetSelectionOwner
@ cdecl ScrollDC(long long long ptr ptr long ptr) X11DRV_ScrollDC
@ cdecl ScrollWindowEx(long long long ptr ptr long ptr long) X11DRV_ScrollWindowEx
@ cdecl SetClipboardData(long long long) X11DRV_SetClipboardData
@ cdecl SetFocus(long) X11DRV_SetFocus
@ cdecl SetParent(long long) X11DRV_SetParent
@ cdecl SetWindowIcon(long long long) X11DRV_SetWindowIcon
@ cdecl SetWindowPos(ptr) X11DRV_SetWindowPos
@ cdecl SetWindowRgn(long long long) X11DRV_SetWindowRgn
@ cdecl SetWindowIcon(long long long) X11DRV_SetWindowIcon
@ cdecl SetWindowStyle(ptr long) X11DRV_SetWindowStyle
@ cdecl SetWindowText(long wstr) X11DRV_SetWindowText
@ cdecl ShowWindow(long long) X11DRV_ShowWindow
@ cdecl SysCommandSizeMove(long long) X11DRV_SysCommandSizeMove
@ cdecl AcquireClipboard() X11DRV_AcquireClipboard
@ cdecl ReleaseClipboard() X11DRV_ReleaseClipboard
@ cdecl SetClipboardData(long) X11DRV_SetClipboardData
@ cdecl GetClipboardData(long) X11DRV_GetClipboardData
@ cdecl IsClipboardFormatAvailable(long) X11DRV_IsClipboardFormatAvailable
@ cdecl RegisterClipboardFormat(str) X11DRV_RegisterClipboardFormat
@ cdecl GetClipboardFormatName(long str long) X11DRV_GetClipboardFormatName
@ cdecl IsSelectionOwner() X11DRV_IsSelectionOwner
@ cdecl ResetSelectionOwner(ptr long) X11DRV_ResetSelectionOwner
# X11 locks
@ cdecl -norelay wine_tsx11_lock()

View File

@ -362,6 +362,13 @@ static void process_attach(void)
ExitProcess(1);
}
/* Initialize clipboard */
if (!X11DRV_InitClipboard( display ))
{
ERR( "Couldn't Initialize clipboard.\n" );
ExitProcess(1);
}
#ifdef HAVE_LIBXXF86VM
/* initialize XVidMode */
X11DRV_XF86VM_Init();

View File

@ -2,6 +2,7 @@
* Copyright 1994 Martin Ayotte
* Copyright 1996 Alex Korobka
* Copyright 1999 Noel Borthwick
* Copyright 2003 Ulrich Czekalla for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -22,29 +23,14 @@
#define __WINE_CLIPBOARD_H
#include "windef.h"
#include "wine/windef16.h"
struct tagWND;
typedef struct tagWINE_CLIPFORMAT {
UINT wFormatID;
UINT wRefCount;
BOOL wDataPresent;
LPSTR Name;
HANDLE16 hData16;
HANDLE hDataSrc32;
HANDLE hData32;
ULONG drvData;
struct tagWINE_CLIPFORMAT *PrevFormat;
struct tagWINE_CLIPFORMAT *NextFormat;
} WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
extern LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID );
extern BOOL CLIPBOARD_IsCacheRendered();
extern void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange);
extern void CLIPBOARD_EmptyCache( BOOL bChange );
extern BOOL CLIPBOARD_IsPresent(WORD wFormat);
extern char * CLIPBOARD_GetFormatName(UINT wFormat, LPSTR buf, INT size);
extern void CLIPBOARD_ReleaseOwner();
typedef struct tagCLIPBOARDINFO
{
HWND hWndOpen;
HWND hWndOwner;
HWND hWndViewer;
UINT seqno;
UINT flags;
} CLIPBOARDINFO, *LPCLIPBOARDINFO;
#endif /* __WINE_CLIPBOARD_H */

View File

@ -82,15 +82,17 @@ typedef struct tagUSER_DRIVER {
BOOL (*pGetScreenSaveActive)(void);
void (*pSetScreenSaveActive)(BOOL);
/* clipboard functions */
void (*pAcquireClipboard)(void); /* Acquire selection */
void (*pReleaseClipboard)(void); /* Release selection */
void (*pSetClipboardData)(UINT); /* Set specified selection data */
BOOL (*pGetClipboardData)(UINT); /* Get specified selection data */
BOOL (*pIsClipboardFormatAvailable)(UINT); /* Check if specified format is available */
INT (*pRegisterClipboardFormat)(LPCSTR); /* Register a clipboard format */
BOOL (*pGetClipboardFormatName)(UINT, LPSTR, UINT); /* Get a clipboard format name */
BOOL (*pIsSelectionOwner)(void); /* Check if we own the selection */
void (*pAcquireClipboard)(HWND); /* Acquire selection */
BOOL (*pCountClipboardFormats)(void); /* Count available clipboard formats */
void (*pEmptyClipboard)(void); /* Empty clipboard data */
BOOL (*pEndClipboardUpdate)(void); /* End clipboard update */
BOOL (*pEnumClipboardFormats)(UINT); /* Enumerate clipboard formats */
BOOL (*pGetClipboardData)(UINT, HANDLE16*, HANDLE*); /* Get specified selection data */
BOOL (*pGetClipboardFormatName)(UINT, LPSTR, UINT); /* Get a clipboard format name */
BOOL (*pIsClipboardFormatAvailable)(UINT); /* Check if specified format is available */
INT (*pRegisterClipboardFormat)(LPCSTR); /* Register a clipboard format */
void (*pResetSelectionOwner)(HWND, BOOL);
BOOL (*pSetClipboardData)(UINT, HANDLE16, HANDLE); /* Set specified selection data */
/* display modes */
LONG (*pChangeDisplaySettingsExW)(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID);
BOOL (*pEnumDisplaySettingsExW)(LPCWSTR,DWORD,LPDEVMODEW,DWORD);
@ -163,6 +165,8 @@ extern INT SYSPARAMS_GetMouseButtonSwap( void );
extern HPALETTE WINAPI SelectPalette( HDC hDC, HPALETTE hPal, BOOL bForceBackground );
extern BOOL CLIPBOARD_ReleaseOwner(void);
extern DWORD USER16_AlertableWait;
/* HANDLE16 <-> HANDLE conversions */

View File

@ -3041,6 +3041,36 @@ struct get_next_hook_reply
};
struct set_clipboard_info_request
{
struct request_header __header;
unsigned int flags;
user_handle_t clipboard;
user_handle_t owner;
user_handle_t viewer;
unsigned int seqno;
};
struct set_clipboard_info_reply
{
struct reply_header __header;
unsigned int flags;
user_handle_t old_clipboard;
user_handle_t old_owner;
user_handle_t old_viewer;
unsigned int seqno;
};
#define SET_CB_OPEN 0x001
#define SET_CB_OWNER 0x002
#define SET_CB_VIEWER 0x004
#define SET_CB_SEQNO 0x008
#define SET_CB_RELOWNER 0x010
#define SET_CB_CLOSE 0x020
#define CB_OPEN 0x040
#define CB_OWNER 0x080
enum request
{
REQ_new_process,
@ -3218,6 +3248,7 @@ enum request
REQ_start_hook_chain,
REQ_finish_hook_chain,
REQ_get_next_hook,
REQ_set_clipboard_info,
REQ_NB_REQUESTS
};
@ -3400,6 +3431,7 @@ union generic_request
struct start_hook_chain_request start_hook_chain_request;
struct finish_hook_chain_request finish_hook_chain_request;
struct get_next_hook_request get_next_hook_request;
struct set_clipboard_info_request set_clipboard_info_request;
};
union generic_reply
{
@ -3580,8 +3612,9 @@ union generic_reply
struct start_hook_chain_reply start_hook_chain_reply;
struct finish_hook_chain_reply finish_hook_chain_reply;
struct get_next_hook_reply get_next_hook_reply;
struct set_clipboard_info_reply set_clipboard_info_reply;
};
#define SERVER_PROTOCOL_VERSION 111
#define SERVER_PROTOCOL_VERSION 112
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -9,6 +9,7 @@ C_SRCS = \
async.c \
atom.c \
change.c \
clipboard.c \
console.c \
context_i386.c \
context_powerpc.c \

160
server/clipboard.c Normal file
View File

@ -0,0 +1,160 @@
/*
* Server-side clipboard management
*
* Copyright (C) 2002 Ulrich Czekalla
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "request.h"
#include "object.h"
#include "user.h"
struct thread *cbthread; /* thread id that has clipboard open */
static user_handle_t clipboard; /* window that has clipboard open */
struct thread *cbowner; /* thread id that owns the clipboard */
static user_handle_t owner; /* window that owns the clipboard data */
static user_handle_t viewer; /* first window in clipboard viewer list */
static unsigned int seqno; /* clipboard change sequence number */
static time_t seqnots; /* time stamp of last seqno increment */
#define MINUPDATELAPSE 2
/* Called when thread terminates to allow release of clipboard */
void cleanup_clipboard_thread(struct thread *thread)
{
if (thread == cbthread)
{
clipboard = 0;
cbthread = NULL;
}
if (thread == cbowner)
{
owner = 0;
cbowner = NULL;
}
}
static int set_clipboard_window(user_handle_t win, int clear)
{
if (cbthread && cbthread != current)
{
set_error(STATUS_WAS_LOCKED);
return 0;
}
else if (!clear)
{
clipboard = win;
cbthread = current;
}
else
{
cbthread = NULL;
clipboard = 0;
}
return 1;
}
static int set_clipboard_owner(user_handle_t win, int clear)
{
if (cbthread == current)
{
if (!clear)
{
cbowner = current;
owner = win;
}
else
{
cbowner = 0;
owner = 0;
}
seqno++;
return 1;
}
else
{
set_error(STATUS_WAS_LOCKED);
return 0;
}
}
static int get_seqno(void)
{
time_t tm = time(NULL);
if (!cbowner && (tm > (seqnots + MINUPDATELAPSE)))
{
seqnots = tm;
seqno++;
}
return seqno;
}
DECL_HANDLER(set_clipboard_info)
{
reply->old_clipboard = clipboard;
reply->old_owner = owner;
reply->old_viewer = viewer;
if (req->flags & SET_CB_OPEN)
{
if (!set_clipboard_window(req->clipboard, 0))
return;
}
else if (req->flags & SET_CB_CLOSE)
{
if (!set_clipboard_window(0, 1))
return;
}
if (req->flags & SET_CB_OWNER)
{
if (!set_clipboard_owner(req->owner, 0))
return;
}
else if (req->flags & SET_CB_RELOWNER)
{
if (!set_clipboard_owner(0, 1))
return;
}
if (req->flags & SET_CB_VIEWER)
viewer = req->viewer;
if (req->flags & SET_CB_SEQNO)
seqno++;
reply->seqno = get_seqno();
if (cbthread == current)
reply->flags |= CB_OPEN;
if (cbowner == current)
reply->flags |= CB_OWNER;
}

View File

@ -2124,3 +2124,28 @@ enum message_type
int next_unicode; /* is the next a unicode hook? */
VARARG(module,unicode_str); /* module name */
@END
/* Set/get clipboard information */
@REQ(set_clipboard_info)
unsigned int flags; /* flags for fields to set (see below) */
user_handle_t clipboard; /* clipboard window */
user_handle_t owner; /* clipboard owner */
user_handle_t viewer; /* first clipboard viewer */
unsigned int seqno; /* change sequence number */
@REPLY
unsigned int flags; /* status flags (see below) */
user_handle_t old_clipboard; /* old clipboard window */
user_handle_t old_owner; /* old clipboard owner */
user_handle_t old_viewer; /* old clipboard viewer */
unsigned int seqno; /* current sequence number */
@END
#define SET_CB_OPEN 0x001
#define SET_CB_OWNER 0x002
#define SET_CB_VIEWER 0x004
#define SET_CB_SEQNO 0x008
#define SET_CB_RELOWNER 0x010
#define SET_CB_CLOSE 0x020
#define CB_OPEN 0x040
#define CB_OWNER 0x080

View File

@ -278,6 +278,7 @@ DECL_HANDLER(remove_hook);
DECL_HANDLER(start_hook_chain);
DECL_HANDLER(finish_hook_chain);
DECL_HANDLER(get_next_hook);
DECL_HANDLER(set_clipboard_info);
#ifdef WANT_REQUEST_HANDLERS
@ -459,6 +460,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_start_hook_chain,
(req_handler)req_finish_hook_chain,
(req_handler)req_get_next_hook,
(req_handler)req_set_clipboard_info,
};
#endif /* WANT_REQUEST_HANDLERS */

View File

@ -210,6 +210,7 @@ static void cleanup_thread( struct thread *thread )
if (thread->wait_fd) release_object( thread->wait_fd );
if (thread->hooks) release_object( thread->hooks );
free_msg_queue( thread );
cleanup_clipboard_thread(thread);
destroy_thread_windows( thread );
for (i = 0; i < MAX_INFLIGHT_FDS; i++)
{

View File

@ -2458,6 +2458,24 @@ static void dump_get_next_hook_reply( const struct get_next_hook_reply *req )
dump_varargs_unicode_str( cur_size );
}
static void dump_set_clipboard_info_request( const struct set_clipboard_info_request *req )
{
fprintf( stderr, " flags=%08x,", req->flags );
fprintf( stderr, " clipboard=%p,", req->clipboard );
fprintf( stderr, " owner=%p,", req->owner );
fprintf( stderr, " viewer=%p,", req->viewer );
fprintf( stderr, " seqno=%08x", req->seqno );
}
static void dump_set_clipboard_info_reply( const struct set_clipboard_info_reply *req )
{
fprintf( stderr, " flags=%08x,", req->flags );
fprintf( stderr, " old_clipboard=%p,", req->old_clipboard );
fprintf( stderr, " old_owner=%p,", req->old_owner );
fprintf( stderr, " old_viewer=%p,", req->old_viewer );
fprintf( stderr, " seqno=%08x", req->seqno );
}
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request,
@ -2634,6 +2652,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_start_hook_chain_request,
(dump_func)dump_finish_hook_chain_request,
(dump_func)dump_get_next_hook_request,
(dump_func)dump_set_clipboard_info_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@ -2812,6 +2831,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_start_hook_chain_reply,
(dump_func)0,
(dump_func)dump_get_next_hook_reply,
(dump_func)dump_set_clipboard_info_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@ -2990,6 +3010,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"start_hook_chain",
"finish_hook_chain",
"get_next_hook",
"set_clipboard_info",
};
/* ### make_requests end ### */

View File

@ -42,6 +42,10 @@ extern user_handle_t get_user_full_handle( user_handle_t handle );
extern void *free_user_handle( user_handle_t handle );
extern void *next_user_handle( user_handle_t *handle, enum user_object type );
/* clipboard functions */
extern void cleanup_clipboard_thread( struct thread *thread );
/* hook functions */
extern void close_global_hooks(void);

File diff suppressed because it is too large Load Diff

View File

@ -1515,6 +1515,9 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
WIN_SendDestroyMsg( hwnd );
if (!IsWindow( hwnd )) return TRUE;
if (GetClipboardOwner() == hwnd)
CLIPBOARD_ReleaseOwner();
/* Unlink now so we won't bother with the children later on */
WIN_UnlinkWindow( hwnd );