119 lines
3.0 KiB
Python
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
|
|
|
|
|