是否可以为特定应用程序指定默认键盘语言?我知道有一个选项可以始终使用默认键盘语言启动应用程序,但这不是我想要的。
我正在寻找类似于“固定工作区”的东西,可以使用CompizConfig进行设置(将Chrome设置为始终在X1Y1处打开,在X2Y1处打开终端等)。我要设置Chrome的地方:捷克语,终端:英语,Spotify:英语,...
是否可以为特定应用程序指定默认键盘语言?我知道有一个选项可以始终使用默认键盘语言启动应用程序,但这不是我想要的。
我正在寻找类似于“固定工作区”的东西,可以使用CompizConfig进行设置(将Chrome设置为始终在X1Y1处打开,在X2Y1处打开终端等)。我要设置Chrome的地方:捷克语,终端:英语,Spotify:英语,...
Answers:
介绍
下面的脚本根据语言菜单中该语言的位置设置每个用户定义程序的语言。例如,如果我的订单是:英语(1),中文(2)和俄语(3),则可以将Firefox设置为使用语言2,将终端设置为语言1,将LibreOffice设置为语言3。
该脚本分为两部分:第一部分是完成任务的实际脚本,第二部分充当控制元素。想法是将语言设置脚本作为启动应用程序运行,并且每当您需要手动更改语言时-双击控制器脚本的快捷方式。
先决条件
wmctrl
程序sudo apt-get install wmctrl
。脚本
#!/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
控制器脚本
#!/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
set-lang.sh脚本的启动器(.desktop)文件
[Desktop Entry]
Name=set-lang.sh
Comment=Script to set languages
Exec=/home/yourusername/bin/set-lang.sh
Type=Application
StartupNotify=true
Terminal=false
set-lang-controller.sh的启动器(.desktop)文件
[Desktop Entry]
Name=lang-control
Comment=Shortcut to controlling script
Exec=/home/yourusername/bin/set-lang-control.sh
Type=Application
StartupNotify=true
Terminal=false
使脚本正常工作
bin
。您可以在文件管理器中执行此操作,也可以mkdir $HOME/bin
在终端中使用命令bin
文件夹中创建两个文件:set-lang.sh
和set-lang-control.sh
。将脚本保存到set-lang.sh
,将控制器脚本保存到set-lang-control.sh
。使两个脚本都可以执行sudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
.desktop
文件。一个是set-lang.desktop
。必须放置在隐藏.config/autostart
目录中。第二个是set-lang-controller.desktop
,可以放在您的bin
文件夹中。接下来,将set-lang-controller.desktop
文件固定在启动器上。这将成为临时停止和恢复脚本执行的快捷方式。注意,Exec=
必须更改该行以在脚本的路径中具有您的实际用户名(因为这是您的实际主目录)。例如,我的会是Exec=/home/serg/bin/set-lang.sh
说明和定制:
该脚本本身在无限while循环中运行,并检查当前活动窗口。如果当前活动窗口与案例结构中的选项之一匹配,我们将切换到适当的语言。为了避免不断进行设置,案例结构的每个部分都有if语句,该语句检查语言是否已设置为所需的值。
双击启动器set-lang-controller.sh
将检查set-lang.sh
脚本的状态。如果脚本正在运行-将被暂停,如果脚本被暂停,将被恢复。通知将显示并带有适当的消息。
为了自定义脚本,您可以打开所需的应用程序,运行wmctrl -lx
并注意第三列-窗口类。样本输出:
$ 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
为每个程序选择适当的窗口类。接下来,转到允许自定义的脚本部分,并为PROG_CLASS和LANG添加两个条目。接下来,在案例结构中添加适当的条目。
例如,如果要添加LibreOffice Writer,则打开LibreOffice Writer窗口,转到终端并运行wmctrl -lx
。它会告诉我Writer窗口具有class libreoffice.libreoffice-writer
。接下来,我将转到脚本,在适当的区域中添加PROG_CLASS_4=libreoffice.libreoffice-writer
和LANG4=3
。注意匹配数字4。接下来,转到案例结构,并在last ;;
和之间添加以下条目esac
:
$PROG_CLASS_4)
if [ $CURRENT -ne $LANG4 ];then
gsettings set org.gnome.desktop.input-sources current $LANG4
fi
;;
再次注意$符号和匹配数字4。
另外,如果脚本正在作为自动启动项运行,并且您想要暂时停止以对其进行自定义,请使用pkill set-lang.sh
并继续nohup set-lang.sh > /dev/null 2&>1 &
小提示:找出程序的窗口类的另一种方法(在case结构中位于单个圆括号之前的内容)是使用this xprop
和awk
oneliner:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}
kill -STOP $(pgrep set-lang.sh)
再用来恢复脚本kill -CONT $(pgrep set-lang.sh)
。这样,您可以暂停它,正常切换语言,然后继续。
~/bin
不需要路径(也不需要扩展名,因为它是$PATH
重新登录后进入的,请参见:lintian.debian.org/tags/script-with-language-extension .html),则可以将停止/启动合并到一个.desktop
文件中;在快速列表或切换功能中。对我来说看起来很完美。
下面的脚本是经过编辑的版本这一个,这是张贴了类似的解决方案单个应用程序(gnome-terminal
)前一阵子。
该脚本已针对该问题进行了部分重写,以便能够将其用于自动为多个应用程序设置语言。
如果脚本是第一次启动,则假定当前语言为默认语言,该语言会在一个隐藏文件中记住:~/.lang_set
。
这样的用法很简单:例如gedit
,如果在最前面的窗口中运行,并设置了另一种语言,则该语言将自动与之连接gedit
,直到您再次gedit
在前面更改语言为止。
特定语言/应用程序的数量原则上不受限制;只需运行该应用程序并在前面的应用程序窗口中设置语言。该应用程序将自动设置并记住,而无需编辑代码。
尽管脚本确实是在循环中运行,但是资源消耗最少。事件驱动将意味着该事件是最前面窗口中的更改。除了检查循环以外,我没有看到其他选项,只能“监视”最前面的窗口。
#!/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
该脚本同时使用xdotool
和wmctrl
:
sudo apt-get install wmctrl xdotool
将上面的脚本复制到一个空文件中,另存为 set_language.py
通过以下命令进行测试:
python3 /path/to/set_language.py
如果所有功能均按预期工作,则将其添加到“启动应用程序”:添加到“启动应用程序”:Dash>“启动应用程序”>“添加”。添加命令:
python3 /path/to/set_language.py