Terminal: [Conpty] Adicionar suporte para entrada de mouse

Criado em 18 fev. 2019  ·  48Comentários  ·  Fonte: microsoft/terminal

Em: Microsoft Windows [Version 10.0.17763.134]

Implementei o conpty em meu emulador de terminal:
https://github.com/wez/wezterm

Posso executar target\debug\wezterm.exe com sucesso para gerar aplicativos de console, como cmd.exe powershell.exe e bash .

O problema que estou vendo é que quando eu lanço o bash, seja indiretamente por meio de cmd.exe ou diretamente por meio do inicializador de bash, o conpty parece engolir o mouse relatando sequências de escape; Não os vejo sendo recebidos pelo meu analisador de terminal e, portanto, vim não tem suporte efetivo para mouse, apesar de estar configurado com set mouse=a .

Executar a mesma instalação WSL via wsl-terminal tem suporte para mouse funcional, e wezterm tem sido meu driver diário no Linux por cerca de um ano com suporte para mouse funcional, então podemos descartar um erro de configuração óbvio com vim e o analisador em wezterm .

Eu também tentei echo -e "\e[?1000h" para habilitar manualmente o relatório do mouse a partir do shell; normalmente (no linux e via wsl-terminal) isso faz com que cliques no terminal enviem dados para o shell (que aparece como entrada de lixo), mas ao executar meu terminal com o conpty, eles também são engolidos em algum lugar.

Existe algo especial necessário para que os aplicativos que eu gero no meu pty possam funcionar com o mouse?

Caso você queira verificar a parte principal do código, o arquivo relevante é:
https://github.com/wez/wezterm/blob/master/src/winpty.rs
O fluxo é para CreatePipe um par de tubos, CreatePseudoConsole , e então passa para um filho gerado por meio dos atributos threadproc, como os exemplos nos documentos do MSDN e neste repo também fazem.

Area-Interop Issue-Feature Product-Conpty

Comentários muito úteis

Apenas um para sua informação para qualquer membro da comunidade que possa estar investigando isso (/ cc @SamuelEnglard!). Nós reservamos oficialmente um trabalho na equipe de desenvolvimento para fazer isso. Espero que não estejamos pisando em seus pés!

Todos 48 comentários

Ei @wez ,
Infelizmente, o ConPTY não transmite relatórios do mouse (ou, de um aplicativo hospedado, _requests para relatórios do mouse_). Temos um item da lista de pendências rastreando isso e esperamos obter em breve.

Infelizmente, não podemos simplesmente passar eventos de mouse codificados: uma vez que ConPTY pode hospedar aplicativos de console do Windows padrão, do tipo que esperaria que MOUSE_EVENT s entrassem por meio de ReadConsoleInput , nós precisa fazer alguma tradução.

Em todos os outros aspectos, porém, parece que você está configurando o pseudoconsole corretamente.


Rastreamento: MSFT: 20469462

@ DHowett-MSFT obrigado pela resposta!
É um pouco chato que o relatório do mouse ainda não esteja lá, mas ainda é bom que o resto das coisas pty seja possível agora!

Não tenho nada a acrescentar além de realmente querer suporte a mouse com ConPTY. Com o alacritty agora tendo suporte para ConPTY usando alacritty + ssh + tmux é um terminal Linux incrível no Windows, apenas o suporte para mouse está faltando agora.

Eu sou um usuário pesado do midnight commander no meu shell bash Ubuntu, onde funciona muito bem. Infelizmente, a guia do shell do Ubuntu no Windows Terminal 0.3.2171.0 não parece enviar NENHUM evento do mouse para o aplicativo mc, tornando-o extremamente difícil de usar. Eu ia postar um bug, mas isso duplicaria isso.

Para meu uso, o envio de eventos de mouse é de extrema importância para uma boa experiência com vim e tmux.

Apenas abandonando meu apoio para isso aqui, além de um pouco de contexto. No mês passado, parei a inicialização dupla e comecei a usar o anel "rápido" de compilações internas do Windows 10 como minha máquina pessoal principal. Nesse caso, o wsl2 está funcionando perfeitamente, o x410 está funcionando perfeitamente, o terminal da microsoft está funcionando bem, o código do visual studio wsl2 funciona perfeitamente e o explorer.exe funciona perfeitamente.

