Skip to content

Commit efa3b1f

Browse files
64-bitmanchrisbra
authored andcommitted
patch 9.1.1927: Wayland: clipboard code too complex
Problem: Wayland: clipboard code too complex Solution: Simplify clipboard related code around W23/W24 (Foxe Chen). Improve Wayland and clipboard related code: - improve documentation - remove unused code - fix error handling - remove warning per Clipboard_T closes: #18794 Signed-off-by: Foxe Chen <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent c11fbe5 commit efa3b1f

File tree

11 files changed

+55
-91
lines changed

11 files changed

+55
-91
lines changed

runtime/doc/options.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*options.txt* For Vim version 9.1. Last change: 2025 Nov 23
1+
*options.txt* For Vim version 9.1. Last change: 2025 Nov 25
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1843,9 +1843,9 @@ A jump table for the options with a short description can be found at |Q_op|.
18431843
option, yank operations (but not delete, change or
18441844
put) will additionally copy the text into register
18451845
'*'. If Wayland is being used and the compositor does
1846-
not support the primary-selection-unstable-v1
1847-
protocol, then the regular selection is used in its
1848-
place. Only available with the |+X11| or
1846+
not support the primary selection then the regular
1847+
selection is used in its place. Only available with
1848+
the |+X11| or
18491849
|+wayland_clipboard| feature. Availability can be
18501850
checked with: >
18511851
if has('unnamedplus')

runtime/doc/wayland.txt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*wayland.txt* For Vim version 9.1. Last change: 2025 Nov 09
1+
*wayland.txt* For Vim version 9.1. Last change: 2025 Nov 25
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -16,7 +16,8 @@ Wayland Protocol Support *wayland*
1616
Functionality such as the clipboard for Wayland requires a seat to use. A
1717
Wayland seat can consist of a keyboard, pointer, and touch device(s). The
1818
seat to use can be set with the 'wlseat' option. Only useful if you use
19-
multiple Wayland seats in the same Wayland session.
19+
multiple Wayland seats in the same Wayland session. If you don't know what
20+
this is means, then it likely does not matter for you.
2021

2122
*wayland-gui*
2223
See |gui-wayland|. Please note that when using the GUI, Vim uses the toolkit
@@ -63,11 +64,18 @@ should be bundled with libwayland on your system: >
6364
If you don't get any match, then please see |wayland-focus-steal| for more
6465
information.
6566

67+
Some compositors that are known to support either or both protocols:
68+
1. KWin (KDE)
69+
2. wlroots based (Sway, Labwc)
70+
3. Niri
71+
4. Hyprland
72+
5. Wayfire
73+
6674
If you come from X11, then the regular Wayland selection is equivalent to the
6775
CLIPBOARD selection in X11, and the primary Wayland selection equates to the
68-
X11 primary selection. Accessing these selections is the same as X11 in Vim,
76+
X11 PRIMARY selection. Accessing these selections is the same as X11 in Vim,
6977
in which the + register is the regular selection, and the * register is the
70-
primary selection, note that your compositor may not support primary
78+
primary selection. Note that your compositor may not support primary
7179
selections, see |wayland-primary-selection| for more details.
7280

7381
*wayland-persist*

src/clipboard.c

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ typedef struct {
100100

101101
clip_wl_selection_T regular;
102102
clip_wl_selection_T primary;
103-
104-
// Array of file descriptors of clients we are sending data to. These should
105-
// be polled for POLLOUT and have the respective callback called for each.
106-
garray_T write_fds;
107103
} clip_wl_T;
108104

109105
// Mime types we support sending and receiving
@@ -172,22 +168,6 @@ clip_init(int can_use)
172168
}
173169
}
174170

