Attribuer la langue du clavier par défaut par application

11

Est-il possible d'attribuer la langue du clavier par défaut à des applications spécifiques? Je sais qu'il existe une option pour toujours démarrer une application avec une langue de clavier par défaut, mais ce n'est pas ce que je veux.

Je recherche quelque chose de similaire aux "espaces de travail fixes" que vous pouvez définir à l'aide de CompizConfig (vous définissez Chrome pour qu'il s'ouvre toujours à X1Y1, le terminal à X2Y1, etc.). Quelque chose où je définirais Chrome: tchèque, terminal: anglais, Spotify: anglais, ...

grongor
la source
Dans "Saisie de texte", il y a l'option "Autoriser différentes sources pour chaque fenêtre". Peut-être un pas dans la bonne direction pour vous.
Gunnar Hjalmarsson
Oui, merci, je le sais. C'est l'étape nécessaire, je dirais, mais ce n'est malheureusement pas ce que je veux réaliser. Merci quand même.
grongor
Il y a une manière de script. Vous n'avez besoin que de ces 3 applications ou il y en a d'autres? Selon la souplesse avec laquelle vous voulez que le script soit, cela pourrait me prendre plus ou moins de temps pour l'écrire
Sergiy Kolodyazhnyy
@JacobVlijm Sonne comme un autre bon travail pour python;)
Sergiy Kolodyazhnyy
Publié une réponse.
Dites-

Réponses:

6

introduction

Le script ci-dessous définit la langue de chaque programme défini par l'utilisateur, en fonction de la position de cette langue dans le menu des langues. Par exemple, si ma commande est: anglais (1), chinois (2) et russe (3), je peux configurer Firefox pour avoir la langue 2, le terminal pour avoir la langue 1 et LibreOffice pour avoir la langue 3.

Le script est divisé en deux parties: la première partie est le script réel qui fait le travail, le deuxième script sert d'élément de contrôle. L'idée est d'exécuter le script de paramétrage de la langue en tant qu'application de démarrage et chaque fois que vous devez modifier manuellement la langue - double-cliquez sur le raccourci vers le script du contrôleur.

Conditions préalables

  1. Installez le wmctrlprogramme avec sudo apt-get install wmctrl.

Scénario

#!/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 du contrôleur

#!/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 

Fichier de lancement (.desktop) pour le 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

Fichier de lancement (.desktop) pour 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

Faire fonctionner le script

  1. Créez un dossier dans votre répertoire personnel appelé bin. Vous pouvez le faire dans le gestionnaire de fichiers ou utiliser la commande mkdir $HOME/bindans le terminal
  2. Dans le bindossier, créez deux fichiers: set-lang.shet set-lang-control.sh. Enregistrer le script dans set-lang.shet le script du contrôleur dans set-lang-control.sh. Rendez les deux scripts exécutables avecsudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. Créez deux .desktopfichiers. L'un est set-lang.desktop. Doit être placé dans le .config/autostartrépertoire caché . Le second est set-lang-controller.desktop, peut être placé dans votre bindossier. Faites ensuite glisser et épingler au lanceur le set-lang-controller.desktopfichier. Cela deviendra le raccourci pour arrêter et reprendre temporairement l'exécution du script.

