How do I get the active window on Gnome Wayland?
Asked Answered
A

4

64

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.

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.

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).

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.

Relevant issues for 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.

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

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

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

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://mcmap.net/q/245173/-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.

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

Apyretic answered 2/8, 2017 at 15:28 Comment(6)
I have similar concerns and my current plan of action is to stick my head in the sand and hope no one uses wayland.Stichous
So do I - currently for me Wayland just means more bugs and less features..Phanotron
I have a piece of software that switches input mappings based the focused window, and I'm invested in the outcome of this thread. On reviewing the links and some more searching it doesn't appear that this is yet resolved.Reitz
Ummm doesn't it seem that this can by design be done in a Gnome extension, like discussed here? I'm a little confused now.Responsory
"It is possible to tighten security to the point where the system is unusable. Security and convenience must be balanced" - ArchWiki/Security. Wayland doesnt make it unusable in any way, but in this case the security is taking away some convenience softwares from users :' (Centaur
Gnome bugtracker has closed you ticket as they have moved. You might consider reopening it at the new localtion.Namely
I
14

The two previous answers are outdated, this is the current state of querying appnames and titles of windows in (Gnome) Wayland.

  1. A Gnome-specific JavaScript API which can be accessed over DBus
  2. The wlr-foreign-toplevel-management Wayland protocol (unfortunately not implemented by Gnome)

The Gnome-specific API will likely break between Gnome versions, but it works. It is heavily dependent on Gnome internal API to work so there is no chance of it becoming a standard 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.

The wlr-foreign-toplevel-management protocol is (at the time of writing this) implemented by the Sway, Mir, Phosh and Wayfire compositors. 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. 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.

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.

Instrumental answered 23/9, 2020 at 14:31 Comment(6)
As the Mutter developer Jonas Ådahl @jadahl said: "wlr-foreign-toplevel-manager, breaks client isolation - it exposes toplevel surfaces of all other clients". What means that it will never be implemented in GNOME and will never be acepted in freedesktop as wayland protocol. Unfortunated, GNONE is prefering the security than funtionalities, but maybe only for others, because internally they implement in the shell what they disapprove as wayland protocol. Long live GNOME and its inconsistencies / conveniences.Mangum
Security is very important. There could be a leeway where special permissions are necessary for obtaining such information, as long as those permissions are part of a cohesive permissions system. As a case in point, in Android, a linux flavour having it's own distinct UI management stack, such levels of introspection/intervention with the active app are provided via an accessibility services framework that indeed requires user consent.Responsory
@matanster Yes, security is very important, but if you can create a gjs code to initialize a DBUS service and then also inyect this code in the shell from outside using another GNOME shell DBus service, then you will need to conclude that security is not the most important thing to GNOME here. It is difficult to know what is the real limitation GNOME people see, because the security does not seem to be the limitation, otherwise not workaround could exist, but it does exist.Mangum
KWin Scripting API allows to obtain the activeClient of a workspace and its caption. I'm not sure if it's possible to expose them from a script for an external process though.Matty
The ability to use GNOME's internal API from outside (1st option in the answer) is going away too. It is presumably up to GNOME to provide a supported external-facing alternative, like this idea, but whether or not something like this is in the works remains a mystery.Mcleroy
@ArnonWeinberg Yeah, I saw that as well. It is however still possible to access this API via a GNOME Shell extension, so there are a couple of extensions out there which use this API and then provide a D-Bus service which other processes can use. Here's one: github.com/ickyicky/window-callsLadonna
M
3

In my opinion the best choice 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 develop an API to internally ask to mutter the active window and restore the functionality. 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. 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.

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.

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

Mangum answered 4/10, 2017 at 4:59 Comment(3)
Interestingly GNOME Shell stops at providing an enumeration of the active windows and then basic info about them, which is, at least, pretty much.Responsory
@matanster Are you notice we are talking here about an specific problem and your message is in defend of GNOME but fully unrelated with the topic, rigth? You are not providing any solution, also not explaining why that happens or why is in that way or who or what is the culprit.Mangum
I do not fully agree with the perspective (and style) of your comment but so be it. There is no culprit, it's how it is currently designed and I think you can discuss changes to the design on the GNOME Shell developer channels if you want to be helpful about it.Responsory
A
2

https://mcmap.net/q/245173/-how-do-i-get-the-active-window-on-gnome-wayland has the correct answer. Nevertheless, here's the concrete and unsatisfying solution that implements option (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):

  1. Install 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" to get the PID of the focus window or use a different method of WindowsExt.
Altruistic answered 18/12, 2022 at 20:38 Comment(0)
A
-4

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.

For my script, I acquired the window title using PyGObject's 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.

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.

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

Atreus answered 18/8, 2017 at 14:4 Comment(3)
At first glance this looks good. I'm unable to test this right now but according to the documentation on screen_get_default: "This can return NULL if not on X11." I'm curbing my optimism for now...Apyretic
This is the warning that Wnck.Screen.get_default () gives : (.:9342): Wnck-WARNING **: libwnck is designed to work in X11 only, no valid display foundSherrilsherrill
I get some interesting behavior. I get the same error as @Sherrilsherrill when running a similar script on the Gnome terminal but when running it on the vscode terminal it works!!Ringer

© 2022 - 2024 — McMap. All rights reserved.