开发者

Get active window title in X

I'm trying to get the title of the active window. The application is a background task so if the user has Eclipse open the function returns "Eclipse - blabla", so it's not getting the window title of my own window. I'm developing this in Python 2.6 using PyQt4.

My current solution, borrowed and slightly modified from an old answer here at SO, looks like this:

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\"')

It works for most windows, but not all. For example it can't find my kopete chat windows, or the name of the application i'm currently developing.

My next try looks like this:

def get_active_window_title(self):
    screen = wnck.screen_get_default()
    if screen == None:
        return "Could not get screen"
    window = scree开发者_StackOverflow中文版n.get_active_window()
    if window == None:
        return "Could not get window"
    title = window.get_name()
    return title;

But for some reason window is always None.

Does somebody have a better way of getting the current window title, or how to modify one of my ways, that works for all windows?

Edit:

In case anybody is wondering this is the way I found that seems to work for all windows.

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"


xdotool can do that.

xdotool getactivewindow


I modified your solution slightly so it should run more efficiently (it passes parameters to xprop so only the data it needs is returned). Also, I'm not sure it's necessary to buffer the output of xprop so I took that out. It should also correct return "Active window not found" if for some reason it can't find the active window.

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"


You can get the active window title with xdotool:

$ xdotool getactivewindow getwindowname


This is too late to be useful but it does work and I have programs that use wnck.

The wnck example needs a call to screen.force_update() before wnck will work. Without that wnck does not have any information about the windows on the screen. That is:

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


I see that the question is a bit dusty by now, also support for Python 2 is nearing the end of its scheduled lifetime, so I thought I'd mention a more Python 3'ic version.

In fact, it's probably better than just more 3-style - in Python 3 "Popen objects are supported as context managers via the with statement: on exit, standard file descriptors are closed, and the process is waited for".

Thus the below is probably more adequate and less resource hungry for newer Pythons:

(also, without withs, you might bump into 'too many open files' problems - which I of course found out about in the hard way :) - should you query for the window title frequently enough on 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"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