Ajoute la configuration des associations application/preset, le service de suivi du focus, l'intégration GUI et les fichiers d'installation nécessaires. Ajoute les tests unitaires ciblés des bindings, du service de focus, des migrations et des composants GUI associés. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
84 lines
3.0 KiB
Python
84 lines
3.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# input-remapper - GUI for device specific keyboard mappings
|
|
# Copyright (C) 2025 sezanzeb <b8x45ygc9@mozmail.com>
|
|
#
|
|
# This file is part of input-remapper.
|
|
#
|
|
# input-remapper is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# input-remapper 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 General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with input-remapper. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
"""Abstractions to detect the currently focused window across compositors.
|
|
|
|
Focus detection is implemented as a registry of backends. To add support for a
|
|
new compositor, implement a new ``FocusBackend`` and append its class to
|
|
``focus_backend_classes`` (ordered by priority). ``select_backend`` returns the
|
|
first backend that reports itself as available, so the most specific backend
|
|
for the current session wins.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import List, Type
|
|
|
|
from inputremapper.focus.backends.hyprland import HyprlandFocusBackend
|
|
from inputremapper.focus.backends.null import NullBackend
|
|
from inputremapper.focus.backends.sway import SwayFocusBackend
|
|
from inputremapper.focus.backends.wlr_foreign_toplevel import (
|
|
WlrForeignToplevelBackend,
|
|
)
|
|
from inputremapper.focus.backends.xorg import XorgFocusBackend
|
|
from inputremapper.focus.focus_backend import FocusBackend, FocusEvent
|
|
from inputremapper.logging.logger import logger
|
|
|
|
# Re-exported for convenience / backwards compatible imports.
|
|
__all__ = [
|
|
"FocusEvent",
|
|
"FocusBackend",
|
|
"focus_backend_classes",
|
|
"select_backend",
|
|
]
|
|
|
|
|
|
# Ordered by priority. The first one that reports is_available() wins.
|
|
# SWAYSOCK -> HYPRLAND_INSTANCE_SIGNATURE -> wlr-foreign-toplevel -> DISPLAY -> Null
|
|
focus_backend_classes: List[Type[FocusBackend]] = [
|
|
SwayFocusBackend,
|
|
HyprlandFocusBackend,
|
|
WlrForeignToplevelBackend,
|
|
XorgFocusBackend,
|
|
NullBackend,
|
|
]
|
|
|
|
|
|
def select_backend() -> FocusBackend:
|
|
"""Instantiate the first available focus backend by priority."""
|
|
for backend_class in focus_backend_classes:
|
|
try:
|
|
available = backend_class.is_available()
|
|
except Exception as error: # pragma: no cover - defensive
|
|
logger.debug(
|
|
"Backend %s failed its availability check: %s",
|
|
backend_class.__name__,
|
|
error,
|
|
)
|
|
available = False
|
|
|
|
if available:
|
|
logger.info("Using focus backend %s", backend_class.name)
|
|
return backend_class()
|
|
|
|
# NullBackend.is_available() always returns True, so this is unreachable
|
|
# as long as it stays in the registry.
|
|
logger.warning("No focus backend available, falling back to NullBackend")
|
|
return NullBackend()
|