如何在Gnome Wayland上获得活动窗口?

时间:2022-03-31 20:36:29

Background: I'm working on a piece of software called ActivityWatch that logs what you do on your computer. Basically an attempt at addressing some of the issues with: RescueTime, selfspy, arbtt, etc.

背景:我正在开发一个名为ActivityWatch的软件,它可以记录您在计算机上执行的操作。基本上是尝试解决一些问题:RescueTime,selfspy,arbtt等。

One of the core things we do is log information about the active window (class and title). In the past, this has been done using on Linux using xprop and now python-xlib without issue.

我们做的核心事情之一是有关活动窗口(类和标题)的日志信息。在过去,这已经在使用xprop和现在的python-xlib的Linux上使用而没有问题。

But now we have a problem: Wayland is on the rise, and as far as I can see Wayland has no notion of an active window. So my fear is that we will have to implement support for each and every desktop environment available for Wayland (assuming they'll provide the capability to get information about the active window at all).

但现在我们遇到了一个问题:Wayland正在崛起,据我所知,Wayland没有一个活跃窗口的概念。所以我担心我们必须为Wayland可用的每个桌面环境实现支持(假设他们将提供获取有关活动窗口的信息的能力)。

Hopefully they'll eventually converge and have some common interface to get this done, but I'm not holding my breath...

希望他们最终能够融合并拥有一些共同的界面来完成这项工作,但我并没有屏住呼吸......

I've been anticipating this issue. But today we got our first user request for Wayland support by an actual Wayland user. As larger distros are adopting Wayland as the default display server protocol (Fedora 25 is already using it, Ubuntu will switch in 17.10 which is coming soon) the situation is going to get more critical over time.

我一直在期待这个问题。但是今天我们得到了Wayland用户对Wayland支持的第一个用户请求。由于较大的发行版采用Wayland作为默认的显示服务器协议(Fedora 25已经在使用它,Ubuntu将在17.10中切换,即将推出)随着时间的推移情况将变得更加重要。

Relevant issues for ActivityWatch:

ActivityWatch的相关问题:

There are other applications like ActivityWatch that would require the same functionality (RescueTime, arbtt, selfspy, etc.), they don't seem to support Wayland right now and I can't find any details about them planning to do so.

还有其他应用程序,如ActivityWatch需要相同的功能(RescueTime,arbtt,selfspy等),他们似乎现在似乎不支持Wayland,我找不到任何有关他们计划这样做的细节。

I'm now interested in implementing support for Gnome to start off with and follow up with others as the path becomes more clear.

我现在有兴趣实现对Gnome的支持,从而开始并跟进其他人,因为路径变得更加清晰。

A similar question concerning Weston has been asked here: get the list of active windows in wayland weston

这里有一个类似的关于韦斯顿的问题:在wayland weston中获取活动窗口的列表

Edit: I asked in #wayland on Freenode, got the following reply:

编辑:我在Freenode的#wayland问道,得到了以下回复:

15:20:44  ErikBjare    Hello everybody. I'm working on a piece of self-tracking software called ActivityWatch (https://github.com/ActivityWatch/activitywatch). I know this isn't exactly the right place to ask, but I was wondering if anyone knew anything about getting the active window in any Wayland-using DE.
15:20:57  ErikBjare    Created a question on SO: https://*.com/questions/45465016/how-do-i-get-the-active-window-on-gnome-wayland
15:21:25  ErikBjare    Here's the issue in my repo for it: https://github.com/ActivityWatch/activitywatch/issues/92
15:22:54  ErikBjare    There are a bunch of other applications that depend on it (RescueTime, selfspy, arbtt, ulogme, etc.) so they'd need it as well
15:24:23  blocage      ErikBjare, in the core protocol you cannot know which windnow has the keyboard or cursor focus
15:24:39  blocage      ErikBjare, in the wayland core protocol *
15:25:10  blocage      ErikBjare, you can just know if your window has the focus or not, it a design choise
15:25:23  blocage      avoid client spying each other
15:25:25  ErikBjare    blocage: I'm aware, that's my reason for concern. I'm not saying it should be included or anything, but as it looks now every DE would need to implement it themselves if these kind of applications are to be supported
15:25:46  ErikBjare    So wondering if anyone knew the teams working with Wayland on Gnome for example
15:26:11  ErikBjare    But thanks for confirming
15:26:29  blocage      ErikBjare, DE should create a custom extension, or use D-bus or other IPC
15:27:31  blocage      ErikBjare, I guess some compositor are around here, but I do not know myself if there is such extension already
15:27:44  blocage      compositor developers *
15:28:36  ErikBjare    I don't think there is (I've done quite a bit of searching), so I guess I need to catch the attention of some DE developers
15:29:16  ErikBjare    Thanks a lot though
15:29:42  ErikBjare    blocage: Would you mind if I shared logs of our conversation in the issue?                                     
15:30:05  blocage      just use it :) it's public                                                                                               
15:30:19  ErikBjare    ty :)

Edit 2: Filed an enhancement issue in the Gnome bugtracker.

编辑2:在Gnome bugtracker中提交了一个增强问题。

tl;dr: How do I get the active window on Gnome when using Wayland?

tl; dr:使用Wayland时如何在Gnome上获得活动窗口?

2 个解决方案

#1


2  

In my opinion the best choise you have is not Wayland or any available library (there are not one). Actually who know in gnome-wayland about the active windows is Mutter, so you need to find a way to ask to Mutter the active windows. Gnome can develp an API to internally ask to mutter the active window and restore the funcionality. But really, you have not a place to ask for it. Mutter will not develop an API to access to his internal representation, becasue this will be pretty specific of Mutter only and not to all Wayland windows manager. So this need to be added to an external library, where this library could talk probably with the current window manager that it's in use to resolve your request in a general way.

在我看来,你所拥有的最好的选择不是Wayland或任何可用的图书馆(没有一个)。实际上谁知道在gnome-wayland中关于活动窗口的是Mutter,所以你需要找到一种方法来向Mutter询问活动窗口。 Gnome可以开发API以在内部要求改变活动窗口并恢复功能。但实际上,你没有地方可以要求它。 Mutter不会开发API来访问他的内部表示,因为这只是Mutter的特定而不是所有Wayland的Windows管理器。因此,需要将其添加到外部库中,此库可能与当前窗口管理器进行通信,该管理器正在使用它以一般方式解析您的请求。

Another posibility is add a Wayland plugin where all windows manager will have a way to share the current active windows and in some way a library to talk directly with wayland to restore the funcionality.

另一个可能性是添加Wayland插件,其中所有窗口管理器将有一种方式来共享当前活动窗口,并以某种方式与库直接对话以恢复功能。

So, your app is in a big problem. Most you can do is request this on mutter (where is know the active windows), but in my opinion it can not be resolved in Mutter.

所以,你的应用程序是一个大问题。你可以做的最多就是在mutter上请求它(在哪里知道活动的窗口),但在我看来它无法在Mutter中解决。

I hope this will help you and you can find a way. Good loock.

我希望这会对你有所帮助,你可以找到一种方法。好loock。

#2


-1  

I have a script called preguiça.py, that does exactly what you're doing, though it is probably a lot simpler and I haven't released it.

我有一个名为preguiça.py的脚本,它正是你正在做的事情,虽然它可能更简单,我还没有发布它。

For my script, I acquired the window title using PyGObject's Window Navigator Construction Kit (Wnck).

对于我的脚本,我使用PyGObject的Window Navigator Construction Kit(Wnck)获取了窗口标题。

Here's a simplified version of it, with the essencial parts:

这是它的简化版本,包括基本部分:

from gi.repository import Wnck
from gi.repository import GObject

def changed (screen, window, data):
    print ("Changed!")
#    window = screen.get_active_window()
    if window:
        print ("Title: %s" % window.get_name())

screen = Wnck.Screen.get_default ()
screen.connect ("active-window-changed", changed, None)

mainLoop = GObject.MainLoop ()

try:
    mainLoop.run ()
except KeyboardInterrupt:
    print ("Hey")

mainLoop.unref ()

The actual code for what you're asking is actually commented out on the example above (I didn't need to capture the window, as the callback already receives it), but you may need it depending on your implementation.

您要问的实际代码实际上是在上面的示例中注释掉的(我不需要捕获窗口,因为回调已经接收到它),但您可能需要它,具体取决于您的实现。

I wrote it for X, and it didn't complain when I switched to Wayland, so it should probably work for you.

我为X写了它,当我切换到Wayland时没有抱怨,所以它应该适合你。

