Atribuir idioma do teclado padrão por aplicativo

11

É possível atribuir o idioma padrão do teclado para aplicativos específicos? Eu sei que existe uma opção para sempre iniciar um aplicativo com um idioma de teclado padrão, mas não é isso que eu quero.

Estou procurando algo semelhante a "áreas de trabalho fixas" que você pode definir usando o CompizConfig (você define o Chrome para sempre abrir no X1Y1, terminal no X2Y1 etc.). Algo onde eu definiria Chrome: Czech, terminal: English, Spotify: English, ...

grongor
fonte
Em "Entrada de texto" existe a opção "Permitir fontes diferentes para cada janela". Possivelmente um passo na direção certa para você.
Gunnar Hjalmarsson
Sim, obrigado, eu sei disso. Este é o passo necessário que eu diria, mas infelizmente não é o que quero alcançar. Obrigado mesmo assim.
grongor
Existe uma maneira de script. Você só precisa desses 3 aplicativos ou tem outros? Dependendo de quão flexível você deseja que o script seja, levará mais ou menos tempo para escrevê-lo #
Sergiy Kolodyazhnyy
@JacobVlijm Soa como outro bom trabalho para python;) #
Sergiy Kolodyazhnyy
Publicou uma resposta. Deixe-me saber o que você pensa
Sergiy Kolodyazhnyy

Respostas:

6

Introdução

O script abaixo define o idioma para cada programa definido pelo usuário, de acordo com a posição desse idioma no menu de idiomas. Por exemplo, se meu pedido for: inglês (1), chinês (2) e russo (3), posso configurar o Firefox para o idioma 2, o terminal para o idioma 1 e o LibreOffice para o idioma 3.

O script vem em duas partes: a primeira parte é o script real que faz o trabalho, o segundo script serve como um elemento de controle. A idéia é executar o script de configuração de idioma como um aplicativo de inicialização e sempre que você precisar alterar manualmente o idioma - clique duas vezes no atalho do script do controlador.

Pré-requisitos

  1. Instale o wmctrlprograma com sudo apt-get install wmctrl.

Roteiro

#!/bin/sh
# Author: Serg Kolo
# Date: August 4, 2015
# Description: This script forces assigned input languages
#              for specific windows
# Version:2

# Use this part to set programs and their respective languages
# PROG_CLASS or a running window can be found with the
# wmctrl -lx command
# If you want to add another program to the list, 
# follow the template PROG_CLASS_num=window.Class
# and bellow that $LANGnum=num


PROG_CLASS_1=gedit.Gedit
LANG1=2

PROG_CLASS_2=gnome-terminal-server.Gnome-terminal
LANG2=0

PROG_CLASS_3=Navigator.Firefox
LANG3=1


# While loop below gets the job done. 
# If you need to send languages for more programs -  copy  
# the first entry and replace  $PROG_CLASS_1 with $PROG_CLASS_num
# where num is respective number of a program
# Replace $LANGnum with the respective language number. After the "="
# post positional number of the language you want to use. 
# Remember the count starts from 0

while [ 1 ];do
  WM_CLASS=$(wmctrl -lx | awk -v search=$(printf %x $(xdotool getactivewindow)) '{ if($1~search) print $3 }' )
  CURRENT=$(gsettings get org.gnome.desktop.input-sources current| awk '{print $2}')
    case  $WM_CLASS in

      $PROG_CLASS_1)  
        if [ $CURRENT -ne  $LANG1 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG1
        fi
      ;;

      $PROG_CLASS_2) 
        if [ $CURRENT -ne  $LANG2 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG2
        fi  
      ;;

       $PROG_CLASS_3) 
         if [ $CURRENT -ne  $LANG3 ];then
           gsettings set org.gnome.desktop.input-sources current $LANG3
         fi  
        ;;
    esac

    sleep 0.250

done

Script do Controlador

