Enabled the persistent clipboard server.
This commit is contained in:
parent
7bf36ad35d
commit
56ab55d374
|
@ -146,7 +146,7 @@ static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);
|
||||||
static HWND OLEClipbrd_CreateWindow();
|
static HWND OLEClipbrd_CreateWindow();
|
||||||
static void OLEClipbrd_DestroyWindow(HWND hwnd);
|
static void OLEClipbrd_DestroyWindow(HWND hwnd);
|
||||||
LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
static HRESULT OLEClipbrd_RenderFormat(LPFORMATETC pFormatetc);
|
static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );
|
||||||
static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
|
static HGLOBAL OLEClipbrd_GlobalDupMem( HGLOBAL hGlobalSrc );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -473,6 +473,7 @@ HRESULT WINAPI OleFlushClipboard()
|
||||||
FORMATETC rgelt;
|
FORMATETC rgelt;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
BOOL bClipboardOpen = FALSE;
|
BOOL bClipboardOpen = FALSE;
|
||||||
|
IDataObject* pIDataObjectSrc = NULL;
|
||||||
|
|
||||||
TRACE("()\n");
|
TRACE("()\n");
|
||||||
|
|
||||||
|
@ -487,6 +488,13 @@ HRESULT WINAPI OleFlushClipboard()
|
||||||
if (!theOleClipboard->pIDataObjectSrc)
|
if (!theOleClipboard->pIDataObjectSrc)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addref and save the source data object we are holding on to temporarily,
|
||||||
|
* since it will be released when we empty the clipboard.
|
||||||
|
*/
|
||||||
|
pIDataObjectSrc = theOleClipboard->pIDataObjectSrc;
|
||||||
|
IDataObject_AddRef(pIDataObjectSrc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the Windows clipboard
|
* Open the Windows clipboard
|
||||||
*/
|
*/
|
||||||
|
@ -503,7 +511,7 @@ HRESULT WINAPI OleFlushClipboard()
|
||||||
* Render all HGLOBAL formats supported by the source into
|
* Render all HGLOBAL formats supported by the source into
|
||||||
* the windows clipboard.
|
* the windows clipboard.
|
||||||
*/
|
*/
|
||||||
if ( FAILED( hr = IDataObject_EnumFormatEtc( (IDataObject*)&(theOleClipboard->lpvtbl1),
|
if ( FAILED( hr = IDataObject_EnumFormatEtc( pIDataObjectSrc,
|
||||||
DATADIR_GET,
|
DATADIR_GET,
|
||||||
&penumFormatetc) ))
|
&penumFormatetc) ))
|
||||||
{
|
{
|
||||||
|
@ -522,7 +530,7 @@ HRESULT WINAPI OleFlushClipboard()
|
||||||
/*
|
/*
|
||||||
* Render the clipboard data
|
* Render the clipboard data
|
||||||
*/
|
*/
|
||||||
if ( FAILED(OLEClipbrd_RenderFormat( &rgelt )) )
|
if ( FAILED(OLEClipbrd_RenderFormat( pIDataObjectSrc, &rgelt )) )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -530,13 +538,9 @@ HRESULT WINAPI OleFlushClipboard()
|
||||||
IEnumFORMATETC_Release(penumFormatetc);
|
IEnumFORMATETC_Release(penumFormatetc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release the data object we are holding on to
|
* Release the source data object we are holding on to
|
||||||
*/
|
*/
|
||||||
if ( theOleClipboard->pIDataObjectSrc )
|
IDataObject_Release(pIDataObjectSrc);
|
||||||
{
|
|
||||||
IDataObject_Release(theOleClipboard->pIDataObjectSrc);
|
|
||||||
theOleClipboard->pIDataObjectSrc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLEANUP:
|
CLEANUP:
|
||||||
|
|
||||||
|
@ -795,7 +799,7 @@ LRESULT CALLBACK OLEClipbrd_WndProc
|
||||||
* Render the clipboard data.
|
* Render the clipboard data.
|
||||||
* (We must have a source data object or we wouldn't be in this WndProc)
|
* (We must have a source data object or we wouldn't be in this WndProc)
|
||||||
*/
|
*/
|
||||||
OLEClipbrd_RenderFormat( &rgelt );
|
OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -835,7 +839,7 @@ LRESULT CALLBACK OLEClipbrd_WndProc
|
||||||
/*
|
/*
|
||||||
* Render the clipboard data.
|
* Render the clipboard data.
|
||||||
*/
|
*/
|
||||||
if ( FAILED(OLEClipbrd_RenderFormat( &rgelt )) )
|
if ( FAILED(OLEClipbrd_RenderFormat( (IDataObject*)&(theOleClipboard->lpvtbl1), &rgelt )) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
|
TRACE("(): WM_RENDERALLFORMATS(cfFormat=%d)\n", rgelt.cfFormat);
|
||||||
|
@ -891,14 +895,13 @@ LRESULT CALLBACK OLEClipbrd_WndProc
|
||||||
* source data object.
|
* source data object.
|
||||||
* Note: This function assumes it is passed an HGLOBAL format to render.
|
* Note: This function assumes it is passed an HGLOBAL format to render.
|
||||||
*/
|
*/
|
||||||
static HRESULT OLEClipbrd_RenderFormat(LPFORMATETC pFormatetc)
|
static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pFormatetc)
|
||||||
{
|
{
|
||||||
STGMEDIUM medium;
|
STGMEDIUM medium;
|
||||||
HGLOBAL hDup;
|
HGLOBAL hDup;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
if ( FAILED(hr = IDataObject_GetData((IDataObject*)&(theOleClipboard->lpvtbl1),
|
if ( FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &medium)) )
|
||||||
pFormatetc, &medium)) )
|
|
||||||
{
|
{
|
||||||
WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
|
WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);
|
||||||
return hr;
|
return hr;
|
||||||
|
|
|
@ -488,7 +488,7 @@ static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
|
||||||
TRACE("\tconverting from '%s' to '%s', %i chars\n",
|
TRACE("\tconverting from '%s' to '%s', %i chars\n",
|
||||||
lpSource->Name, lpTarget->Name, size);
|
lpSource->Name, lpTarget->Name, size);
|
||||||
|
|
||||||
lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT, size);
|
lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
|
||||||
lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
|
lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
|
||||||
|
|
||||||
if( lpstrT )
|
if( lpstrT )
|
||||||
|
@ -791,7 +791,8 @@ HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert between 32 -> 16 bit data, if necessary */
|
/* Convert between 32 -> 16 bit data, if necessary */
|
||||||
if( lpRender->hData32 && !lpRender->hData16 )
|
if( lpRender->hData32 && !lpRender->hData16
|
||||||
|
&& CLIPBOARD_IsMemoryObject(wFormat) )
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
if( lpRender->wFormatID == CF_METAFILEPICT )
|
if( lpRender->wFormatID == CF_METAFILEPICT )
|
||||||
|
@ -857,7 +858,8 @@ HANDLE WINAPI GetClipboardData( UINT wFormat )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert between 16 -> 32 bit data, if necessary */
|
/* Convert between 16 -> 32 bit data, if necessary */
|
||||||
if( lpRender->hData16 && !lpRender->hData32 )
|
if( lpRender->hData16 && !lpRender->hData32
|
||||||
|
&& CLIPBOARD_IsMemoryObject(wFormat) )
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
if( lpRender->wFormatID == CF_METAFILEPICT )
|
if( lpRender->wFormatID == CF_METAFILEPICT )
|
||||||
|
|
|
@ -171,11 +171,6 @@ static void USER_AppExit( HINSTANCE16 hInstance )
|
||||||
* but does nothing);
|
* 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" */
|
/* ModuleUnload() in "Internals" */
|
||||||
|
|
||||||
hInstance = GetExePtr( hInstance );
|
hInstance = GetExePtr( hInstance );
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
DEFS = @DLLFLAGS@ -D__WINE__
|
DEFS = @DLLFLAGS@ -D__WINE__ -DBINDIR="\"$(bindir)\""
|
||||||
TOPSRCDIR = @top_srcdir@
|
TOPSRCDIR = @top_srcdir@
|
||||||
TOPOBJDIR = ../..
|
TOPOBJDIR = ../..
|
||||||
SRCDIR = @srcdir@
|
SRCDIR = @srcdir@
|
||||||
|
@ -23,8 +23,6 @@ all: $(MODULE).o $(PROGRAMS)
|
||||||
wineclipsrv: wineclipsrv.c
|
wineclipsrv: wineclipsrv.c
|
||||||
$(CC) $(ALLCFLAGS) -o wineclipsrv $(SRCDIR)/wineclipsrv.c $(X_LIBS) $(XLIB) $(LIBS)
|
$(CC) $(ALLCFLAGS) -o wineclipsrv $(SRCDIR)/wineclipsrv.c $(X_LIBS) $(XLIB) $(LIBS)
|
||||||
|
|
||||||
all: $(MODULE).o
|
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
### Dependencies:
|
### Dependencies:
|
||||||
|
|
|
@ -49,13 +49,15 @@
|
||||||
|
|
||||||
#ifndef X_DISPLAY_MISSING
|
#ifndef X_DISPLAY_MISSING
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "ts_xlib.h"
|
#include "ts_xlib.h"
|
||||||
|
|
||||||
#include "wine/winuser16.h"
|
#include "wine/winuser16.h"
|
||||||
#include "clipboard.h"
|
#include "clipboard.h"
|
||||||
#include "debugtools.h"
|
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
|
@ -63,6 +65,8 @@
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
#include "commctrl.h"
|
#include "commctrl.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "debugtools.h"
|
||||||
|
|
||||||
DEFAULT_DEBUG_CHANNEL(clipboard)
|
DEFAULT_DEBUG_CHANNEL(clipboard)
|
||||||
|
|
||||||
|
@ -76,13 +80,14 @@ DEFAULT_DEBUG_CHANNEL(clipboard)
|
||||||
|
|
||||||
static char _CLIPBOARD[] = "CLIPBOARD"; /* CLIPBOARD atom name */
|
static char _CLIPBOARD[] = "CLIPBOARD"; /* CLIPBOARD atom name */
|
||||||
static char FMT_PREFIX[] = "<WCF>"; /* Prefix for windows specific formats */
|
static char FMT_PREFIX[] = "<WCF>"; /* Prefix for windows specific formats */
|
||||||
static int selectionAcquired = 0; /* Contains the current selection masks */
|
static int selectionAcquired = 0; /* Contains the current selection masks */
|
||||||
static Window selectionWindow = None; /* The top level X window which owns the selection */
|
static Window selectionWindow = None; /* The top level X window which owns the selection */
|
||||||
static Window selectionPrevWindow = None; /* The last X window that owned the selection */
|
static Window selectionPrevWindow = None; /* The last X window that owned the selection */
|
||||||
static Window PrimarySelectionOwner = None; /* The window which owns the primary selection */
|
static Window PrimarySelectionOwner = None; /* The window which owns the primary selection */
|
||||||
static Window ClipboardSelectionOwner = None; /* The window which owns the clipboard selection */
|
static Window ClipboardSelectionOwner = None; /* The window which owns the clipboard selection */
|
||||||
static unsigned long cSelectionTargets = 0; /* Number of target formats reported by TARGETS selection */
|
static unsigned long cSelectionTargets = 0; /* Number of target formats reported by TARGETS selection */
|
||||||
static Atom selectionCacheSrc = XA_PRIMARY; /* The selection source from which the clipboard cache was filled */
|
static Atom selectionCacheSrc = XA_PRIMARY; /* The selection source from which the clipboard cache was filled */
|
||||||
|
static HANDLE selectionClearEvent = NULL; /* Synchronization object used to block until server is started */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dynamic pointer arrays to manage destruction of Pixmap resources
|
* Dynamic pointer arrays to manage destruction of Pixmap resources
|
||||||
|
@ -205,6 +210,106 @@ BOOL X11DRV_CLIPBOARD_IsNativeProperty(Atom prop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* X11DRV_CLIPBOARD_LaunchServer
|
||||||
|
* Launches the clipboard server. This is called from X11DRV_CLIPBOARD_ResetOwner
|
||||||
|
* when the selection can no longer be recyled to another top level window.
|
||||||
|
* In order to make the selection persist after Wine shuts down a server
|
||||||
|
* process is launched which services subsequent selection requests.
|
||||||
|
*/
|
||||||
|
BOOL X11DRV_CLIPBOARD_LaunchServer()
|
||||||
|
{
|
||||||
|
int iWndsLocks;
|
||||||
|
|
||||||
|
/* If persistant selection has been disabled in the .winerc Clipboard section,
|
||||||
|
* don't launch the server
|
||||||
|
*/
|
||||||
|
if ( !PROFILE_GetWineIniInt("Clipboard", "PersistentSelection", 1) )
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
selectionWindow = selectionPrevWindow;
|
||||||
|
if ( !fork() )
|
||||||
|
{
|
||||||
|
/* NOTE: This code only executes in the context of the child process
|
||||||
|
* Do note make any Wine specific calls here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int dbgClasses = 0;
|
||||||
|
char selMask[8], dbgClassMask[8], clearSelection[8];
|
||||||
|
|
||||||
|
sprintf(selMask, "%d", selectionAcquired);
|
||||||
|
|
||||||
|
/* Build the debug class mask to pass to the server, by inheriting
|
||||||
|
* the settings for the clipboard debug channel.
|
||||||
|
*/
|
||||||
|
dbgClasses |= __GET_DEBUGGING(__DBCL_FIXME, dbch_clipboard) ? 1 : 0;
|
||||||
|
dbgClasses |= __GET_DEBUGGING(__DBCL_ERR, dbch_clipboard) ? 2 : 0;
|
||||||
|
dbgClasses |= __GET_DEBUGGING(__DBCL_WARN, dbch_clipboard) ? 4 : 0;
|
||||||
|
dbgClasses |= __GET_DEBUGGING(__DBCL_TRACE, dbch_clipboard) ? 8 : 0;
|
||||||
|
sprintf(dbgClassMask, "%d", dbgClasses);
|
||||||
|
|
||||||
|
/* Get the clear selection preference */
|
||||||
|
sprintf(clearSelection, "%d",
|
||||||
|
PROFILE_GetWineIniInt("Clipboard", "ClearAllSelections", 0));
|
||||||
|
|
||||||
|
/* Exec the clipboard server passing it the selection and debug class masks */
|
||||||
|
execl( BINDIR "/wineclipsvr", "wineclipsvr",
|
||||||
|
selMask, dbgClassMask, clearSelection, NULL );
|
||||||
|
execlp( "wineclipsvr", "wineclipsvr", selMask, dbgClassMask, clearSelection, NULL );
|
||||||
|
execl( "./windows/x11drv/wineclipsvr", "wineclipsvr",
|
||||||
|
selMask, dbgClassMask, clearSelection, NULL );
|
||||||
|
|
||||||
|
/* Exec Failed! */
|
||||||
|
perror("Could not start Wine clipboard server");
|
||||||
|
exit( 1 ); /* Exit the child process */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until the clipboard server acquires the selection.
|
||||||
|
* We must release the windows lock to enable Wine to process
|
||||||
|
* selection messages in response to the servers requests.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iWndsLocks = WIN_SuspendWndsLock();
|
||||||
|
|
||||||
|
/* We must wait until the server finishes acquiring the selection,
|
||||||
|
* before proceeding, otherwise the window which owns the selection
|
||||||
|
* will be destroyed prematurely!
|
||||||
|
* Create a non-signalled, auto-reset event which will be set by
|
||||||
|
* X11DRV_CLIPBOARD_ReleaseSelection, and wait until this gets
|
||||||
|
* signalled before proceeding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( !(selectionClearEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) )
|
||||||
|
ERR("Could not create wait object. Clipboard server won't start!\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Make the event object's handle global */
|
||||||
|
selectionClearEvent = ConvertToGlobalHandle(selectionClearEvent);
|
||||||
|
|
||||||
|
/* Wait until we lose the selection, timing out after a minute */
|
||||||
|
|
||||||
|
TRACE("Waiting for clipboard server to acquire selection\n");
|
||||||
|
|
||||||
|
if ( WaitForSingleObject( selectionClearEvent, 60000 ) != WAIT_OBJECT_0 )
|
||||||
|
TRACE("Server could not acquire selection, or a time out occured!\n");
|
||||||
|
else
|
||||||
|
TRACE("Server successfully acquired selection\n");
|
||||||
|
|
||||||
|
/* Release the event */
|
||||||
|
CloseHandle(selectionClearEvent);
|
||||||
|
selectionClearEvent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WIN_RestoreWndsLock(iWndsLocks);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* X11DRV_CLIPBOARD_CacheDataFormats
|
* X11DRV_CLIPBOARD_CacheDataFormats
|
||||||
*
|
*
|
||||||
|
@ -567,14 +672,14 @@ END:
|
||||||
* Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
|
* Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
|
||||||
* to a SelectionClear event.
|
* to a SelectionClear event.
|
||||||
* This can occur in response to another client grabbing the X selection.
|
* This can occur in response to another client grabbing the X selection.
|
||||||
* If the XA_CLIPBOARD selection is lost we relinquish XA_PRIMARY as well.
|
* If the XA_CLIPBOARD selection is lost, we relinquish XA_PRIMARY as well.
|
||||||
*/
|
*/
|
||||||
void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
|
void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
|
||||||
{
|
{
|
||||||
Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
|
Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
|
||||||
|
int clearAllSelections = PROFILE_GetWineIniInt("Clipboard", "ClearAllSelections", 0);
|
||||||
|
|
||||||
/* w is the window that lost selection,
|
/* w is the window that lost the selection
|
||||||
*
|
|
||||||
* selectionPrevWindow is nonzero if CheckSelection() was called.
|
* selectionPrevWindow is nonzero if CheckSelection() was called.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -585,12 +690,15 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
|
||||||
{
|
{
|
||||||
if( w == selectionWindow || selectionPrevWindow == None)
|
if( w == selectionWindow || selectionPrevWindow == None)
|
||||||
{
|
{
|
||||||
/* alright, we really lost it */
|
/* If we're losing the CLIPBOARD selection, or if the preferences in .winerc
|
||||||
|
* dictate that *all* selections should be cleared on loss of a selection,
|
||||||
if ( selType == xaClipboard ) /* completely give up the selection */
|
* we must give up all the selections we own.
|
||||||
|
*/
|
||||||
|
if ( clearAllSelections || (selType == xaClipboard) )
|
||||||
{
|
{
|
||||||
TRACE("Lost CLIPBOARD selection\n");
|
/* completely give up the selection */
|
||||||
|
TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
|
||||||
|
|
||||||
/* We are completely giving up the selection.
|
/* We are completely giving up the selection.
|
||||||
* Make sure we can open the windows clipboard first. */
|
* Make sure we can open the windows clipboard first. */
|
||||||
|
|
||||||
|
@ -607,24 +715,23 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectionPrevWindow = selectionWindow;
|
/* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
|
||||||
|
if ( (selType == xaClipboard)
|
||||||
|
&& (selectionAcquired & S_PRIMARY) )
|
||||||
|
{
|
||||||
|
XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */
|
||||||
|
if ( (selType == XA_PRIMARY)
|
||||||
|
&& (selectionAcquired & S_CLIPBOARD) )
|
||||||
|
{
|
||||||
|
XSetSelectionOwner(display, xaClipboard, None, CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
selectionWindow = None;
|
selectionWindow = None;
|
||||||
PrimarySelectionOwner = ClipboardSelectionOwner = 0;
|
PrimarySelectionOwner = ClipboardSelectionOwner = 0;
|
||||||
|
|
||||||
/* Voluntarily give up the PRIMARY selection if we still own it */
|
|
||||||
if ( selectionAcquired & S_PRIMARY )
|
|
||||||
{
|
|
||||||
XEvent xe;
|
|
||||||
TRACE("Releasing XA_PRIMARY selection\n");
|
|
||||||
|
|
||||||
TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
|
|
||||||
|
|
||||||
/* Wait until SelectionClear is processed */
|
|
||||||
if( selectionPrevWindow )
|
|
||||||
while( !XCheckTypedWindowEvent( display, selectionPrevWindow,
|
|
||||||
SelectionClear, &xe ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Empty the windows clipboard.
|
/* Empty the windows clipboard.
|
||||||
* We should pretend that we still own the selection BEFORE calling
|
* We should pretend that we still own the selection BEFORE calling
|
||||||
* EmptyClipboard() since otherwise this has the side effect of
|
* EmptyClipboard() since otherwise this has the side effect of
|
||||||
|
@ -633,12 +740,13 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
|
||||||
*/
|
*/
|
||||||
selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
|
selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
|
||||||
EmptyClipboard();
|
EmptyClipboard();
|
||||||
selectionAcquired = S_NOSELECTION;
|
|
||||||
|
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
|
||||||
/* Give up ownership of the windows clipboard */
|
/* Give up ownership of the windows clipboard */
|
||||||
CLIPBOARD_ReleaseOwner();
|
CLIPBOARD_ReleaseOwner();
|
||||||
|
|
||||||
|
/* Reset the selection flags now that we are done */
|
||||||
|
selectionAcquired = S_NOSELECTION;
|
||||||
}
|
}
|
||||||
else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
|
else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
|
||||||
{
|
{
|
||||||
|
@ -664,6 +772,13 @@ void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Signal to a selectionClearEvent listener if the selection is completely lost */
|
||||||
|
if (selectionClearEvent && !selectionAcquired)
|
||||||
|
{
|
||||||
|
TRACE("Lost all selections, signalling to selectionClearEvent listener\n");
|
||||||
|
SetEvent(selectionClearEvent);
|
||||||
|
}
|
||||||
|
|
||||||
selectionPrevWindow = None;
|
selectionPrevWindow = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,21 +1111,6 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
|
||||||
TRACE("clipboard owner = %04x, selection window = %08x\n",
|
TRACE("clipboard owner = %04x, selection window = %08x\n",
|
||||||
hWndClipOwner, (unsigned)selectionWindow);
|
hWndClipOwner, (unsigned)selectionWindow);
|
||||||
|
|
||||||
#if(0)
|
|
||||||
/* Check if all formats are already in the clipboard cache */
|
|
||||||
if( !CLIPBOARD_IsCacheRendered() )
|
|
||||||
{
|
|
||||||
SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
|
|
||||||
|
|
||||||
/* check if all formats were rendered */
|
|
||||||
if ( !CLIPBOARD_IsCacheRendered() )
|
|
||||||
{
|
|
||||||
ERR("\tCould not render all formats\n");
|
|
||||||
CLIPBOARD_ReleaseOwner();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* now try to salvage current selection from being destroyed by X */
|
/* now try to salvage current selection from being destroyed by X */
|
||||||
|
|
||||||
TRACE("\tchecking %08x\n", (unsigned) XWnd);
|
TRACE("\tchecking %08x\n", (unsigned) XWnd);
|
||||||
|
@ -1041,7 +1141,10 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
|
||||||
TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
|
TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
|
||||||
|
|
||||||
TSXSetSelectionOwner(display, xaClipboard, selectionWindow, CurrentTime);
|
TSXSetSelectionOwner(display, xaClipboard, selectionWindow, CurrentTime);
|
||||||
|
|
||||||
|
/* Restore the selection masks */
|
||||||
|
selectionAcquired = saveSelectionState;
|
||||||
|
|
||||||
/* Lose the selection if something went wrong */
|
/* Lose the selection if something went wrong */
|
||||||
if ( ( (saveSelectionState & S_PRIMARY) &&
|
if ( ( (saveSelectionState & S_PRIMARY) &&
|
||||||
(TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow) )
|
(TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow) )
|
||||||
|
@ -1053,7 +1156,6 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Update selection state */
|
/* Update selection state */
|
||||||
selectionAcquired = saveSelectionState;
|
|
||||||
if (saveSelectionState & S_PRIMARY)
|
if (saveSelectionState & S_PRIMARY)
|
||||||
PrimarySelectionOwner = selectionWindow;
|
PrimarySelectionOwner = selectionWindow;
|
||||||
|
|
||||||
|
@ -1069,26 +1171,33 @@ void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
|
||||||
END:
|
END:
|
||||||
if (bLostSelection)
|
if (bLostSelection)
|
||||||
{
|
{
|
||||||
/* Empty the windows clipboard.
|
/* Launch the clipboard server if the selection can no longer be recyled
|
||||||
* We should pretend that we still own the selection BEFORE calling
|
* to another top level window. */
|
||||||
* EmptyClipboard() since otherwise this has the side effect of
|
|
||||||
* triggering X11DRV_CLIPBOARD_Acquire() and causing the X selection
|
if ( !X11DRV_CLIPBOARD_LaunchServer() )
|
||||||
* to be re-acquired by us!
|
{
|
||||||
*/
|
/* Empty the windows clipboard if the server was not launched.
|
||||||
|
* We should pretend that we still own the selection BEFORE calling
|
||||||
|
* EmptyClipboard() since otherwise this has the side effect of
|
||||||
|
* triggering X11DRV_CLIPBOARD_Acquire() and causing the X selection
|
||||||
|
* to be re-acquired by us!
|
||||||
|
*/
|
||||||
|
|
||||||
|
TRACE("\tLost the selection! Emptying the clipboard...\n");
|
||||||
|
|
||||||
|
OpenClipboard(NULL);
|
||||||
|
selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
|
||||||
|
EmptyClipboard();
|
||||||
|
|
||||||
|
CloseClipboard();
|
||||||
|
|
||||||
|
/* Give up ownership of the windows clipboard */
|
||||||
|
CLIPBOARD_ReleaseOwner();
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("\tLost the selection! Emptying the clipboard...\n");
|
selectionAcquired = S_NOSELECTION;
|
||||||
|
ClipboardSelectionOwner = PrimarySelectionOwner = 0;
|
||||||
OpenClipboard(NULL);
|
selectionWindow = 0;
|
||||||
selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
|
|
||||||
EmptyClipboard();
|
|
||||||
selectionAcquired = S_NOSELECTION;
|
|
||||||
|
|
||||||
CloseClipboard();
|
|
||||||
|
|
||||||
/* Give up ownership of the windows clipboard */
|
|
||||||
CLIPBOARD_ReleaseOwner();
|
|
||||||
ClipboardSelectionOwner = PrimarySelectionOwner = 0;
|
|
||||||
selectionWindow = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,50 +3,123 @@
|
||||||
*
|
*
|
||||||
* Copyright 1999 Noel Borthwick
|
* Copyright 1999 Noel Borthwick
|
||||||
*
|
*
|
||||||
|
* USAGE:
|
||||||
|
* wineclipsrv [selection_mask] [debugClass_mask] [clearAllSelections]
|
||||||
|
*
|
||||||
|
* The optional selection-mask argument is a bit mask of the selection
|
||||||
|
* types to be acquired. Currently two selections are supported:
|
||||||
|
* 1. PRIMARY (mask value 1)
|
||||||
|
* 2. CLIPBOARD (mask value 2).
|
||||||
|
*
|
||||||
|
* debugClass_mask is a bit mask of all debugging classes for which messages
|
||||||
|
* are to be output. The standard Wine debug class set FIXME(1), ERR(2),
|
||||||
|
* WARN(4) and TRACE(8) are supported.
|
||||||
|
*
|
||||||
|
* If clearAllSelections == 1 *all* selections are lost whenever a SelectionClear
|
||||||
|
* event is received.
|
||||||
|
*
|
||||||
|
* If no arguments are supplied the server aquires all selections. (mask value 3)
|
||||||
|
* and defaults to output of only FIXME(1) and ERR(2) messages. The default for
|
||||||
|
* clearAllSelections is 0.
|
||||||
|
*
|
||||||
* NOTES:
|
* NOTES:
|
||||||
* This file contains the implementation for the Clipboard server
|
*
|
||||||
|
* The Wine Clipboard Server is a standalone XLib application whose
|
||||||
|
* purpose is to manage the X selection when Wine exits.
|
||||||
|
* The server itself is started automatically with the appropriate
|
||||||
|
* selection masks, whenever Wine exits after acquiring the PRIMARY and/or
|
||||||
|
* CLIPBOARD selection. (See X11DRV_CLIPBOARD_ResetOwner)
|
||||||
|
* When the server starts, it first proceeds to capture the selection data from
|
||||||
|
* Wine and then takes over the selection ownership. It does this by querying
|
||||||
|
* the current selection owner(of the specified selections) for the TARGETS
|
||||||
|
* selection target. It then proceeds to cache all the formats exposed by
|
||||||
|
* TARGETS. If the selection does not support the TARGETS target, or if no
|
||||||
|
* target formats are exposed, the server simply exits.
|
||||||
|
* Once the cache has been filled, the server then actually acquires ownership
|
||||||
|
* of the respective selection and begins fielding selection requests.
|
||||||
|
* Selection requests are serviced from the cache. If a selection is lost the
|
||||||
|
* server flushes its internal cache, destroying all data previously saved.
|
||||||
|
* Once ALL selections have been lost the server terminates.
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/Xos.h>
|
#include <X11/Xos.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/* Lightweight debug definitions */
|
/*
|
||||||
|
* Lightweight debug definitions for Wine Clipboard Server.
|
||||||
|
* The standard FIXME, ERR, WARN & TRACE classes are supported
|
||||||
|
* without debug channels.
|
||||||
|
* The standard defines NO_TRACE_MSGS and NO_DEBUG_MSGS will compile out
|
||||||
|
* TRACE, WARN and ERR and FIXME message displays.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Internal definitions (do not use these directly) */
|
||||||
|
|
||||||
|
enum __DEBUG_CLASS { __DBCL_FIXME, __DBCL_ERR, __DBCL_WARN, __DBCL_TRACE, __DBCL_COUNT };
|
||||||
|
|
||||||
|
extern char __debug_msg_enabled[__DBCL_COUNT];
|
||||||
|
|
||||||
|
extern const char * const debug_cl_name[__DBCL_COUNT];
|
||||||
|
|
||||||
|
#define DEBUG_CLASS_COUNT __DBCL_COUNT
|
||||||
|
|
||||||
|
#define __GET_DEBUGGING(dbcl) (__debug_msg_enabled[(dbcl)])
|
||||||
|
#define __SET_DEBUGGING(dbcl,on) (__debug_msg_enabled[(dbcl)] = (on))
|
||||||
|
|
||||||
|
|
||||||
|
#define __DPRINTF(dbcl) \
|
||||||
|
(!__GET_DEBUGGING(dbcl) || \
|
||||||
|
(printf("%s:%s:%s ", debug_cl_name[(dbcl)], progname, __FUNCTION__),0)) \
|
||||||
|
? 0 : printf
|
||||||
|
|
||||||
#define __DPRINTF(dbname) (printf("%s:%s:%s ", dbname, progname, __FUNCTION__),0) ? 0 : printf
|
|
||||||
#define __DUMMY_DPRINTF 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
|
#define __DUMMY_DPRINTF 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
|
||||||
|
|
||||||
|
/* use configure to allow user to compile out debugging messages */
|
||||||
#ifndef NO_TRACE_MSGS
|
#ifndef NO_TRACE_MSGS
|
||||||
#define TRACE __DPRINTF("TRACE")
|
#define TRACE __DPRINTF(__DBCL_TRACE)
|
||||||
#else
|
#else
|
||||||
#define TRACE __DUMMY_DPRINTF
|
#define TRACE __DUMMY_DPRINTF
|
||||||
#endif /* NO_TRACE_MSGS */
|
#endif /* NO_TRACE_MSGS */
|
||||||
|
|
||||||
#ifndef NO_DEBUG_MSGS
|
#ifndef NO_DEBUG_MSGS
|
||||||
#define WARN __DPRINTF("WARN")
|
#define WARN __DPRINTF(__DBCL_WARN)
|
||||||
#define FIXME __DPRINTF("FIXME")
|
#define FIXME __DPRINTF(__DBCL_FIXME)
|
||||||
#else
|
#else
|
||||||
#define WARN __DUMMY_DPRINTF
|
#define WARN __DUMMY_DPRINTF
|
||||||
#define FIXME __DUMMY_DPRINTF
|
#define FIXME __DUMMY_DPRINTF
|
||||||
#endif /* NO_DEBUG_MSGS */
|
#endif /* NO_DEBUG_MSGS */
|
||||||
|
|
||||||
#define ERR __DPRINTF("ERROR")
|
/* define error macro regardless of what is configured */
|
||||||
|
#define ERR __DPRINTF(__DBCL_ERR)
|
||||||
|
|
||||||
|
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
typedef int BOOL;
|
typedef int BOOL;
|
||||||
|
|
||||||
|
/* Internal definitions for debugging messages(do not use these directly) */
|
||||||
|
const char * const debug_cl_name[] = { "fixme", "err", "warn", "trace" };
|
||||||
|
char __debug_msg_enabled[DEBUG_CLASS_COUNT] = {1, 1, 0, 0};
|
||||||
|
|
||||||
|
|
||||||
/* Selection masks */
|
/* Selection masks */
|
||||||
|
|
||||||
#define S_NOSELECTION 0
|
#define S_NOSELECTION 0
|
||||||
#define S_PRIMARY 1
|
#define S_PRIMARY 1
|
||||||
#define S_CLIPBOARD 2
|
#define S_CLIPBOARD 2
|
||||||
|
|
||||||
|
/* Debugging class masks */
|
||||||
|
|
||||||
|
#define C_FIXME 1
|
||||||
|
#define C_ERR 2
|
||||||
|
#define C_WARN 4
|
||||||
|
#define C_TRACE 8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables
|
* Global variables
|
||||||
|
@ -62,10 +135,10 @@ static char *g_szOutOfMemory = "Insufficient memory!\n";
|
||||||
|
|
||||||
/* X selection context info */
|
/* X selection context info */
|
||||||
static char _CLIPBOARD[] = "CLIPBOARD"; /* CLIPBOARD atom name */
|
static char _CLIPBOARD[] = "CLIPBOARD"; /* CLIPBOARD atom name */
|
||||||
static char FMT_PREFIX[] = "<WCF>"; /* Prefix for windows specific formats */
|
|
||||||
static int g_selectionToAcquire = 0; /* Masks for the selection to be acquired */
|
static int g_selectionToAcquire = 0; /* Masks for the selection to be acquired */
|
||||||
static int g_selectionAcquired = 0; /* Contains the current selection masks */
|
static int g_selectionAcquired = 0; /* Contains the current selection masks */
|
||||||
|
static int g_clearAllSelections = 0; /* If TRUE *all* selections are lost on SelectionClear */
|
||||||
|
|
||||||
/* Selection cache */
|
/* Selection cache */
|
||||||
typedef struct tag_CACHEENTRY
|
typedef struct tag_CACHEENTRY
|
||||||
{
|
{
|
||||||
|
@ -119,7 +192,6 @@ void getGC(Window win, GC *gc);
|
||||||
void main(int argc, char **argv)
|
void main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
XEvent event;
|
XEvent event;
|
||||||
unsigned int width, height; /* window size */
|
|
||||||
|
|
||||||
if ( !Init(argc, argv) )
|
if ( !Init(argc, argv) )
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -130,6 +202,8 @@ void main(int argc, char **argv)
|
||||||
*/
|
*/
|
||||||
if ( AcquireSelection() == S_NOSELECTION )
|
if ( AcquireSelection() == S_NOSELECTION )
|
||||||
TerminateServer(0);
|
TerminateServer(0);
|
||||||
|
|
||||||
|
TRACE("Clipboard server running...\n");
|
||||||
|
|
||||||
/* Start an X event loop */
|
/* Start an X event loop */
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -243,8 +317,23 @@ BOOL Init(int argc, char **argv)
|
||||||
g_selectionToAcquire = atoi(argv[1]);
|
g_selectionToAcquire = atoi(argv[1]);
|
||||||
else
|
else
|
||||||
g_selectionToAcquire = S_PRIMARY | S_CLIPBOARD;
|
g_selectionToAcquire = S_PRIMARY | S_CLIPBOARD;
|
||||||
|
|
||||||
|
/* Set the debugging class state from the command line argument */
|
||||||
|
if (argc > 2)
|
||||||
|
{
|
||||||
|
int dbgClasses = atoi(argv[2]);
|
||||||
|
|
||||||
TRACE("Clipboard server running...\n");
|
__SET_DEBUGGING(__DBCL_FIXME, dbgClasses & C_FIXME);
|
||||||
|
__SET_DEBUGGING(__DBCL_ERR, dbgClasses & C_ERR);
|
||||||
|
__SET_DEBUGGING(__DBCL_WARN, dbgClasses & C_WARN);
|
||||||
|
__SET_DEBUGGING(__DBCL_TRACE, dbgClasses & C_TRACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the "ClearSelections" state from the command line argument */
|
||||||
|
if (argc > 3)
|
||||||
|
g_clearAllSelections = atoi(argv[3]);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -287,27 +376,39 @@ int AcquireSelection()
|
||||||
{
|
{
|
||||||
TRACE("Acquiring PRIMARY selection...\n");
|
TRACE("Acquiring PRIMARY selection...\n");
|
||||||
g_cPrimaryTargets = CacheDataFormats( XA_PRIMARY, &g_pPrimaryCache );
|
g_cPrimaryTargets = CacheDataFormats( XA_PRIMARY, &g_pPrimaryCache );
|
||||||
if (g_cPrimaryTargets)
|
TRACE("Cached %ld formats...\n", g_cPrimaryTargets);
|
||||||
XSetSelectionOwner(g_display, XA_PRIMARY, g_win, CurrentTime);
|
|
||||||
else
|
|
||||||
TRACE("No PRIMARY targets - ownership not acquired.\n");
|
|
||||||
}
|
}
|
||||||
if (g_selectionToAcquire & S_CLIPBOARD)
|
if (g_selectionToAcquire & S_CLIPBOARD)
|
||||||
{
|
{
|
||||||
TRACE("Acquiring CLIPBOARD selection...\n");
|
TRACE("Acquiring CLIPBOARD selection...\n");
|
||||||
g_cClipboardTargets = CacheDataFormats( xaClipboard, &g_pClipboardCache );
|
g_cClipboardTargets = CacheDataFormats( xaClipboard, &g_pClipboardCache );
|
||||||
|
TRACE("Cached %ld formats...\n", g_cClipboardTargets);
|
||||||
if (g_cClipboardTargets)
|
|
||||||
XSetSelectionOwner(g_display, xaClipboard, g_win, CurrentTime);
|
|
||||||
else
|
|
||||||
TRACE("No CLIPBOARD targets - ownership not acquired.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember the acquired selections */
|
/*
|
||||||
if( XGetSelectionOwner(g_display,XA_PRIMARY) == g_win )
|
* Now that we have cached the data, we proceed to acquire the selections
|
||||||
|
*/
|
||||||
|
if (g_cPrimaryTargets)
|
||||||
|
{
|
||||||
|
/* Acquire the PRIMARY selection */
|
||||||
|
while (XGetSelectionOwner(g_display,XA_PRIMARY) != g_win)
|
||||||
|
XSetSelectionOwner(g_display, XA_PRIMARY, g_win, CurrentTime);
|
||||||
|
|
||||||
g_selectionAcquired |= S_PRIMARY;
|
g_selectionAcquired |= S_PRIMARY;
|
||||||
if( XGetSelectionOwner(g_display,xaClipboard) == g_win )
|
}
|
||||||
|
else
|
||||||
|
TRACE("No PRIMARY targets - ownership not acquired.\n");
|
||||||
|
|
||||||
|
if (g_cClipboardTargets)
|
||||||
|
{
|
||||||
|
/* Acquire the CLIPBOARD selection */
|
||||||
|
while (XGetSelectionOwner(g_display,xaClipboard) != g_win)
|
||||||
|
XSetSelectionOwner(g_display, xaClipboard, g_win, CurrentTime);
|
||||||
|
|
||||||
g_selectionAcquired |= S_CLIPBOARD;
|
g_selectionAcquired |= S_CLIPBOARD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TRACE("No CLIPBOARD targets - ownership not acquired.\n");
|
||||||
|
|
||||||
return g_selectionAcquired;
|
return g_selectionAcquired;
|
||||||
}
|
}
|
||||||
|
@ -398,7 +499,7 @@ int CacheDataFormats( Atom SelectionSrc, PCACHEENTRY *ppCache )
|
||||||
|
|
||||||
/* Populate the cache entry */
|
/* Populate the cache entry */
|
||||||
if (!FillCacheEntry( SelectionSrc, targetList[i], &((*ppCache)[i])))
|
if (!FillCacheEntry( SelectionSrc, targetList[i], &((*ppCache)[i])))
|
||||||
ERR("Failed to fill cache entry!");
|
ERR("Failed to fill cache entry!\n");
|
||||||
|
|
||||||
XFree(itemFmtName);
|
XFree(itemFmtName);
|
||||||
}
|
}
|
||||||
|
@ -453,8 +554,11 @@ BOOL FillCacheEntry( Atom SelectionSrc, Atom target, PCACHEENTRY pCacheEntry )
|
||||||
reqType = xe.xselection.target;
|
reqType = xe.xselection.target;
|
||||||
|
|
||||||
if(prop == None)
|
if(prop == None)
|
||||||
|
{
|
||||||
|
TRACE("\tOwner failed to convert selection!\n");
|
||||||
return bRet;
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("\tretrieving property %s from window %ld into %s\n",
|
TRACE("\tretrieving property %s from window %ld into %s\n",
|
||||||
XGetAtomName(g_display,reqType), (long)w, XGetAtomName(g_display,prop) );
|
XGetAtomName(g_display,reqType), (long)w, XGetAtomName(g_display,prop) );
|
||||||
|
|
||||||
|
@ -600,7 +704,7 @@ void EmptyCache(PCACHEENTRY pCache, int nItems)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE("Freeing %s (0x%x)...\n",
|
TRACE("Freeing %s (%p)...\n",
|
||||||
XGetAtomName(g_display, pCache[i].target), pCache[i].pData);
|
XGetAtomName(g_display, pCache[i].target), pCache[i].pData);
|
||||||
|
|
||||||
/* Free the cached data item (allocated by X) */
|
/* Free the cached data item (allocated by X) */
|
||||||
|
@ -621,8 +725,10 @@ void EmptyCache(PCACHEENTRY pCache, int nItems)
|
||||||
*/
|
*/
|
||||||
void EVENT_ProcessEvent( XEvent *event )
|
void EVENT_ProcessEvent( XEvent *event )
|
||||||
{
|
{
|
||||||
// TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window );
|
/*
|
||||||
|
TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window );
|
||||||
|
*/
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case Expose:
|
case Expose:
|
||||||
|
@ -652,7 +758,7 @@ void EVENT_ProcessEvent( XEvent *event )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PropertyNotify:
|
case PropertyNotify:
|
||||||
EVENT_PropertyNotify( (XPropertyEvent *)event );
|
// EVENT_PropertyNotify( (XPropertyEvent *)event );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* ignore all other events */
|
default: /* ignore all other events */
|
||||||
|
@ -771,7 +877,6 @@ void EVENT_SelectionRequest( XSelectionRequestEvent *event, BOOL bIsMultiple )
|
||||||
XSelectionEvent result;
|
XSelectionEvent result;
|
||||||
Atom rprop = None;
|
Atom rprop = None;
|
||||||
Window request = event->requestor;
|
Window request = event->requestor;
|
||||||
BOOL couldOpen = FALSE;
|
|
||||||
Atom xaMultiple = XInternAtom(g_display, "MULTIPLE", False);
|
Atom xaMultiple = XInternAtom(g_display, "MULTIPLE", False);
|
||||||
PCACHEENTRY pCacheEntry = NULL;
|
PCACHEENTRY pCacheEntry = NULL;
|
||||||
void *pData = NULL;
|
void *pData = NULL;
|
||||||
|
@ -803,7 +908,7 @@ void EVENT_SelectionRequest( XSelectionRequestEvent *event, BOOL bIsMultiple )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the X property */
|
/* Update the X property */
|
||||||
TRACE("\tUpdating property %s...", XGetAtomName(g_display, rprop));
|
TRACE("\tUpdating property %s...\n", XGetAtomName(g_display, rprop));
|
||||||
|
|
||||||
/* If we have a request for a pixmap, return a duplicate */
|
/* If we have a request for a pixmap, return a duplicate */
|
||||||
|
|
||||||
|
@ -853,17 +958,36 @@ void EVENT_SelectionClear( XSelectionClearEvent *event )
|
||||||
|
|
||||||
TRACE("()\n");
|
TRACE("()\n");
|
||||||
|
|
||||||
if (event->selection == XA_PRIMARY)
|
/* If we're losing the CLIPBOARD selection, or if the preferences in .winerc
|
||||||
|
* dictate that *all* selections should be cleared on loss of a selection,
|
||||||
|
* we must give up all the selections we own.
|
||||||
|
*/
|
||||||
|
if ( g_clearAllSelections || (event->selection == xaClipboard) )
|
||||||
|
{
|
||||||
|
TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
|
||||||
|
|
||||||
|
/* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
|
||||||
|
if ( (event->selection == xaClipboard)
|
||||||
|
&& (g_selectionAcquired & S_PRIMARY) )
|
||||||
|
{
|
||||||
|
XSetSelectionOwner(g_display, XA_PRIMARY, None, CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */
|
||||||
|
if ( (event->selection == XA_PRIMARY)
|
||||||
|
&& (g_selectionAcquired & S_CLIPBOARD) )
|
||||||
|
{
|
||||||
|
XSetSelectionOwner(g_display, xaClipboard, None, CurrentTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_selectionAcquired = S_NOSELECTION; /* Clear the selection masks */
|
||||||
|
}
|
||||||
|
else if (event->selection == XA_PRIMARY)
|
||||||
{
|
{
|
||||||
g_selectionAcquired &= ~S_PRIMARY; /* Clear the PRIMARY flag */
|
|
||||||
TRACE("Lost PRIMARY selection...\n");
|
TRACE("Lost PRIMARY selection...\n");
|
||||||
|
g_selectionAcquired &= ~S_PRIMARY; /* Clear the PRIMARY flag */
|
||||||
}
|
}
|
||||||
else if (event->selection == xaClipboard)
|
|
||||||
{
|
|
||||||
g_selectionAcquired &= ~S_CLIPBOARD; /* Clear the CLIPBOARD flag */
|
|
||||||
TRACE("Lost CLIPBOARD selection...\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Once we lose all our selections we have nothing more to do */
|
/* Once we lose all our selections we have nothing more to do */
|
||||||
if (g_selectionAcquired == S_NOSELECTION)
|
if (g_selectionAcquired == S_NOSELECTION)
|
||||||
TerminateServer(1);
|
TerminateServer(1);
|
||||||
|
@ -915,7 +1039,7 @@ Pixmap DuplicatePixmap(Pixmap pixmap)
|
||||||
unsigned border_width; /* Unused */
|
unsigned border_width; /* Unused */
|
||||||
unsigned int depth, width, height;
|
unsigned int depth, width, height;
|
||||||
|
|
||||||
TRACE("\t() Pixmap=%ul\n", pixmap);
|
TRACE("\t() Pixmap=%ld\n", (long)pixmap);
|
||||||
|
|
||||||
/* Get the Pixmap dimensions and bit depth */
|
/* Get the Pixmap dimensions and bit depth */
|
||||||
if ( 0 == XGetGeometry(g_display, pixmap, &root, &x, &y, &width, &height,
|
if ( 0 == XGetGeometry(g_display, pixmap, &root, &x, &y, &width, &height,
|
||||||
|
@ -933,7 +1057,7 @@ Pixmap DuplicatePixmap(Pixmap pixmap)
|
||||||
|
|
||||||
XDestroyImage(xi);
|
XDestroyImage(xi);
|
||||||
|
|
||||||
TRACE("\t() New Pixmap=%ul\n", newPixmap);
|
TRACE("\t() New Pixmap=%ld\n", (long)newPixmap);
|
||||||
return newPixmap;
|
return newPixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue