x11drv: clipboard

Ulrich Czekalla ulrich.czekalla at utoronto.ca
Tue Jan 4 11:17:45 CST 2005


This patch removes the clearAllSelection option and always forces it to be
on. Not clearing CLIPBOARD when we release PRIMARY can get us into an odd
state such as the wine app not being able to paste data it put in the
clipboard because we bias towards the PRIMARY selection. Also, when copying
data, we always grab both selections when we use primary so it makes sense
to release both.

ChangeLog:
   Ulrich Czekalla <ulrich at codeweavers.com>
   Always clearAllSelections since not clearing CLIPBOARD can get us
   into an odd state.
-------------- next part --------------
Index: dlls/x11drv/clipboard.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/clipboard.c,v
retrieving revision 1.28
diff -u -p -r1.28 clipboard.c
--- dlls/x11drv/clipboard.c	11 Aug 2004 23:45:34 -0000	1.28
+++ dlls/x11drv/clipboard.c	4 Jan 2005 16:23:26 -0000
@@ -110,11 +110,8 @@ typedef struct
 
 static int selectionAcquired = 0;              /* Contains the current selection masks */
 static Window selectionWindow = None;          /* The top level X window which owns the selection */
-static BOOL clearAllSelections = FALSE;        /* Always lose all selections */
 static BOOL usePrimary = FALSE;                /* Use primary selection in additon to the clipboard selection */
 static Atom selectionCacheSrc = XA_PRIMARY;    /* The selection source from which the clipboard cache was filled */
-static Window PrimarySelectionOwner = None;    /* The window which owns the primary selection */
-static Window ClipboardSelectionOwner = None;  /* The window which owns the clipboard selection */
 
 INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName);
 void X11DRV_EmptyClipboard(BOOL keepunowned);
@@ -282,9 +279,6 @@ void X11DRV_InitClipboard(void)
     {
 	char buffer[20];
 	DWORD type, count = sizeof(buffer);
-	if(!RegQueryValueExA(hkey, "ClearAllSelections", 0, &type, buffer, &count))
-            clearAllSelections = IS_OPTION_TRUE( buffer[0] );
-        count = sizeof(buffer);
         if(!RegQueryValueExA(hkey, "UsePrimary", 0, &type, buffer, &count))
             usePrimary = IS_OPTION_TRUE( buffer[0] );
         RegCloseKey(hkey);
@@ -1923,12 +1917,9 @@ static HANDLE X11DRV_CLIPBOARD_Serialize
 /**************************************************************************
  *		X11DRV_CLIPBOARD_ReleaseSelection
  *
- * 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.
+ * Release XA_CLIPBOARD and XA_PRIMARY in response to a SelectionClear event.
  */
-void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
+void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd, Time time)
 {
     Display *display = thread_display();
 
@@ -1937,98 +1928,65 @@ void X11DRV_CLIPBOARD_ReleaseSelection(A
     TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
 	  (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionAcquired);
 
-    if (selectionAcquired)
+    if (selectionAcquired && (w == selectionWindow))
     {
-	if (w == selectionWindow)
-        {
-            /* 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 == x11drv_atom(CLIPBOARD)))
-            {
-                CLIPBOARDINFO cbinfo;
-
-                /* completely give up the selection */
-                TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
-
-              /* We are completely giving up the selection. There is a
-               * potential race condition where the apps that now owns
-	       * the selection has already grabbed both selections. In
-	       * this case, if we clear any selection we may clear the
-	       * new owners selection. To prevent this common case we
-	       * try to open the clipboard. If we can't, we assume it
-	       * was a wine apps that took it and has taken both selections.
-	       * In this case, don't bother releasing the other selection.
-	       * Otherwise only release the selection if we still own it.
-               */
-                X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
+        CLIPBOARDINFO cbinfo;
 
-                if (cbinfo.flags & CB_OWNER)
-                {
-                    /* Since we're still the owner, this wasn't initiated by 
-		       another Wine process */
-                    if (OpenClipboard(hwnd))
-                    {
-                      /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
-                      if ((selType == x11drv_atom(CLIPBOARD)) && (selectionAcquired & S_PRIMARY))
-                      {
-		          TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
-                          wine_tsx11_lock();
-                          if (selectionWindow == XGetSelectionOwner(display,XA_PRIMARY))
-                          {
-		             TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
-                             XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
-                          }
-		          else
-		             TRACE("We no longer own PRIMARY\n");
-                          wine_tsx11_unlock();
-                      }
-
-                      /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD  */
-                      if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
-                      {
-		          TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
-                          wine_tsx11_lock();
-                          if (selectionWindow == XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
-                          {
-		              TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
-                              XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), None, CurrentTime);
-                          }
-		          else
-		              TRACE("We no longer own CLIPBOARD\n");
-                          wine_tsx11_unlock();
-                      }
+        /* completely give up the selection */
+        TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
 
-                      /* Destroy private objects */
-                      SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
-   
-                      /* Give up ownership of the windows clipboard */
-                      X11DRV_CLIPBOARD_ReleaseOwnership();
+        X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
 
-                      CloseClipboard();
-                    }
-                }
-	        else
-                {
-                    TRACE("Lost selection to other Wine process.\n");
-                }
+        if (cbinfo.flags & CB_OWNER)
+        {
+            /* Since we're still the owner, this wasn't initiated by 
+               another Wine process */
+            if (OpenClipboard(hwnd))
+            {
+                /* Destroy private objects */
+                SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
 
-                selectionWindow = None;
-                PrimarySelectionOwner = ClipboardSelectionOwner = 0;
+                /* Give up ownership of the windows clipboard */
+                X11DRV_CLIPBOARD_ReleaseOwnership();
+                CloseClipboard();
+            }
+        }
 
-                X11DRV_EmptyClipboard(FALSE);
+        if ((selType == x11drv_atom(CLIPBOARD)) && (selectionAcquired & S_PRIMARY))
+        {
+            TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
 
-                /* Reset the selection flags now that we are done */
-                selectionAcquired = S_NOSELECTION;
+            wine_tsx11_lock();
+            if (selectionWindow == XGetSelectionOwner(display, XA_PRIMARY))
+            {
+                TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
+                XSetSelectionOwner(display, XA_PRIMARY, None, time);
             }
-            else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
+            else
+                TRACE("We no longer own PRIMARY\n");
+            wine_tsx11_unlock();
+        }
+        else if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
+        {
+            TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
+
+            wine_tsx11_lock();
+            if (selectionWindow == XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
             {
-                TRACE("Lost PRIMARY selection\n");
-                PrimarySelectionOwner = 0;
-                selectionAcquired &= ~S_PRIMARY;  /* clear S_PRIMARY mask */
+                TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
+                XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), None, time);
             }
-	}
+            else
+                TRACE("We no longer own CLIPBOARD\n");
+            wine_tsx11_unlock();
+        }
+
+        selectionWindow = None;
+
+        X11DRV_EmptyClipboard(FALSE);
+
+        /* Reset the selection flags now that we are done */
+        selectionAcquired = S_NOSELECTION;
     }
 }
 
