简体   繁体   English

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

[英]How do I get the active window on Gnome Wayland?

Background: I'm working on a piece of software called ActivityWatch that logs what you do on your computer.背景:我正在开发一款名为ActivityWatch的软件,它可以记录您在计算机上的操作。 Basically an attempt at addressing some of the issues with: RescueTime, selfspy, arbtt, etc.基本上是尝试解决一些问题: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.过去,这是在 Linux 上使用 xprop 和现在的 python-xlib 完成的,没有问题。

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.但现在我们有一个问题: Wayland 正在崛起,据我所知,Wayland 没有活动窗口的概念。 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 可用的每个桌面环境实现支持(假设他们将提供获取活动窗口信息的能力)。

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.但是今天,我们收到了一位实际 Wayland 用户对 Wayland 支持的第一个用户请求 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 作为默认显示服务器协议(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此处提出了有关韦斯顿的类似问题: get the list of active windows in 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://stackoverflow.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 上获取活动窗口?

The two previous answers are outdated, this is the current state of querying appnames and titles of windows in (Gnome) Wayland.前两个答案已过时,这是在(Gnome)Wayland 中查询应用程序名称和窗口标题的当前状态。

  1. A Gnome-specific JavaScript API which can be accessed over DBus可以通过 DBus 访问的 Gnome 特定的 JavaScript API
  2. The wlr-foreign-toplevel-management Wayland protocol (unfortunately not implemented by Gnome) wlr-foreign-toplevel-management Wayland 协议(遗憾的是 Gnome 没有实现)

The Gnome-specific API will likely break between Gnome versions, but it works. Gnome 特定的 API 可能会在 Gnome 版本之间中断,但它可以工作。 It is heavily dependent on Gnome internal API to work so there is no chance of it becoming a standard API.它严重依赖 Gnome 内部 API 来工作,因此它不可能成为标准 API。 There is a PR on aw-watcher-window to add this , but it needs some clean-up and afk-support if that's possible. aw-watcher-window 上一个 PR 来添加这个,但如果可能的话,它需要一些清理和 afk 支持。

The wlr-foreign-toplevel-management protocol is (at the time of writing this) implemented by the Sway, Mir, Phosh and Wayfire compositors. wlr-foreign-toplevel-management协议(在撰写本文时)由 Sway、Mir、Phosh 和 Wayfire 合成器实现。 Together with the idle.xml protocol which is pretty widely implemented by wayland compositors there's a complete implementation with afk-detection for ActivityWatch in aw-watcher-window-wayland .连同由wayland 合成器广泛实现的 idle.xml 协议,在aw-watcher-window-wayland 中为 ActivityWatch 提供了一个完整的 afk-detection 实现。 I've been in discussions with sway/rootston developers about whether wayland appnames and X11 wm_class is interchangeable and both Sway and Phosh use these interchangeably now so there should no longer be any distinguishable differences between Wayland and XWayland windows in the API anymore.我一直在与 sway/rootston 开发人员讨论 Wayland appnames 和 X11 wm_class 是否可以互换,现在 Sway 和 Phosh 都可以互换使用它们,因此 API 中的 Wayland 和 XWayland 窗口之间不应再有任何可区分的差异。

I have not researched if KWin has some API similar to Gnome Shell to fetch appnames and titles, but it does at least not implement wlr-foreign-toplevel-management.我还没有研究过 KWin 是否有一些类似于 Gnome Shell 的 API 来获取应用程序名称和标题,但它至少没有实现 wlr-foreign-toplevel-management。

In my opinion the best choice you have is not Wayland or any available library (there are not one).在我看来,您拥有的最佳选择不是 Wayland 或任何可用的图书馆(没有)。 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-wayland 中谁知道活动窗口是 Mutter,因此您需要找到一种方法来询问活动窗口。 Gnome can develop an API to internally ask to mutter the active window and restore the functionality. Gnome 可以开发一个 API 来在内部要求关闭活动窗口并恢复功能。 But really, you don't have a place to ask for it.但实际上,你没有地方要求它。 Mutter will not develop an API to access to his internal representation, because this will be pretty specific of Mutter only and not to all Wayland windows manager. Mutter 不会开发一个 API 来访问他的内部表示,因为这将只针对 Mutter 而不是所有 Wayland 窗口管理器。 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.所以这需要添加到一个外部库中,这个库可能会与当前的窗口管理器进行对话,以一般方式解决您的请求。

Another possibility 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 functionality.另一种可能性是添加一个 Wayland 插件,所有窗口管理器都可以在其中共享当前活动的窗口,并以某种方式直接与 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 luck.祝你好运。

https://stackoverflow.com/a/64030239/388010 has the correct answer. https://stackoverflow.com/a/64030239/388010有正确答案。 Nevertheless, here's the concrete and unsatisfying solution that implements option (1).然而,这是实现选项 (1) 的具体且不令人满意的解决方案。 The following works through a gnome extension using Gnome 43 at the time of writing (and perhaps will keep on working as long as the extension is maintained):以下是在撰写本文时通过使用 Gnome 43 的 gnome 扩展进行的(并且只要扩展得到维护,它可能会继续工作):

  1. Install https://extensions.gnome.org/extension/4974/window-calls-extended/安装https://extensions.gnome.org/extension/4974/window-calls-extended/
  2. Run gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/WindowsExt --method org.gnome.Shell.Extensions.WindowsExt.FocusPID | sed -E "s/\\('(.*)',\\)/\\1/g"运行gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/WindowsExt --method org.gnome.Shell.Extensions.WindowsExt.FocusPID | sed -E "s/\\('(.*)',\\)/\\1/g" gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/WindowsExt --method org.gnome.Shell.Extensions.WindowsExt.FocusPID | sed -E "s/\\('(.*)',\\)/\\1/g" to get the PID of the focus window or use a different method of WindowsExt . gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/WindowsExt --method org.gnome.Shell.Extensions.WindowsExt.FocusPID | sed -E "s/\\('(.*)',\\)/\\1/g"获取焦点窗口的 PID 或使用WindowsExt的不同方法。

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.请注意,正如您所问的那样,它没有从 Wayland获取信息,但实际上它可能更好,因为它与 X/Wayland 无关。 It got the title from an xterm I opened, so it should be toolkit-agnostic, as well.它的标题来自我打开的 xterm,因此它也应该与工具包无关。

Don't ask me on the details of the implementation, though.不过,不要问我实施的细节。 The code is at least four years old :)代码至少有四年历史了:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM