覆盖 KDE 中任意窗口的窗口标题并设置自定义窗口标题

覆盖 KDE 中任意窗口的窗口标题并设置自定义窗口标题

此处使用 KDE,但可能有一个也适用于其他桌面环境的解决方案。我经常要处理很多很多窗口。大多数窗口包含许多选项卡(例如,带有许多选项卡的 Dolphin 窗口,或 Firefox、Konsole 等)。窗口标题将根据我当前的选项卡进行更改(这在大多数情况下都是有用的),但是当使用如此多的窗口时,我想对它们进行一些组织并能够手动重命名窗口,覆盖应用程序给出的窗口标题。我可能会将一个 Firefox 窗口命名为“研究”,将另一个 Firefox 窗口命名为“文档”,以便能够轻松区分我用来相应组织和分组不同选项卡的窗口。

理想情况下,我能够单击窗口标题栏并轻松为其指定自定义名称,但只要它有效,我会选择稍微麻烦一点的解决方案。

我已经尝试过wmctrl -r :SELECT: -T "Research",但这只是暂时有效(当应用程序更改标题时,例如切换选项卡时,标题会恢复)。

答案1

我遇到了同样的问题。

所以我编写了一个绑定到热键的 shell 脚本。

当我按下热键时,它会获取当前活动窗口(具有焦点的窗口)的窗口 ID。

然后它会给您一个弹出对话框,您可以在其中输入您希望该窗口具有的标题。

然后,每次该窗口更改名称时,它都会将其更改回您想要的标题。