#!/bin/sh
# set -x
# Author: Serg Kolo
# Date: August 8, 2015
# Description: Controller script for set-lang.sh script
# Allows pausing and resuming execution of set-lang.sh
STATUS=$(ps -o stat -p $(pgrep -o  set-lang.sh) | awk '{getline;print }')

case $STATUS in
    T) kill -CONT $(pgrep set-lang.sh) 
       notify-send 'RESUMED'
    ;;

    S) kill -STOP $(pgrep set-lang.sh)
       notify-send 'STOPED'
    ;;

    *) exit ;;
esac 

Arquivo do iniciador (.desktop) para o script set-lang.sh

[Desktop Entry]
Name=set-lang.sh
Comment=Script to set languages
Exec=/home/yourusername/bin/set-lang.sh
Type=Application
StartupNotify=true
Terminal=false

Arquivo do Launcher (.desktop) para set-lang-controller.sh

[Desktop Entry]
Name=lang-control
Comment=Shortcut to controlling script
Exec=/home/yourusername/bin/set-lang-control.sh
Type=Application
StartupNotify=true
Terminal=false

Fazendo o script funcionar

  1. Crie uma pasta no seu diretório pessoal chamada bin. Você pode fazer isso no gerenciador de arquivos ou usar o comando mkdir $HOME/binno terminal
  2. Na binpasta, crie dois arquivos: set-lang.she set-lang-control.sh. Salve o script set-lang.she o script do controlador em set-lang-control.sh. Torne os dois scripts executáveis ​​comsudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. Crie dois .desktoparquivos. Um é set-lang.desktop. Deve ser colocado no .config/autostartdiretório oculto . O segundo é set-lang-controller.desktop, pode ser colocado em sua binpasta. Em seguida, arraste e fixe o set-lang-controller.desktoparquivo no iniciador . Isso se tornará o atalho para interromper e retomar temporariamente a execução do script.

Observe que a linha Exec=deve ser alterada para ter seu nome de usuário real no caminho para o script (porque esse é seu diretório pessoal). Por exemplo, o meu seriaExec=/home/serg/bin/set-lang.sh

Explicação e personalização:

O próprio script é executado em um loop while infinito e verifica a janela ativa atual. Se a janela ativa atual corresponder a uma das opções na estrutura do caso, mudaremos para o idioma apropriado. Para evitar a configuração constante, cada parte da estrutura do caso possui uma instrução if que verifica se o idioma já foi definido com o valor desejado.

O clique duplo no iniciador set-lang-controller.shverificará o status do set-lang.shscript; se o script estiver em execução - ele será pausado e, se o script estiver em pausa, será retomado. Uma notificação será mostrada com a mensagem apropriada.

Para personalizar o script, você pode abrir os aplicativos desejados, executar wmctrl -lxe anotar a terceira coluna - a classe da janela. Saída de amostra:

$ wmctrl -lx | awk '$4="***" {print}'                                                                                                            
0x02c00007 0 gnome-terminal-server.Gnome-terminal *** Terminal
0x03a0000a 0 desktop_window.Nautilus *** Desktop
0x04a00002 0 N/A *** XdndCollectionWindowImp
0x04a00005 0 N/A *** unity-launcher
0x04a00008 0 N/A *** unity-panel
0x04a0000b 0 N/A *** unity-dash
0x04a0000c 0 N/A *** Hud
0x012000a6 0 Navigator.Firefox *** unity - Assign default keyboard language per-application - Ask Ubuntu - Mozilla Firefox

Selecione as classes de janela apropriadas para cada programa. Em seguida, vá para a parte do script que permite a personalização e adicione duas entradas para PROG_CLASS e LANG. Em seguida, adicione a entrada apropriada na estrutura do caso.

