- 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.
This commit is contained in:
parent
05bf5344f0
commit
2970067b14
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
{
|
||||
|
@ -39,6 +46,35 @@ BOOL TTYDRV_CLIPBOARD_GetData(UINT wFormat)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -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" */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -835,34 +835,132 @@ 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;
|
||||
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)
|
||||
{
|
||||
HANDLE16 hText;
|
||||
LPSTR text;
|
||||
int size,i,j;
|
||||
/*
|
||||
* 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->selection != XA_PRIMARY )
|
||||
rprop = None;
|
||||
else
|
||||
if( !CLIPBOARD_IsPresent(CF_OEMTEXT) )
|
||||
rprop = None;
|
||||
else
|
||||
if(event->target == xaTargets) /* Return a list of all supported targets */
|
||||
{
|
||||
/* open to make sure that clipboard is available */
|
||||
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;
|
||||
|
||||
BOOL couldOpen = OpenClipboard( hWnd );
|
||||
char* lpstr = 0;
|
||||
|
||||
hText = GetClipboardData16(CF_TEXT);
|
||||
|
@ -880,19 +978,53 @@ static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event )
|
|||
}
|
||||
lpstr[j]='\0';
|
||||
|
||||
TSXChangeProperty(display, request, rprop,
|
||||
/* 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;
|
||||
|
||||
/* close only if we opened before */
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue