Przypisz domyślny język klawiatury dla aplikacji


11

Czy można przypisać domyślny język klawiatury dla określonych aplikacji? Wiem, że istnieje opcja, aby zawsze uruchamiać aplikację z domyślnym językiem klawiatury, ale nie tego chcę.

Szukam czegoś podobnego do „stałych obszarów roboczych”, które można ustawić za pomocą CompizConfig (Chrome ustawia się tak, aby zawsze otwierał się na X1Y1, terminal na X2Y1 itp.). Coś, w czym ustawiłbym Chrome: czeski, terminal: angielski, Spotify: angielski, ...


W „Wprowadzaniu tekstu” dostępna jest opcja „Zezwalaj na różne źródła dla każdego okna”. Być może krok we właściwym kierunku dla Ciebie.
Gunnar Hjalmarsson

Tak, dziękuję, wiem o tym. Jest to konieczny krok, który powiedziałbym, ale niestety nie jest to, co chcę osiągnąć. W każdym razie dzięki.
grongor

Jest sposób na skryptowanie. Potrzebujesz tylko tych 3 aplikacji, czy są jeszcze inne? W zależności od tego, jak elastyczny ma być skrypt, napisanie go może zająć mi mniej więcej czasu
Sergiy Kolodyazhnyy

@JobobVlijm Brzmi jak kolejna dobra robota dla python;)
Sergiy Kolodyazhnyy

Wysłano odpowiedź. Daj mi znać, co myślisz
Sergiy Kolodyazhnyy

Odpowiedzi:


6

Wprowadzenie

Skrypt poniżej ustawia język dla każdego programu zdefiniowanego przez użytkownika, zgodnie z pozycją tego języka w menu języka. Na przykład, jeśli moje zamówienie to: angielski (1), chiński (2) i rosyjski (3), mogę ustawić Firefoksa na język 2, terminal na język 1 i LibreOffice na język 3.

Skrypt składa się z dwóch części: pierwsza to skrypt, który wykonuje zadanie, drugi skrypt służy jako element sterujący. Chodzi o to, aby uruchomić skrypt ustawiania języka jako aplikację startową i ilekroć trzeba ręcznie zmienić język - dwukrotnie kliknij skrót do skryptu kontrolera.

Warunki wstępne

  1. Zainstaluj wmctrlprogram za pomocą sudo apt-get install wmctrl.

Scenariusz

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

Skrypt kontrolera

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

Plik uruchamiający (.desktop) dla skryptu 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

Plik uruchamiania (.desktop) dla 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

Uruchamianie skryptu

  1. Utwórz folder w swoim katalogu domowym o nazwie bin. Możesz to zrobić w menedżerze plików lub użyć polecenia mkdir $HOME/binw terminalu
  2. W binfolderze utwórz dwa pliki: set-lang.shi set-lang-control.sh. Zapisz skrypt set-lang.shi skrypt kontrolera w set-lang-control.sh. Spraw, by oba skrypty były uruchamialnesudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. Utwórz dwa .desktoppliki. Jednym jest set-lang.desktop. Musi być umieszczony w ukrytym .config/autostartkatalogu. Drugim jest set-lang-controller.desktopumieszczenie go w binfolderze. Następnie przeciągnij i przypnij do programu uruchamiającego set-lang-controller.desktopplik. Stanie się skrótem do tymczasowego zatrzymania i wznowienia wykonywania skryptu.

UWAGA: wiersz Exec=musi zostać zmieniony, aby rzeczywista nazwa użytkownika znajdowała się w ścieżce do skryptu (ponieważ jest to rzeczywisty katalog domowy). Na przykład mój byłbyExec=/home/serg/bin/set-lang.sh

Objaśnienie i dostosowanie:

Sam skrypt działa w nieskończonej pętli while i sprawdza bieżące aktywne okno. Jeśli bieżące aktywne okno pasuje do jednej z opcji w strukturze sprawy, przełączamy się na odpowiedni język. Aby uniknąć ciągłego ustawiania, każda część struktury sprawy ma instrukcję if, która sprawdza, czy język został już ustawiony na żądaną wartość.

Podwójne kliknięcie programu uruchamiającego set-lang-controller.shspowoduje sprawdzenie stanu set-lang.shskryptu; jeśli skrypt jest uruchomiony - zostanie wstrzymany, a jeśli skrypt zostanie wstrzymany, zostanie wznowiony. Powiadomienie zostanie wyświetlone z odpowiednim komunikatem.

Aby dostosować skrypt, możesz otworzyć żądane aplikacje, uruchomić wmctrl -lxi zanotować trzecią kolumnę - klasę okna. Przykładowe dane wyjściowe:

$ 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

Wybierz odpowiednie klasy okien dla każdego programu. Następnie przejdź do części skryptu, która umożliwia dostosowanie i dodaj dwa wpisy dla PROG_CLASS i LANG. Następnie dodaj odpowiedni wpis w strukturze sprawy.

Na przykład, jeśli chcę dodać, LibreOffice's Writer, otwieram okno LibreOffice Writer, idę do terminalu i uruchamiam wmctrl -lx. Powie mi, że okno Writer ma klasę libreoffice.libreoffice-writer. Następnie przejdę do skryptu, dodam PROG_CLASS_4=libreoffice.libreoffice-writeri LANG4=3w odpowiednim obszarze. Zwróć uwagę na pasujący numer 4. Następnie przejdź do struktury sprawy i dodaj następujący wpis między ostatnim ;;a esac:

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

