changeset 2586:538cd3220874 v7.3.011

updated for version 7.3.011 Problem: X11 clipboard doesn't work in Athena/Motif GUI. First selection after a shell command doesn't work. Solution: When using the GUI use XtLastTimestampProcessed() instead of changing a property. (partly by Toni Ronkko) When executing a shell command disown the selection.
author Bram Moolenaar <bram@vim.org>
date Tue, 21 Sep 2010 22:09:37 +0200
parents 03d49a7c8319
children d0049ff5969e
files src/os_unix.c src/ui.c src/version.c
diffstat 3 files changed, 72 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1123,6 +1123,30 @@ sigcont_handler SIGDEFARG(sigarg)
 }
 #endif
 
+# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
+static void loose_clipboard __ARGS((void));
+
+/*
+ * Called when Vim is going to sleep or execute a shell command.
+ * We can't respond to requests for the X selections.  Lose them, otherwise
+ * other applications will hang.  But first copy the text to cut buffer 0.
+ */
+    static void
+loose_clipboard()
+{
+    if (clip_star.owned || clip_plus.owned)
+    {
+	x11_export_final_selection();
+	if (clip_star.owned)
+	    clip_lose_selection(&clip_star);
+	if (clip_plus.owned)
+	    clip_lose_selection(&clip_plus);
+	if (x11_display != NULL)
+	    XFlush(x11_display);
+    }
+}
+#endif
+
 /*
  * If the machine has job control, use it to suspend the program,
  * otherwise fake it by starting a new shell.
@@ -1137,19 +1161,7 @@ mch_suspend()
     out_flush();	    /* needed to disable mouse on some systems */
 
 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
-    /* Since we are going to sleep, we can't respond to requests for the X
-     * selections.  Lose them, otherwise other applications will hang.  But
-     * first copy the text to cut buffer 0. */
-    if (clip_star.owned || clip_plus.owned)
-    {
-	x11_export_final_selection();
-	if (clip_star.owned)
-	    clip_lose_selection(&clip_star);
-	if (clip_plus.owned)
-	    clip_lose_selection(&clip_plus);
-	if (x11_display != NULL)
-	    XFlush(x11_display);
-    }
+    loose_clipboard();
 # endif
 
 # if defined(_REENTRANT) && defined(SIGCONT)
@@ -3706,6 +3718,10 @@ mch_call_shell(cmd, options)
     if (options & SHELL_COOKED)
 	settmode(TMODE_COOK);	    /* set to normal mode */
 
+# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
+    loose_clipboard();
+# endif
+
 # ifdef __EMX__
     if (cmd == NULL)
 	x = system("");	/* this starts an interactive shell in emx */
@@ -3814,13 +3830,17 @@ mch_call_shell(cmd, options)
 # endif
     int		did_settmode = FALSE;	/* settmode(TMODE_RAW) called */
 
+    newcmd = vim_strsave(p_sh);
+    if (newcmd == NULL)		/* out of memory */
+	goto error;
+
     out_flush();
     if (options & SHELL_COOKED)
 	settmode(TMODE_COOK);		/* set to normal mode */
 
-    newcmd = vim_strsave(p_sh);
-    if (newcmd == NULL)		/* out of memory */
-	goto error;
+# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
+    loose_clipboard();
+# endif
 
     /*
      * Do this loop twice:
--- a/src/ui.c
+++ b/src/ui.c
@@ -469,7 +469,7 @@ clip_own_selection(cbd)
      */
 #ifdef FEAT_X11
     /* Always own the selection, we might have lost it without being
-     * notified. */
+     * notified, e.g. during a ":sh" command. */
     if (cbd->available)
     {
 	int was_owned = cbd->owned;
@@ -1944,10 +1944,9 @@ x11_setup_atoms(dpy)
  */
 
 static Boolean	clip_x11_convert_selection_cb __ARGS((Widget, Atom *, Atom *, Atom *, XtPointer *, long_u *, int *));
-
 static void  clip_x11_lose_ownership_cb __ARGS((Widget, Atom *));
-
 static void clip_x11_timestamp_cb __ARGS((Widget w, XtPointer n, XEvent *event, Boolean *cont));
+static void  clip_x11_request_selection_cb __ARGS((Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *));
 
 /*
  * Property callback to get a timestamp for XtOwnSelection.
@@ -1985,8 +1984,17 @@ clip_x11_timestamp_cb(w, n, event, cont)
 	return;
 
     /* Get the selection, using the event timestamp. */
-    XtOwnSelection(w, xproperty->atom, xproperty->time,
-	    clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb, NULL);
+    if (XtOwnSelection(w, xproperty->atom, xproperty->time,
+	    clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
+	    NULL) == OK)
+    {
+	/* Set the "owned" flag now, there may have been a call to
+	 * lose_ownership_cb in between. */
+	if (xproperty->atom == clip_plus.sel_atom)
+	    clip_plus.owned = TRUE;
+	else
+	    clip_star.owned = TRUE;
+    }
 }
 
     void
@@ -1997,8 +2005,6 @@ x11_setup_selection(w)
 	    /*(XtEventHandler)*/clip_x11_timestamp_cb, (XtPointer)NULL);
 }
 
-static void  clip_x11_request_selection_cb __ARGS((Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *));
-
     static void
 clip_x11_request_selection_cb(w, success, sel_atom, type, value, length,
 			      format)
@@ -2336,7 +2342,7 @@ clip_x11_lose_ownership_cb(w, sel_atom)
 
     void
 clip_x11_lose_selection(myShell, cbd)
-    Widget	myShell;
+    Widget		myShell;
     VimClipboard	*cbd;
 {
     XtDisownSelection(myShell, cbd->sel_atom, CurrentTime);
@@ -2344,14 +2350,29 @@ clip_x11_lose_selection(myShell, cbd)
 
     int
 clip_x11_own_selection(myShell, cbd)
-    Widget	myShell;
+    Widget		myShell;
     VimClipboard	*cbd;
 {
-    /* Get the time by a zero-length append, clip_x11_timestamp_cb will be
-     * called with the current timestamp.  */
-    if (!XChangeProperty(XtDisplay(myShell), XtWindow(myShell), cbd->sel_atom,
-	    timestamp_atom, 32, PropModeAppend, NULL, 0))
+    /* When using the GUI we have proper timestamps, use the one of the last
+     * event.  When in the console we don't get events (the terminal gets
+     * them), Get the time by a zero-length append, clip_x11_timestamp_cb will
+     * be called with the current timestamp.  */
+#ifdef FEAT_GUI
+    if (gui.in_use)
+    {
+	if (XtOwnSelection(myShell, cbd->sel_atom,
+	       XtLastTimestampProcessed(XtDisplay(myShell)),
+	       clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
+	       NULL) == False)
 	return FAIL;
+    }
+    else
+#endif
+    {
+	if (!XChangeProperty(XtDisplay(myShell), XtWindow(myShell),
+		  cbd->sel_atom, timestamp_atom, 32, PropModeAppend, NULL, 0))
+	return FAIL;
+    }
     /* Flush is required in a terminal as nothing else is doing it. */
     XFlush(XtDisplay(myShell));
     return OK;
--- a/src/version.c
+++ b/src/version.c
@@ -715,6 +715,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    11,
+/**/
     10,
 /**/
     9,