要使用该脚本,您需要:

  • shell (我用fish而不是bash写的fish
    因为bash让我头疼)

  • kdialog

  • 将脚本绑定到热键的某种方法
    (我使用xbindkeys,因为要让它工作我所要做的就是添加:

"[PATH TO SCRIPT]/[NAME OF SCRIPT]" Mod4 + t

(即,window 键 + t)
到 my /home/o1/.xbindkeysrc

谢谢这家伙,谁给了我有关神奇 xprop 的信息。

(就像一年前,然后直到今天我才开始写剧本。xD)

PS 如果任何新手找到这个答案并且不知道如何使用它,请问我,我会引导您完成它。 ^^

-t编辑:我更新了它,以便您可以通过fortitle_i_want-wfor开关从命令行使用它window_id

这是脚本:

#!/usr/local/bin/fish

# this block is so you can use it from the command line with -t and -w
if test "$argv" != "" -a (math (count $argv)%2 == 0)
    for i in (seq 1 (count $argv))
        if test $argv[$i] = '-t'
            set title_i_want $argv[(math 1 + $i)]
        else if test $argv[$i] = '-w'
            set window_id $argv[(math 1 + $i)]
        end
    end
    if not test $window_id
        echo "YOU DIDN'T ENTER A `window_id` WITH `-w`,
SO MAKE SURE THE WINDOW YOU WANT HAS FOCUS
TWO SECONDS FROM NOW!"
        sleep 2
    end
end

# get the id of the currently focused window
if not test $window_id
    set window_id (xprop -root _NET_ACTIVE_WINDOW | grep -P -o "0x\w+")
end

# get the title to force on that window

if not test $title_i_want
    set title_i_want (kdialog --title "entitled" --inputbox "type the title you want and hit enter.
to stop renaming,
just enter nothing and hit esc")
end

# this bit is needed for a kludge that allows window renaming
set has_renamed_before "FALSE"
set interrupt_message "WAIT WAIT I WANT A TURN BLOO BLOO BLEE BLUH BLOO" # hopefully i never want to actually use that as a title xD
xprop -f _NET_WM_NAME 8u -set _NET_WM_NAME $interrupt_message -id $window_id

# take the output of xprop
# pipe it into a while loop
# everytime it outputs a new line
# stuff it into a variable named "current_title"
xprop -spy _NET_WM_NAME -id $window_id | while read current_title

    # cut off extraneous not-the-title bits of that string
    set current_title (echo $current_title | grep -P -o '(?<=_NET_WM_NAME\(UTF8_STRING\) = ").*(?="\z)')

    # if the current title is the interrupt message
    # AND
    # this script has renamed the window at least once before
    # then we wanna let the new name take over
    if test $current_title = $interrupt_message -a $has_renamed_before = "TRUE"
        exit
    # if title_i_want is an empty string, exit
    else if test $title_i_want = ""
        xprop -f _NET_WM_NAME 8u -set _NET_WM_NAME "WIDNOW WILL START RENAMING ITSELF AS NORMAL" -id $window_id
        exit
    # otherwise just change the title to what i want
    else if test $current_title != $title_i_want
        xprop -f _NET_WM_NAME 8u -set _NET_WM_NAME "$title_i_want" -id $window_id
        set has_renamed_before "TRUE"
    end
end

编辑:实际上我不再使用这个 Fish 脚本了;
我用 Ruby 重写了它:

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'trollop'
opts = Trollop.options do
                        opt :title_i_want,  "title_i_want",     default: ""
                        opt :bluh,          "write to bluh",    default: nil
                        opt :copy_title,    "copy_title",       default: nil
# TODO - AUTO OPTION                                            
                        opt :auto,          "auto",             default: nil
end

title_i_want    = opts[:title_i_want]


def get_current_wid
    `xprop -root _NET_ACTIVE_WINDOW`[/0x\w+/]
end

def with_current_title wid, &block
    IO.popen("xprop -spy _NET_WM_NAME _NET_WM_ICON_NAME -id #{wid}") do |io|
        loop do
            line = io.gets
            exit if line.nil?
            line = line.strip
            # cut off extraneous not-the-title bits of that string
            current_title = line[/(?:_NET_WM_(?:ICON_)?NAME\(UTF8_STRING\) = ")(.*)("$)/, 1]

            block.call current_title unless current_title.nil?
        end
    end
end
def get_current_title wid
    IO.popen("xprop _NET_WM_NAME _NET_WM_ICON_NAME -id #{wid}") do |io|
            line = io.gets.strip
            # cut off extraneous not-the-title bits of that string
            current_title = line[/(?:_NET_WM_(?:ICON_)?NAME\(UTF8_STRING\) = ")(.*)("$)/, 1]

            return current_title unless current_title.nil?
    end
end

if opts[:copy_title]
    # require "muflax"
    p 1
    wid = get_current_wid
    `echo -n '#{get_current_title wid}(WID: #{wid})'|xclip -selection c`
    exit
end
if opts[:bluh]
    require "muflax"
    loop do
        # p 1   #db
        wid = get_current_wid
        # p 2   #db
        File.open "bluh", "a+" do |f| f.puts get_current_title wid end
        while wid == get_current_wid
            # puts "..."    #db
            sleep 1
        end
    end
    exit
end

#> 1A - from terminal - give title_i_want
if not title_i_want.empty?
#> 1A.1 - get current wid - assume it's the terminal_wid
    terminal_wid = get_current_wid
#> 1A.2 - wait for wid to change
    while get_current_wid == terminal_wid
        puts "focus the window you want to title «#{title_i_want}»..."
        sleep 1
    end
#> 1A.3 - set new wid to target TWID
    TWID = get_current_wid

#> 1B - from hotkey (or just sleeping) - no give title_i_want
else
#> 1B.1 - set current wid to target TWID
    TWID = get_current_wid
#> 1B.2 - get title_i_want (with kdialog)
#> 1B.2.1 - default to current title
    with_current_title TWID do |current_title|
        # v :current_title  #db
        default_title = current_title

        sublime_match = /
            (?<beginning>.*?)                                   # beginning might be...
                                                                #           path
                                                                #           untitled, find results, other useless junk
                                                                #           

答案2

你正在寻找的听起来像窗口标记设施。我怀疑 KDE 是否支持这一点,其他 WM(例如X莫纳德或 DWM 等)。

因此,实现生产率提升的一种可能性是以旧换新kwinXMonad配置 XMonad 进行标记。第二个链接中描述的 XMonad 标记机制将绑定一个组合键来打开一个提示,让您标记焦点窗口。 (XMonad 的配置实际上是一个 Haskell 程序,因此请随时在 #xmonad 中寻求帮助。

编辑:虽然我建议每个人至少尝试一下平铺 WM,但我忘记指出,虽然 XMonad 通常被称为平铺 WM,但它有一个“简单浮动”模式。当然还有其他 WM 支持标记和非平铺布局,但我不知道它们与 KDE 的互操作性。

答案3

由于无法将窗口标题设置为写保护,因此该问题将无法解决,因为正如您已经发现的那样,许多程序会根据不同的操作重置其标题。

但对于 KDE 和 Gnome 用户来说也许是一个很好的建议;-)

答案4

如果您可以从脚本启动要重新命名的窗口(然后您可以为其创建菜单项),那么这里有一个简单的版本。该脚本根据启动程序的 PID 来识别窗口。它每 2 秒重置一次标题,并在无法从 PID 获取窗口 ID 时退出。它以 vlc 为例。

#!/bin/bash

vlc &
VLCPID=$!

sleep 1 # Wait for VLC to build its window

while [ /bin/true ]
do

  WINDOW_ID=$(wmctrl -l -p | awk -v vpid=$VLCPID '$3 == vpid{ print $1 }')

  if [ -z ${WINDOW_ID} ]; then
    echo "No window ID found. Exiting."
    exit
  fi

  wmctrl -i -r ${WINDOW_ID} -N "new window title"
  sleep 2

done

相关内容