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


14

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

理想情况下,我可以单击窗口标题栏并轻松为其指定一个自定义名称,但我会选择一个解决方案,只要它可行,该解决方案就会比较麻烦。

我已经尝试过,wmctrl -r :SELECT: -T "Research"但是只能暂时使用(在应用程序更改标题时,例如在切换选项卡时,标题会还原)。


本地KDE应用程序确实具有--caption命令行选项,可用于设置窗口标题,但我认为这并不是您所要的。
大卫·Z

@SeanMadsen Heya,您还需要这个吗?如果您愿意,我很想知道是否可以让我的脚本为您工作。^^;
Owen_R 2015年

谢谢@Owen_R您的脚本有效,我在GitHub上为其添加了一个存储
肖恩

@SeanMadsen哈,我很高兴听到别人终于对我的答案有所帮助!尽管有趣的是,我本人不再使用该鱼脚本;我不久前用红宝石改写了它。不过,我实际上自己不会很快将它放到github上,因此,如果您愿意,我只是将其编辑到答案的结尾。
Owen_R

Answers:


4

我有这个完全相同的问题。

因此,我写了一个绑定到热键的shell脚本。

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

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

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

要使用脚本,您需要:

  • fish外壳
    (我写的鱼,而不是庆典庆典的Cuz让我头疼)

  • kdialog

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

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

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

感谢这个花花公子,他给了我有关神奇的xprop东西的信息。

(就像一年前一样,然后直到今天我再也没写过脚本。xD)

PS:如果有任何新手找到此答案并且不知道如何使用,请问我,我将带您逐步解决。^^

编辑:我对其进行了更新,以便您可以在命令行中使用-tfor title_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
                                                                #           𝌆 dired
            (?<dirty>\s•)?                                      # dirty?
            (?:\s\(\.?(?<projname>[^()]*)\))?                   # project name, preceded by "." (i name them that way), and in rkaks (sublime does that)
                                                                # or, sans dot, it's the dir, if the window was opened as a dir
            (?<issub>\s-\sSublime\sText\s2\s\(UNREGISTERED\))   # garbage at the end that marks it as a sublime window
        /x =~ current_title

        #if it's a sublime window...
        if sublime_match
            dummy = beginning.split("/")
            if dummy.length > 1
                taildir = dummy[-2]
            end
            /𝌆 (?<direddir>.*)/ =~ beginning

            default_title =
            if      projname    ;   projname
            elsif   taildir     ;   taildir
            elsif   direddir    ;   direddir
            else                ;   beginning
            end
        end

        if opts[:auto]
            title_i_want = default_title
        else
            title_i_want = `kdialog --title "entitled" --inputbox "type the title you want and hit enter.\nto stop renaming,\njust enter nothing and hit esc" '#{default_title}'`.chomp
        end
        break
    end
end


# v :terminal_wid   #db
# v :TWID           #db
# v :ARGV           #db
# v :title_i_want   #db


def set_title wid, title
    `xprop  -f _NET_WM_NAME 8u      -set _NET_WM_NAME       "#{title}"  -id #{wid}`
    `xprop  -f _NET_WM_ICON_NAME 8u -set _NET_WM_ICON_NAME  "#{title}"  -id #{wid}`
end


#> 2 - apply title to TWID
#> 2.1 - allow de-naming
#> 2.2 - allow renaming

# this bit is needed for a kludge that allows window renaming
has_renamed_before  = false
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 #{TWID}`

with_current_title TWID do |current_title|

    # if title_i_want is an empty string, exit
    if title_i_want.empty?
        # p 1   #db
        set_title TWID, "WINDOW WILL START RENAMING ITSELF AS NORMAL"
        exit

    # 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
    elsif current_title == interrupt_message and has_renamed_before
        # p 2   #db
        exit


    # otherwise just change the title to what i want
    elsif current_title != title_i_want
        # p 3   #db
        set_title TWID, title_i_want
        has_renamed_before = true
    end
end

是的,这对我有用!
肖恩

在GitHub上找到此脚本github.com/seanmadsen/kustom-window-title
Sean

ruby脚本在Kubuntu 16.04上似乎不起作用?我得到了弹出窗口,但是窗口标题没有改变。鱼脚本效果很好,但是!
超常

2

您正在寻找的声音听起来像是窗口标记工具。我怀疑KDE是否支持此功能,其他WM(例如XMonad或DWM等)是否支持。

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

编辑:虽然我建议大家至少在一段时间内尝试平铺WM,但我忘了指出,尽管XMonad通常被称为平铺WM,但存在“简单浮动”模式。当然,还有其他WM支持标记和非平铺布局,但是我不知道它们与KDE的互操作性。


1

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

但是对于KDE和Gnome的人来说可能是一个不错的建议;-)


0

我在寻找相同的东西,出于同样的原因。最终,用此70行脚本在此上花费了太多时间。

它是如何工作的?

  • 启动脚本
  • 单击您要设置标题的窗口
  • 然后输入您想要的标题

然后它将在后台启动循环,每3秒检查一次,并设置标题(如果更改)。

警告:不要在同一窗口上运行两次,脚本不是完美的。

示例脚本名称:sticky-title

#!/bin/bash


# stop all instance of this script if "killall" provided as first argument
if [ "$1" == "killall" ]; then
  scriptname=$(basename "$0")
  pattern="[0-9]* /bin/bash .*$scriptname$"
  pids=$(ps ax -o pid,cmd | grep -P "$pattern" | sed 's/^ *//;s/ *$//' | grep -Pv ' grep|killall$' | cut -d" " -f1)
  if [ "$pids" != "" ]; then
    kill -TERM $pids
    echo "$(echo '$pids' | wc -l) instances stopped"
  else
    echo "None found to stop"
  fi
  exit 0
fi

# ask for window
echo -en "\nClick the window you want to set its title "
id=$(printf %i $(xwininfo | grep 'Window id' | cut -d" " -f4))

# fail if no window id
if [ "$id" == "" ]; then
  echo 'Error: Window id not found'
  exit 1
else
  echo "- Got it"
fi

# ask for title
read -e -p "Enter target title: " title

# fail if no title
if [ "$title" == "" ]; then
  echo "Error: No title to set"
  exit 1
fi

# define loop as a function, so we can run it in background
windowByIdSetStickyTitle() {
  local id title curr_title
  id="$1"
  title="$2"

  while true; do
    # get current title
    curr_title="$(xdotool getwindowname $id 2>/dev/null)"

    # exit if we can't find window anymore
    if [ $? -ne 0 ]; then
      echo "Window id does not exist anymore"
      break
    fi

    # update title if changed
    if [ "$curr_title" != "$title" ]; then
      xdotool set_window --name "$title" $id
    fi

    # needed else you will eat up a significant amount of cpu
    sleep 3
  done
}

# infinite loop
windowByIdSetStickyTitle $id "$title" &


# done
echo "Sticky title set"
exit 0
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.