-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
killown
committed
Sep 8, 2024
1 parent
c60c358
commit 96dec36
Showing
5 changed files
with
239 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import asyncio | ||
import os | ||
import orjson as json | ||
import time | ||
from concurrent.futures import ThreadPoolExecutor | ||
from wayfire import WayfireSocket | ||
from wayfire.extra.ipc_utils import WayfireUtils | ||
|
||
|
||
#why forward ipc for socket files, why not just one? | ||
#because this is the most reliable way to provide ipc through GLib which in rare cases the code would break/hang | ||
#this is the best choice until there is a more reliable way to provide IPC without breaking the GTK main loop with freezing issues. | ||
|
||
socket_paths = ['/tmp/waypanel.sock', '/tmp/waypanel-dockbar.sock', '/tmp/waypanel-utils.sock'] | ||
|
||
for path in socket_paths: | ||
if os.path.exists(path): | ||
os.remove(path) | ||
|
||
sock = WayfireSocket() | ||
utils = WayfireUtils(sock) | ||
sock.watch() | ||
|
||
executor = ThreadPoolExecutor() | ||
|
||
event_queue = asyncio.Queue() | ||
|
||
|
||
def reconnect_wayfire_socket(): | ||
sock = WayfireSocket() | ||
utils = WayfireUtils(sock) | ||
sock.watch() | ||
|
||
def is_socket_active(): | ||
if not sock.is_connected(): | ||
try: | ||
reconnect_wayfire_socket() | ||
except Exception as e: | ||
print(f"retrying in 10 seconds: {e}") | ||
time.sleep(10) | ||
return False | ||
return True | ||
|
||
def read_events(): | ||
while True: | ||
if not is_socket_active(): | ||
continue | ||
|
||
try: | ||
event = sock.read_next_event() # blocking call | ||
asyncio.run_coroutine_threadsafe(event_queue.put(event), loop) | ||
except Exception as e: | ||
print(f"skiping the event: {e}") | ||
continue | ||
|
||
# handle events and send them to connected clients | ||
async def handle_event(clients): | ||
while True: | ||
event = await event_queue.get() | ||
serialized_event = json.dumps(event) | ||
# Broadcast the event to all connected clients | ||
for client in clients: | ||
try: | ||
client.write((serialized_event + b'\n')) | ||
await client.drain() | ||
except (ConnectionResetError, BrokenPipeError): | ||
clients.remove(client) # Remove clients that have disconnected | ||
|
||
async def handle_client(reader, writer, clients): | ||
clients.append(writer) | ||
try: | ||
while True: | ||
await asyncio.sleep(3600) # Keep the client connection alive | ||
except (ConnectionResetError, BrokenPipeError): | ||
pass | ||
finally: | ||
clients.remove(writer) | ||
writer.close() | ||
await writer.wait_closed() | ||
|
||
# start a server for a given path | ||
async def start_server(path, clients): | ||
server = await asyncio.start_unix_server(lambda r, w: handle_client(r, w, clients), path=path) | ||
async with server: | ||
await server.serve_forever() | ||
|
||
async def main(): | ||
clients = [] | ||
servers = [start_server(path, clients) for path in socket_paths] | ||
# Start the event reader in a separate thread | ||
global loop | ||
loop = asyncio.get_running_loop() | ||
executor.submit(read_events) | ||
await asyncio.gather(*servers, handle_event(clients)) | ||
|
||
if __name__ == '__main__': | ||
asyncio.run(main()) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import socket | ||
import orjson | ||
from gi.repository import GLib | ||
|
||
class WayfireClientIPC: | ||
def __init__(self, handle_event): | ||
self.client_socket = None | ||
self.source = None | ||
self.buffer = "" | ||
self.socket_path = None | ||
self.handle_event = handle_event # Store the custom handle_event function | ||
|
||
def connect_socket(self, socket_path): | ||
self.socket_path = socket_path | ||
self.client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||
self.client_socket.connect(socket_path) | ||
self.source = GLib.io_add_watch(self.client_socket, GLib.PRIORITY_DEFAULT, GLib.IO_IN, self.handle_socket_event) | ||
|
||
def handle_socket_event(self, fd, condition): | ||
# try decode before actually handle the event | ||
# if the code fail, glib will stop watching | ||
try: | ||
chunk = fd.recv(1024).decode() | ||
if not chunk: | ||
return GLib.SOURCE_REMOVE | ||
|
||
self.buffer += chunk | ||
|
||
while '\n' in self.buffer: | ||
event_str, self.buffer = self.buffer.split('\n', 1) | ||
if event_str: | ||
try: | ||
event = orjson.loads(event_str) | ||
self.process_event(event) | ||
except orjson.JSONDecodeError as e: | ||
print(f"JSON decode error: {e}") | ||
except UnicodeDecodeError as e: | ||
print(f"{e}") | ||
|
||
|
||
return GLib.SOURCE_CONTINUE | ||
|
||
def process_event(self, event): | ||
self.handle_event(event) # Call the custom handle_event function | ||
|
||
def disconnect_socket(self): | ||
if self.source: | ||
self.source.remove() | ||
if self.client_socket: | ||
self.client_socket.close() | ||
|
||
def wayfire_events_setup(self, socket_path): | ||
self.connect_socket(socket_path) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.