Por exemplo, se eu quiser adicionar o Writer do LibreOffice, abro a janela do LibreOffice Writer, vou para o terminal e corro wmctrl -lx. Isso me dirá que a janela do Writer tem classe libreoffice.libreoffice-writer. Em seguida, irei ao script, adicionarei PROG_CLASS_4=libreoffice.libreoffice-writere LANG4=3na área apropriada. Observe o número correspondente 4. Em seguida, vá para estrutura do caso e adicione a seguinte entrada entre last ;;e esac:

$PROG_CLASS_4) 
  if [ $CURRENT -ne  $LANG4 ];then
    gsettings set org.gnome.desktop.input-sources current $LANG4
  fi  
;;

Mais uma vez, observe o sinal $ e o número correspondente 4.

Além disso, se o script estiver sendo executado como um item de inicialização automática e você desejar pará-lo temporariamente para personalizá-lo, use pkill set-lang.she continue comnohup set-lang.sh > /dev/null 2&>1 &

Nota pequena: outra maneira de descobrir a classe de janela para um programa (o material que antecede o suporte redondo único na estrutura do caso) é usar this xprope awkoneliner:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}

Sergiy Kolodyazhnyy
fonte
Obrigado, este é um bom começo. O único (mas principal) problema é que não poderei alternar o idioma nesses aplicativos. O script simplesmente substituirá minhas configurações o tempo todo. Eu gostaria de poder mudar o idioma nessas janelas também. Então, talvez adicione alguma verificação do aplicativo pid e force a linguagem apenas na primeira vez ou algo assim?
grongor
Eu também preferiria que esse script fosse orientado a eventos, não baseado em loop. Não é grande coisa, mas eu realmente apreciaria se você pudesse fornecer um pequeno tutorial sobre como fazer isso funcionar com o dbus ou algo assim (se for possível).
grongor
@GRoNGoR, então eu pensei um pouco sobre isso e, até agora, não vejo uma maneira de pausar o script, exceto kill -STOP $(pgrep set-lang.sh)e depois continuar com o script kill -CONT $(pgrep set-lang.sh). Dessa forma, você pode pausá-lo, alternar idiomas normalmente e depois continuar.
Sergiy Kolodyazhnyy 8/08/2015
Um pensamento rápido que tive foi que talvez usando um atalho de teclado para os dois comandos possa ser o caminho para fazê-lo, mas ainda não o testei, apenas uma teoria até agora. Vai testar amanhã uma vez que recebo bastante sono e relatório de volta :) Deixe-me saber se isso seria uma idéia aceitável
Sergiy Kolodyazhnyy
1
+1 pelo excelente e minucioso trabalho! Duas pequenas coisas que eu gostaria de mencionar: os executáveis ​​em ~/binnão precisam do caminho (nem da extensão, pois está $PATHapós um novo login, consulte: lintian.debian.org/tags/script-with-language-extension .html ) e você pode combinar parar / iniciar em um .desktoparquivo; em uma lista rápida ou em uma função de alternância. parece muito perfeito para mim.
Jacob Vlijm 9/08/2015
1

Você pode instalar gxneurpara isso executando

sudo apt-get install gxneur

Este software pode alternar automaticamente os layouts, mas não é perfeito com isso.

Mas possui ferramentas muito boas para configurar opções de layout manual.

Você pode fazer exatamente o que quiser. Para definir layouts específicos para aplicativos específicos.

Pilot6
fonte
0

O script abaixo é uma versão editada deste , que foi postada como uma solução semelhante para um único aplicativo ( gnome-terminal) há um tempo atrás.

O script foi parcialmente reescrito para esta pergunta, para poder usá-lo para definir automaticamente idiomas para vários aplicativos.

Como usar na prática; lembrar automaticamente o idioma definido por aplicativo

Se o script for iniciado pela primeira vez, o idioma atual é assumido como sendo o idioma padrão, que é lembrado em um arquivo oculto: ~/.lang_set.

Então o uso é simples: se você executar, por exemplo, geditna janela da frente, e definir um idioma diferente, esse idioma será automaticamente conectado a geditpartir de então, até você mudar o idioma novamente com geditna frente.

