Files
InputRemapper/inputremapper/focus/focus_watcher.py
Blomios 9ef2c1439c feat(app-binding): lier les presets aux applications
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>
2026-06-19 23:52:34 +02:00

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