diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index f0c380d6e6..64deb34684 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 9.1. Last change: 2025 Jul 22 +*eval.txt* For Vim version 9.1. Last change: 2025 Aug 18 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2245,8 +2245,9 @@ v:clipmethod The current method of accessing the clipboard that is being used. Can either have the value of: wayland The Wayland protocol is being used. x11 X11 selections are being used. - none The above methods are unavailable or - cannot be used. + gui GUI specific method is being used. + none Clipboard functionality is disabled or + unavailable. See 'clipmethod' for more details. *v:cmdarg* *cmdarg-variable* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 74fddabbf5..d98303c28a 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2025 Aug 16 +*options.txt* For Vim version 9.1. Last change: 2025 Aug 18 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1891,9 +1891,9 @@ A jump table for the options with a short description can be found at |Q_op|. {pattern}, this must be the last entry. *'clipmethod'* *'cpm'* -'clipmethod' 'cpm' string (default for Unix: "wayland,x11", - for VMS: "x11", - otherwise: "") +'clipmethod' 'cpm' string (default for Unix: "wayland,x11,gui", + for VMS: "x11,gui", + otherwise: "gui") global {only when the |+xterm_clipboard| or |+wayland_clipboard| features are included} @@ -1902,19 +1902,16 @@ A jump table for the options with a short description can be found at |Q_op|. methods are: wayland Wayland selections x11 X11 selections - - Note: This option is ignored when either the GUI is running or if Vim - is run on a system without Wayland or X11 support, such as Windows or - macOS. The GUI or system way of accessing the clipboard is always - used instead. + gui GUI specific method The option value is a list of comma separated items. The list is parsed left to right in order, and the first method that Vim determines is available or is working is used as the actual method for - accessing the clipboard. + accessing the clipboard. Setting this option to an empty value + disables the clipboard functionality on all systems. - The current method that is being used can be found in the |v:clipmethod| - variable. + The current method that is being used can be found in the + |v:clipmethod| variable. *'cmdheight'* *'ch'* 'cmdheight' 'ch' number (default 1) diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt index d69afab2ef..2790f0fef8 100644 --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -41608,7 +41608,8 @@ Completion~ Platform specific~ ----------------- -- Support for Wayland UI and support for the Wayland clipboard has been added. +- Support for Wayland UI and support for the Wayland clipboard has been added + |wayland|. - Support for the XDG Desktop Specification |xdg-base-dir| has been added and the environment variable |$MYVIMDIR| is set to the users personal runtime @@ -41829,6 +41830,7 @@ Options: ~ 'autocompletion' Enable auto completion |ins-autocompletion| 'autocompletedelay' Delay in msec before menu appears after typing 'chistory' Size of the quickfix stack |quickfix-stack|. +'clipmethod' How to access the clipboard. 'completefuzzycollect' Enable fuzzy collection of candidates for (some) |ins-completion| modes 'completeitemalign' Order of |complete-items| in Insert mode completion @@ -41850,10 +41852,14 @@ Options: ~ 't_xo' Terminal uses XON/XOFF handshaking (e.g. vt420) 't_CF' Support for alternate font highlighting terminal code 'winfixbuf' Keep buffer focused in a window +'wlseat' Specify Wayland seat to use for the |wayland| feature +'wlsteal' Steal focus to access the |wayland| clipboard +'wltimeout' Specify the connection timeout for the |wayland| + compositor Vim Arguments: ~ -|-Y| Do not connect to the Wayland compositor. -|--clientserver| Specify backend for clientserver functionality. +|-Y| Do not connect to the |wayland| compositor. +|--clientserver| Specify backend for clientserver functionality. ============================================================================== diff --git a/runtime/doc/wayland.txt b/runtime/doc/wayland.txt index 9ffcbbaec2..ccb05fb917 100644 --- a/runtime/doc/wayland.txt +++ b/runtime/doc/wayland.txt @@ -1,4 +1,4 @@ -*wayland.txt* For Vim version 9.1. Last change: 2025 Jun 28 +*wayland.txt* For Vim version 9.1. Last change: 2025 Aug 18 VIM REFERENCE MANUAL by Bram Moolenaar @@ -22,7 +22,7 @@ multiple Wayland seats in the same Wayland session. See |gui-wayland|. Please note that when using the GUI, Vim uses the toolkit such as GTK for accessing the clipboard, and does not access the clipboard though Wayland. You can check this though the |v:clipmethod| variable, which -should equal to "none" when running the GUI. +should equal to "gui" when running the GUI. Wayland commands: *:wlrestore* *:wl* @@ -72,7 +72,7 @@ selections, see |wayland-primary-selection| for more details. *wayland-persist* If you use X11 cut buffers, no such things exist on Wayland. Instead to emulate such functionality, a separate clipboard manager must be used in order -to persist selection data when a Wayland client exists. +to persist selection data when a Wayland client exits. *wayland-and-x11* If your version of Vim comes compiled with both X11 and Wayland support, then diff --git a/src/clipboard.c b/src/clipboard.c index 5d2dec3afe..510f6b51a3 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -142,32 +142,28 @@ clip_update_selection(Clipboard_T *clip) } static int -clip_gen_own_selection(Clipboard_T *cbd) +clip_gen_own_selection(Clipboard_T *cbd UNUSED) { -#if defined(FEAT_XCLIPBOARD) || defined(FEAT_WAYLAND_CLIPBOARD) -# ifdef FEAT_GUI - if (gui.in_use) - return clip_mch_own_selection(cbd); - else -# endif + if (clipmethod == CLIPMETHOD_GUI) + { +#ifdef FEAT_GUI + if (gui.in_use) + return clip_mch_own_selection(cbd); +#endif + } + else if (clipmethod == CLIPMETHOD_WAYLAND) { - if (clipmethod == CLIPMETHOD_WAYLAND) - { #ifdef FEAT_WAYLAND_CLIPBOARD - return clip_wl_own_selection(cbd); + return clip_wl_own_selection(cbd); #endif - } - else if (clipmethod == CLIPMETHOD_X11) - { + } + else if (clipmethod == CLIPMETHOD_X11) + { #ifdef FEAT_XCLIPBOARD - return clip_xterm_own_selection(cbd); + return clip_xterm_own_selection(cbd); #endif - } } return FAIL; -#else - return clip_mch_own_selection(cbd); -#endif } void @@ -207,31 +203,27 @@ clip_own_selection(Clipboard_T *cbd) } static void -clip_gen_lose_selection(Clipboard_T *cbd) +clip_gen_lose_selection(Clipboard_T *cbd UNUSED) { -#if defined(FEAT_XCLIPBOARD) || defined(FEAT_WAYLAND_CLIPBOARD) -# ifdef FEAT_GUI - if (gui.in_use) - clip_mch_lose_selection(cbd); - else -# endif + if (clipmethod == CLIPMETHOD_GUI) { - if (clipmethod == CLIPMETHOD_WAYLAND) - { -#ifdef FEAT_WAYLAND_CLIPBOARD - clip_wl_lose_selection(cbd); +#ifdef FEAT_GUI + if (gui.in_use) + clip_mch_lose_selection(cbd); #endif - } - else if (clipmethod == CLIPMETHOD_X11) - { -#ifdef FEAT_XCLIPBOARD - clip_xterm_lose_selection(cbd); -#endif - } } -#else - clip_mch_lose_selection(cbd); + else if (clipmethod == CLIPMETHOD_WAYLAND) + { +#ifdef FEAT_WAYLAND_CLIPBOARD + clip_wl_lose_selection(cbd); #endif + } + else if (clipmethod == CLIPMETHOD_X11) + { +#ifdef FEAT_XCLIPBOARD + clip_xterm_lose_selection(cbd); +#endif + } } void @@ -1257,57 +1249,49 @@ clip_gen_set_selection(Clipboard_T *cbd) return; } } -#if defined(FEAT_XCLIPBOARD) || defined(FEAT_WAYLAND_CLIPBOARD) -# ifdef FEAT_GUI - if (gui.in_use) - clip_mch_set_selection(cbd); - else -# endif + if (clipmethod == CLIPMETHOD_GUI) { - if (clipmethod == CLIPMETHOD_WAYLAND) - { -#ifdef FEAT_WAYLAND_CLIPBOARD - clip_wl_set_selection(cbd); +#ifdef FEAT_GUI + if (gui.in_use) + clip_mch_set_selection(cbd); #endif - } - else if (clipmethod == CLIPMETHOD_X11) - { -#ifdef FEAT_XCLIPBOARD - clip_xterm_set_selection(cbd); -#endif - } } -#else - clip_mch_set_selection(cbd); + else if (clipmethod == CLIPMETHOD_WAYLAND) + { +#ifdef FEAT_WAYLAND_CLIPBOARD + clip_wl_set_selection(cbd); #endif + } + else if (clipmethod == CLIPMETHOD_X11) + { +#ifdef FEAT_XCLIPBOARD + clip_xterm_set_selection(cbd); +#endif + } } static void -clip_gen_request_selection(Clipboard_T *cbd) +clip_gen_request_selection(Clipboard_T *cbd UNUSED) { -#if defined(FEAT_XCLIPBOARD) || defined(FEAT_WAYLAND_CLIPBOARD) -# ifdef FEAT_GUI - if (gui.in_use) - clip_mch_request_selection(cbd); - else -# endif + if (clipmethod == CLIPMETHOD_GUI) { - if (clipmethod == CLIPMETHOD_WAYLAND) - { -#ifdef FEAT_WAYLAND_CLIPBOARD - clip_wl_request_selection(cbd); -#endif - } - else if (clipmethod == CLIPMETHOD_X11) - { -#ifdef FEAT_XCLIPBOARD - clip_xterm_request_selection(cbd); -#endif - } +# ifdef FEAT_GUI + if (gui.in_use) + clip_mch_request_selection(cbd); +# endif } -#else - clip_mch_request_selection(cbd); + else if (clipmethod == CLIPMETHOD_WAYLAND) + { +#ifdef FEAT_WAYLAND_CLIPBOARD + clip_wl_request_selection(cbd); #endif + } + else if (clipmethod == CLIPMETHOD_X11) + { +#ifdef FEAT_XCLIPBOARD + clip_xterm_request_selection(cbd); +#endif + } } #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD) && defined(USE_SYSTEM)) \ @@ -1324,31 +1308,28 @@ clip_x11_owner_exists(Clipboard_T *cbd) int clip_gen_owner_exists(Clipboard_T *cbd UNUSED) { -#ifdef FEAT_XCLIPBOARD -# ifdef FEAT_GUI_GTK - if (gui.in_use) - return clip_gtk_owner_exists(cbd); - else -# endif + if (clipmethod == CLIPMETHOD_OTHER) { - if (clipmethod == CLIPMETHOD_WAYLAND) - { -#ifdef FEAT_WAYLAND_CLIPBOARD - return clip_wl_owner_exists(cbd); -#endif - } - else if (clipmethod == CLIPMETHOD_X11) - { -#ifdef FEAT_XCLIPBOARD - return clip_x11_owner_exists(cbd); -#endif - } - else - return FALSE; +# ifdef FEAT_GUI_GTK + if (gui.in_use) + return clip_gtk_owner_exists(cbd); +# endif } -#else - return TRUE; -#endif + else if (clipmethod == CLIPMETHOD_WAYLAND) + { +# ifdef FEAT_WAYLAND_CLIPBOARD + return clip_wl_owner_exists(cbd); +# endif + } + else if (clipmethod == CLIPMETHOD_X11) + { +# ifdef FEAT_XCLIPBOARD + return clip_x11_owner_exists(cbd); +# endif + } + else + return FALSE; + return FALSE; } #endif @@ -2735,25 +2716,42 @@ get_clipmethod(char_u *str) if (STRCMP(buf, "wayland") == 0) { -#ifdef FEAT_WAYLAND_CLIPBOARD - if (wayland_cb_is_ready()) - method = CLIPMETHOD_WAYLAND; +#ifdef FEAT_GUI + if (!gui.in_use) #endif + { +#ifdef FEAT_WAYLAND_CLIPBOARD + if (wayland_cb_is_ready()) + method = CLIPMETHOD_WAYLAND; +#endif + } } else if (STRCMP(buf, "x11") == 0) { -#ifdef FEAT_XCLIPBOARD - // x_IOerror_handler() in os_unix.c should set xterm_dpy to NULL if - // we lost connection to the X server. - if (xterm_dpy != NULL) +#ifdef FEAT_GUI + if (!gui.in_use) +#endif { - // If the X connection is lost then that handler will longjmp - // somewhere else, in that case we will call choose_clipmethod() - // again from there, and this if block won't be executed since - // xterm_dpy will be set to NULL. - xterm_update(); - method = CLIPMETHOD_X11; +#ifdef FEAT_XCLIPBOARD + // x_IOerror_handler() in os_unix.c should set xterm_dpy to NULL + // if we lost connection to the X server. + if (xterm_dpy != NULL) + { + // If the X connection is lost then that handler will + // longjmp somewhere else, in that case we will call + // choose_clipmethod() again from there, and this if block + // won't be executed since xterm_dpy will be set to NULL. + xterm_update(); + method = CLIPMETHOD_X11; + } +#endif } + } + else if (STRCMP(buf, "gui") == 0) + { +#ifdef FEAT_GUI + if (gui.in_use) + method = CLIPMETHOD_GUI; #endif } else @@ -2779,17 +2777,19 @@ exit: /* * Returns name of clipmethod in a statically allocated string. */ - static char * + static char_u * clipmethod_to_str(clipmethod_T method) { switch(method) { case CLIPMETHOD_WAYLAND: - return "wayland"; + return (char_u *)"wayland"; case CLIPMETHOD_X11: - return "x11"; + return (char_u *)"x11"; + case CLIPMETHOD_GUI: + return (char_u *)"gui"; default: - return "none"; + return (char_u *)"none"; } } @@ -2807,29 +2807,13 @@ choose_clipmethod(void) if (method == CLIPMETHOD_FAIL) return e_invalid_argument; -// If GUI is running or we are not on a system with Wayland or X11, then always -// return CLIPMETHOD_NONE. System or GUI clipboard handling always overrides. -#if defined(FEAT_XCLIPBOARD) || defined(FEAT_WAYLAND_CLIPBOARD) -#if defined(FEAT_GUI) - if (gui.in_use) - { -#ifdef FEAT_WAYLAND +#if defined(FEAT_GUI) && defined(FEAT_WAYLAND) + if (method == CLIPMETHOD_GUI) // We only interact with Wayland for the clipboard, we can just deinit // everything. wayland_uninit_client(); #endif - method = CLIPMETHOD_NONE; - goto lose_sel_exit; - } -#endif -#else - // If on a system like windows or macos, then clipmethod is irrelevant, we - // use their way of accessing the clipboard. - method = CLIPMETHOD_NONE; - goto exit; -#endif - // Deinitialize clipboard if there is no way to access clipboard if (method == CLIPMETHOD_NONE) clip_init(FALSE); @@ -2844,24 +2828,16 @@ choose_clipmethod(void) // Disown clipboard if we are switching to a new method if (clipmethod != CLIPMETHOD_NONE && method != clipmethod) { -#if (defined(FEAT_XCLIPBOARD) || defined(FEAT_WAYLAND_CLIPBOARD)) \ - && defined(FEAT_GUI) -lose_sel_exit: -#endif if (clip_star.owned) clip_lose_selection(&clip_star); if (clip_plus.owned) clip_lose_selection(&clip_plus); } -#if !defined(FEAT_XCLIPBOARD) && !defined(FEAT_WAYLAND_CLIPBOARD) -exit: -#endif - clipmethod = method; #ifdef FEAT_EVAL - set_vim_var_string(VV_CLIPMETHOD, (char_u*)clipmethod_to_str(method), -1); + set_vim_var_string(VV_CLIPMETHOD, clipmethod_to_str(method), -1); #endif return NULL; diff --git a/src/gui.c b/src/gui.c index 13ce0523b6..5f7452d9d6 100644 --- a/src/gui.c +++ b/src/gui.c @@ -147,7 +147,7 @@ gui_start(char_u *arg UNUSED) #endif } else - // Reset clipmethod to CLIPMETHOD_NONE + // Reset clipmethod to CLIPMETHOD_GUI choose_clipmethod(); #ifdef FEAT_SOCKETSERVER diff --git a/src/optiondefs.h b/src/optiondefs.h index d716d89952..c582f3586e 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -634,11 +634,11 @@ static struct vimoption options[] = #ifdef FEAT_CLIPBOARD (char_u *)&p_cpm, PV_NONE, did_set_clipmethod, expand_set_clipmethod, # ifdef UNIX - {(char_u *)"wayland,x11", (char_u *)0L} + {(char_u *)"wayland,x11,gui", (char_u *)0L} # elif defined(VMS) - {(char_u *)"x11", (char_u *)0L} + {(char_u *)"x11,gui", (char_u *)0L} # else - {(char_u *)"", (char_u *)0L} + {(char_u *)"gui", (char_u *)0L} # endif #else (char_u *)NULL, PV_NONE, NULL, NULL, diff --git a/src/optionstr.c b/src/optionstr.c index bbae339736..03fdc87836 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -45,7 +45,7 @@ static char *(p_ff_values[]) = {FF_UNIX, FF_DOS, FF_MAC, NULL}; // Note: Keep this in sync with did_set_clipboard() static char *(p_cb_values[]) = {"unnamed", "unnamedplus", "autoselect", "autoselectplus", "autoselectml", "html", "exclude:", NULL}; // Note: Keep this in sync with get_clipmethod() -static char *(p_cpm_values[]) = {"wayland", "x11", NULL}; +static char *(p_cpm_values[]) = {"wayland", "x11", "gui", NULL}; #endif #ifdef FEAT_CRYPT static char *(p_cm_values[]) = {"zip", "blowfish", "blowfish2", diff --git a/src/testdir/test_clipmethod.vim b/src/testdir/test_clipmethod.vim index 9b34658426..a14876832c 100644 --- a/src/testdir/test_clipmethod.vim +++ b/src/testdir/test_clipmethod.vim @@ -1,14 +1,12 @@ " Tests for clipmethod -source util/window_manager.vim - -CheckFeature clipboard_working -CheckFeature xterm_clipboard -CheckFeature wayland_clipboard -CheckUnix +if has('unix') + source util/window_manager.vim +endif " Test if no available clipmethod sets v:clipmethod to none and deinits clipboard func Test_no_clipmethod_sets_v_clipmethod_none() + CheckFeature clipboard_working CheckNotGui set clipmethod= @@ -19,6 +17,9 @@ endfunc " Test if method chosen is in line with clipmethod order func Test_clipmethod_order() CheckNotGui + CheckFeature clipboard_working + CheckFeature xterm_clipboard + CheckFeature wayland_clipboard set cpm=wayland,x11 @@ -62,12 +63,12 @@ func Test_clipmethod_order() call EndWaylandCompositor(l:wayland_display) endfunc -" Test if clipmethod is set to 'none' when gui is started -func Test_clipmethod_is_none_when_gui() +" Test if clipmethod is set to 'gui' when gui is started +func Test_clipmethod_is_gui_when_gui_started() CheckCanRunGui + CheckFeature clipboard_working let lines =<< trim END - set cpm=wayland,x11 call writefile([v:clipmethod != ""], 'Cbdscript') gui -f call writefile([v:clipmethod], 'Cbdscript', 'a') @@ -78,12 +79,15 @@ func Test_clipmethod_is_none_when_gui() call writefile(lines, 'Cbdscript', 'D') call system($'{GetVimCommand()} -S Cbdscript') - call assert_equal(['1', 'none', 'none'], readfile('Cbdscript')) + call assert_equal(['1', 'gui', 'gui'], readfile('Cbdscript')) endfunc " Test if :clipreset switches methods when current one doesn't work func Test_clipreset_switches() CheckNotGui + CheckFeature clipboard_working + CheckFeature xterm_clipboard + CheckFeature wayland_clipboard CheckFeature clientserver CheckXServer CheckWaylandCompositor diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index f6da0a8a60..b17f823e7e 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -529,7 +529,7 @@ func Test_set_completion_string_values() if has('unix') || has('vms') call assert_match('wayland', getcompletion('set clipmethod=', 'cmdline')[1]) else - call assert_match('wayland', getcompletion('set clipmethod=', 'cmdline')[0]) + call assert_match('gui', getcompletion('set clipmethod=', 'cmdline')[0]) endif endif call assert_equal('.', getcompletion('set complete=', 'cmdline')[1]) diff --git a/src/version.c b/src/version.c index f04f283d82..663e3f5ae2 100644 --- a/src/version.c +++ b/src/version.c @@ -724,6 +724,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1652, /**/ 1651, /**/ diff --git a/src/vim.h b/src/vim.h index 79d3add8ac..80547c2656 100644 --- a/src/vim.h +++ b/src/vim.h @@ -2299,6 +2299,7 @@ typedef enum { CLIPMETHOD_NONE, CLIPMETHOD_WAYLAND, CLIPMETHOD_X11, + CLIPMETHOD_GUI } clipmethod_T; // Info about selected text