diff --git a/autoload/vimtex/view/_template.vim b/autoload/vimtex/view/_template.vim index f9762fb7f5..d2d6f303d1 100644 --- a/autoload/vimtex/view/_template.vim +++ b/autoload/vimtex/view/_template.vim @@ -132,17 +132,20 @@ endfunction function! s:viewer.xdo_get_id() dict abort " {{{1 if !self.xdo_check() | return 0 | endif - if self.xwin_id <= 0 - " Allow some time for the viewer to start properly - sleep 500m + if self.xwin_id > 0 | return self.xwin_id | endif - let l:xwin_ids = vimtex#jobs#capture('xdotool search --class ' . self.name) - if len(l:xwin_ids) == 0 - call vimtex#log#warning('Viewer cannot find ' . self.name . ' window ID!') - let self.xwin_id = 0 - else - let self.xwin_id = l:xwin_ids[-1] - endif + " Allow some time for the viewer to start properly + sleep 500m + + " Try finding viewer's window ID, first attempting search by PID, then by + " window name, and finally, as a fallback, by window class. + for l:method in ['pid', 'name', 'class'] + execute "let self.xwin_id = self.xdo_find_win_id_by_" . l:method . "()" + if self.xwin_id > 0 | break | endif + endfor + + if self.xwin_id <= 0 + call vimtex#log#warning('Viewer cannot find ' . self.name . ' window ID!') endif return self.xwin_id @@ -152,7 +155,7 @@ endfunction function! s:viewer.xdo_exists() dict abort " {{{1 if !self.xdo_check() | return v:false | endif - " If xwin_id is already set, check if it still exists + " If xwin_id is already set, check if a matching viewer window still exists if self.xwin_id > 0 let xwin_ids = vimtex#jobs#capture('xdotool search --class ' . self.name) if index(xwin_ids, self.xwin_id) < 0 @@ -162,31 +165,61 @@ function! s:viewer.xdo_exists() dict abort " {{{1 " If xwin_id is unset, check if matching viewer windows exist if self.xwin_id == 0 - let l:pid = has_key(self, 'get_pid') ? self.get_pid() : 0 - if l:pid > 0 - let xwin_ids = vimtex#jobs#capture( - \ 'xdotool search --all --pid ' . l:pid - \ . ' --name ' . fnamemodify(self.out(), ':t')) - let self.xwin_id = get(xwin_ids, 0) - else - let xwin_ids = vimtex#jobs#capture( - \ 'xdotool search --name ' . fnamemodify(self.out(), ':t')) - let ids_already_used = filter(map( - \ deepcopy(vimtex#state#list_all()), - \ {_, x -> get(get(x, 'viewer', {}), 'xwin_id')}), - \ 'v:val > 0') - for id in xwin_ids - if index(ids_already_used, id) < 0 - let self.xwin_id = id - break - endif - endfor + + " First try searching for window ID by viewer PID... + let self.xwin_id = self.xdo_find_win_id_by_pid() + + " ...then potentially search by the viewer's window name as a fallback. + if self.xwin_id > 0 + let self.xwin_id = self.xdo_find_win_id_by_name() endif endif return self.xwin_id > 0 endfunction +" }}}1 +function! s:viewer.xdo_find_win_id_by_class() dict abort " {{{1 + " Attempts to find the viewer's X window ID using `xdotool` search by window + " class. Returns the viewer's window ID if one is found, and `0` otherwise. + let l:xwin_ids = vimtex#jobs#capture('xdotool search --class ' . self.name) + return empty(l:xwin_ids) ? 0 : l:xwin_ids[-1] +endfunction + +" }}}1 +function! s:viewer.xdo_find_win_id_by_name() dict abort " {{{1 + " Attempts to find the viewer's X window ID using `xdotool` search by window + " name (i.e. the string in the window titlebar). Returns the viewer's window + " ID if one is found, and `0` otherwise. + let l:xwin_ids = vimtex#jobs#capture( + \ 'xdotool search --name ' . fnamemodify(self.out(), ':t')) + let ids_already_used = filter(map( + \ deepcopy(vimtex#state#list_all()), + \ {_, x -> get(get(x, 'viewer', {}), 'xwin_id')}), + \ 'v:val > 0') + for id in l:xwin_ids + if index(ids_already_used, id) < 0 + return id + endif + endfor + " If loop exits with no window ID found + return 0 +endfunction + +" }}}1 +function! s:viewer.xdo_find_win_id_by_pid() dict abort " {{{1 + " Attempts to find the viewer's X window ID using `xdotool` search by the + " viewer's process ID. Returns the viewer's window ID if one is found, and `0` + " otherwise. + let l:pid = has_key(self, 'get_pid') ? self.get_pid() : 0 + if l:pid <= 0 | return 0 | endif + + let xwin_ids = vimtex#jobs#capture( + \ 'xdotool search --all --pid ' . l:pid + \ . ' --name ' . fnamemodify(self.out(), ':t')) + return get(xwin_ids, 0) +endfunction + " }}}1 function! s:viewer.xdo_send_keys(keys) dict abort " {{{1 if !self.xdo_check() || empty(a:keys) || self.xwin_id <= 0 | return | endif