0
0
mirror of https://github.com/vim/vim.git synced 2025-10-24 08:54:47 -04:00

patch 9.1.1725: Wayland code can be improved

Problem:  Wayland code can be improved
Solution: Refactor Wayland Clipboard code (Foxe Chen)

This refactor makes the Wayland codebase less convoluted:
- Move clipboard code in wayland.c to clipboard.c
- Use C99 bool type
- Properly poll the Wayland display file descriptor
- Instead of checking if the data source is not NULL in order to
  determine if a selection event comes from us, use a special mime type to
  identify selection events coming from ourselves. The problem with the
  previous approach is that race conditions may occur.
- Put the focus stealing code under a new feature "wayland_focus_steal"
- Use ELAPSED_* macros instead of gettimeofday()
- Pass tests
- Reimplement commented out code
- Update docs
- Make Wayland clipboard behaviour more in line with X11 when connection is lost
- add missing malloc checks and possible memory leaks + refactored some
  tests.

closes: #18139

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-09-01 20:52:44 +02:00
committed by Christian Brabandt
parent 6a2d0496a1
commit f50504a87b
29 changed files with 2613 additions and 2684 deletions

View File

@@ -21,12 +21,17 @@ let s:old_wayland_display = $WAYLAND_DISPLAY
" every test function
func s:PreTest()
let $WAYLAND_DISPLAY=s:global_wayland_display
exe 'wlrestore ' .. $WAYLAND_DISPLAY
" Always reconnect so we have a clean state each time and clear both
" selections.
call system('wl-copy -c')
call system('wl-copy -p -c')
exe 'wlrestore! ' .. $WAYLAND_DISPLAY
set cpm=wayland
endfunc
func s:SetupFocusStealing()
CheckFeature wayland_focus_steal
if !executable('wayland-info')
throw "Skipped: wayland-info program not available"
endif
@@ -35,7 +40,7 @@ func s:SetupFocusStealing()
" seat, so we must use the user's existing Wayland session if they are in one.
let $WAYLAND_DISPLAY = s:old_wayland_display
exe 'wlrestore ' .. $WAYLAND_DISPLAY
exe 'wlrestore! ' .. $WAYLAND_DISPLAY
" Check if we have keyboard capability for seat
if system("wayland-info -i wl_seat | grep capabilities") !~? "keyboard"
@@ -50,17 +55,14 @@ func s:UnsetupFocusStealing()
unlet $VIM_WAYLAND_FORCE_FS
endfunc
" Need X connection for tests that use client server communication
func s:CheckXConnection()
CheckFeature x11
try
call remote_send('xxx', '')
catch
if v:exception =~ 'E240:'
thrclientserverow 'Skipped: no connection to the X server'
func s:CheckClientserver()
CheckFeature clientserver
if has('socketserver') && !has('x11')
if v:servername == ""
call remote_startserver('VIMSOCKETSERVER')
endif
" ignore other errors
endtry
endif
endfunc
func s:EndRemoteVim(name, job)
@@ -77,11 +79,7 @@ endfunc
func Test_wayland_startup()
call s:PreTest()
call s:CheckXConnection()
if v:servername == ""
call remote_startserver('VIMSOCKETSERVER')
endif
call s:CheckClientserver()
let l:name = 'WLVIMTEST'
let l:cmd = GetVimCommand() .. ' --servername ' .. l:name
@@ -169,18 +167,12 @@ func Test_wayland_connection_lost()
call EndWaylandCompositor(l:wayland_display)
call assert_equal('', getreg('+'))
call assert_fails('put +', 'E353:')
call assert_fails('yank +', 'E1548:')
endfunc
" Basic paste tests
func Test_wayland_paste()
call s:PreTest()
" Prevent 'Register changed while using it' error, guessing this works because
" it makes Vim lose the selection?
wlrestore!
" Regular selection
new
@@ -219,8 +211,6 @@ endfunc
func Test_wayland_yank()
call s:PreTest()
wlrestore!
new
call setline(1, 'testing')
@@ -265,7 +255,8 @@ func Test_wayland_mime_types_correct()
\ 'text/plain',
\ 'UTF8_STRING',
\ 'STRING',
\ 'TEXT'
\ 'TEXT',
\ 'application/x-vim-instance-' .. getpid()
\ ]
call setreg('+', 'text', 'c')
@@ -360,7 +351,7 @@ endfunc
" Test if autoselect option in 'clipboard' works properly for Wayland
func Test_wayland_autoselect_works()
call s:PreTest()
call s:CheckXConnection()
call s:CheckClientserver()
let l:lines =<< trim END
set cpm=wayland
@@ -376,10 +367,6 @@ func Test_wayland_autoselect_works()
call writefile(l:lines, 'Wltester', 'D')
if v:servername == ""
call remote_startserver('VIMSOCKETSERVER')
endif
let l:name = 'WLVIMTEST'
let l:cmd = GetVimCommand() .. ' -S Wltester --servername ' .. l:name
let l:job = job_start(cmd, {'stoponexit': 'kill', 'out_io': 'null'})
@@ -408,24 +395,13 @@ func Test_wayland_autoselect_works()
eval remote_send(l:name, "\<Esc>:qa!\<CR>")
try
call WaitForAssert({-> assert_equal("dead", job_status(l:job))})
finally
if job_status(l:job) != 'dead'
call assert_report('Vim instance did not exit')
call job_stop(l:job, 'kill')
endif
endtry
call s:EndRemoteVim(l:name, l:job)
endfunc
" Check if the -Y flag works properly
func Test_no_wayland_connect_cmd_flag()
call s:PreTest()
call s:CheckXConnection()
if v:servername == ""
call remote_startserver('VIMSOCKETSERVER')
endif
call s:CheckClientserver()
let l:name = 'WLFLAGVIMTEST'
let l:cmd = GetVimCommand() .. ' -Y --servername ' .. l:name
@@ -449,25 +425,13 @@ func Test_no_wayland_connect_cmd_flag()
call WaitForAssert({-> assert_equal('',
\ remote_expr(l:name, 'v:wayland_display'))})
eval remote_send(l:name, "\<Esc>:qa!\<CR>")
try
call WaitForAssert({-> assert_equal("dead", job_status(l:job))})
finally
if job_status(l:job) != 'dead'
call assert_report('Vim instance did not exit')
call job_stop(l:job, 'kill')
endif
endtry
call s:EndRemoteVim(l:name, l:job)
endfunc
" Test behaviour when we do something like suspend Vim
func Test_wayland_become_inactive()
call s:PreTest()
call s:CheckXConnection()
if v:servername == ""
call remote_startserver('VIMSOCKETSERVER')
endif
call s:CheckClientserver()
let l:name = 'WLLOSEVIMTEST'
let l:cmd = GetVimCommand() .. ' --servername ' .. l:name
@@ -489,15 +453,7 @@ func Test_wayland_become_inactive()
call WaitForAssert({-> assert_equal("Nothing is copied\n",
\ system('wl-paste -n'))})
eval remote_send(l:name, "\<Esc>:qa!\<CR>")
try
call WaitForAssert({-> assert_equal("dead", job_status(l:job))})
finally
if job_status(l:job) != 'dead'
call assert_report('Vim instance did not exit')
call job_stop(l:job, 'kill')
endif
endtry
call s:EndRemoteVim(l:name, l:job)
endfunc
" Test wlseat option
@@ -528,6 +484,7 @@ endfunc
" Test focus stealing
func Test_wayland_focus_steal()
CheckFeature wayland_focus_steal
call s:PreTest()
call s:SetupFocusStealing()
@@ -553,17 +510,13 @@ endfunc
" Test when environment is not suitable for Wayland
func Test_wayland_bad_environment()
call s:PreTest()
call s:CheckXConnection()
call s:CheckClientserver()
unlet $WAYLAND_DISPLAY
let l:old = $XDG_RUNTIME_DIR
unlet $XDG_RUNTIME_DIR
if v:servername == ""
call remote_startserver('VIMSOCKETSERVER')
endif
let l:name = 'WLVIMTEST'
let l:cmd = GetVimCommand() .. ' --servername ' .. l:name
let l:job = job_start(cmd, {
@@ -577,15 +530,7 @@ func Test_wayland_bad_environment()
call WaitForAssert({-> assert_equal('',
\ remote_expr(l:name, 'v:wayland_display'))})
eval remote_send(l:name, "\<Esc>:qa!\<CR>")
try
call WaitForAssert({-> assert_equal("dead", job_status(l:job))})
finally
if job_status(l:job) != 'dead'
call assert_report('Vim instance did not exit')
call job_stop(l:job, 'kill')
endif
endtry
call s:EndRemoteVim(l:name, l:job)
let $XDG_RUNTIME_DIR = l:old
endfunc
@@ -612,7 +557,11 @@ func Test_wayland_lost_selection()
call assert_equal('regular', getreg('+'))
call assert_equal('primary', getreg('*'))
" Test focus stealing
endfunc
" Same as above but for the focus stealing method
func Test_wayland_lost_selection_focus_steal()
call s:PreTest()
call s:SetupFocusStealing()
call setreg('+', 'regular')
@@ -636,14 +585,14 @@ func Test_wayland_lost_selection()
call s:UnsetupFocusStealing()
endfunc
" Test when there are no supported mime types for the selecftion
" Test when there are no supported mime types for the selection
func Test_wayland_no_mime_types_supported()
call s:PreTest()
wlrestore!
call system('wl-copy tester')
call assert_equal('tester', getreg('+'))
call system('wl-copy -t image/png testing')
call assert_equal('', getreg('+'))
call assert_fails('put +', 'E353:')
endfunc
@@ -652,28 +601,17 @@ endfunc
func Test_wayland_handle_large_data()
call s:PreTest()
call writefile([''], 'data_file', 'D')
call writefile([''], 'data_file_cmp', 'D')
call system('yes c | head -5000000 > data_file') " ~ 10 MB
call system('wl-copy -t TEXT < data_file')
let l:file = tempname()
let l:contents = repeat('c', 1000000) " ~ 1 MB
edit data_file_cmp
call writefile([l:contents], l:file, 'b')
call system('cat ' .. l:file .. ' | wl-copy -t TEXT')
put! +
call assert_equal(l:contents, getreg('+'))
write
call setreg('+', l:contents, 'c')
call system('truncate -s -1 data_file_cmp') " Remove newline at the end
call system('cmp --silent data_file data_file_cmp')
call assert_equal(0, v:shell_error)
call feedkeys('gg0v$G"+yy', 'x')
call system('wl-paste -n -t TEXT > data_file')
call system('cmp --silent data_file data_file_cmp')
call assert_equal(0, v:shell_error)
bw!
call assert_equal(l:contents, system('wl-paste -n -t TEXT'))
endfunc
" vim: shiftwidth=2 sts=2 expandtab