lervag / vimtex

VimTeX: A modern Vim and neovim filetype plugin for LaTeX files.
MIT License
5.54k stars 390 forks source link

Zathura forward synctex steals vim window focus #2733

Closed user202729 closed 1 year ago

user202729 commented 1 year ago

Is your feature request related to a problem? Please describe it.

As in the title.

Describe the solution you'd like

Not sure if there's a good solution, but maybe implement a similar hack as in the blog post below can work...?

https://www.ejmastnak.com/tutorials/vim-latex/pdf-reader/#refocus-vim-after-forward-search also describe a similar problem and use a xdotool hack.

I'm thinking maybe implement something as the following.

diff --git a/autoload/vimtex/options.vim b/autoload/vimtex/options.vim
index 34d0a3f..880f84e 100644
--- a/autoload/vimtex/options.vim
+++ b/autoload/vimtex/options.vim
@@ -480,6 +480,7 @@ function! vimtex#options#init() abort " {{{1
   call s:init_option('vimtex_view_texshop_activate', 0)
   call s:init_option('vimtex_view_texshop_sync', 0)
   call s:init_option('vimtex_view_zathura_options', '')
+  call s:init_option('vimtex_view_zathura_return_focus', 0)
   call s:init_option('vimtex_view_zathura_check_libsynctex', 1)

   " Fallback option
diff --git a/autoload/vimtex/view/zathura.vim b/autoload/vimtex/view/zathura.vim
index 3bb4e79..2a34254 100644
--- a/autoload/vimtex/view/zathura.vim
+++ b/autoload/vimtex/view/zathura.vim
@@ -100,7 +100,25 @@ function! s:viewer._forward_search(outfile) dict abort " {{{1
   let self.cmd_forward_search
         \ = vimtex#view#zathura#cmdline(a:outfile, self.has_synctex, 0)

+  if g:vimtex_view_zathura_return_focus
+    let l:activewindow = vimtex#jobs#capture('xdotool getactivewindow')[0]
+    if l:activewindow == ''
+      echoerr "Window manager does not support EWMH/_NET_ACTIVE_WINDOW, consider disabling g:vimtex_view_zathura_return_focus"
+    endif
+  endif
   call vimtex#jobs#run(self.cmd_forward_search)
+  if g:vimtex_view_zathura_return_focus && l:activewindow != ''
+    let l:num_iteration = 0
+    while l:activewindow == vimtex#jobs#capture('xdotool getactivewindow')[0]
+      if l:num_iteration >= 20  " hardcoded...? equivalent to 200ms
+        echoerr "Zathura doesn't seem to take focus on synctex-forward, consider disabling g:vimtex_view_zathura_return_focus"
+        break
+      endif
+      sleep 10m  " wait until zathura takes focus (apparently this is necessary)
+      let l:num_iteration += 1
+    endwhile
+    call vimtex#jobs#run('xdotool windowactivate '..l:activewindow)
+  endif
 endfunction

 " }}}1

We're already relying on xdotool anyway so it will probably be fine.

It may be a good idea to make this a feature that is disabled by default unless the user manually set some flag though (as well as implementing a timeout for the wait), as time not sure if zathura will get the focus on synctex-forward in all window managers; as well as getactivewindow/windowactivate will not work at all on window managers without ewmh.