Esse tíquete de entrada do mouse é praticamente a única coisa que me impede de chamar o terminal wsl2 / microsoft de um substituto razoável para ter uma caixa de partição / desenvolvimento separada. Uma vez que alguns pontos aqui são de código aberto, há alguma indicação de como ver as entradas do dispositivo de mouse em algum lugar em /dev ou devo apenas esperar?

Obrigado por tudo isso! Eu realmente gosto disso :)

Mais um voto para dizer / solicitar que o suporte ao mouse seria tão bom, e faz muita falta para qualquer pessoa que use o tmux, embora possa sobreviver sem ele.

Por favor, habilite o suporte ao mouse 😄

@ DHowett-MSFT, desculpe o chato, há algum plano para consertar isso em breve? Vendo rótulos / prioridades atribuídos em outras questões, mas este não é um deles, então apenas verificando. Obrigada.

@damnskippy Prioridade está sendo atribuída a coisas que precisamos consertar no host do console do Windows in-box (devido a prazos de bugs internos). Este é um recurso _grande_ (e requer uma especificação em escala adequada) e, embora saibamos que precisamos dele para a v1.0, não estamos trabalhando ativamente nisso hoje.

Se pudéssemos apenas "consertá-lo" como um bug, eu adoraria - mas é preciso muito mais do que uma correção.

Obrigado pela atualização. Seu trabalho é apreciado.

Eu amo o que você está fazendo aqui, eu amo, mas até conseguirmos suporte para mouse, temos que complementar este terminal com outro terminal, de alguma forma frustrando o propósito deste terminal.

Midnight Commander sem isso é um pesadelo.

A entrada do mouse em geral pode ser útil, digamos, se alguém na comunidade criar um suplemento do DosBox e um perfil que possa ser executado no Terminal do Windows.

Sou um usuário pesado do vim; até eu sinto falta do suporte ao mouse 😢

Acabei de ler a atualização do blog @ cinnamon-msft, parece que a equipe está mirando no 1.0 até o final deste ano ? Isso significa que teremos suporte para mouse até o final do ano? Em caso afirmativo, ele está sendo trabalhado ativamente agora?

Isso significa que teremos suporte para mouse até o final do ano?

Talvez, mas sem compromissos rígidos. Estimar quanto tempo leva para o software ser feito é quase tão difícil quanto provar P == NP. Eu iria mais longe e diria que o terminal não estaria pronto para 1.0 sem isso.

Em caso afirmativo, ele está sendo trabalhado ativamente agora?

Atualmente não. Ninguém é designado para a tarefa e, geralmente, quando alguém da equipe elimina uma tarefa, eles atribuem a si mesmos.

Por curiosidade, é tudo necessário para fazer isso aqui? Um desenvolvedor ambicioso (leia-se: louco) poderia assumir e fazer um PR?

Claro, alguém ambicioso com certeza poderia tentar isso por conta própria. Por onde começar?

Primeiro, vamos delinear algum escopo. Há muito trabalho a ser feito com a entrada do mouse, então é melhor começar pequeno e trabalhar em partes para chegar a uma solução completa. Acho que a primeira coisa que devemos fazer funcionar são simples sequências de mouse para cima / para baixo codificadas por SGR . Podemos trabalhar nos eventos da roda do mouse e, em seguida, passar o mouse depois disso, mas acho que clicar irá resolver _a maioria_ dos casos de uso.

Comece dando uma olhada em InputStateMachineEngine.cpp . O InputStateMachineEngine é responsável por analisar a entrada enviada pelo conpty e traduzi-la em INPUT_RECORD s. Um jovem desenvolvedor empreendedor iria querer modificar essa classe para poder também analisar essas sequências de mouse e traduzi-las em INPUT_RECORD s. Assim que tiver INPUT_RECORD s, chame InteractDispatch::WriteInput . Isso adicionará aqueles INPUT_RECORD s ao buffer de entrada. Assim que estiverem no buffer de entrada, serão entregues ao aplicativo cliente do console conectado normalmente.

