Glfw: Adicionar suporte para transferência incremental de seleções

Criado em 15 abr. 2014  ·  5Comentários  ·  Fonte: glfw/glfw

Você pode reproduzir isso com o aplicativo da um arquivo lixo de 26214 bytes , copie tudo e cole na janela, você obterá:

Error: X11: Failed to convert selection to string
Clipboard does not contain a string
X11 bug verified

Comentários muito úteis

Estive investigando isso sozinho, mas não consegui concluir a implementação. Esperançosamente, parte da experiência na tentativa de implementá-lo pode ser útil para outra pessoa que esteja tentando fazer o mesmo. Em poucas palavras, aqui está o que acontece e o que o ICCCM espera que façamos para lidar com este átomo INCR:

Abaixo, ao chamar _glfwPlatformGetClipboardString é onde X11 fica muito triste:

if (_glfwGetWindowPropertyX11(event.xselection.requestor,
                              event.xselection.property,
                              event.xselection.target,
                              (unsigned char**) &data))
    _glfw.x11.clipboardString = strdup(data);

E a razão é porque estamos solicitando event.xselection.target do tipo UTF8_STRING , que funcionará na maior parte do tempo, exceto quando tivermos passado o tamanho máximo de transferência de lote único permitido pelo proprietário da seleção (262146 bytes em este caso). Em vez disso, o proprietário da seleção nos dará um actualType de INCR que não é o mesmo que o tipo solicitado UTF8_STRING . O proprietário deseja enviar dados de forma incremental , ou seja, em blocos de vários XGetWindowProperty s contendo UTF8_STRING s.

Para resolver isso, precisamos seguir a recomendação do ICCCM "Propriedades INCR". Mas em poucas palavras:

  1. Pegue uma alça para INCR -atom com XInternAtom por exemplo, com o nome INCR_STRING .
  2. Veja em _glfwGetWindowPropertyX11 se recebemos actualType de INCR_STRING , se assim for:
    a) Busque INCR_STRING usando XGetWindowProperty , ele contém um limite de transferência inferior.
    b) Exclua esta INCR_STRING propriedade para que o proprietário possa começar a nos enviar as coisas boas.
    c) Aguarde um evento PropertyNotify , sinalizando a chegada de uma parte dos dados completos.
    d) Recupere os dados do bloco usando XGetWindowProperty e anexe-os a um buffer.
    e) Exclua a propriedade, sinalizando ao proprietário para enviar pedaços adicionais.
    f) Verifique se o tamanho dos dados é zero, caso contrário, volte para c.
    g) Transferência concluída, agora você tem todos os dados!

Se você estiver interessado, aqui está um resumo da
Aqui estão alguns links que achei úteis ao analisar o problema:

Espero que isso seja útil para alguém, mas eu não fui capaz de descobrir sozinho, infelizmente.

Todos 5 comentários

O GLFW ainda não suporta transferência incremental de dados da área de transferência.

Nota para mim mesmo: UTF8_STRING

Estive investigando isso sozinho, mas não consegui concluir a implementação. Esperançosamente, parte da experiência na tentativa de implementá-lo pode ser útil para outra pessoa que esteja tentando fazer o mesmo. Em poucas palavras, aqui está o que acontece e o que o ICCCM espera que façamos para lidar com este átomo INCR:

Abaixo, ao chamar _glfwPlatformGetClipboardString é onde X11 fica muito triste:

if (_glfwGetWindowPropertyX11(event.xselection.requestor,
                              event.xselection.property,
                              event.xselection.target,
                              (unsigned char**) &data))
    _glfw.x11.clipboardString = strdup(data);

E a razão é porque estamos solicitando event.xselection.target do tipo UTF8_STRING , que funcionará na maior parte do tempo, exceto quando tivermos passado o tamanho máximo de transferência de lote único permitido pelo proprietário da seleção (262146 bytes em este caso). Em vez disso, o proprietário da seleção nos dará um actualType de INCR que não é o mesmo que o tipo solicitado UTF8_STRING . O proprietário deseja enviar dados de forma incremental , ou seja, em blocos de vários XGetWindowProperty s contendo UTF8_STRING s.

Para resolver isso, precisamos seguir a recomendação do ICCCM "Propriedades INCR". Mas em poucas palavras:

  1. Pegue uma alça para INCR -atom com XInternAtom por exemplo, com o nome INCR_STRING .
  2. Veja em _glfwGetWindowPropertyX11 se recebemos actualType de INCR_STRING , se assim for:
    a) Busque INCR_STRING usando XGetWindowProperty , ele contém um limite de transferência inferior.
    b) Exclua esta INCR_STRING propriedade para que o proprietário possa começar a nos enviar as coisas boas.
    c) Aguarde um evento PropertyNotify , sinalizando a chegada de uma parte dos dados completos.
    d) Recupere os dados do bloco usando XGetWindowProperty e anexe-os a um buffer.
    e) Exclua a propriedade, sinalizando ao proprietário para enviar pedaços adicionais.
    f) Verifique se o tamanho dos dados é zero, caso contrário, volte para c.
    g) Transferência concluída, agora você tem todos os dados!

Se você estiver interessado, aqui está um resumo da
Aqui estão alguns links que achei úteis ao analisar o problema:

Espero que isso seja útil para alguém, mas eu não fui capaz de descobrir sozinho, infelizmente.

Obrigado, é uma excelente descrição! É um pouco absurdo o que os clientes precisam fazer para realizar coisas que são algumas chamadas de função em outras plataformas.

Comecei a implementar o INCR há dois dias. Tenho leitura funcionando, assim como conversão de STRING / Latin-1, mas tive um breve momento de desespero quando percebi que INCR, MULTIPLE e STRING podem se combinar para escrever. Alguma reestruturação é necessária antes que possa ser implementada de forma limpa.

Empurrei agora para o branch selection-fixes se alguém quiser dar uma olhada.

Preciso me concentrar nas revisões de solicitação de pull por um tempo. Eu mantive muitos códigos finos esperando por um período vergonhoso de tempo. Se alguém quiser continuar trabalhando nisso, com base no código acima ou não, por favor, continue.

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

Questões relacionadas

leo150 picture leo150  ·  4Comentários

dmitshur picture dmitshur  ·  4Comentários

MarcoLizza picture MarcoLizza  ·  4Comentários

elmindreda picture elmindreda  ·  4Comentários

floooh picture floooh  ·  5Comentários