Added better support for kubuntu and fixed some issues with telemetry.
This commit is contained in:
@@ -106,6 +106,7 @@ def collect_extended_environment(
|
||||
"dependencies": dependencies,
|
||||
}
|
||||
display = _display_info(sysfs_drm)
|
||||
display.update(_kde_display_scaling_info(environment, run_probe))
|
||||
if display:
|
||||
result["display"] = display
|
||||
if gpu:
|
||||
@@ -263,6 +264,23 @@ def _vulkan_info(
|
||||
return result
|
||||
|
||||
|
||||
def inspect_vulkan_support(
|
||||
environment: Mapping[str, str],
|
||||
*,
|
||||
probe_runner: ProbeRunner | None = None,
|
||||
manifest_directories: Sequence[Path] = _VULKAN_MANIFEST_DIRECTORIES,
|
||||
library_roots: Sequence[Path] = _LIBRARY_ROOTS,
|
||||
) -> dict[str, object]:
|
||||
"""Return host Vulkan loader and ICD readiness for dependency checks."""
|
||||
|
||||
return _vulkan_info(
|
||||
environment,
|
||||
probe_runner or _run_probe,
|
||||
manifest_directories=manifest_directories,
|
||||
library_roots=library_roots,
|
||||
)
|
||||
|
||||
|
||||
def _gpu_info(
|
||||
vulkan_summary: object,
|
||||
*,
|
||||
@@ -362,7 +380,7 @@ def _dependency_health(
|
||||
try:
|
||||
from .doctor import inspect_host
|
||||
|
||||
report = inspect_host(environment)
|
||||
report = inspect_host(environment, vulkan_support=runtime)
|
||||
for item in report.tools:
|
||||
available = item.path is not None
|
||||
tools[item.name] = available
|
||||
@@ -834,15 +852,18 @@ def _vulkan_manifests(
|
||||
directories: Sequence[Path],
|
||||
) -> tuple[Path, ...]:
|
||||
candidates: list[Path] = []
|
||||
explicit = environment.get("VK_ICD_FILENAMES", "")
|
||||
for value in explicit.split(os.pathsep):
|
||||
if value:
|
||||
candidates.append(Path(value).expanduser())
|
||||
for directory in directories:
|
||||
try:
|
||||
candidates.extend(sorted(directory.glob("*.json")))
|
||||
except OSError:
|
||||
continue
|
||||
override = environment.get("VK_DRIVER_FILES", "").strip()
|
||||
if not override:
|
||||
override = environment.get("VK_ICD_FILENAMES", "").strip()
|
||||
if override:
|
||||
candidates.extend(_manifest_entries(override))
|
||||
else:
|
||||
candidates.extend(_manifest_entries(environment.get("VK_ADD_DRIVER_FILES", "")))
|
||||
for directory in _vulkan_manifest_search_directories(environment, directories):
|
||||
try:
|
||||
candidates.extend(sorted(directory.glob("*.json")))
|
||||
except OSError:
|
||||
continue
|
||||
seen: set[Path] = set()
|
||||
result: list[Path] = []
|
||||
for candidate in candidates:
|
||||
@@ -857,6 +878,54 @@ def _vulkan_manifests(
|
||||
return tuple(result)
|
||||
|
||||
|
||||
def _manifest_entries(value: str) -> tuple[Path, ...]:
|
||||
result: list[Path] = []
|
||||
for raw_entry in value.split(os.pathsep):
|
||||
if not raw_entry:
|
||||
continue
|
||||
entry = Path(raw_entry).expanduser()
|
||||
try:
|
||||
if entry.is_dir():
|
||||
result.extend(sorted(entry.glob("*.json")))
|
||||
else:
|
||||
result.append(entry)
|
||||
except OSError:
|
||||
continue
|
||||
return tuple(result)
|
||||
|
||||
|
||||
def _vulkan_manifest_search_directories(
|
||||
environment: Mapping[str, str],
|
||||
directories: Sequence[Path],
|
||||
) -> tuple[Path, ...]:
|
||||
if directories is not _VULKAN_MANIFEST_DIRECTORIES:
|
||||
return tuple(dict.fromkeys(directories))
|
||||
home = environment.get("HOME", "").strip()
|
||||
config_home = environment.get("XDG_CONFIG_HOME", "").strip()
|
||||
data_home = environment.get("XDG_DATA_HOME", "").strip()
|
||||
config_directories = environment.get("XDG_CONFIG_DIRS", "/etc/xdg")
|
||||
data_directories = environment.get(
|
||||
"XDG_DATA_DIRS",
|
||||
"/usr/local/share:/usr/share",
|
||||
)
|
||||
result = list(directories)
|
||||
if config_home:
|
||||
result.append(Path(config_home).expanduser() / "vulkan/icd.d")
|
||||
elif home:
|
||||
result.append(Path(home).expanduser() / ".config/vulkan/icd.d")
|
||||
for value in config_directories.split(os.pathsep):
|
||||
if value:
|
||||
result.append(Path(value).expanduser() / "vulkan/icd.d")
|
||||
if data_home:
|
||||
result.append(Path(data_home).expanduser() / "vulkan/icd.d")
|
||||
elif home:
|
||||
result.append(Path(home).expanduser() / ".local/share/vulkan/icd.d")
|
||||
for value in data_directories.split(os.pathsep):
|
||||
if value:
|
||||
result.append(Path(value).expanduser() / "vulkan/icd.d")
|
||||
return tuple(dict.fromkeys(result))
|
||||
|
||||
|
||||
def _vulkan_loader_architectures(library_roots: Sequence[Path]) -> set[int]:
|
||||
architectures: set[int] = set()
|
||||
for root in library_roots:
|
||||
@@ -967,6 +1036,101 @@ def _display_info(sysfs_drm: Path) -> dict[str, object]:
|
||||
return {"monitor_count": monitor_count} if monitor_count is not None else {}
|
||||
|
||||
|
||||
def _kde_display_scaling_info(
|
||||
environment: Mapping[str, str],
|
||||
probe_runner: ProbeRunner,
|
||||
) -> dict[str, object]:
|
||||
"""Collect bounded Plasma scale facts without monitor names or resolutions."""
|
||||
|
||||
if not environment.get("WAYLAND_DISPLAY", "").strip() or not _is_kde_desktop(
|
||||
environment
|
||||
):
|
||||
return {}
|
||||
result: dict[str, object] = {"kde_wayland": True}
|
||||
executable = shutil.which(
|
||||
"kscreen-doctor",
|
||||
path=environment.get("PATH", ""),
|
||||
)
|
||||
result["kscreen_doctor_available"] = executable is not None
|
||||
if executable is None:
|
||||
return result
|
||||
probe = probe_runner(
|
||||
(executable, "--json"),
|
||||
environment,
|
||||
PROBE_TIMEOUT_SECONDS,
|
||||
)
|
||||
if probe is None or probe.returncode != 0:
|
||||
result["scale_probe_succeeded"] = False
|
||||
return result
|
||||
try:
|
||||
payload = json.loads(probe.stdout)
|
||||
except (json.JSONDecodeError, TypeError, UnicodeError):
|
||||
result["scale_probe_succeeded"] = False
|
||||
return result
|
||||
if not isinstance(payload, dict):
|
||||
result["scale_probe_succeeded"] = False
|
||||
return result
|
||||
raw_outputs = payload.get("outputs")
|
||||
if isinstance(raw_outputs, list):
|
||||
outputs = raw_outputs
|
||||
elif isinstance(raw_outputs, dict):
|
||||
outputs = list(raw_outputs.values())
|
||||
else:
|
||||
outputs = []
|
||||
scales: list[float] = []
|
||||
for output in outputs[:32]:
|
||||
if not isinstance(output, dict):
|
||||
continue
|
||||
if output.get("connected") is False or output.get("enabled") is False:
|
||||
continue
|
||||
value = output.get("scale")
|
||||
if isinstance(value, bool):
|
||||
continue
|
||||
try:
|
||||
scale = float(value)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if not 0.5 <= scale <= 8.0:
|
||||
continue
|
||||
scales.append(round(scale, 3))
|
||||
result["scale_probe_succeeded"] = bool(scales)
|
||||
if not scales:
|
||||
return result
|
||||
unique_scales = sorted(set(scales))
|
||||
result.update(
|
||||
{
|
||||
"scale_output_count": len(scales),
|
||||
"scale_min": unique_scales[0],
|
||||
"scale_max": unique_scales[-1],
|
||||
"fractional_scaling": any(
|
||||
abs(scale - round(scale)) > 0.001 for scale in unique_scales
|
||||
),
|
||||
"mixed_scaling": len(unique_scales) > 1,
|
||||
"scale_detection": "kscreen_doctor",
|
||||
}
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
def _is_kde_desktop(environment: Mapping[str, str]) -> bool:
|
||||
if environment.get("KDE_FULL_SESSION", "").strip().casefold() in {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
}:
|
||||
return True
|
||||
if environment.get("KDE_SESSION_VERSION", "").strip():
|
||||
return True
|
||||
for key in ("XDG_CURRENT_DESKTOP", "XDG_SESSION_DESKTOP", "DESKTOP_SESSION"):
|
||||
tokens = re.split(
|
||||
r"[^a-z0-9]+",
|
||||
environment.get(key, "").strip().casefold(),
|
||||
)
|
||||
if "kde" in tokens or any(token.startswith("plasma") for token in tokens):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _connected_monitor_count(sysfs_drm: Path) -> int | None:
|
||||
try:
|
||||
connectors = sorted(sysfs_drm.glob("card[0-9]*-*/status"))[:32]
|
||||
|
||||
Reference in New Issue
Block a user