Commit 2970067b authored by Noel Borthwick's avatar Noel Borthwick Committed by Alexandre Julliard

- Implement interprocess clipboard communication.

- Support for the PRIMARY and CLIPBOARD selection atoms. - Support for the TARGETS selection format. - Expose native Windows clipboard formats through X selection targets.
parent 05bf5344
......@@ -10,26 +10,35 @@ typedef struct tagWINE_CLIPFORMAT {
WORD wRefCount;
WORD wDataPresent;
LPSTR Name;
HANDLE16 hData16;
HANDLE hDataSrc32;
HANDLE hData32;
DWORD BufSize;
ULONG drvData;
struct tagWINE_CLIPFORMAT *PrevFormat;
struct tagWINE_CLIPFORMAT *NextFormat;
HANDLE16 hData16;
} WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
typedef struct tagCLIPBOARD_DRIVER
{
void (*pEmpty)(void);
void (*pSetData)(UINT);
BOOL (*pGetData)(UINT);
void (*pAcquire)(void); /* Acquire selection */
void (*pRelease)(void); /* Release selection */
void (*pSetData)(UINT); /* Set specified selection data */
BOOL (*pGetData)(UINT); /* Get specified selection data */
BOOL (*pIsFormatAvailable)(UINT); /* Check if specified format is available */
BOOL (*pRegisterFormat)(LPCSTR); /* Register a clipboard format */
BOOL (*pIsSelectionOwner)(void); /* Check if we own the selection */
void (*pResetOwner)(struct tagWND *, BOOL);
} CLIPBOARD_DRIVER;
extern CLIPBOARD_DRIVER *CLIPBOARD_Driver;
extern void CLIPBOARD_ResetLock(HQUEUE16 hqRef, HQUEUE16 hqNew);
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);
extern void CLIPBOARD_ReleaseOwner();
#endif /* __WINE_CLIPBOARD_H */
......@@ -73,9 +73,13 @@ extern void TTYDRV_USER_EndDebugging(void);
extern struct tagCLIPBOARD_DRIVER TTYDRV_CLIPBOARD_Driver;
extern void TTYDRV_CLIPBOARD_Empty(void);
extern void TTYDRV_CLIPBOARD_Acquire(void);
extern void TTYDRV_CLIPBOARD_Release(void);
extern void TTYDRV_CLIPBOARD_SetData(UINT wFormat);
extern BOOL TTYDRV_CLIPBOARD_GetData(UINT wFormat);
extern BOOL TTYDRV_CLIPBOARD_IsFormatAvailable(UINT wFormat);
extern BOOL TTYDRV_CLIPBOARD_RegisterFormat( LPCSTR FormatName );
extern BOOL TTYDRV_CLIPBOARD_IsSelectionowner();
extern void TTYDRV_CLIPBOARD_ResetOwner(struct tagWND *pWnd, BOOL bFooBar);
/* TTY desktop driver */
......
......@@ -313,11 +313,17 @@ extern void X11DRV_USER_EndDebugging(void);
extern struct tagCLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver;
extern void X11DRV_CLIPBOARD_Empty(void);
extern void X11DRV_CLIPBOARD_Acquire(void);
extern void X11DRV_CLIPBOARD_Release(void);
extern void X11DRV_CLIPBOARD_SetData(UINT wFormat);
extern BOOL X11DRV_CLIPBOARD_GetData(UINT wFormat);
extern BOOL X11DRV_CLIPBOARD_IsFormatAvailable(UINT wFormat);
extern BOOL X11DRV_CLIPBOARD_RegisterFormat( LPCSTR FormatName );
extern BOOL X11DRV_CLIPBOARD_IsSelectionowner();
extern UINT X11DRV_CLIPBOARD_MapPropertyToFormat(char *itemFmtName);
extern Atom X11DRV_CLIPBOARD_MapFormatToProperty(UINT id);
extern void X11DRV_CLIPBOARD_ResetOwner(struct tagWND *pWnd, BOOL bFooBar);
extern void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND hwnd);
extern void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd);
/* X11 desktop driver */
......
......@@ -827,7 +827,7 @@ LRESULT CALLBACK OLEClipbrd_WndProc
WARN("(): WM_RENDERALLFORMATS failed to retrieve EnumFormatEtc!\n");
return 0;
}
while ( S_OK == IEnumFORMATETC_Next(penumFormatetc, 1, &rgelt, NULL) )
{
if ( rgelt.tymed == TYMED_HGLOBAL )
......@@ -1093,6 +1093,9 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
STGMEDIUM* pmedium)
{
HANDLE hData = 0;
BOOL bClipboardOpen = FALSE;
HRESULT hr = S_OK;
/*
* Declare "This" pointer
*/
......@@ -1124,8 +1127,11 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
*/
/*
* Otherwise, delegate to the Windows clipboard function GetClipboardData
* Otherwise, get the data from the windows clipboard using GetClipboardData
*/
if ( !(bClipboardOpen = OpenClipboard(theOleClipboard->hWndClipboard)) )
HANDLE_ERROR( CLIPBRD_E_CANT_OPEN );
hData = GetClipboardData(pformatetcIn->cfFormat);
/*
......@@ -1135,6 +1141,17 @@ static HRESULT WINAPI OLEClipbrd_IDataObject_GetData(
pmedium->u.hGlobal = (HGLOBAL)hData;
pmedium->pUnkForRelease = NULL;
hr = S_OK;
CLEANUP:
/*
* Close Windows clipboard
*/
if ( bClipboardOpen && !CloseClipboard() )
hr = CLIPBRD_E_CANT_CLOSE;
if ( FAILED(hr) )
return hr;
return (hData == 0) ? DV_E_FORMATETC : S_OK;
}
......
......@@ -13,9 +13,16 @@
char *TTYDRV_CLIPBOARD_szSelection = NULL;
/***********************************************************************
* TTYDRV_CLIPBOARD_EmptyClipboard
* TTYDRV_CLIPBOARD_Acquire
*/
void TTYDRV_CLIPBOARD_Empty()
void TTYDRV_CLIPBOARD_Acquire()
{
}
/***********************************************************************
* TTYDRV_CLIPBOARD_Release
*/
void TTYDRV_CLIPBOARD_Release()
{
if(TTYDRV_CLIPBOARD_szSelection)
{
......@@ -40,6 +47,35 @@ BOOL TTYDRV_CLIPBOARD_GetData(UINT wFormat)
}
/***********************************************************************
* TTYDRV_CLIPBOARD_IsFormatAvailable
*/
BOOL TTYDRV_CLIPBOARD_IsFormatAvailable(UINT wFormat)
{
return FALSE;
}
/**************************************************************************
* TTYDRV_CLIPBOARD_RegisterFormat
*
* Registers a custom clipboard format
* Returns: TRUE - new format registered, FALSE - Format already registered
*/
BOOL TTYDRV_CLIPBOARD_RegisterFormat( LPCSTR FormatName )
{
return TRUE;
}
/**************************************************************************
* X11DRV_CLIPBOARD_IsSelectionowner
*
* Returns: TRUE - We(WINE) own the selection, FALSE - Selection not owned by us
*/
BOOL TTYDRV_CLIPBOARD_IsSelectionowner()
{
return FALSE;
}
/***********************************************************************
* TTYDRV_CLIPBOARD_ResetOwner
*/
void TTYDRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
......
......@@ -24,9 +24,13 @@ USER_DRIVER TTYDRV_USER_Driver =
CLIPBOARD_DRIVER TTYDRV_CLIPBOARD_Driver =
{
TTYDRV_CLIPBOARD_Empty,
TTYDRV_CLIPBOARD_Acquire,
TTYDRV_CLIPBOARD_Release,
TTYDRV_CLIPBOARD_SetData,
TTYDRV_CLIPBOARD_GetData,
TTYDRV_CLIPBOARD_IsFormatAvailable,
TTYDRV_CLIPBOARD_RegisterFormat,
TTYDRV_CLIPBOARD_IsSelectionowner,
TTYDRV_CLIPBOARD_ResetOwner
};
......
......@@ -153,7 +153,6 @@ static void USER_QueueCleanup( HQUEUE16 hQueue )
QUEUE_SetExitingQueue( hQueue );
WIN_ResetQueueWindows( desktop, hQueue, (HQUEUE16)0);
CLIPBOARD_ResetLock( hQueue, 0 );
QUEUE_SetExitingQueue( 0 );
/* Free the message queue */
......@@ -168,8 +167,13 @@ static void USER_QueueCleanup( HQUEUE16 hQueue )
*/
static void USER_AppExit( HINSTANCE16 hInstance )
{
/* FIXME: empty clipboard if needed, maybe destroy menus (Windows
* only complains about them but does nothing);
/* FIXME: maybe destroy menus (Windows only complains about them
* but does nothing);
*/
/* TODO: Start up persistant WINE X clipboard server process which will
* take ownership of the X selection and continue to service selection
* requests from other apps.
*/
/* ModuleUnload() in "Internals" */
......
......@@ -835,64 +835,196 @@ static void EVENT_ConfigureNotify( HWND hWnd, XConfigureEvent *event )
/***********************************************************************
* EVENT_SelectionRequest
* Note: We only receive this event when WINE owns the X selection
*/
static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event )
{
XSelectionEvent result;
Atom rprop = None;
Window request = event->requestor;
Atom rprop = None;
Window request = event->requestor;
UINT wFormat;
char * itemFmtName;
BOOL couldOpen = FALSE;
Atom xaClipboard = XInternAtom(display, "CLIPBOARD", False);
Atom xaTargets = XInternAtom(display, "TARGETS", False);
int xRc;
if(event->target == XA_STRING)
/*
* Map the requested X selection property type atom name to a
* windows clipboard format ID.
*/
itemFmtName = TSXGetAtomName(display, event->target);
wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
TRACE_(event)("Request for %s\n", itemFmtName);
TSXFree(itemFmtName);
/*
* We can only handle the selection request if :
* The selection is PRIMARY or CLIPBOARD,
* AND we can successfully open the clipboard.
* AND we have a request for a TARGETS selection target,
* OR the requested format is available in the clipboard
*/
if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
|| !(couldOpen = OpenClipboard(hWnd)) )
goto END;
if ( (event->target != xaTargets)
&& ( (0 == wFormat) || !CLIPBOARD_IsPresent(wFormat) ) )
goto END;
/* We can handle the request */
rprop = event->property;
if( rprop == None )
rprop = event->target;
if(event->target == xaTargets) /* Return a list of all supported targets */
{
Atom* targets;
Atom prop;
UINT wFormat;
unsigned long cTargets;
BOOL bHavePixmap;
/*
* 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
*/
cTargets = CountClipboardFormats() + 1;
if ( CLIPBOARD_IsPresent(CF_DIB) || CLIPBOARD_IsPresent(CF_BITMAP) )
cTargets++;
/* Allocate temp buffer */
targets = (Atom*)HEAP_xalloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
/* Create TARGETS property list (First item in list is TARGETS itself) */
for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
(wFormat = 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;
/* Add PIXMAP prop for bitmaps additionally */
if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
&& !bHavePixmap )
{
targets[cTargets++] = XA_PIXMAP;
bHavePixmap = TRUE;
}
}
}
}
#ifdef DEBUG_RUNTIME
{
int i;
for ( i = 0; i < cTargets; i++)
{
if (targets[i])
{
char *itemFmtName = TSXGetAtomName(display, targets[i]);
TRACE_(event)("\tAtom# %d: Type %s\n", i, itemFmtName);
TSXFree(itemFmtName);
}
}
}
#endif
/* Update the X property */
TRACE_(event)("\tUpdating property %s...", TSXGetAtomName(display, rprop));
xRc = TSXChangeProperty(display, request, rprop,
XA_ATOM, 32, PropModeReplace,
(unsigned char *)targets, cTargets);
TRACE_(event)("(Rc=%d)\n", xRc);
HeapFree( GetProcessHeap(), 0, targets );
}
else if(event->target == XA_STRING) /* treat CF_TEXT as Unix text */
{
HANDLE16 hText;
LPSTR text;
int size,i,j;
rprop = event->property;
char* lpstr = 0;
if( rprop == None )
rprop = event->target;
hText = GetClipboardData16(CF_TEXT);
text = GlobalLock16(hText);
size = GlobalSize16(hText);
if( event->selection != XA_PRIMARY )
rprop = None;
else
if( !CLIPBOARD_IsPresent(CF_OEMTEXT) )
rprop = None;
else
/* remove carriage returns */
lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- );
for(i=0,j=0; i < size && text[i]; i++ )
{
/* open to make sure that clipboard is available */
BOOL couldOpen = OpenClipboard( hWnd );
char* lpstr = 0;
hText = GetClipboardData16(CF_TEXT);
text = GlobalLock16(hText);
size = GlobalSize16(hText);
/* remove carriage returns */
lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- );
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';
TSXChangeProperty(display, request, rprop,
XA_STRING, 8, PropModeReplace,
lpstr, j);
HeapFree( GetProcessHeap(), 0, lpstr );
/* close only if we opened before */
if(couldOpen) CloseClipboard();
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_(event)("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
xRc = TSXChangeProperty(display, request, rprop,
XA_STRING, 8, PropModeReplace,
lpstr, j);
TRACE_(event)("(Rc=%d)\n", xRc);
GlobalUnlock16(hText);
HeapFree( GetProcessHeap(), 0, lpstr );
}
else if(event->target == XA_PIXMAP) /* Convert DIB's to Pixmaps */
{
FIXME_(event)("DIB to PIXMAP conversion not yet implemented!\n");
rprop = None;
}
else /* For other data types (WCF_*) simply copy the data to X without conversion */
{
HANDLE hClipData = 0;
void* lpClipData;
int cBytes;
hClipData = GetClipboardData16(wFormat);
if( hClipData && (lpClipData = GlobalLock16(hClipData)) )
{
cBytes = GlobalSize16(hClipData);
TRACE_(event)("\tUpdating property %s, %d bytes...\n",
TSXGetAtomName(display, rprop), cBytes);
xRc = TSXChangeProperty(display, request, rprop,
event->target, 8, PropModeReplace,
(unsigned char *)lpClipData, cBytes);
TRACE_(event)("(Rc=%d)\n", xRc);
GlobalUnlock16(hClipData);
}
else
rprop = None; /* Fail the request */
}
END:
/* close clipboard only if we opened before */
if(couldOpen) CloseClipboard();
if( rprop == None)
TRACE_(event)("Request for %s ignored\n", TSXGetAtomName(display,event->target));
TRACE_(event)("\tRequest ignored\n");
/* reply to sender */
......@@ -911,8 +1043,10 @@ static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event )
*/
static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
{
if (event->selection != XA_PRIMARY) return;
X11DRV_CLIPBOARD_ReleaseSelection( event->window, hWnd );
Atom xaClipboard = XInternAtom(display, "CLIPBOARD", False);
if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
}
......@@ -1210,7 +1344,7 @@ static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
if ( !Options.managed || !bIsDisabled )
PostMessage16( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
PostMessage16( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
}
else if ( event->message_type == dndProtocol &&
(event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
......
......@@ -28,9 +28,13 @@ USER_DRIVER X11DRV_USER_Driver =
CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver =
{
X11DRV_CLIPBOARD_Empty,
X11DRV_CLIPBOARD_Acquire,
X11DRV_CLIPBOARD_Release,
X11DRV_CLIPBOARD_SetData,
X11DRV_CLIPBOARD_GetData,
X11DRV_CLIPBOARD_IsFormatAvailable,
X11DRV_CLIPBOARD_RegisterFormat,
X11DRV_CLIPBOARD_IsSelectionowner,
X11DRV_CLIPBOARD_ResetOwner
};
......
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