[input] Add per-PID UNIX socket for additional commands

Allow passing in commands / events via a unix socket. This should allow
for "emulating" input events.

see #547
This commit is contained in:
Tobias Witek 2020-02-14 21:39:55 +01:00
parent 8ae8fbb989
commit ef35c957b2

View file

@ -1,9 +1,11 @@
"""Input classes""" """Input classes"""
import os
import sys import sys
import json import json
import uuid import uuid
import time import time
import socket
import select import select
import logging import logging
import threading import threading
@ -23,38 +25,62 @@ def is_terminated():
return True return True
return False return False
class CommandSocket(object):
def __init__(self):
self._name = "/tmp/.bumblebee-status.{}".format(os.getpid())
self._socket = None
def __enter__(self):
self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self._socket.bind(self._name)
self._socket.listen(5)
return self._socket
def __exit__(self, type, value, traceback):
self._socket.close()
os.unlink(self._name)
def read_input(inp): def read_input(inp):
"""Read i3bar input and execute callbacks""" """Read i3bar input and execute callbacks"""
poll = select.poll()
poll.register(sys.stdin.fileno(), select.POLLIN)
log.debug("starting click event processing")
while inp.running:
if is_terminated():
return
try: with CommandSocket() as cmdsocket:
events = poll.poll(1000) poll = select.poll()
except Exception: poll.register(sys.stdin, select.POLLIN)
continue poll.register(cmdsocket, select.POLLIN)
for fileno, event in events: log.debug("starting click event processing")
line = "[" while inp.running:
while line.startswith("["): if is_terminated():
line = sys.stdin.readline().strip(",").strip() return
log.debug("new event: {}".format(line))
inp.has_event = True
try: try:
event = json.loads(line) events = poll.poll(1000)
if "instance" in event: except Exception:
inp.callback(event) continue
inp.redraw() for fileno, event in events:
if fileno == cmdsocket.fileno():
tmp, _ = cmdsocket.accept()
line = tmp.recv(4096).decode()
tmp.close()
else: else:
log.debug("field 'instance' missing in input, not processing the event") line = "["
except ValueError as e: while line.startswith("["):
log.debug("failed to parse event: {}".format(e)) line = sys.stdin.readline().strip(",").strip()
log.debug("exiting click event processing") log.debug("new event: {}".format(line))
poll.unregister(sys.stdin.fileno()) inp.has_event = True
inp.has_event = True try:
inp.clean_exit = True event = json.loads(line)
if "instance" in event:
inp.callback(event)
inp.redraw()
else:
log.debug("field 'instance' missing in input, not processing the event")
except ValueError as e:
log.debug("failed to parse event: {}".format(e))
log.debug("exiting click event processing")
poll.unregister(sys.stdin.fileno())
inp.has_event = True
inp.clean_exit = True
class I3BarInput(object): class I3BarInput(object):
"""Process incoming events from the i3bar""" """Process incoming events from the i3bar"""