O número de idiomas / aplicativos específicos é, em princípio, ilimitado; basta executar o aplicativo e definir o idioma com a janela do aplicativo na frente. O aplicativo será automaticamente definido e lembrado sem editar o código.

Evento impulsionado?

Embora o script seja executado em um loop, o consumo de recursos é mínimo. Evento orientado significaria que o evento é uma alteração na janela da frente. Não vejo outra opção senão "espionar" a janela da frente mais do que fazer check-in em um loop.

O script

#!/usr/bin/env python3
import subprocess
import os
import time

key = [
    "org.gnome.desktop.input-sources",
    "gsettings get ", "gsettings set ",
    " sources", " current",
    ]

prev = os.environ["HOME"]+"/.lang_set"

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")

def get_front():
    # produce the frontmost application
    try:
        focus = str(hex(int(get("xdotool getwindowfocus").strip())))
        front = focus[:2]+"0"+focus[2:]
        cmd = "wmctrl -lp"
        w_list = subprocess.check_output(["/bin/bash", "-c",cmd]).decode("utf-8")
        w_match = [w for w in w_list.splitlines() if front in w][0].split()[2]
        application = get("ps -p "+w_match+" -o comm=").strip()
        # fix for 15.04, where the process name of gnome-terminal varies
        application = "gnome-terminal" if "gnome-terminal" in application else application
        return application
    except subprocess.CalledProcessError:
        return None

def get_lang():
    # get the currently running language (output = string)
    curr_n = int(get(key[1]+key[0]+key[4]).strip().split()[-1])
    return str(eval(get(key[1]+key[0]+key[3]))[curr_n])

def read_prev(application):
    # reads the possibly set languages for general and specific use (list)
    if not os.path.exists(prev):
        currlang = get_lang()
        open(prev, "wt").write("default "+currlang+"\n"+application+" "+currlang)
        return [currlang, currlang]
    else:
        return [l.strip() for l in open(prev).readlines()]

def write_changed(application, lang):
    changelist = read_prev(front_2)
    try:
        match = changelist.index([l for l in changelist if application in l][0])
        changelist[match] = application+" "+lang+"\n"
    except IndexError:
        changelist.append(application+" "+lang+"\n")
    open(prev, "wt").write(("\n").join(changelist))

def set_lang(lang):
    # set the currently used language (input = string)
    lang_i = eval(get(key[1]+key[0]+key[3])).index(eval(lang))  
    cmd = key[2]+key[0]+key[4]+" "+str(lang_i)
    subprocess.Popen(["/bin/bash", "-c", cmd])

front_1 = get_front(); lang_1 = get_lang()

while True:
    time.sleep(1)
    front_2 = get_front(); lang_2 = get_lang()
    if front_2 != None:
        if front_2 != front_1:
            try:
                setlist = read_prev(front_2)
                match = [l for l in setlist if front_2 in l][0]
            except IndexError:
                match = [l for l in setlist if "default" in l][0]
                set_lang(match[match.find(" ")+1:])            
        elif lang_2 != lang_1:
            write_changed(front_2, lang_2)
    front_1 = front_2; lang_1 = lang_2

Como configurar

  1. O script usa ambos xdotoole wmctrl:

    sudo apt-get install wmctrl xdotool
    
  2. Copie o script acima em um arquivo vazio, salve-o como set_language.py

  3. Execute-o de teste pelo comando:

    python3 /path/to/set_language.py
    
  4. Se tudo funcionar como esperado, adicione-o a Aplicativos de inicialização: Adicionar a Aplicativos de inicialização: Dash> Aplicativos de inicialização> Adicionar. Adicione o comando:

    python3 /path/to/set_language.py
    
Jacob Vlijm
fonte
Um tamanho serve para todos! 1
Fabby
Hey obrigado muito para isso, eu vou olhar para ele em breve e que você saiba como me sinto sobre isso :)
grongor