2025-02-14 17:42:48 -07:00

150 lines
4.1 KiB
Python

from abc import ABC, abstractmethod
from .config import OutputConfig
class AbstractWorkspaceBackend(ABC):
"""
Abstract class for workspace backends (i.e. an IPC interface to a compositor / window manager)
"""
_instance: "AbstractWorkspaceBackend" = None
def __init__(self):
super().__init__()
if self._instance is not None:
raise RuntimeError(
"Cannot instantiate more than one WorkspaceBackend at a time. Use getBackend() to get the current backend."
)
self._instance = self
def _scaleToString(self, scale: int) -> str:
"""Convert the fixed-point scale to a string"""
# We do it this way to not lose precision when converting to a float
return f"{scale // 100}.{scale % 100}"
@abstractmethod
async def focusWorkspace(self, index: int):
"""Focus a workspace in the compositor based off of its compositor index"""
pass
@abstractmethod
async def moveWorkspace(self, index: int, output: str):
"""Move a workspace to a given output"""
pass
@abstractmethod
async def focusOutput(self, output: str):
"""Focus an output in the compositor"""
pass
@abstractmethod
async def moveContainer(self, workspace: int):
"""Move the focused container to a given workspace compositor index"""
pass
@abstractmethod
async def configureOutput(self, output: str, config: OutputConfig):
"""Configure an output"""
pass
@abstractmethod
async def disableOutput(self, output: str):
"""Disable an output"""
pass
@abstractmethod
def onWorkspaceChange(self, callback):
"""Register a callback to be called when the workspace changes"""
pass
@abstractmethod
def onOutputChange(self, callback):
"""Register a callback to be called when the output configuration changes"""
pass
@abstractmethod
def onModeChange(self, callback):
"""Register a callback to be called when the binding mode changes, in compositors that support it"""
pass
@abstractmethod
async def getOutputs(self) -> list[OutputAdapter]:
"""Get the currently connected outputs"""
@abstractmethod
@property
def name(self) -> str:
"""The name of the backend"""
pass
def getBackend() -> AbstractWorkspaceBackend:
"""
Get the currently-active workspace backend
"""
if AbstractWorkspaceBackend._instance is None:
raise RuntimeError(
"No workspace backend is currently active. Please instantiate one."
)
return AbstractWorkspaceBackend._instance
class WorkspaceAdapter:
"""
Common interface for workspace backends that represents the result of a
workspace query. Only contains information that the workspace manager needs to know.
"""
def __init__(
self, index: int, output: str, focused: bool, visible: bool, urgent: bool
):
self.index = index
self.output = output
self.focused = focused
self.visible = visible
self.urgent = urgent
class RectAdapter:
"""
Common interface for workspace backends that represents a rectangle.
"""
def __init__(self, x: int, y: int, width: int, height: int):
self.x = x
self.y = y
self.width = width
self.height = height
class OutputAdapter:
"""
Common interface for workspace backends that represents the result of an
output query. Only contains information that the workspace manager needs to know.
"""
def __init__(
self,
name: str,
active: bool,
rect: RectAdapter,
scale: int,
transform: str,
focused: bool,
current_workspace: int,
make: str,
model: str,
serial: str,
):
self.name = name
self.active = active
self.rect = rect
self.scale = scale
self.transform = transform
self.focused = focused
self.current_workspace = current_workspace
self.make = make
self.model = model
self.serial = serial