Note it doesn't get the information from Wayland, as you asked, but it is probably actually better, as it will be X/Wayland-agnostic. It got the title from an xterm I opened, so it should be toolkit-agnostic, as well.

请注意,它没有得到Wayland的信息,正如你所说,但它实际上可能更好,因为它将是X / Wayland不可知的。它得到了我打开的xterm的标题,所以它应该是与工具包无关的。

Don't ask me on the details of the implementation, though. The code is at least four years old :)

但是,请不要问我有关实施细节的问题。代码至少有四年了:)

#1


2  

In my opinion the best choise you have is not Wayland or any available library (there are not one). Actually who know in gnome-wayland about the active windows is Mutter, so you need to find a way to ask to Mutter the active windows. Gnome can develp an API to internally ask to mutter the active window and restore the funcionality. But really, you have not a place to ask for it. Mutter will not develop an API to access to his internal representation, becasue this will be pretty specific of Mutter only and not to all Wayland windows manager. So this need to be added to an external library, where this library could talk probably with the current window manager that it's in use to resolve your request in a general way.

在我看来,你所拥有的最好的选择不是Wayland或任何可用的图书馆(没有一个)。实际上谁知道在gnome-wayland中关于活动窗口的是Mutter,所以你需要找到一种方法来向Mutter询问活动窗口。 Gnome可以开发API以在内部要求改变活动窗口并恢复功能。但实际上,你没有地方可以要求它。 Mutter不会开发API来访问他的内部表示,因为这只是Mutter的特定而不是所有Wayland的Windows管理器。因此,需要将其添加到外部库中,此库可能与当前窗口管理器进行通信,该管理器正在使用它以一般方式解析您的请求。

Another posibility is add a Wayland plugin where all windows manager will have a way to share the current active windows and in some way a library to talk directly with wayland to restore the funcionality.

另一个可能性是添加Wayland插件,其中所有窗口管理器将有一种方式来共享当前活动窗口,并以某种方式与库直接对话以恢复功能。

So, your app is in a big problem. Most you can do is request this on mutter (where is know the active windows), but in my opinion it can not be resolved in Mutter.

所以,你的应用程序是一个大问题。你可以做的最多就是在mutter上请求它(在哪里知道活动的窗口),但在我看来它无法在Mutter中解决。

I hope this will help you and you can find a way. Good loock.

我希望这会对你有所帮助,你可以找到一种方法。好loock。

#2


-1  

I have a script called preguiça.py, that does exactly what you're doing, though it is probably a lot simpler and I haven't released it.

我有一个名为preguiça.py的脚本,它正是你正在做的事情,虽然它可能更简单,我还没有发布它。

For my script, I acquired the window title using PyGObject's Window Navigator Construction Kit (Wnck).

对于我的脚本,我使用PyGObject的Window Navigator Construction Kit(Wnck)获取了窗口标题。

Here's a simplified version of it, with the essencial parts:

这是它的简化版本,包括基本部分:

from gi.repository import Wnck
from gi.repository import GObject

def changed (screen, window, data):
    print ("Changed!")
#    window = screen.get_active_window()
    if window:
        print ("Title: %s" % window.get_name())

screen = Wnck.Screen.get_default ()
screen.connect ("active-window-changed", changed, None)

mainLoop = GObject.MainLoop ()

try:
    mainLoop.run ()
except KeyboardInterrupt:
    print ("Hey")

mainLoop.unref ()

The actual code for what you're asking is actually commented out on the example above (I didn't need to capture the window, as the callback already receives it), but you may need it depending on your implementation.

您要问的实际代码实际上是在上面的示例中注释掉的(我不需要捕获窗口,因为回调已经接收到它),但您可能需要它,具体取决于您的实现。

I wrote it for X, and it didn't complain when I switched to Wayland, so it should probably work for you.

我为X写了它,当我切换到Wayland时没有抱怨,所以它应该适合你。

Note it doesn't get the information from Wayland, as you asked, but it is probably actually better, as it will be X/Wayland-agnostic. It got the title from an xterm I opened, so it should be toolkit-agnostic, as well.

请注意,它没有得到Wayland的信息,正如你所说,但它实际上可能更好,因为它将是X / Wayland不可知的。它得到了我打开的xterm的标题,所以它应该是与工具包无关的。

Don't ask me on the details of the implementation, though. The code is at least four years old :)

但是,请不要问我有关实施细节的问题。代码至少有四年了:)