如何永久更改窗口标题?


17

生成窗口标题涉及哪些文件?例如,如果打开Rhythmbox,您会看到程序名称作为窗口标题。但是它不是由.desktop文件生成的。我需要编辑哪个文件才能在应用程序标题中添加文本?我希望更改是永久的

我将Ubuntu GNOME 15.04与GNOME 3.16一起使用。


嗨,莫德 我喜欢您的问题,它为您提供了一个很好的解决方案。但是,我不能抗拒地提一提以后的问题要记住的一件事:请不要在发布答案大幅度改变问题的含义。它做出的答案本来可以适当地张贴在问题的第一个版本上,但似乎放在编辑后的版本上。我认为这就是我的答案实际发生的情况。如果重新考虑您的问题,我建议您发布一个新问题,尤其是针对您的实际问题。
Jacob Vlijm

1
我理解您的意见,我当然会在以后的问题中做到这一点,因为我可以看到这可能会给人们造成很大的困扰。我当然不会低估您对线程的贡献,请明确说明。我希望标题更加具体,因为原始标题实际上并未涵盖我的真实问题,并且使我对该线程的目标有所不确定。谢谢你的帮助!:)
Maud Kon

Answers:


21

初始名称通常由应用程序本身(中的代码)设置。但是,您可以更改它,例如,使用xdotool,您必须先安装它:

sudo apt-get install xdotool

然后,一旦安装,您可以通过(例如)以下命令设置另一个窗口名称:

xdotool search --name "Unity LauncherSwitcher" set_window --name "Monkey"

这将改变:

在此处输入图片说明

变成:

在此处输入图片说明

注意

如您所见,该命令存在于:

xdotool search --name "<current_name>" set_window --name "<new_name>"

<current_name>具有完全匹配。


替代编辑

根据您的评论,我了解上面的命令不起作用。我用不同的应用程序对其进行了测试,并且可以正常工作...

但是由于某种原因,我不明白,不可以Rhytmbox(!!可能是一个错误)

一种替代方法是使用wmctrl,您还必须安装:

sudo apt-get install wmctrl

然后使用以下命令:

xprop -id "$(wmctrl -l | grep 'Rhythmbox' | awk '{ print $1 }')" -set WM_NAME "Music"

我在上成功测试了它Rhythmbox

在此处输入图片说明

在此处输入图片说明

是否使更改永久生效?

如前所述,默认窗口名称在应用程序的代码中定义。

更改默认窗口标题将需要更改代码。如果代码可用,在很多情况下需要重新编译,并且取决于所使用的语言,则可以这样做。我认为,一般性的指导是完全不可能的,并且超出(超出)非盟的范围。


编辑2

通过单个文件灵活地管理/设置每个应用程序的自定义窗口名称

在您最初的问题中,您想知道是否存在某种文件来设置特定应用程序的新窗口的标题。如前所述,不是这种情况,但是可以创建它。

在下面的设置中,您可以轻松地在每个应用程序基础上定义新窗口的命名方式。只需在~(您的主目录)中创建一个名为的文件window_names.txt。对于要为其设置特定窗口名称的每个应用程序,在其后依次添加一行应用程序和所需的窗口名称:

文本文件,定义每个应用程序的窗口名称

gnome-terminal Monkey eats
gedit Banana
rhythmbox if he runs out of peanuts

在此处输入图片说明

说明

该设置存在一个简单的后台脚本。该脚本非常简短,因此对性能不会有任何明显的影响。

脚本启动后,它将读取文件~/window_names.txt并为每个应用程序加载设置。然后,它会关注创建的窗口。如果出现一个属于文件中定义的应用程序之一的窗口,它将相应地设置窗口名称。

如何设定

  1. 该脚本同时使用wmctrlxdotool

    sudo apt-get install wmctrl
    sudo apt-get install xdotool
    
  2. 将脚本复制到一个空文件中,另存为 setwindowname.py

  3. 创建文件~/window_names.txt(完全命名为window_names.txt),然后以以下格式添加您的应用程序:

    <application> <window_name>
    

    例如

    gedit Text editor
    

    窗口名称可能包含空格。

  4. 通过以下命令从终端测试脚本:

    python3 /path/to/setwindowname.py
    
  5. 如果一切正常,请将其添加到启动应用程序:Dash>启动应用程序>添加

    请注意,在某些情况下,如果在桌面尚未完全加载时启动脚本,则脚本可能会中断。如果是这种情况,添加到启​​动应用程序中的命令将是:

    /bin/bash -c "sleep 15&&python3 /path/to/setwindowname.py"
    

剧本

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

f = os.environ["HOME"]+"/"+"window_names.txt"

