Mercurial > vim
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;