Ponownie zauważ znak $ i pasującą liczbę 4.

Ponadto, jeśli skrypt działa jako element autostartu i chcesz go tymczasowo zatrzymać, aby go dostosować, użyj pkill set-lang.shi wznów znohup set-lang.sh > /dev/null 2&>1 &

Mała uwaga: innym sposobem na znalezienie klasy okna dla programu (rzeczy, które występują przed pojedynczym okrągłym nawiasiem w strukturze obudowy) jest użycie tego xpropi awkoneliner:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}


Dziękuję, to całkiem niezły początek. Jedynym (ale głównym) problemem jest to, że nie będę w stanie zmienić języka w tych aplikacjach. Skrypt po prostu cały czas nadpisuje moje ustawienia. Chciałbym także móc zmienić język w tych oknach. Więc może dodaj jakieś sprawdzanie pid aplikacji i wymuś język dopiero za pierwszym razem czy coś takiego?
grongor

Wolałbym również, aby ten skrypt był sterowany zdarzeniami, a nie oparty na pętli. Nie jest to wielka sprawa, ale naprawdę byłbym wdzięczny, gdybyś mógł podać mały poradnik, jak to zrobić z dbus lub coś takiego (jeśli to możliwe).
grongor

@GRoNGoR, więc zastanowiłem się nad tym przez chwilę i jak dotąd nie widzę sposobu na wstrzymanie skryptu poza, kill -STOP $(pgrep set-lang.sh)a następnie wznowieniem skryptu kill -CONT $(pgrep set-lang.sh). W ten sposób możesz go zatrzymać, normalnie zmienić języki, a następnie wznowić.
Sergiy Kolodyazhnyy

Szybka myśl, którą miałem, to być może użycie skrótu klawiaturowego do dwóch poleceń może być sposobem, aby to zrobić, ale jeszcze tego nie przetestowałem, tylko jak dotąd teoria. Będę testować jutro, gdy tylko będę spać i
zdam

1
+1 za świetną i dokładną pracę! Dwie małe rzeczy, o których chciałbym wspomnieć: pliki wykonywalne ~/binnie potrzebują ścieżki (ani rozszerzenia, ponieważ jest ona dostępna $PATHpo ponownym zalogowaniu, zobacz: lintian.debian.org/tags/script-with-language-extension .html ), a można połączyć stop / start w jednym .desktoppliku; na szybkiej liście lub w funkcji przełączania. wygląda mi idealnie.
Jacob Vlijm,

1

Możesz zainstalować gxneurw tym celu, uruchamiając

sudo apt-get install gxneur

To oprogramowanie może automatycznie przełączać układy, ale nie jest do tego idealne.

Ale ma bardzo ładne narzędzia do konfigurowania ręcznych przełączników układu.

Możesz robić dokładnie to, co chcesz. Aby ustawić określone układy dla określonych aplikacji.


0

Poniższy skrypt to edytowana wersja tego , która jakiś czas temu została opublikowana jako podobne rozwiązanie dla pojedynczej aplikacji ( gnome-terminal).

Skrypt został częściowo przepisany na to pytanie, aby można go było używać do automatycznego ustawiania języków dla wielu aplikacji.

Jak korzystać w praktyce; automatycznie zapamiętuje ustawiony język dla aplikacji

Jeśli skrypt jest uruchamiany po raz pierwszy, obecny język jest przyjmowany jako domyślny język, który jest pamiętany w ukrytym pliku: ~/.lang_set.

Użycie jest wtedy proste: jeśli uruchomisz np. geditW najbardziej wysuniętym oknie i ustawisz inny język, język ten jest automatycznie łączony geditod tego momentu, dopóki nie zmienisz języka ponownie z geditprzodu.

Liczba określonych języków / aplikacji jest w zasadzie nieograniczona; wystarczy uruchomić aplikację i ustawić język z oknem aplikacji z przodu. Aplikacja zostanie automatycznie ustawiona i zapamiętana bez edycji kodu.

Zdarzenie napędzane?

Chociaż skrypt działa w pętli, zużycie zasobów jest minimalne. Kierowanie zdarzeniem oznaczałoby, że zdarzenie jest zmianą w oknie z przodu. Nie widzę innej opcji niż „szpiegowanie” okna z przodu, jak tylko sprawdzenie w pętli.

Scenariusz

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

Jak skonfigurować

  1. Skrypt korzysta zarówno xdotoola wmctrl:

    sudo apt-get install wmctrl xdotool
    
  2. Skopiuj powyższy skrypt do pustego pliku i zapisz go jako set_language.py

  3. Uruchom go testowo za pomocą polecenia:

    python3 /path/to/set_language.py
    
  4. Jeśli wszystko działa zgodnie z oczekiwaniami, dodaj go do aplikacji startowych: Dodaj do aplikacji startowych: Dash> Aplikacje startowe> Dodaj. Dodaj polecenie:

    python3 /path/to/set_language.py
    

Jeden rozmiar dla wszystkich! +1
Fabby,

Hej, dziękuję bardzo za to, przyjrzę się temu wkrótce i dam znać, jak się z tym czuję :)
grongor
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.