change = []
lines = open(f).read().splitlines()
for l in lines:
    try:
        change.append([l.split()[0], (" ").join(l.split()[1:])])
    except IndexError:
        pass

get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()
curr_1 = []

while True:
    try:
        curr_2 = get(["wmctrl", "-lp"]).splitlines()
        new = [w for w in curr_2 if not w in curr_1]
        for item in new:
            line = item.split(); pid = line[2]
            procs = get(["ps", "-e"]).splitlines()
            match = [l for l in procs if pid in l][0]
            for app in [app for app in change if app[0] in match]:
                subprocess.Popen(["xdotool", "set_window", "--name", app[1], line[0]])
        curr_1 = curr_2
        time.sleep(0.3)
    except:
        pass

笔记

  • 如果文件~/window_names.txt被编辑,则脚本需要重新启动。
  • 无论如何启动应用程序,它都有效。当从终端/和使用或运行应用程序时,它也可以工作sudo
  • 它与任何应用程序的右键单击选项都不兼容。
  • 该脚本还可以“维护”窗口名称。如果另一个进程随后更改了窗口名称(打开选项卡,例如更改目录),则脚本会将窗口视为“新窗口”,并保留您选择的窗口名称。

抱歉,这对我不起作用。
Maud Kon

xdotool search --name "Rhythmbox" set_window --name "Music" 我在打开,关闭应用程序的情况下执行了该命令,然后重新启动(alt + f2 + r)来检查其是否有效,但仍显示相同的窗口标题。
莫德·康

哇!这次我真的很感动!早上我会尝试第一件事。我必须说,这看起来非常令人鼓舞:)感谢您的辛勤工作并将其发布,雅各布!
莫德·康

我完全按照您说的那样尝试了该脚本,但是它不起作用。这可能不适用于GNOME 3.16还是应该在我的设置中使用?我现在对此感到困惑,并希望使其在我的系统上运行。如果我发现它仍然无法运行的原因,我会尽快与您联系。
莫德·康

1
@MaudKon您可能已经编辑了设置文件,并且可能在最后无意间添加了一条或多条白线。我为此“免疫”了脚本。您现在可以使用任意多的白线:)
Jacob Vlijm 2015年

9

标题是由应用程序可执行文件生成的,没有简单的方法对其进行编辑。


打开应用程序后更改其标题:

  • xdotool与安装sudo apt-get install xdotool
  • 使用pgrep myapp(即pgrep rythmbox)获取应用程序的pid
  • 更改窗口标题(替换HERE_THE_PID为应用程序的进程ID):

    xdotool search --onlyvisible --pid HERE_THE_PID --name "\a\b\c" set_window --name "$new_name"
    

编写脚本以启动具有自定义标题的任何应用程序:

  • 创建一个change-title具有以下内容的bash脚本:

    #!/bin/bash
    
    ## The new name of the window is the first argument passed to the script:
    new_name="${1}"
    
    ## application is all arguments but the first (the title)
    application=${@:2}
    
    ## Run the app in background and in quiet mode:
    $application &> /dev/null &
    
    ## Get the pid of the app:
    app_pid=$!
    
    ## Wait until the window appears:
    until xdotool search --onlyvisible --pid $app_pid &> /dev/null; do sleep 0.01; done
    
    ## Change the window name:
    xdotool \
             search \
                    --onlyvisible \
                    --pid $app_pid \
                    --name "\a\b\c" \
             set_window \
                    --name "$new_name"
    
    ## Comment this line to run the app in background:
    wait $app_pid
    
  • 使它可执行 chmod a+x change-title

  • 运行它 ./change-title "NewTitle" theapp --its-arguments

要使更改永久生效:

  • 运行gksudo gedit /usr/local/bin/custom-title(fx用户/本地/ bin /音乐)
  • 在文本编辑器上,粘贴上面的脚本并保存。
  • sudo chmod a+x /usr/local/bin/custom-title
  • gksudo gedit /usr/share/applications/rhythmbox.desktop
  • 在此文件上,有一行(我的行号是35)说:

    Exec=rhythmbox %U
    
  • 将其替换为创建的文件名:

    Exec=custom title (fx. Exec=music)
    
  • 将文件另存为新的custom-name.desktop fx。music.desktop。注意不要覆盖原始文件!

使更改对“打开方式”功能有效

  • gksudo gedit /usr/share/applications/rhythmbox-device.desktop
  • 更改rhythmbox为上一个.desktop文件中使用的名称。
  • 保存文件。
  • 使用系统监视器或通过使用命令杀死节奏盒的活动进程 sudo kill rhythmbox
  • 插入您的手机/音乐播放器,然后按“打开方式(音乐应用程序)”以查看其是否有效。

(摘要)您应该拥有的文件概述

