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>
This commit is contained in:
88
inputremapper/focus/focus_backend.py
Normal file
88
inputremapper/focus/focus_backend.py
Normal file
@ -0,0 +1,88 @@
|
||||
# -*- 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/>.
|
||||
|
||||
"""The base class and event for all focus backends.
|
||||
|
||||
This lives in its own module to avoid a circular import between the backend
|
||||
registry (``focus_watcher``) and the concrete backends.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, Optional
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FocusEvent:
|
||||
"""A normalized description of the currently focused window.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
app_id
|
||||
The canonical application identifier (WM_CLASS on X11, app_id on
|
||||
Wayland). This is the value bindings are matched against. May be empty
|
||||
for transient focus changes (menus, popups, no focus).
|
||||
title
|
||||
The human readable window title (_NET_WM_NAME / title).
|
||||
backend
|
||||
The name of the backend that produced this event.
|
||||
"""
|
||||
|
||||
app_id: str
|
||||
title: str
|
||||
backend: str
|
||||
|
||||
|
||||
# Type alias for the focus callback passed to FocusBackend.start.
|
||||
OnFocus = Callable[[FocusEvent], None]
|
||||
|
||||
|
||||
class FocusBackend(ABC):
|
||||
"""Detects the focused window for a specific compositor / display server.
|
||||
|
||||
Backends integrate into the GLib main loop (e.g. via ``GLib.io_add_watch``
|
||||
on a file descriptor) and call the ``on_focus`` callback whenever the
|
||||
focused window changes.
|
||||
"""
|
||||
|
||||
# A short, human readable identifier, also used as FocusEvent.backend.
|
||||
name: str = "base"
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def is_available() -> bool:
|
||||
"""Whether this backend can run in the current session."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def start(self, on_focus: OnFocus) -> None:
|
||||
"""Begin watching for focus changes, invoking on_focus on each change."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def stop(self) -> None:
|
||||
"""Stop watching and release all resources."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def get_current(self) -> Optional[FocusEvent]:
|
||||
"""Return the currently focused window, or None if unavailable."""
|
||||
raise NotImplementedError
|
||||
Reference in New Issue
Block a user