Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable native clipboard provider by default #718

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -208,6 +224,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 @@ -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
Expand All @@ -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(<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
13 changes: 13 additions & 0 deletions src/gui/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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() };
Expand Down
1 change: 1 addition & 0 deletions src/gui/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down