175-
static void
176-
clip_init_single(Clipboard_T *cb, int can_use)
177-
{
178-
// No need to init again if cbd is already available
179-
if (can_use && cb->available)
180-
return;
181-
182-
cb->available = can_use;
183-
cb->owned = FALSE;
184-
cb->start.lnum = 0;
185-
cb->start.col = 0;
186-
cb->end.lnum = 0;
187-
cb->end.col = 0;
188-
cb->state = SELECT_CLEARED;
189-
}
190-
191171
/*
192172
* Check whether the VIsual area has changed, and if so try to become the owner
193173
* of the selection, and free any old converted selection we may still have
@@ -2428,7 +2408,7 @@ adjust_clip_reg(int *rp)
24282408
if ((!clip_star.available && *rp == '*') ||
24292409
(!clip_plus.available && *rp == '+'))
24302410
{
2431-
msg_warn_missing_clipboard(!clip_plus.available, !clip_star.available);
2411+
msg_warn_missing_clipboard();
24322412
*rp = 0;
24332413
}
24342414
}
@@ -2874,6 +2854,8 @@ clip_init_wayland(void)
28742854
if (wayland_ct == NULL)
28752855
return FAIL;
28762856

2857+
memset(&clip_wl, 0, sizeof(clip_wl));
2858+
28772859
clip_wl.seat = vwl_connection_get_seat(wayland_ct, (char *)p_wse);
28782860

28792861
if (clip_wl.seat == NULL)
@@ -2891,12 +2873,14 @@ clip_init_wayland(void)
28912873
clip_wl.regular.available = true;
28922874
else
28932875
{
2876+
// Shouldn't happen
28942877
vwl_data_device_manager_discard(clip_wl.regular.manager);
28952878
clip_wl.regular.manager = NULL;
2879+
return FAIL;
28962880
}
28972881
}
28982882

2899-
// If we still don't support the primary selection, find one for it
2883+
// If we still don't support the primary selection, try finding one for it
29002884
// specifically.
29012885
if (!(supported & WAYLAND_SELECTION_PRIMARY))
29022886
{
@@ -2917,10 +2901,12 @@ clip_init_wayland(void)
29172901
}
29182902
}
29192903
}
2920-
else if (clip_wl.regular.available)
2904+
2905+
if (clip_wl.regular.available && !clip_wl.primary.available)
29212906
{
29222907
// The protocol supports both regular and primary selections, just use
2923-
// one data device manager and one data device.
2908+
// one data device manager and one data device. Or the primary selection
2909+
// is not supported, make it point to the regular selection instead.
29242910
clip_wl.primary.available = true;
29252911
clip_wl.primary.manager = clip_wl.regular.manager;
29262912
clip_wl.primary.device = clip_wl.regular.device;
@@ -3435,7 +3421,7 @@ clip_wl_owner_exists(Clipboard_T *cbd)
34353421
* depending on the order of values in str.
34363422
*/
34373423
static clipmethod_T
3438-
get_clipmethod(char_u *str, bool *plus UNUSED, bool *star UNUSED)
3424+
get_clipmethod(char_u *str)
34393425
{
34403426
int len = (int)STRLEN(str) + 1;
34413427
char_u *buf = alloc(len);
@@ -3460,11 +3446,7 @@ get_clipmethod(char_u *str, bool *plus UNUSED, bool *star UNUSED)
34603446
{
34613447
#ifdef FEAT_WAYLAND_CLIPBOARD
34623448
if (clip_wl.regular.available || clip_wl.primary.available)
3463-
{
34643449
method = CLIPMETHOD_WAYLAND;
3465-
*plus = clip_wl.regular.available;
3466-
*star = clip_wl.primary.available;
3467-
}
34683450
#endif
34693451
}
34703452
}
@@ -3485,7 +3467,6 @@ get_clipmethod(char_u *str, bool *plus UNUSED, bool *star UNUSED)
34853467
// xterm_dpy will be set to NULL.
34863468
xterm_update();
34873469
method = CLIPMETHOD_X11;
3488-
*plus = *star = TRUE;
34893470
}
34903471
#endif
34913472
}
@@ -3534,8 +3515,7 @@ clipmethod_to_str(clipmethod_T method)
35343515
char *
35353516
choose_clipmethod(void)
35363517
{
3537-
bool regular = false, primary = false;
3538-
clipmethod_T method = get_clipmethod(p_cpm, &regular, &primary);
3518+
clipmethod_T method = get_clipmethod(p_cpm);
35393519

35403520
if (method == CLIPMETHOD_FAIL)
35413521
return e_invalid_argument;
@@ -3569,10 +3549,8 @@ choose_clipmethod(void)
35693549
// If we have a clipmethod that works now, then initialize clipboard
35703550
else if (clipmethod == CLIPMETHOD_NONE && method != CLIPMETHOD_NONE)
35713551
{
3572-
clip_init_single(&clip_plus, regular);
3573-
clip_init_single(&clip_star, primary);
3574-
clip_plus.did_warn = false;
3575-
clip_star.did_warn = false;
3552+
clip_init(TRUE);
3553+
did_warn_clipboard = false;
35763554
}
35773555
// Disown clipboard if we are switching to a new method
35783556
else if (clipmethod != CLIPMETHOD_NONE && method != clipmethod)
@@ -3590,8 +3568,8 @@ choose_clipmethod(void)
35903568
if (!gui.in_use)
35913569
#endif
35923570
{
3593-
clip_init_single(&clip_plus, regular);
3594-
clip_init_single(&clip_star, primary);
3571+
clip_init(TRUE);
3572+
did_warn_clipboard = false;
35953573
}
35963574
}
35973575

src/globals.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,6 +2067,9 @@ EXTERN char_u showcmd_buf[SHOWCMD_BUFLEN];
20672067
EXTERN int p_tgc_set INIT(= FALSE);
20682068
#endif
20692069