REMARQUE : la ligne Exec=doit être modifiée pour avoir votre nom d'utilisateur réel dans le chemin d'accès au script (car il s'agit de votre répertoire personnel). Par exemple, le mien seraitExec=/home/serg/bin/set-lang.sh

Explication et personnalisation:

Le script lui-même s'exécute dans une boucle while infinie et vérifie la fenêtre active actuelle. Si la fenêtre active actuelle correspond à l'une des options de la structure de cas, nous basculons vers la langue appropriée. Pour éviter un réglage constant, chaque partie de la structure de cas possède une instruction if qui vérifie si la langue a déjà été définie sur la valeur souhaitée.

Le double-clic sur le lanceur pour set-lang-controller.shvérifiera l'état du set-lang.shscript; si le script est en cours d'exécution - il sera suspendu, et si le script est suspendu, il sera repris. Une notification sera affichée avec le message approprié.

Afin de personnaliser le script, vous pouvez ouvrir les applications souhaitées, exécuter wmctrl -lxet noter la troisième colonne - la classe de fenêtre. Exemple de sortie:

$ 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

Sélectionnez les classes de fenêtres appropriées pour chaque programme. Ensuite, accédez à la partie du script qui permet la personnalisation et ajoutez deux entrées pour PROG_CLASS et LANG. Ajoutez ensuite l'entrée appropriée dans la structure de cas.

Par exemple, si je veux ajouter, LibreOffice's Writer, j'ouvre la fenêtre de LibreOffice Writer, vais dans le terminal et je lance wmctrl -lx. Il me dira que la fenêtre Writer a une classe libreoffice.libreoffice-writer. Ensuite, je vais aller au script, ajouter PROG_CLASS_4=libreoffice.libreoffice-writeret LANG4=3dans la zone appropriée. Remarquez le numéro 4 correspondant. Ensuite, accédez à la structure de cas et ajoutez l'entrée suivante entre le dernier ;;et le esac:

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

Encore une fois, notez le signe $ et le numéro correspondant 4.

De plus, si le script s'exécute en tant qu'élément de démarrage automatique et que vous souhaitez l'arrêter temporairement pour le personnaliser, utilisez pkill set-lang.shet reprenez avecnohup set-lang.sh > /dev/null 2&>1 &

Petite note: une autre façon de découvrir la classe de fenêtre pour un programme (ce truc qui va avant le crochet rond unique dans la structure du boîtier) est d'utiliser ceci xpropet awkoneliner:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}

Sergiy Kolodyazhnyy
la source
Merci, c'est un très bon début. Le seul problème (mais majeur) est que je ne pourrai pas changer de langue dans ces applications. Le script remplacera simplement mes paramètres tout le temps. Je voudrais pouvoir changer la langue dans ces fenêtres aussi. Alors peut-être ajouter une vérification du pid d'application et forcer le langage uniquement la première fois ou quelque chose comme ça?
grongor
Je préférerais également que ce script soit piloté par les événements et non basé sur une boucle. Ce n'est pas un gros problème mais j'apprécierais vraiment si vous pouviez fournir un petit mode d'emploi pour que cela fonctionne avec dbus ou quelque chose (si c'est possible).
grongor
@GRoNGoR, donc j'y ai réfléchi un peu, et jusqu'à présent, je ne vois pas de moyen de mettre le script en pause kill -STOP $(pgrep set-lang.sh), puis de reprendre le script avec kill -CONT $(pgrep set-lang.sh). De cette façon, vous pouvez le suspendre, changer de langue normalement, puis reprendre.
Sergiy Kolodyazhnyy
Une pensée rapide que j'ai eue est que peut-être utiliser un raccourci clavier pour les deux commandes pourrait être le moyen de le faire, mais je ne l'ai pas encore testé, juste une théorie jusqu'à présent. Je testerai demain une fois que j'aurai suffisamment dormi et que je ferai rapport :) Faites-moi savoir si ce serait une idée acceptable
Sergiy Kolodyazhnyy
1
+1 pour le travail formidable et approfondi! Deux petites choses que je voudrais mentionner: les exécutables ~/binn'ont pas besoin du chemin (ni de l'extension, car il se trouve $PATHaprès une reconnexion , voir: lintian.debian.org/tags/script-with-language-extension .html ), et vous pourriez combiner stop / start dans un seul .desktopfichier; soit dans une liste rapide ou une fonction à bascule. semble assez parfait pour moi.
Jacob Vlijm
1

Vous pouvez installer gxneurpour cela en exécutant

sudo apt-get install gxneur

Ce logiciel peut changer automatiquement de disposition, mais il n'est pas parfait avec cela.

Mais il a de très bons outils pour configurer des commutateurs de disposition manuels.

Vous pouvez faire exactement ce que vous voulez. Pour définir des dispositions spécifiques pour des applications spécifiques.

Pilot6
la source
0

Le script ci-dessous est une version modifiée de celui-ci , qui a été publiée il y a quelque temps comme une solution similaire pour une seule application ( gnome-terminal).

Le script a été partiellement réécrit pour cette question, afin de pouvoir l'utiliser pour définir automatiquement les langues pour plusieurs applications.

Comment utiliser dans la pratique; mémoriser automatiquement la langue définie par application

Si le script est lancé pour la première fois, la langue courante est supposée être la langue par défaut, dont on se souvient dans un fichier caché: ~/.lang_set.

Ensuite, l'utilisation est simple: si vous exécutez par exemple geditdans la fenêtre la plus en avant et définissez une langue différente, cette langue est automatiquement connectée à geditpartir de là, jusqu'à ce que vous changiez à nouveau la langue avec gediten face.

Le nombre de langues / applications spécifiques est en principe illimité; exécutez simplement l'application et définissez la langue avec la fenêtre d'application en face. L'application sera automatiquement définie et mémorisée sans modifier le code.

Evénementiel?

Bien que le script s'exécute en boucle, la consommation de ressources est minime. L'événement piloté signifierait que l' événement est un changement dans la fenêtre la plus en avant. Je ne vois pas d'autre option que "d'espionner" la fenêtre la plus en avant que de vérifier dans une boucle.

Le scénario

#!/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

Comment installer

  1. Le script utilise à la fois xdotoolet wmctrl:

    sudo apt-get install wmctrl xdotool
    
  2. Copiez le script ci-dessus dans un fichier vide, enregistrez-le sous set_language.py

  3. Testez-le par la commande:

    python3 /path/to/set_language.py
    
  4. Si tout fonctionne comme prévu, ajoutez-le aux applications de démarrage: Ajouter aux applications de démarrage: Dash> Applications de démarrage> Ajouter. Ajoutez la commande:

    python3 /path/to/set_language.py
    
Jacob Vlijm
la source
Taille unique! +1
Fabby
Hé, merci beaucoup pour cela, je vais y jeter un œil bientôt et vous faire savoir ce que j'en pense :)
grongor