Skip to content

Commit

Permalink
Enable native clipboard provider by default
Browse files Browse the repository at this point in the history
After successfuly loading the shim call GuiClipboard to enable the
native GUI clipboard.

- A new command GuiClipboard enables/disables the clipboard.
- Internally the Shim keeps the state of the setting and sets autocommands
  to reconfigure the clipboard on UI attachment.

The old function GuiClipboard is kept for compatibility.

ref #298
  • Loading branch information
equalsraf committed Feb 3, 2022
1 parent e7a51dd commit 95a301c
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 25 deletions.
17 changes: 17 additions & 0 deletions src/gui/runtime/doc/nvim_gui_shim.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -199,6 +215,7 @@ menu can be mapped to right click events in ginit.vim, e.g.
nnoremap <silent><RightMouse> :call GuiShowContextMenu()<CR>
inoremap <silent><RightMouse> <Esc>:call GuiShowContextMenu()<CR>
vnoremap <silent><RightMouse> :call GuiShowContextMenu()<CR>gv
<

==============================================================================
4. Internals
Expand Down
106 changes: 81 additions & 25 deletions src/gui/runtime/plugin/nvim_gui_shim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,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
Expand All @@ -148,45 +150,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(<args>)

" 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!
Expand Down
14 changes: 14 additions & 0 deletions src/gui/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ void Shell::setAttached(bool attached)

auto 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);

auto gviminit = qgetenv("GVIMINIT");
if (gviminit.isEmpty()) {
auto req_ginit = m_nvim->api0()->vim_command("runtime! ginit.vim");
Expand Down Expand Up @@ -1869,6 +1871,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() };
Expand Down
1 change: 1 addition & 0 deletions src/gui/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,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:
Expand Down

0 comments on commit 95a301c

Please sign in to comment.