Coisas que eu observaria:

  • conhost pode não inserir MouseEvents no buffer, a menos que estejamos no modo de entrada do mouse. Se for esse o caso, devemos nos certificar de apenas ignorar essas sequências também.
  • Os aplicativos que desejam entrada do mouse do VT não receberão um fluxo de INPUT_RECORD s, mas um fluxo de caracteres. Em algum ponto do conhost, tentamos traduzir aqueles INPUT_RECORD s do mouse em um fluxo de caracteres, se o aplicativo anexado estiver no modo de mouse VT. Se fizermos essa tradução _antes_ dos eventos do mouse estarem no buffer, fazer o acima pode não funcionar para aplicativos VT (leia: wsl ). Se for esse o caso, então precisaremos nos certificar de que a tradução de INPUT_RECORD de mouse para eventos de mouse codificados por VT seja feita manualmente para os eventos de mouse gerados por InputStateMachineEngine .

    • Olhando mais para dentro, parece que sim. Apenas traduzimos a entrada do mouse para eventos que foram iniciados pela janela, infelizmente. Veja este código:

      https://github.com/microsoft/terminal/blob/2c8b3243dca0c48dd05ecd7b420a7a03b3e19c93/src/interactivity/win32/windowio.cpp#L113 -L129

      terminalMouseInput.HandleMouse sintetizará sequências VT para o aplicativo cliente, mas infelizmente só é chamado a partir do proc da janela. Portanto, precisaremos de alguma forma expor uma maneira para que InputStateMachineEngine chame isso (por meio de um novo método em InteractDispatch ) e, se esse método falhar, gere o INPUT_RECORD apropriado

    • Tecnicamente, alguém poderia mover a chamada terminalMouseInput.HandleMouse ao invés para a leitura do InputBuffer, e fazer com que ele tentasse traduzir INPUT_RECORD s corretamente como eles são lidos, mas isso pode ser mais complicado.

Qual é o problema com esse problema? O mouse funciona perfeitamente no antigo console do Windows. Isso significa que tenho que usar o console até que isso seja corrigido?

Se você precisar de suporte para mouse VT, sim.

Apenas um para sua informação para qualquer membro da comunidade que possa estar investigando isso (/ cc @SamuelEnglard!). Nós reservamos oficialmente um trabalho na equipe de desenvolvimento para fazer isso. Espero que não estejamos pisando em seus pés!

Eu pensei sobre isso, mas não consegui reservar meu próprio tempo tão perfeito rsrsrs!

Eu estava apenas brincando com o VSCode com as extensões de desenvolvimento remoto e descobri que o terminal integrado nele realmente suporta o modo mouse no tmux! Seleção de painel, seleção de janela, redimensionamento de painel e roda de rolagem suportam todo o trabalho. Eu sou novo nesses projetos, então eu não sei se o terminal é parte do código aberto VS Codium e pode ser usado como ponto de partida ... desculpe se esta informação não é realmente útil

Apenas um para sua informação para qualquer membro da comunidade que possa estar investigando isso (/ cc @SamuelEnglard!). Nós reservamos oficialmente um trabalho na equipe de desenvolvimento para fazer isso. Espero que não estejamos pisando em seus pés!

@ DHowett-MSFT @ zadjii-msft @bitcrazed Sua comunicação sobre este problema aqui e em outros lugares foi fantástica; este é um exemplo para envolver com sucesso a comunidade na construção de seu software e isso mostra. Sua (s) equipe (s) (console / WSL / msft-linux) são pessoalmente responsáveis ​​por meus negócios com instalações do Windows (não-nix). Continue com o excelente trabalho 🥇

@thinkjrs Muito obrigado por suas amáveis ​​palavras.

E nossos mais sinceros agradecimentos a você e a todos em nossa comunidade que executam e testam / arquivam bugs / enviam solicitações, ideias e solicitações pull para Terminal, Código Cascadia, WSL, etc. Seu feedback nos influencia diretamente conforme priorizamos o trabalho e planejamos e recursos de design.

Não estávamos brincando quando dizemos que criamos esses recursos para e com nossa comunidade 😜

