Enabled the persistent clipboard server.
diff --git a/windows/clipboard.c b/windows/clipboard.c
index 7122167..27fe04b 100644
--- a/windows/clipboard.c
+++ b/windows/clipboard.c
@@ -488,7 +488,7 @@
TRACE("\tconverting from '%s' to '%s', %i chars\n",
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);
if( lpstrT )
@@ -791,7 +791,8 @@
}
/* Convert between 32 -> 16 bit data, if necessary */
- if( lpRender->hData32 && !lpRender->hData16 )
+ if( lpRender->hData32 && !lpRender->hData16
+ && CLIPBOARD_IsMemoryObject(wFormat) )
{
int size;
if( lpRender->wFormatID == CF_METAFILEPICT )
@@ -857,7 +858,8 @@
}
/* Convert between 16 -> 32 bit data, if necessary */
- if( lpRender->hData16 && !lpRender->hData32 )
+ if( lpRender->hData16 && !lpRender->hData32
+ && CLIPBOARD_IsMemoryObject(wFormat) )
{
int size;
if( lpRender->wFormatID == CF_METAFILEPICT )
diff --git a/windows/user.c b/windows/user.c
index ff920b2..672783b 100644
--- a/windows/user.c
+++ b/windows/user.c
@@ -171,11 +171,6 @@
* 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" */
hInstance = GetExePtr( hInstance );
diff --git a/windows/x11drv/Makefile.in b/windows/x11drv/Makefile.in
index afc90d3..8d54cf0 100644
--- a/windows/x11drv/Makefile.in
+++ b/windows/x11drv/Makefile.in
@@ -1,4 +1,4 @@
-DEFS = @DLLFLAGS@ -D__WINE__
+DEFS = @DLLFLAGS@ -D__WINE__ -DBINDIR="\"$(bindir)\""
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
@@ -23,8 +23,6 @@
wineclipsrv: wineclipsrv.c
$(CC) $(ALLCFLAGS) -o wineclipsrv $(SRCDIR)/wineclipsrv.c $(X_LIBS) $(XLIB) $(LIBS)
-all: $(MODULE).o
-
@MAKE_RULES@
### Dependencies:
diff --git a/windows/x11drv/clipboard.c b/windows/x11drv/clipboard.c
index 3db480b..fcdc4c9 100644
--- a/windows/x11drv/clipboard.c
+++ b/windows/x11drv/clipboard.c
@@ -49,13 +49,15 @@
#ifndef X_DISPLAY_MISSING
+#include <errno.h>
#include <X11/Xatom.h>
#include <string.h>
+#include <unistd.h>
+
#include "ts_xlib.h"
#include "wine/winuser16.h"
#include "clipboard.h"
-#include "debugtools.h"
#include "message.h"
#include "win.h"
#include "windef.h"
@@ -63,6 +65,8 @@
#include "bitmap.h"
#include "commctrl.h"
#include "heap.h"
+#include "options.h"
+#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(clipboard)
@@ -76,13 +80,14 @@
static char _CLIPBOARD[] = "CLIPBOARD"; /* CLIPBOARD atom name */
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 selectionPrevWindow = None; /* The last X window that owned the selection */
static Window PrimarySelectionOwner = None; /* The window which owns the primary 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 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
@@ -206,6 +211,106 @@
/**************************************************************************
+ * 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
*
* Caches the list of data formats available from the current selection.
@@ -567,14 +672,14 @@
* Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
* to a SelectionClear event.
* 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)
{
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.
*/
@@ -585,12 +690,15 @@
{
if( w == selectionWindow || selectionPrevWindow == None)
{
- /* alright, we really lost it */
-
- if ( selType == xaClipboard ) /* completely give up the selection */
+ /* 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 ( 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.
* Make sure we can open the windows clipboard first. */
@@ -607,24 +715,23 @@
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;
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.
* We should pretend that we still own the selection BEFORE calling
* EmptyClipboard() since otherwise this has the side effect of
@@ -633,12 +740,13 @@
*/
selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
EmptyClipboard();
- selectionAcquired = S_NOSELECTION;
-
CloseClipboard();
/* Give up ownership of the windows clipboard */
CLIPBOARD_ReleaseOwner();
+
+ /* Reset the selection flags now that we are done */
+ selectionAcquired = S_NOSELECTION;
}
else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
{
@@ -664,6 +772,13 @@
}
}
+ /* 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;
}
@@ -996,21 +1111,6 @@
TRACE("clipboard owner = %04x, selection window = %08x\n",
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 */
TRACE("\tchecking %08x\n", (unsigned) XWnd);
@@ -1041,7 +1141,10 @@
TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
TSXSetSelectionOwner(display, xaClipboard, selectionWindow, CurrentTime);
-
+
+ /* Restore the selection masks */
+ selectionAcquired = saveSelectionState;
+
/* Lose the selection if something went wrong */
if ( ( (saveSelectionState & S_PRIMARY) &&
(TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow) )
@@ -1053,7 +1156,6 @@
else
{
/* Update selection state */
- selectionAcquired = saveSelectionState;
if (saveSelectionState & S_PRIMARY)
PrimarySelectionOwner = selectionWindow;
@@ -1069,26 +1171,33 @@
END:
if (bLostSelection)
{
- /* Empty the windows clipboard.
- * 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!
- */
+ /* Launch the clipboard server if the selection can no longer be recyled
+ * to another top level window. */
+
+ if ( !X11DRV_CLIPBOARD_LaunchServer() )
+ {
+ /* 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");
-
- OpenClipboard(NULL);
- selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
- EmptyClipboard();
- selectionAcquired = S_NOSELECTION;
-
- CloseClipboard();
-
- /* Give up ownership of the windows clipboard */
- CLIPBOARD_ReleaseOwner();
- ClipboardSelectionOwner = PrimarySelectionOwner = 0;
- selectionWindow = 0;
+ selectionAcquired = S_NOSELECTION;
+ ClipboardSelectionOwner = PrimarySelectionOwner = 0;
+ selectionWindow = 0;
}
}
diff --git a/windows/x11drv/wineclipsrv.c b/windows/x11drv/wineclipsrv.c
index 63276f7..97ff7a7 100644
--- a/windows/x11drv/wineclipsrv.c
+++ b/windows/x11drv/wineclipsrv.c
@@ -3,50 +3,123 @@
*
* 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:
- * 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:
- *
*/
+
+#include <stdio.h>
+#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.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.
+ */
-#define __DPRINTF(dbname) (printf("%s:%s:%s ", dbname, progname, __FUNCTION__),0) ? 0 : printf
+/* 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 __DUMMY_DPRINTF 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
+/* use configure to allow user to compile out debugging messages */
#ifndef NO_TRACE_MSGS
- #define TRACE __DPRINTF("TRACE")
+ #define TRACE __DPRINTF(__DBCL_TRACE)
#else
#define TRACE __DUMMY_DPRINTF
#endif /* NO_TRACE_MSGS */
#ifndef NO_DEBUG_MSGS
- #define WARN __DPRINTF("WARN")
- #define FIXME __DPRINTF("FIXME")
+ #define WARN __DPRINTF(__DBCL_WARN)
+ #define FIXME __DPRINTF(__DBCL_FIXME)
#else
#define WARN __DUMMY_DPRINTF
#define FIXME __DUMMY_DPRINTF
#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 FALSE 0
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 */
#define S_NOSELECTION 0
#define S_PRIMARY 1
#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
@@ -62,10 +135,10 @@
/* X selection context info */
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_selectionAcquired = 0; /* Contains the current selection masks */
-
+static int g_clearAllSelections = 0; /* If TRUE *all* selections are lost on SelectionClear */
+
/* Selection cache */
typedef struct tag_CACHEENTRY
{
@@ -119,7 +192,6 @@
void main(int argc, char **argv)
{
XEvent event;
- unsigned int width, height; /* window size */
if ( !Init(argc, argv) )
exit(0);
@@ -130,6 +202,8 @@
*/
if ( AcquireSelection() == S_NOSELECTION )
TerminateServer(0);
+
+ TRACE("Clipboard server running...\n");
/* Start an X event loop */
while (1)
@@ -243,8 +317,23 @@
g_selectionToAcquire = atoi(argv[1]);
else
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 @@
{
TRACE("Acquiring PRIMARY selection...\n");
g_cPrimaryTargets = CacheDataFormats( XA_PRIMARY, &g_pPrimaryCache );
- if (g_cPrimaryTargets)
- XSetSelectionOwner(g_display, XA_PRIMARY, g_win, CurrentTime);
- else
- TRACE("No PRIMARY targets - ownership not acquired.\n");
+ TRACE("Cached %ld formats...\n", g_cPrimaryTargets);
}
if (g_selectionToAcquire & S_CLIPBOARD)
{
TRACE("Acquiring CLIPBOARD selection...\n");
g_cClipboardTargets = CacheDataFormats( xaClipboard, &g_pClipboardCache );
-
- if (g_cClipboardTargets)
- XSetSelectionOwner(g_display, xaClipboard, g_win, CurrentTime);
- else
- TRACE("No CLIPBOARD targets - ownership not acquired.\n");
+ TRACE("Cached %ld formats...\n", g_cClipboardTargets);
}
- /* 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;
- 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;
+ }
+ else
+ TRACE("No CLIPBOARD targets - ownership not acquired.\n");
return g_selectionAcquired;
}
@@ -398,7 +499,7 @@
/* Populate the cache entry */
if (!FillCacheEntry( SelectionSrc, targetList[i], &((*ppCache)[i])))
- ERR("Failed to fill cache entry!");
+ ERR("Failed to fill cache entry!\n");
XFree(itemFmtName);
}
@@ -453,8 +554,11 @@
reqType = xe.xselection.target;
if(prop == None)
+ {
+ TRACE("\tOwner failed to convert selection!\n");
return bRet;
-
+ }
+
TRACE("\tretrieving property %s from window %ld into %s\n",
XGetAtomName(g_display,reqType), (long)w, XGetAtomName(g_display,prop) );
@@ -600,7 +704,7 @@
}
else
{
- TRACE("Freeing %s (0x%x)...\n",
+ TRACE("Freeing %s (%p)...\n",
XGetAtomName(g_display, pCache[i].target), pCache[i].pData);
/* Free the cached data item (allocated by X) */
@@ -621,8 +725,10 @@
*/
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)
{
case Expose:
@@ -652,7 +758,7 @@
break;
case PropertyNotify:
- EVENT_PropertyNotify( (XPropertyEvent *)event );
+ // EVENT_PropertyNotify( (XPropertyEvent *)event );
break;
default: /* ignore all other events */
@@ -771,7 +877,6 @@
XSelectionEvent result;
Atom rprop = None;
Window request = event->requestor;
- BOOL couldOpen = FALSE;
Atom xaMultiple = XInternAtom(g_display, "MULTIPLE", False);
PCACHEENTRY pCacheEntry = NULL;
void *pData = NULL;
@@ -803,7 +908,7 @@
}
/* 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 */
@@ -853,17 +958,36 @@
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) )
{
- g_selectionAcquired &= ~S_PRIMARY; /* Clear the PRIMARY flag */
+ 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)
+ {
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 */
if (g_selectionAcquired == S_NOSELECTION)
TerminateServer(1);
@@ -915,7 +1039,7 @@
unsigned border_width; /* Unused */
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 */
if ( 0 == XGetGeometry(g_display, pixmap, &root, &x, &y, &width, &height,
@@ -933,7 +1057,7 @@
XDestroyImage(xi);
- TRACE("\t() New Pixmap=%ul\n", newPixmap);
+ TRACE("\t() New Pixmap=%ld\n", (long)newPixmap);
return newPixmap;
}