2070+
// If we've already warned about missing/unavailable clipboard
2071+
EXTERN bool did_warn_clipboard INIT(= FALSE);
2072+
20702073
#ifdef FEAT_CLIPBOARD
20712074
EXTERN clipmethod_T clipmethod INIT(= CLIPMETHOD_NONE);
20722075
#endif
@@ -2079,6 +2082,9 @@ EXTERN char *wayland_display_name INIT(= NULL);
20792082
// Special mime type used to identify selection events that came from us setting
20802083
// the selection. Is in format of "application/x-vim-instance-<pid>" where <pid>
20812084
// is the PID of the Vim process. Set in main.c
2085+
//
2086+
// This is more reliable than just checking if our data source is non-NULL, as
2087+
// that may be subject to data races in the Wayland protocol.
20822088
EXTERN char wayland_vim_special_mime[
20832089
sizeof("application/x-vim-instance-") + NUMBUFLEN - 1]; // Includes NUL
20842090

src/message.c

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4177,37 +4177,17 @@ msg_advance(int col)
41774177
* Warn about missing Clipboard Support
41784178
*/
41794179
void
4180-
msg_warn_missing_clipboard(bool plus UNUSED, bool star UNUSED)
4180+
msg_warn_missing_clipboard(void)
41814181
{
4182-
#ifndef FEAT_CLIPBOARD
4183-
static bool did_warn;
4184-
4185-
if (!global_busy && !did_warn)
4182+
if (!global_busy && !did_warn_clipboard)
41864183
{
4187-
msg(_("W24: Clipboard register not available. See :h W24"));
4188-
did_warn = true;
4189-
}
4184+
#ifdef FEAT_CLIPBOARD
4185+
msg(_("W23: Clipboard register not available, using register 0"));
41904186
#else
4191-
if (!global_busy)
4192-
{
4193-
if (plus && star && !clip_plus.did_warn && !clip_star.did_warn)
4194-
{
4195-
msg(_("W23: Clipboard register not available, using register 0"));
4196-
clip_plus.did_warn = true;
4197-
clip_star.did_warn = true;
4198-
}
4199-
else if (plus && !clip_plus.did_warn)
4200-
{
4201-
msg(_("W23: Clipboard register + not available, using register 0"));
4202-
clip_plus.did_warn = true;
4203-
}
4204-
else if (star && !clip_star.did_warn)
4205-
{
4206-
msg(_("W23: Clipboard register * not available, using register 0"));
4207-
clip_star.did_warn = true;
4208-
}
4209-
}
4187+
msg(_("W24: Clipboard register not available. See :h W24"));
42104188
#endif
4189+
did_warn_clipboard = TRUE;
4190+
}
42114191
}
42124192

42134193
#if defined(FEAT_CON_DIALOG)

src/po/vim.pot

Lines changed: 5 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/proto/message.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void give_warning(char_u *message, int hl);
7474
void give_warning_with_source(char_u *message, int hl, int with_source);
7575
void give_warning2(char_u *message, char_u *a1, int hl);
7676
void msg_advance(int col);
77-
void msg_warn_missing_clipboard(bool plus, bool star);
77+
void msg_warn_missing_clipboard(void);
7878
int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd);
7979
int vim_dialog_yesno(int type, char_u *title, char_u *message, int dflt);
8080
int vim_dialog_yesnocancel(int type, char_u *title, char_u *message, int dflt);

src/register.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ valid_yank_reg(
204204
else if (regname == '*' || regname == '+')
205205
{
206206
// Warn about missing clipboard support once
207-
msg_warn_missing_clipboard(true, true);
207+
msg_warn_missing_clipboard();
208208
return FALSE;
209209
}
210210
#endif
@@ -1189,7 +1189,7 @@ op_yank(oparg_T *oap, int deleting, int mess)
11891189
(!clip_plus.available && oap->regname == '+'))
11901190
{
11911191
oap->regname = 0;
1192-
msg_warn_missing_clipboard(!clip_plus.available, !clip_star.available);
1192+
msg_warn_missing_clipboard();
11931193
}
11941194
#endif
11951195

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,8 @@ static char *(features[]) =
729729

730730
static int included_patches[] =
731731
{ /* Add new patch number below this line */
732+
/**/
733+
1927,
732734
/**/
733735
1926,
734736
/**/

src/vim.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,8 +2364,6 @@ typedef struct
23642364
# ifdef FEAT_GUI_HAIKU
23652365
// No clipboard at the moment. TODO?
23662366
# endif
2367-
// If we've already warned about missing/unavailable clipboard
2368-
bool did_warn;
23692367
} Clipboard_T;
23702368
#else
23712369
typedef int Clipboard_T; // This is required for the prototypes.

0 commit comments

Comments
 (0)