[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:
parent
8ae8fbb989
commit
ef35c957b2
1 changed files with 53 additions and 27 deletions
|
@ -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"""
|
||||||
|
|
Loading…
Reference in a new issue