frontends (tools): module to handle display servers:

rel 433
This commit is contained in:
Goffi 2024-01-16 10:41:58 +01:00
commit 3fecc07a7e
2 changed files with 117 additions and 0 deletions

View file

@ -0,0 +1,116 @@
#!/usr/bin/env python3
# Libervia tools for display servers
# Copyright (C) 2009-2024 Jérôme Poisson (goffi@goffi.org)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
try:
from Xlib import X, display
from Xlib.xobject.drawable import Window
except ImportError:
pass
import os
X11 = "X11"
WAYLAND = "Wayland"
def x11_list_windows() -> list[dict[str, object]]:
"""Lists all X11 windows with their metadata.
@param disp: The X11 display connection.
@return: A list of dictionaries with window metadata. Each dictionary contains the
metadata returned by [x11_get_window_metadata].
"""
disp = display.Display()
window_list = []
root = disp.screen().root
window_ids = root.get_full_property(
disp.intern_atom("_NET_CLIENT_LIST"), X.AnyPropertyType
).value
for window_id in window_ids:
window = disp.create_resource_object("window", window_id)
window_metadata = x11_get_window_metadata(window)
window_list.append(window_metadata)
return window_list
def x11_get_window_metadata(window: Window) -> dict[str, object]:
"""Extracts metadata from a given X11 window.
@param window: The X11 window object.
@return: A dictionary with the window's metadata, including:
``id`` (int)
window id
``type`` (str)
"application" or "virtual desktop"
``title`` (str)
combined class name and window name, truncated if long
``window_name`` (str|none)
original window name
``class`` (tuple[str, str]|none)
window class
``geometry`` (dict)
dictionary with keys ``x``, ``y``, ``width``, ``height``
"""
window_id = window.id
window_name = window.get_wm_name()
window_class = window.get_wm_class()
geometry = window.get_geometry()
# Q&D virtual desktop detection
virtual_desktop_classes = ["plasmashell", "gnome-shell", "xfdesktop", "mate-panel"]
window_type = (
"virtual desktop"
if window_class and any(vc in window_class[1] for vc in virtual_desktop_classes)
else "application"
)
class_name = window_class[1] if window_class else "Unknown"
title = f"{class_name}: {window_name or ''}"
if len(title) > 50:
title = f"{title[:47]}…"
return {
"id": window_id,
"type": window_type,
"title": title,
"window_name": window_name,
"class": window_class,
"geometry": {
"x": geometry.x,
"y": geometry.y,
"width": geometry.width,
"height": geometry.height,
},
}
def detect() -> str | None:
"""Detects the type of window manager or display server in use.
@return: A string indicating the type of window manager/display server ("X11",
"Wayland", or None).
"""
if "WAYLAND_DISPLAY" in os.environ:
return WAYLAND
elif "DISPLAY" in os.environ:
return X11
else:
return None

View file

@ -49,6 +49,7 @@ dependencies = [
# "python-potr < 1.1",
"pyxdg < 0.30",
"pyyaml < 7.0.0",
"python-xlib ~= 0.33",
"prompt_toolkit ~= 3.0",
"rich ~= 13.5",
"sat_tmp @ hg+https://repos.goffi.org/sat_tmp#egg=sat_tmp",