为了使应用程序完全正常运行,/usr/share/applications完成后应该包含3个.desktop文件:

  1. music.desktop 或您提供的名称

    Exec=musicHidden=true(如果不存在则添加最后一个)

  2. rhythmbox.desktop

    Exec=rhythmbox %UHidden=true

  3. rhythmbox-device.desktop

    使用Exec=music --select-source %U使用隐藏条目

这意味着您始终打开最后一个文件,标题始终保持应有的状态。重置自身的唯一方法是使用ALT + F2 + R刷新会话。

  1. 当然,您应该拥有bash脚本/usr/local/bin

最后说明:

  • 当我使用的--name "\a\b\c"是修复错误时,请不要用应用程序名称替换!
  • 如果您取消注释脚本的最后一行,则脚本将在应用程序关闭之前结束。
  • 的交代${@:2}中所要求的代码@Maud昆

    1. $@ 是一个存储所有位置参数的数组。
    2. ${@:2}表示:除第一个位置参数外的所有位置参数
    3. 假设我以这种方式调用程序:

      awesome-program foo bar baz fooz
      
      • ${@:1} 将会 foo bar baz fooz
      • ${@:2} 将会 bar baz fooz
      • ${@:3} 将会 baz fooz
      • ${@:4} 将会 fooz
      • ${@:5} 为空,因为没有更多的位置参数。
    4. $@${@}并且${@:1}是同一件事:所有位置参数。

    5. 在此处了解有关此主题的更多信息:http : //wiki.bash-hackers.org/scripting/posparams

我已经尝试了两种方式(这里也是一种方式),并且您的bash脚本部分起作用。它会使用新名称启动一个新窗口,但是如果我再次从概述中启动它,它仍然具有旧条目...我在做错什么吗?
莫德·康

@MaudKon:概述是什么?立即尝试脚本。如果您将“概述”称为破折号(包含许多应用程序的大面板),我会告诉您我的脚本不会进行永久更改。
Helio

我的意思是应用程序概述,我已经隐藏了破折号本身,哈哈。嗯,是的,比您的脚本有用。是否有使变更永久化的方法?就像用fx编辑可执行文件一样。GHex?或更改.desktop文件中的可执行文件?
Maud Kon

现在试试。使用新脚本并按照“ 使更改永久生效 ”部分下的方法进行操作。现在我知道您正在伪装您的Ubuntu ;-)
Helio,2015年

1
@Helio我用对我有用的步骤更新了您的帖子。我还添加了使“打开方式”功能起作用的过程。
莫德·康

2

只需使用翻译文件!

我对Thunar 遇到了一个非常棘手的挑战:当Compiz Scale将Thunar窗口标题显示为“ AnyFolder-File Manager”并占用了不必要的信息时,这变得很烦人。

我用xdotool和尝试了上述方法,wmctrl但是它们并不是永久的,因为Thunar每次我转到另一个文件夹时都会更改其窗口标题。每次Thunar更改标题时,都会在后台闲坐一个脚本来更改标题,这感觉有点夸张。

一个更简单的解决方案是使用每个应用程序随附的翻译文件。您只需要msgfmt使用gettext软件包中包含的工具重新编译翻译源文件。我只是为gThumb做到了这一点-只是为了好玩-并且它也起作用。

1.获取有关应用程序的源代码。
输入 或转到http://packages.ubuntu.com,获取源代码并查找名为的文件夹:该文件夹包含纯文本语言文件。寻找您的语言。假设您来自巴西,该文件将是$ sudo apt-get source APPLICATIONpopt_BR.po

2.根据您的需要更改文件
寻找确切的文件!您想要摆脱或更改的窗口标题。在Thunar的情况下是“文件管理器”,在pt_BR.po我发现

:. set window title
: ../thunar/thunar-window.c:3154 ../Thunar.desktop.in.in.h:3
: ../thunar/thunar-settings.desktop.in.h:1
msgid "File Manager"
msgstr "Gerenciador de arquivos"

这里msgid是应用程序发送的信号和msgstr什么LangPack的将其转换为。
更改msgstr为您喜欢的任何东西,即msgstr "o_-"
我了解到,如果您将翻译留空,msgstr ""则应用程序将退回到msgid。如果希望它为“空”,请使用空格。或一个点。或任何时髦的ASCII符号。

3.获取编译器
如前所述,您需要msgfmtgettext程序包中输入内容,因此需要输入
$ sudo apt-get install gettext

4.编译
打开一个终端,进入修改后的文件夹pt_BR.po并让msgfmt检查文件是否存在错误:
$ msgfmt --check --check-accelerators=_ -o /dev/null pt_BR.po
如果可以,请继续编译:
$ msgfmt -c -o pt_BR.mo pt_BR.po

