patch 9.1.1652: cannot determine non-X11/Wayland clipmethods

Problem:  Cannot determine non-X11/Wayland clipmethods
Solution: Add the "gui" value to the 'clipmethod' option (Foxe Chen)

closes: #18006

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Foxe Chen
2025-08-18 22:09:27 +02:00
committed by Christian Brabandt
parent 96b2154b73
commit 3e152c76ad
12 changed files with 169 additions and 182 deletions

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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",

View File

@ -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

View File

@ -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])

View File

@ -724,6 +724,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1652,
/**/
1651,
/**/

View File

@ -2299,6 +2299,7 @@ typedef enum {
CLIPMETHOD_NONE,
CLIPMETHOD_WAYLAND,
CLIPMETHOD_X11,
CLIPMETHOD_GUI
} clipmethod_T;
// Info about selected text