diff --git a/src/gui/runtime/doc/nvim_gui_shim.txt b/src/gui/runtime/doc/nvim_gui_shim.txt index 5e7497212..fc3491bb9 100644 --- a/src/gui/runtime/doc/nvim_gui_shim.txt +++ b/src/gui/runtime/doc/nvim_gui_shim.txt @@ -86,6 +86,22 @@ GuiWindowOpacity Set window opacity. Takes a single argument, a double in the range 0.0 to 1.0 (fully opaque). This capability might not be supported in some platforms. + *GuiClipboard* +GuiClipboard Enable or disable the native GUI clipboard. + When enabled, neovim will use the GUI as its clipboard + provider. + + To enable, +> + GuiClipboard 1 +< + to disable pass 0 to the command +> + GuiClipboard 0 +< + After disabling the GUI clipboard, neovim will select + a clipboard provider from the available options. + ============================================================================== 2. GUI variables @@ -208,6 +224,7 @@ menu can be mapped to right click events in ginit.vim, e.g. nnoremap :call GuiShowContextMenu() inoremap :call GuiShowContextMenu() vnoremap :call GuiShowContextMenu()gv +< ============================================================================== 4. Internals diff --git a/src/gui/runtime/plugin/nvim_gui_shim.vim b/src/gui/runtime/plugin/nvim_gui_shim.vim index 67ca4e316..1de6cb23f 100644 --- a/src/gui/runtime/plugin/nvim_gui_shim.vim +++ b/src/gui/runtime/plugin/nvim_gui_shim.vim @@ -142,6 +142,8 @@ function GuiName() return get(info.client, 'name', '') endfunction +let s:ui_clipboard_enabled = 0 + function s:ui_has_clipboard(idx, ui_info) if has_key(a:ui_info, 'chan') == 0 return 0 @@ -158,45 +160,99 @@ function s:ui_has_clipboard(idx, ui_info) endif endfunction -"Enable a GUI provided clipboard -function GuiClipboard() +function s:reload_clipboard_provider() + " We need to reload the neovim clipboard provider here so it picks up on + " g:clipboard. In older versions of neovim (<=0.3.8) the provider would + " short circuit if a working clipboard was not available. After 0.3.8 + " the provider should not short circuit, and unsetting + " g:loaded_clipboard_provider will enable a full reload of the provider. + " + " TLDR; source this to reinitialize the clipboard provider, this may not + " work + unlet! g:loaded_clipboard_provider + runtime autoload/provider/clipboard.vim +endfunction + +function s:disable_custom_clipboard() + if exists("g:clipboard") + unlet g:clipboard + endif + call s:reload_clipboard_provider() +endfunction + +"Enable a GUI clipboard +function s:SetupGuiClipboard(silent) if !has("nvim-0.3.2") - echoerr "UI clipboard requires nvim >=0.3.2" + if a:silent == 0 + echoerr "UI clipboard requires nvim >=0.3.2" + endif return endif let uis = nvim_list_uis() call filter(uis, funcref('s:ui_has_clipboard')) if len(uis) == 0 - echoerr "No UIs with clipboard support are attached" + if a:silent == 0 + echoerr "No UIs with clipboard support are attached" + end + call s:disable_custom_clipboard() return endif let ui_chan = uis[-1].chan - let g:clipboard = { - \ 'name': 'custom', - \ 'copy': { - \ '+': {lines, regtype -> rpcnotify(ui_chan, 'Gui', 'SetClipboard', lines, regtype, '+')}, - \ '*': {lines, regtype -> rpcnotify(ui_chan, 'Gui', 'SetClipboard', lines, regtype, '*')}, - \ }, - \ 'paste': { - \ '+': {-> rpcrequest(ui_chan, 'Gui', 'GetClipboard', '+')}, - \ '*': {-> rpcrequest(ui_chan, 'Gui', 'GetClipboard', '*')}, - \ }, - \ } + let g:clipboard = { + \ 'name': 'custom', + \ 'copy': { + \ '+': {lines, regtype -> rpcnotify(ui_chan, 'Gui', 'SetClipboard', lines, regtype, '+')}, + \ '*': {lines, regtype -> rpcnotify(ui_chan, 'Gui', 'SetClipboard', lines, regtype, '*')}, + \ }, + \ 'paste': { + \ '+': {-> rpcrequest(ui_chan, 'Gui', 'GetClipboard', '+')}, + \ '*': {-> rpcrequest(ui_chan, 'Gui', 'GetClipboard', '*')}, + \ }, + \ } + + call s:reload_clipboard_provider() +endfunction - " We need to reload the neovim clipboard provider here so it picks up on - " g:clipboard. In older versions of neovim (<=0.3.8) the provider would - " short circuit if a working clipboard was not available. After 0.3.8 - " the provider should not short circuit, andunsetting - " g:loaded_clipboard_provider will enable a full reload of the provider. - " - " TLDR; source this to reinitialize the clipboard provider, this may not - " work - unlet! g:loaded_clipboard_provider - runtime autoload/provider/clipboard.vim +" For compatibility with an earlier version +function GuiClipboard() + call s:SetupGuiClipboard(0) +endfunction + +" Enable/Disable the GUI clipboard +function s:GuiClipboardSet(enable) + if a:enable == 0 + let s:ui_clipboard_enabled = 0 + call s:disable_custom_clipboard() + elseif s:ui_clipboard_enabled == 1 + " clipboard already enabled + else + if exists("g:clipboard") + echoerr "A custom g:clipboard is already configured" + endif + + call s:SetupGuiClipboard(0) + let s:ui_clipboard_enabled = 1 + endif +endfunction +command! -nargs=1 GuiClipboard call s:GuiClipboardSet() + +" If enabled reconfigure the GUI clipboard +function s:UpdateGuiClipboard() + if s:ui_clipboard_enabled == 1 + call s:SetupGuiClipboard(1) + endif endfunction +" When a UI attaches/detaches try to reconfigure the GUI +" clipboard +augroup GuiClipboard + autocmd! + autocmd UIEnter * :call s:UpdateGuiClipboard() + autocmd UILeave * :call s:UpdateGuiClipboard() +augroup END + " Directory autocommands for Treeview augroup guiDirEvents autocmd! diff --git a/src/gui/shell.cpp b/src/gui/shell.cpp index f25374aed..e2e34e156 100644 --- a/src/gui/shell.cpp +++ b/src/gui/shell.cpp @@ -279,6 +279,7 @@ void Shell::setAttached(bool attached) MsgpackRequest* req_shim{ m_nvim->api0()->vim_command("runtime plugin/nvim_gui_shim.vim") }; connect(req_shim, &MsgpackRequest::error, this, &Shell::handleShimError); + connect(req_shim, &MsgpackRequest::finished, this, &Shell::handleShimLoad); MsgpackRequest* req_ginit{ m_nvim->api0()->vim_command(GetGVimInitCommand()) }; connect(req_ginit, &MsgpackRequest::error, this, &Shell::handleGinitError); @@ -1882,6 +1883,18 @@ void Shell::handleShimError(quint32 msgid, quint64 fun, const QVariant& err) qDebug() << "GUI shim error " << err; } +void Shell::handleShimLoad(quint32 msgid, quint64 fun, const QVariant& resp) +{ + // Enable native clipboard, if api version 6 is available + auto api6 = m_nvim->api6(); + if (api6) { + qDebug() << "Enabling native clipboard"; + QVariantList args; + auto req = api6->nvim_command("GuiClipboard 1"); + connect(req, &MsgpackRequest::error, this, &Shell::handleShimError); + } +} + void Shell::handleGetBackgroundOption(quint32 msgid, quint64 fun, const QVariant& val) { const QString mode{ val.toString() }; diff --git a/src/gui/shell.h b/src/gui/shell.h index 674618180..b29e71cb6 100644 --- a/src/gui/shell.h +++ b/src/gui/shell.h @@ -114,6 +114,7 @@ protected slots: void updateClientInfo(); void handleGinitError(quint32 msgid, quint64 fun, const QVariant& err); void handleShimError(quint32 msgid, quint64 fun, const QVariant& err); + void handleShimLoad(quint32 msgid, quint64 fun, const QVariant& resp); void handleGetBackgroundOption(quint32 msgid, quint64 fun, const QVariant& val); protected: