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

119 lines
3.0 KiB
Python

from gi.repository import Gtk, Gdk, GLib, GObject
from i3ipc.aio import Connection
from i3ipc.events import WorkspaceEvent, OutputEvent, ModeEvent
from i3ipc import Event
import asyncio
from typing import Optional
class GWorkspaceEvent(GObject.Object):
def __init__(self, event: WorkspaceEvent):
super().__init__()
self.event = event
def __getattr__(self, name):
return getattr(self.event, name)
def __str__(self):
return str(self.event)
class GOutputEvent(GObject.Object):
def __init__(self, event: OutputEvent):
super().__init__()
self.event = event
def __getattr__(self, name):
return getattr(self.event, name)
def __str__(self):
return str(self.event)
class GModeEvent(GObject.Object):
def __init__(self, event: ModeEvent):
super().__init__()
self.event = event
def __getattr__(self, name):
return getattr(self.event, name)
def __str__(self):
return str(self.event)
def async_debounce(wait):
def decorator(func):
task: asyncio.Task | None = None
@wraps(func)
async def debounced(*args, **kwargs):
nonlocal task
if task and not task.done():
return
async def call_func():
await asyncio.sleep(wait)
await func(*args, **kwargs)
task = asyncio.create_task(call_func())
return task
return debounced
return decorator
class SwayIPC(GObject.Object, Connection):
__instance: Optional["SwayIPC"] = None
def __init__(self):
if SwayIPC.__instance is not None:
raise Exception("SwayIPC is a singleton")
super().__init__()
super(Connection, self).__init__(auto_reconnect=True)
SwayIPC.__instance = self
# Run async initialization
loop = asyncio.get_event_loop()
loop.create_task(self._init())
@staticmethod
def get_instance():
if SwayIPC.__instance is None:
SwayIPC()
return SwayIPC.__instance
async def _init(self):
await self.connect()
self.on(Event.WORKSPACE, self._on_workspace)
self.on(Event.OUTPUT, self._on_output)
self.on(Event.MODE, self._on_mode)
self.on(Event.SHUTDOWN, self._on_shutdown)
async def _on_workspace(self, event):
self.emit('workspace', GWorkspaceEvent(event))
@async_debounce(0.1)
async def _on_output(self, event):
self.emit('output', GOutputEvent(event))
async def _on_mode(self, event):
self.emit('mode', GModeEvent(event))
async def _on_shutdown(self, event):
# exit the application
Gtk.main_quit()
@GObject.Signal(arg_types=(GWorkspaceEvent,))
def workspace(self, event: GWorkspaceEvent):
pass
@GObject.Signal(arg_types=(GOutputEvent,))
def output(self, event: GOutputEvent):
pass
@GObject.Signal(arg_types=(GModeEvent,))
def mode(self, event: GModeEvent):
pass