Move Wnck logic to a separate helper program
Instead of using Wnck directly in-process
in the WnckWindowManager class, move the
logic to a new helper program wnck-window-infos.py
that retrieves the relevant logic using Wnck and
prints it in JSON format to stdout.
Let WnckWindowManager call that Python script and process the JSON output, somewhat similar to how KWinWindowManager and GnomeShellWindowManager already do it with the information they receive from KWin or GNOME Shell/Mutter.
While doing things in-process is faster, splitting the Wnck logic into a separate helper program gets rid of the Wnck dependency in the main Acccerciser application, which came with an implicit dependency on GTK 3 and the need to run Accerciser on X11/XWayland as Wnck doesn't work on Wayland or with GTK 4.
Due to the way that Wnck works, the helper program can still only detect X11 applications, no native Wayland clients, but this would now still work when Accerciser itself runs as a native Wayland application.
For now, still keep setting the GDK_BACKEND=x11
environment
variable for the main application as well, however, to force
it to run on X11/XWayland, too.
While it's no longer needed for Wnck, the highlighting
feature (e.g. when clicking on an accessible in the
treeview) still requires running on X11, as the highlighting
window otherwise cannot be moved to the correct position on
screen when run on Wayland.
Once an alternative solution for this has been implemented,
the main application can run as a native Wayland app.
And when using either KWinWindowManager or GnomeShellWindowManager, XWayland also isn't needed for determinining window information either. Leaving WnckWindowManager around for now still makes sense in my opinion, as it allows using the highlighting feature (for X11/XWayland apps at least) on desktop environments other than GNOME and KDE Plasma and with applications/toolkits (versions) not (yet) properly reporting window-relative coordinates, but only screen coordinates.
Call Wnck.Screen.force_update
[1] in the new helper program,
as the window information isn't otherwise available there as
described in the doc [1]:
Synchronously and immediately updates the list of Wnck.Window on self. This bypasses the standard update mechanism, where the list of Wnck.Window is updated in the idle loop.
This is usually a bad idea for both performance and correctness reasons (to get things right, you need to write model-view code that tracks changes, not get a static list of open windows). However, this function can be useful for small applications that just do something and then exit.
For debugging purposes, the script can also be run standalone. Example use in a Wayland session with a gtk3-demo and gtk4-demo running on XWayland:
Get window infos:
$ GDK_BACKEND=x11 python3 ./src/wnck-window-infos.py window-infos
[{"caption": "Application Class", "geometry.x": 2265, "geometry.y": 150, "geometry.width": 800, "geometry.height": 651, "isOnCurrentWorkspace": true, "pid": 142858, "stackingOrder": 0}, {"caption": "GTK Demo", "geometry.x": 2759, "geometry.y": 351, "geometry.width": 800, "geometry.height": 600, "isOnCurrentWorkspace": true, "pid": 151933, "stackingOrder": 1}, {"caption": "Accerciser Accessibility Explorer", "geometry.x": 0, "geometry.y": 72, "geometry.width": 1920, "geometry.height": 1052, "isOnCurrentWorkspace": true, "pid": 156725, "stackingOrder": 2}]
Get icon infos for gtk4-demo's "GTK Demo" window, which can be used to create a GdkPixmap:
$ GDK_BACKEND=x11 python3 ./src/wnck-window-infos.py icon "GTK Demo"
{"pixels": "0000000000000000000000000000000000000000000000001a1a1a02c7c9cb5dc9cbce5f1f1f1f030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0c0c03fccdaeacfa8cbf3ffa7caf3ffcbdaebd2c1c1c1430000000000000000000000000000000000000000000000000000000000000000aeaeae1fced7e1aab6d3f4fe98c1f1ff98c1f1ff98c1f1ff98c1f1ffb4d2f4feced7e2afb0b0b022000000000000000000000000000000003c3c3c06d5dadf83bed5f1f69ac2f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff9ac2f1ffbdd5f1f7d4d9df863b3b3b060000000000000000d7d7d766e2d0deffa7caf3ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ffa6c9f2ffcce9ecffd8d8d8660000000000000000d0d0d081ee3e45fff2888dffd0d4e9ff9ec5f1ff98c1f1ff98c1f1ff98c1f1ff98c1f1ff9dc4f1ffc5e0f1ff99e7beff54d890ffd5d5d5820000000000000000d0d0d081ed3b43ffed333bffee4148ffefa3a9ffc1d7f3ff99c1f1ff98c1f1ffbed8f5ffaee9cfff58d992ff48d688ff50d78dffd5d5d5820000000000000000d0d0d081ed3b43ffed333affed3638ffee3a34fff25e54ffe8c3c8ffc1e9e1ff6bde9fff48d688ff48d688ff48d688ff50d78dffd5d5d5820000000000000000d0d0d081ed3b43ffee3736ffef3d31fff0422efff1452bfff57b66ff7be1a9ff4bd585ff53d47fff5ad37aff5ad379ff5dd583ffd5d5d5820000000000000000d0d0d081ee3f40ffef3d31fff1442cfff24927fff34d24fff78061ff82e0a4ff62d274ff71d06aff7ad064ff7bcf63ff7bd26effd5d5d5820000000000000000d0d0d081f0443cfff1432cfff34a26fff45021fff5551dfff8865cff91de99ff7bcf63ff8fcd55ff9ccb4cff9ecb4bff99cf5affd5d5d5820000000000000000cacac964f7aba4fff35437fff45022fff6571bfff75c17fffa8c57ff9ddd91ff8fcd55ffaaca43ffbec835ffc4ca3effd3e0a0ffc5c4c46400000000000000002b2b2b05bdbdbb7de0d3cff4f89c7cfff85f1afff96311fffb9252ffa3dc8dff9acc4effbac83affe4da79ffd5d2c0f6a19f9d80252524050000000000000000000000000000000081807f1cc1c1bfa4efd7c9fefc9451fffd984dffa2dc8effb0d97cffd9ddc0feadacaaa9706e6b1d00000000000000000000000000000000000000000000000000000000000000009999983ad6d6d4caf9e6d5ffdbebd9ffbebdbbce7e7d7a3d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0e0e01b7b7b659a1a19f5b0e0e0d02000000000000000000000000000000000000000000000000", "has_alpha": true, "bits_per_sample": 8, "width": 16, "height": 16, "rowstride": 64}
[1] https://lazka.github.io/pgi-docs/Wnck-3.0/classes/Screen.html#Wnck.Screen.force_update
Issue: #41