Qual é o processo? Há algum mouse funcional no WSL? Ou seja, tmux troca de painel, clicando para mudar de canal / servidor em weechat & irssi , (n)vim cliques, aptitude clicando, htop clicando, etc.

Qual é o processo? Há algum mouse funcional no WSL? Ou seja, tmux troca de painel, clicando para mudar de canal / servidor em weechat & irssi , (n)vim cliques, aptitude clicando, htop clicando, etc.

@dmxt Atualmente eu uso wsltty, que é a mais compatível de todas as opções de terminal para mim. Estou ansioso para mudar para o Terminal assim que alguns desses recursos surgirem.

Qual é o processo? Há algum mouse funcional no WSL? Ou seja, tmux troca de painel, clicando para mudar de canal / servidor em weechat & irssi , (n)vim cliques, aptitude clicando, htop clicando, etc.

@dmxt Atualmente eu uso wsltty, que é a mais compatível de todas as opções de terminal para mim. Estou ansioso para mudar para o Terminal assim que alguns desses recursos surgirem.

Eu concordo com seu comentário, depois de experimentar todos os emuladores de terminal conhecidos do público para Windows nos últimos anos, por enquanto, no momento em que este artigo foi escrito, wsltty é o melhor que existe. O repo oficial deles também é ótimo, eles têm um guia maravilhoso para eu começar de maneira rápida. Você não poderia pedir melhor com o espirituoso, ele tem suporte total para mouse sem soluços em vários fluxos de trabalho e ferramentas diferentes.

Percebi uma leve latência no I / O e acho que é o gargalo do sistema WSL1. Estou no Linux bare-metal e há latência de 0 ms com entrada do mouse.

@dmxt @offero Tive sucesso com o XShell (linha de comando real de recursos experimentais, ou ssh em WSL) - tem suporte a mouse etc, apenas FYI. Além disso, os aplicativos que precisam de suporte para mouse são o midnight commander e o micro editor

Por favor, veja como isso é resolvido no ConEmu

Algum roteiro ou cronograma para quando exatamente isso será implementado? Parece ser um recurso muito importante para lançar. É meio surpreendente para mim que a v1.0 esteja sendo lançada sem que isso seja resolvido. Acho que versionar não significa nada hoje em dia.

@kvnxiao na versão mais recente da Microsoft Store da entrada do mouse do Windows Terminal é compatível (pelo menos no Vim), pelo que eu posso dizer

@ fat0troll Pelo que eu posso dizer, esse definitivamente não é o caso. Mesmo no vim com set mouse=a , a entrada do mouse funciona no antigo conhost, mas não no Windows Terminal 1.0.1401.0.

set nocompatible
syntax on
set number
set mouse=a
set backspace=indent,eol,start

Com essa configuração do vim, posso clicar dentro da janela do vim e o cursor se moverá para o lugar onde eu cliquei. 1.0.1401.0, Windows build 18368.836 (se tiver algum efeito sobre isso).

@kvnxiao Imagino que você esteja usando OpenSSH_For_Windows_7.7. Há um bug nele (resolvido no 8.x) que o impede de funcionar no modo mouse.

Implementamos isso explicitamente para todos os aplicativos VT que desejam receber entrada do mouse.

Acho que versionar não significa nada hoje em dia.

Não há necessidade de ser indelicado.

Com relação ao vim, tentei usar o neovim desenvolvido para windows como um executável do windows. Se outros estão dizendo que o suporte do mouse funciona para o vim (por exemplo, por meio de ssh / wsl, etc.), então não estou duvidando de você, mas isso mostra que o suporte "completo" ainda não existe, o que representa uma forma mais específica pergunta:

O que sobraria no roteiro para suporte "total" ao mouse em comparação com o que o conhost é capaz atualmente?

Estou falando em termos de desejo de lançar aplicativos genéricos baseados em terminal que suportem a entrada do mouse (e funcionem em conhost) por meio do WT. Por exemplo, executar vários aplicativos de interface de usuário de terminal / baseados em texto construídos diretamente como um executável do Windows. Eles funcionam bem quando clicados duas vezes para executar, que recorrem ao uso de conhost, mas quando executados pelo Terminal do Windows acabam com apenas o mouse selecionando o texto exibido.