(side note, I only notice zathura taking focus when I enable ewmh. Using windowfocus/getwindowfocus works in xmonad with ewmh disabled as well, but it has some other quirks it's best to use getactivewindow/windowactivate instead as suggested by xdotool documentation)

Meanwhile some other user describe that they get the opposite problem https://tex.stackexchange.com/questions/207889/how-to-set-up-forward-inverse-searches-with-auctex-and-zathura so I'm not sure what's going on, maybe it depends on window manager quirks which is not good for maintenance...

ejmastnak commented 1 year ago

Just chiming in to say that if this feature were to be added to VimTeX, I agree with @user202729 that I think it would need to be opt-in with a configurable delay time (i.e. the 10 ms in the sleep 10m above) before attempting refocusing Vim.

Also, as an aside, @lervag I'm realizing far too many of the articles in the blog series suggest ftplugin/tex.vim were e.g. plugin/vimtex.vim would be a better option. I'll fix this in the next day or two. This is done now: https://www.ejmastnak.com/tutorials/vim-latex/vimtex/#configuration; any suggestions/advice welcome!

lervag commented 1 year ago

This is already supported by use of xdotool. Use something like this:

autocmd User VimtexEventView call b:vimtex.viewer.xdo_focus_vim()

The relevant function is here:

https://github.com/lervag/vimtex/blob/e80108757cd03345be263c87009e68b7ab282311/autoload/vimtex/view/_template.vim#L238-L272

Also, see :help VimtexEventView.

lervag commented 1 year ago

Also: xdotool only works on Xwin and I would not be surprised if there can be difference between different dinwod managers here.

I will not add this as a feature behind an option. Instead, it is available by use of user customization by use of events. It could probably be better documented, though...

lervag commented 1 year ago

Also, as an aside, @lervag I'm realizing far too many of the articles in the blog series suggest ftplugin/tex.vim were e.g. plugin/vimtex.vim would be a better option. ~I'll fix this in the next day or two.~ This is done now: https://www.ejmastnak.com/tutorials/vim-latex/vimtex/#configuration; any suggestions/advice welcome!

Great, thanks! You are right, I've been "plagued" (hyperbole!) with issues where people are using ftplugin/tex.vim without really knowing the consequences. I think your blog posts are really reaching out, so having them updated is very good!

ejmastnak commented 1 year ago

Great, thanks!

Absolutely, should have done it sooner!

You are right, I've been "plagued" (hyperbole!) with issues where people are using ftplugin/tex.vim without really knowing the consequences. I think your blog posts are really reaching out, so having them updated is very good!

Yes, I've noticed this myself and apologize for the inconvenience caused. I'm by all means commited to keeping the blog posts up to date and reflecting best practice; if a similar situation comes up in the future and you notice before I do please don't hesitate to let me know.

lervag commented 1 year ago

You are right, I've been "plagued" (hyperbole!) with issues where people are using ftplugin/tex.vim without really knowing the consequences. I think your blog posts are really reaching out, so having them updated is very good!

Yes, I've noticed this myself and apologize for the inconvenience caused. I'm by all means commited to keeping the blog posts up to date and reflecting best practice; if a similar situation comes up in the future and you notice before I do please don't hesitate to let me know.

No problem, and thanks; I'll let you know if I should notice anything!

user202729 commented 1 year ago

One thing while I use the approach above, if I do <c-o>\lv in Insert mode, the line

      call feedkeys("\<c-l>", 'tn')

will insert a ^L character (because it's insert mode) instead of redraw the window. Can we use something like redraw! or normal! ^L instead? (personally I don't really see any issue if I just comment that line out also)

lervag commented 1 year ago

I don't remember why that line was added. But I guess there's an implicit assumption that most Vim'ers tend to stay in normal mode by default, in which case it should not pose the problem you raise here?

In any case, I agree that it should likely not be necessary, so I've removed it. If I'm wrong and it actually should be there, then someone will probably open an issue and I'll fix it with a comment that explains why.

lervag commented 1 year ago

Can I close the issue as resolved, then?

user202729 commented 1 year ago

Note that it was explicitly introduced in fb06ad181a800fbfa14d440d336fe71359140aad which was in https://github.com/lervag/vimtex/pull/1069

I test using xterm which does update the cursor position, although without the ctrl-L it's slower.

It's not very clear to include the <c-l> in xdo_focus_vim itself, because in some cases we want to focus vim without the cursor location being automatically changed (e.g. here)

lervag commented 1 year ago

The <c-l> is only about performing a refresh. But we could probably solve it with normal! <c-l> or simply a redraw!?

user202729 commented 1 year ago

Indeed. The linked pull request says redraw! does not work, not sure about normal!, and I don't have Konsole to test for now.

lervag commented 1 year ago

Neither do I. But I guess we can hope this is no longer an issue after 5-6 years of updates to neovim and Vim?

user202729 commented 1 year ago

Meanwhile maybe it's a good idea if @ejmastnak update the blog to call the already-provided function by vimtex (it's probably less hacky -- does not rely on the exact timing...?) It assumes the interface is "public API" i.e. unlikely to change later though.