5.放置文件
看一下/ usr / share / locale / YOUR_LANGUAGE / LC_MESSAGES // usr / share / locale-langpack / YOUR_LANGUAGE / LC_MESSAGES /中原始翻译的命名方式,并将文件放置在此处。如果两个地方都不存在,请将其放在其中一个位置,然后尝试使用文件名:小写,Camelcase或类似的名称,即gthumb.moYOUR-APP.mo
首先备份原始文件: 然后在其中复制新翻译
$ sudo cp /usr/share/locale/YOUR_LANGUAGE/LC_MESSAGES/YOUR-APP.mo /usr/share/locale/YOUR_LANGUAGE/LC_MESSAGES/YOUR-APP.mo.BAK

$ sudo cp pt_BR.mo /usr/share/locale/YOUR_LANGUAGE/LC_MESSAGES/YOUR-APP.mo

如果YOUR_APP正在运行,请关闭它的所有实例。
测试一下!

暗示 如果像我一样,正在运行具有EN本地化功能的Ubuntu,只需使用任何* .po,从中删除或注释所有未更改的msgid / msgstr对,并将其放在/ usr / share / locale / en / LC_MESSAGES /中

资料来源:http :
//wiki.xfce.org/translations/translation_guidance_in_xfce


仅作记录;我怀疑您实际上尝试过该脚本,因为它保留了名称,如答案中所述。
Jacob Vlijm 2015年

没错,我没有尝试过脚本,而是从其他地方尝试了一个(简单)脚本,以及xdotool和wmctrl的技巧。如前所述,对我来说,与在源文件中更改一行相比,感觉就像是用大炮射击麻雀。但是,可以从脚本中学到很多东西。
ronso0

我很好奇如果升级应用程序会发生什么。* .desktop文件和本地化文件是否被覆盖?
ronso0

由于这里解释askubuntu.com/a/703942/72216,我不同意的fobia的背景剧本,如果它是写得很好,添加了重要的功能。关于.desktop文件:同样,您必须将我的答案与可能已经读过的另一个答案混淆。答案不会编辑.desktop文件,重新安装应用程序时无需采取任何措施。
Jacob Vlijm

这是一个普遍的问题,因为答案2会修改.desktop文件,而我会翻译文件。你知道吗?而且,自从我现在阅读“ mu__Incoming-”(其中有“ mu__Incoming-文件管理器”)以来,我可能会给任何脚本解决方案第二次机会。对于具有静态窗口标题但没有任何“路径/目标/文件夹”的应用程序,我的解决方案可以正常工作。
ronso0

1

用wmctrl替换(部分)窗口标题

由于我自己使用该应用程序的翻译文件所做的回答不足以满足我的要求,因此我以Jacob Vlijm的解决方案为基础,并修改了他的脚本以替换窗口标题中的某些字符串。我希望可以单独发布此答案。致谢Jacob Vlijm提出想法并设置脚本!

例如,我喜欢阅读Some fancy website而不是Some fancy website - Mozilla Firefox。现在,Compiz扩展插件更加清晰了,因为我也删除了- File manager其他字符串。

我所做的更改:

  1. 使用//作为分隔符在window_names.txt允许的空格
  2. 使用wmctrl而不是xdotool修改窗口标题(因为xdotool不能很好地处理非ASCII字符):wmctrl -i -r [WindowIdentifier] -N 'new Title'
  3. 脚本中一些额外的行来进行字符串替换等。

修改后window_names.txt的结构如下:
[process name]//[exact text to replace]//[replacement text]

firefox// - Mozilla Firefox// (whitespace!)
thunar// - File Manager// ° xyz
gedit// - gedit// - 123

imp脚的脚本:

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

f = os.environ["HOME"]+"window_names.txt"

change = []
lines = open(f).read().splitlines()
for l in lines:
    try:
        change.append(l.split("//"))
    except IndexError:
        pass

get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()
curr_1 = []

while True:
    try:
        curr_2 = get(["wmctrl", "-lp"]).splitlines()
        new = [w for w in curr_2 if not w in curr_1]

        for item in new:
            line = item.split(None, 4)
            winID = line[0] ; pid = line[2] ; currentTitle = line[4]
            procs = get(["ps", "-e"]).splitlines()
            match = [l for l in procs if pid in l][0]
            for app in [app for app in change if app[0] in match]:
                newTitle = str.replace(currentTitle, app[1], app[2])
                subprocess.Popen(["wmctrl", "-i", "-r", winID, "-N", newTitle])
        curr_1 = curr_2
        time.sleep(0.3)
    except:
        pass

再次:致谢Jacob Vlijm提出想法并设置了脚本!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.