@niklaskorz Qual é o sentido de votar a favor e contra os comentários mencionados acima, quando pessoas como eu têm questões relevantes relacionadas a este tópico, que podem ou não ainda estar sem solução?

Você está totalmente certo. Este item de trabalho, que você identificou corretamente como sendo para aplicativos de console Win32 que recebem eventos de mouse de qualquer terminal, está programado para “terminal 1.x” (marco), o que indica que queremos resolvê-lo entre agora e 2.0. Não tenho uma estimativa mais precisa do que essa.

Obrigado pelo esclarecimento! Um pouco triste que este item de trabalho não tenha conseguido competir pelo 1.0, mas estou aguardando ansiosamente quando isso acontecer, e espero que não demore muito 😀.

FIWW, caso você não saiba, o novo Powershell Out-ConsoleGridView (https://github.com/PowerShell/GraphicalTools) é um caso de teste matador para isso. Veja bug de rastreamento relacionado ao mouse aqui: https://github.com/PowerShell/GraphicalTools/issues/95

Ele é baseado em Terminal.Gui (https://github.com/tig/gui.cs).

Além disso, acabamos de construir um novo aplicativo de amostra para Terminal.Gui que vocês devem ser capazes de usar para testar o suporte do mouse conforme ele ganha vida no WT.

Estou realmente ansioso por isso!

Existe alguma maneira de ajudar a resolver esse problema? É uma verdadeira chatice para aplicativos de console GUI construídos com Terminal.Gui (https://github.com/tig/gui.cs).

@kvnxiao Imagino que você esteja usando OpenSSH_For_Windows_7.7. Há um bug nele (resolvido no 8.x) que o impede de funcionar no modo mouse.

Implementamos isso explicitamente para todos os aplicativos VT que desejam receber entrada do mouse.

Acho que versionar não significa nada hoje em dia.

Não há necessidade de ser indelicado.

Como posso atualizar o openssh integrado para a versão mais recente?

@kvnxiao Imagino que você esteja usando OpenSSH_For_Windows_7.7. Há um bug nele (resolvido no 8.x) que o impede de funcionar no modo mouse.
Implementamos isso explicitamente para todos os aplicativos VT que desejam receber entrada do mouse.

Acho que versionar não significa nada hoje em dia.

Não há necessidade de ser indelicado.

Como posso atualizar o openssh integrado para a versão mais recente?

Acho que você está procurando algo descrito nesta postagem do blog (instalação do Openssh do chocolatey): https://blog.frankfu.com.au/2019/03/21/moving-from-windows-1809s-openssh-to- openssh-portable /

Vou supor que você está usando OpenSSH_For_Windows_7.7. Há um bug nele (resolvido no 8.x) que o impede de funcionar no modo mouse.

Implementamos isso explicitamente para todos os aplicativos VT que desejam receber entrada do mouse.

@DHowett, a partir desse contexto, parece que o uso de OpenSSH_for_Windows_8.0p1, LibreSSL 2.6.5 deveria funcionar?

Estou usando a versão de visualização do Terminal para SSH em uma máquina Ubuntu com o modo de mouse tmux habilitado, mas minhas entradas de mouse ainda parecem estar controlando apenas o próprio terminal.

Também tentei atualizar o servidor para OpenSSH 8.0, mas também não ajudou.

Esse problema ainda está impedindo esse tipo de coisa de funcionar?

Ah, x em 8.x pode ser 1. Eu não sabia que eles lançaram uma versão 8.0.

Ah, ax em 8.x pode ser 1. Eu não sabia que eles lançaram uma compilação 8.0.

Vou tentar.

Funciona! Incrível, obrigado!

Comecei a entender esse problema.

Infelizmente, o MS ainda não implementa a função de entrada do mouse da API Win32 no Windows Terminal.
(Apenas a sequência de escape VT é compatível.)

Tentei substituir ReadConsoleInputW e PeekConsoleInputW em meu aplicativo
para trabalhar com o mouse no Terminal Windows.

Primeiro, executo o código a seguir.

SetConsoleMode(hin,  ENABLE_VIRTUAL_TERMINAL_INPUT);
SetConsoleMode(hout, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
char *vt_mouse_input_enable_cmd  = "\x1b[?1000h\x1b[?1003h\x1b[?1006h";
DWORD written;
WriteConsoleA(hout, vt_mouse_input_enable_cmd, strlen(vt_mouse_input_enable_cmd), &written, NULL);

Então, a entrada do mouse pode ser recebida como sequência de escape VT (sgr-1006) (por exemplo, \x1b[<0;10;20M ).

Mas, outro problema ocorreu.

Algumas entradas de tecla (como as teclas de seta) também são recebidas como sequência de escape VT (por exemplo, \x1b[A ).

Tentei converter essa sequência de escape VT indesejada em evento-chave da API win32,
mas isso está incompleto.
(código de chave virtual e código de varredura virtual casualmente tornam-se zero, etc.)

Meu código está aqui.
https://gist.github.com/Hamayama/6add968870269f2426716fad79724b31
(PDC_read_console_input_w e PDC_peek_console_input_w são funções alternativas.)

Eu quero um método para desativar a sequência de escape VT, exceto para a entrada do mouse.

por exemplo

char *vt_key_input_disable_cmd = "\x1b[?9XXXl";
DWORD written;
WriteConsoleA(hout, vt_key_input_disable_cmd, strlen(vt_key_input_disable_cmd), &written, NULL);

ou

SetConsoleMode(hin, ENABLE_VIRTUAL_TERMINAL_MOUSE_INPUT_ONLY);

Mas, isso pode ser uma ideia errada para o futuro ...

Descobri que não há rastreamento do movimento do mouse em src/terminal/parser/InputStateMachineEngine.cpp: 391 (tradução de sequências SGR VT em INPUT_RECORD s).

Em outras palavras, o Terminal envia sequências VT para ConPTY, mas ConPTY apenas monitora o estado dos botões do mouse. Mudanças nas coordenadas do mouse são ignoradas:

src/terminal/parser/InputStateMachineEngine.cpp: 391 :

success = _UpdateSGRMouseButtonState(id, firstParameter, buttonState, eventFlags);
success = success && _WriteMouseEvent(parameters.at(1), parameters.at(2), buttonState, modifierState, eventFlags);

Com o estado atual de suporte para entrada de mouse, a seguinte opção é possível.

Você pode adicionar rastreamento de coordenadas e o movimento do mouse começará a funcionar em aplicativos de console clássicos.

src/terminal/parser/InputStateMachineEngine.hpp: 172 :

+ size_t _mouseColumn = 0;
+ size_t _mouseLine = 0;

src/terminal/parser/InputStateMachineEngine.cpp: 391 :

- success = success && _WriteMouseEvent(parameters.at(1), parameters.at(2), buttonState, modifierState, eventFlags);
+ auto mouseColumn = parameters.at(1).value_or(0);
+ auto mouseLine = parameters.at(2).value_or(0);
+ auto isMoved = mouseColumn! = _mouseColumn || mouseLine! = _mouseLine;
+ if (isMoved)
+ {
+     _mouseColumn = mouseColumn;
+     _mouseLine = mouseLine;
+ }
+ success = (success || isMoved) && _WriteMouseEvent(mouseColumn, mouseLine, buttonState, modifierState, eventFlags);

Observação: antes de iniciar um aplicativo de console clássico, você precisa solicitar o rastreamento do mouse no formato SGR:

Windows PowerShell

PS C:\Users> [char]0x1b + "[?1003;1004;1006h"

Prompt de comando

C:\Users> echo Ctrl + [ [?1003;1004;1006h

Parâmetros
  • 1003 - ANY_EVENT_MOUSE_MODE
  • 1004 - qualquer modo não suportado (por exemplo, 1001 ou 9999 ) para encaminhar a sequência através do ConPTY para o próprio Terminal
  • 1006 - SGR_EXTENDED_MODE

como resultado, o Terminal começará a enviar eventos de mouse para ConpTY, que começará a gerar INPUT_RECORD s para o aplicativo de console clássico.

Boa pegada. Teremos que nos certificar de que corrigiremos isso quando realmente movermos para oferecer suporte a este: sorriso:

Esta página foi útil?
0 / 5 - 0 avaliações