Ответ 1
xdotool
может это сделать.
xdotool getactivewindow
Я пытаюсь получить заголовок активного окна. Приложение является фоновой задачей, поэтому, если пользователь открывает Eclipse, функция возвращает "Eclipse - blabla", поэтому он не получает заголовок окна моего собственного окна. Я разрабатываю это в Python 2.6 с помощью PyQt4.
Мое текущее решение, заимствованное и слегка измененное из старого ответа здесь, в 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;
Но по какой-то причине окно всегда отсутствует.
У кого-то есть лучший способ получить текущий заголовок окна или как изменить один из моих способов, который работает для всех окон?
Edit:
В случае, если кто-то задается вопросом, так это то, как я нашел, что, похоже, работает для всех окон.
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
может это сделать.
xdotool getactivewindow
Я немного изменил ваше решение, чтобы он работал более эффективно (он передает параметры xprop, поэтому возвращаются только те данные, которые ему нужны). Кроме того, я не уверен, что необходимо буферировать вывод xprop, поэтому я взял это. Он также должен исправить возврат "Active window not found", если по какой-то причине он не может найти активное окно.
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"
Вы можете получить заголовок активного окна с помощью xdotool
:
$ xdotool getactivewindow getwindowname
Я вижу, что вопрос немного запутан, также поддержка Python 2 подходит к концу его запланированного срока службы, поэтому я решил упомянуть более версию Python 3'ic.
На самом деле, это, вероятно, лучше, чем просто стиль 3 - в Python 3 "Popen-объекты поддерживаются как контекстные менеджеры с помощью оператора with: при выходе стандартные файловые дескрипторы закрываются, и процесс ожидает".
Таким образом, приведенное ниже, вероятно, более адекватно и менее требовательно к ресурсам для новых Питонов:
(также, без with
, вы можете столкнуться с проблемами "слишком много открытых файлов", о которых я, конечно же, узнал довольно сложно :) - если вы будете достаточно часто запрашивать заголовок окна в 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"
Это слишком поздно, чтобы быть полезным, но это работает, и у меня есть программы, которые используют 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