【问题标题】:Get active window title in X在 X 中获取活动窗口标题
【发布时间】:2010-10-21 02:52:32
【问题描述】:

我正在尝试获取活动窗口的标题。该应用程序是一项后台任务,因此如果用户打开 Eclipse,该函数将返回“Eclipse - blabla”,因此它不会获得我自己窗口的窗口标题。我正在使用 PyQt4 在 Python 2.6 中开发它。

我目前的解决方案是从 SO 的旧答案借用并稍作修改的,如下所示:

def get_active_window_title():
    title = ''
    root_check = ''

    root = Popen(['xprop', '-root'],  stdout=PIPE)

    if root.stdout != root_check:
        root_check = root.stdout

        for i in root.stdout:
            if '_NET_ACTIVE_WINDOW(WINDOW):' in i:
                id_ = i.split()[4]
                id_w = Popen(['xprop', '-id', id_], stdout=PIPE)

        for j in id_w.stdout:
            if 'WM_ICON_NAME(STRING)' in j:
                if title != j.split()[2]:
                    return j.split("= ")[1].strip(' \n\"')

它适用于大多数窗口,但不是全部。例如,它找不到我的 kopete 聊天窗口,或我当前正在开发的应用程序的名称。

我的下一次尝试是这样的:

def get_active_window_title(self):
    screen = wnck.screen_get_default()
    if screen == None:
        return "Could not get screen"
    window = screen.get_active_window()
    if window == None:
        return "Could not get window"
    title = window.get_name()
    return title;

但出于某种原因,window 始终为 None。

是否有人有更好的方法来获取当前窗口标题,或者如何修改我的一种方法,适用于所有窗口?

编辑:

如果有人想知道这是我发现似乎适用于所有窗口的方式。

def get_active_window_title(self):
    root_check = ''
    root = Popen(['xprop', '-root'],  stdout=PIPE)

    if root.stdout != root_check:
        root_check = root.stdout

        for i in root.stdout:
            if '_NET_ACTIVE_WINDOW(WINDOW):' in i:
                id_ = i.split()[4]
                id_w = Popen(['xprop', '-id', id_], stdout=PIPE)
        id_w.wait()
        buff = []
        for j in id_w.stdout:
            buff.append(j)

        for line in buff:
            match = re.match("WM_NAME\((?P<type>.+)\) = (?P<name>.+)", line)
            if match != None:
                type = match.group("type")
                if type == "STRING" or type == "COMPOUND_TEXT":
                    return match.group("name")
        return "Active window not found"

【问题讨论】:

  • 如果stdout非空,是否有目的将stdout复制到root_check?
  • 进一步查看 Alex Spurlings 解决方案,他已将那部分排除在外。

标签: python linux pyqt4


【解决方案1】:

xdotool 可以做到。

xdotool getactivewindow

【讨论】:

  • 我查看了 xdotool 的源代码,它似乎也使用了 NET_ACTIVE_WINDOW,他们写了一条评论“xprop 的略微修改版本”。但我会试一试,看看他们的轻微修改是否能奏效。
【解决方案2】:

我稍微修改了您的解决方案,使其运行效率更高(它将参数传递给 xprop,因此只返回它需要的数据)。另外,我不确定是否有必要缓冲 xprop 的输出,所以我把它拿出来了。如果由于某种原因找不到活动窗口,它还应该正确返回“找不到活动窗口”。

def get_active_window_title(self):
    root = Popen(['xprop', '-root', '_NET_ACTIVE_WINDOW'], stdout=PIPE)

    for line in root.stdout:
        m = re.search('^_NET_ACTIVE_WINDOW.* ([\w]+)$', line)
        if m != None:
            id_ = m.group(1)
            id_w = Popen(['xprop', '-id', id_, 'WM_NAME'], stdout=PIPE)
            break

    if id_w != None:
        for line in id_w.stdout:
            match = re.match("WM_NAME\(\w+\) = (?P<name>.+)$", line)
            if match != None:
                return match.group("name")

    return "Active window not found"

【讨论】:

  • 很好,将使用它来代替。但我认为我已经正确返回“找不到活动窗口”。
  • 我认为我们可以使用if m: 而不是if m != None:
【解决方案3】:

您可以使用xdotool获取活动窗口标题:

$ xdotool getactivewindow getwindowname

【讨论】:

    【解决方案4】:

    这已经太晚了,但它确实有效,而且我有使用 wnck 的程序。

    wnck 示例需要调用screen.force_update(),然后wnck 才能工作。没有那个wnck 没有关于屏幕上窗口的任何信息。那就是:

    def get_active_window_title(self):
        screen = wnck.screen_get_default()
        if screen is None:
            return "Could not get screen"
        screen.force_update()
        window = screen.get_active_window()
        if window is None:
            return "Could not get window"
        title = window.get_name()
        return title
    

    【讨论】:

    • 它可能根本没有用,因为我希望改进从原始答案中提取的内容。我的目的是防止其他人错过。至于这个,我对wnck几乎一无所知。抱歉,这可能是一个愚蠢的问题,但它是否会造成部署问题 github.com/ssokolow/quicktile/issues/95
    • 这是绑定的问题。也许,我没有做太多的部署。
    【解决方案5】:

    我看到这个问题现在有点尘埃落定,对 Python 2 的支持也接近其预定生命周期的结束,所以我想我会提到一个更 Python 3'ic 的版本。

    事实上,它可能比更多的 3 样式更好——在 Python 3 中“通过 with 语句支持 Popen 对象作为上下文管理器:退出时,标准文件描述符被关闭,并等待进程”。

    因此,对于较新的 Python,以下内容可能更充足且资源消耗更少:

    (另外,如果没有withs,您可能会遇到“打开的文件太多”的问题——我当然很难发现这个问题:)——您是否应该在 Ubuntu 上足够频繁地查询窗口标题? 16 .)

        with Popen(['xprop', '-root', '_NET_ACTIVE_WINDOW'], stdout=PIPE) as root:
            for line in root.stdout:
                line = str(line, encoding="UTF-8")
    
                m = re.search('^_NET_ACTIVE_WINDOW.* ([\w]+)$', line)
                if m is not None:
                    id_ = m.group(1)
                    with Popen(['xprop', '-id', id_, 'WM_NAME'],
                               stdout=PIPE) as id_w:
                        for line in id_w.stdout:
                            line = str(line, encoding="UTF-8")
                            match = re.match("WM_NAME\(\w+\) = \"(?P<name>.+)\"$",
                                             line)
                        if match is not None:
                            return match.group("name")
                    break
        return "Active window not found"
    

    【讨论】:

    • 您可以将代码展平并取消嵌套 with 语句,因为每个 for 循环最多只能匹配一行。
    • 我知道,绝对是一个选择——我实际上做了相反的事情。但它说明了逻辑依赖关系和 with 概念(可能会为那些以前使用嵌入式 try finally 块操作的人敲响警钟)并且它并没有那么深(恕我直言,我同意有更严格的学校),而且它有点短。我个人的喜好是提取一个函数以使局部变量彼此远离,或者添加几个逻辑分组的 cmets。我不确定我是否缺少break,我不完全理解原始代码,但必须记下。忙碌的一天:)
    • (我会仔细看一下,因为它变得方便。感谢您的跟进!我的意思是我知道扁平化选项,而不是“最多一次”属性。)
    • 我添加了break——希望人们在此期间不要感到困惑。谢谢!
    猜你喜欢
    • 2013-02-06
    • 2010-10-03
    • 2023-04-10
    • 2015-05-03
    • 2018-08-10
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多