@@ -2485,14 +2443,6 @@ void X11DRV_ResetSelectionOwner(HWND hwn
         {
             bLostSelection = TRUE;
         }
-        else
-        {
-            /* Update selection state */
-            if (saveSelectionState & S_PRIMARY)
-               PrimarySelectionOwner = selectionWindow;
-
-            ClipboardSelectionOwner = selectionWindow;
-        }
         wine_tsx11_unlock();
     }
     else
@@ -2506,7 +2456,6 @@ void X11DRV_ResetSelectionOwner(HWND hwn
 
         X11DRV_CLIPBOARD_ReleaseOwnership();
         selectionAcquired = S_NOSELECTION;
-        ClipboardSelectionOwner = PrimarySelectionOwner = 0;
         selectionWindow = 0;
     }
 }
Index: dlls/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/event.c,v
retrieving revision 1.37
diff -u -p -r1.37 event.c
--- dlls/x11drv/event.c	29 Sep 2004 21:11:28 -0000	1.37
+++ dlls/x11drv/event.c	4 Jan 2005 16:23:27 -0000
@@ -913,7 +913,7 @@ END:
 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
 {
   if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
-      X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
+      X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd, event->time );
 }
 
 /***********************************************************************
Index: dlls/x11drv/x11drv.h
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv.h,v
retrieving revision 1.39
diff -u -p -r1.39 x11drv.h
--- dlls/x11drv/x11drv.h	17 Dec 2004 19:35:16 -0000	1.39
+++ dlls/x11drv/x11drv.h	4 Jan 2005 16:23:27 -0000
@@ -483,7 +483,7 @@ typedef struct tagWINE_CLIPFORMAT {
 #define CF_FLAG_SYNTHESIZED  8 /* Implicitly converted data */
 
 extern void X11DRV_InitClipboard(void);
-extern void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd);
+extern void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd, Time time);
 extern INT X11DRV_CountClipboardFormats(void);
 extern UINT X11DRV_EnumClipboardFormats(UINT wFormat);
 extern LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID);
Index: documentation/samples/config
===================================================================
RCS file: /home/wine/wine/documentation/samples/config,v
retrieving revision 1.72
diff -u -p -r1.72 config
--- documentation/samples/config	21 Oct 2004 22:20:47 -0000	1.72
+++ documentation/samples/config	4 Jan 2005 16:23:27 -0000
@@ -154,7 +154,6 @@ WINE REGISTRY Version 2
 "SaveOnlyUpdatedKeys" = "Y"
 
 [Clipboard]
-"ClearAllSelections" = "0"
 "UsePrimary" = "0"
 
 ; List of all directories directly contain .AFM files


More information about the wine-patches mailing list