You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
5.0 KiB
198 lines
5.0 KiB
import util.x as xutil
|
|
|
|
# Pointer states
|
|
SLAVE, MASTER, FLOATING = range(3)
|
|
|
|
|
|
class XInput:
|
|
"""Base XInput class
|
|
|
|
Attributes:
|
|
name (str): name of the input
|
|
id (int): id of the input
|
|
is_master (bool): True if device is master
|
|
"""
|
|
|
|
def __init__(self, name, id, state) -> None:
|
|
"""Initializes the class with name, id and master status
|
|
|
|
Args:
|
|
name (str): name of the input. No processing is done on the name
|
|
id (int): id of the input
|
|
is_master (bool): master status of the input device
|
|
"""
|
|
self.name = name
|
|
self.id = id
|
|
self.state = state
|
|
|
|
|
|
class Pointer(XInput):
|
|
"""Pointer class
|
|
|
|
This class is a wrapper around xinput commandline --list output.
|
|
|
|
|
|
Attrs:
|
|
is_master (bool): True if the pointer is a master pointer else False
|
|
"""
|
|
|
|
def __init__(self, name, id, state) -> None:
|
|
super().__init__(name, id, state)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Pointer: {self.name}-{self.id}-{self.state}>"
|
|
|
|
@property
|
|
def slave(self):
|
|
return self.state == SLAVE
|
|
|
|
@property
|
|
def master(self):
|
|
return self.state == MASTER
|
|
|
|
def floating(self):
|
|
return self.state == FLOATING
|
|
|
|
|
|
def get_short_pointer(id) -> Pointer:
|
|
"""Generates Pointer object corresponding to id (short attrs)
|
|
|
|
Args:
|
|
id (int): pointer id
|
|
|
|
Returns:
|
|
Pointer: pointer object with name, id and is_master props
|
|
|
|
Rises:
|
|
ValueError: if id is not reistered with xinput
|
|
ValueError: if id is not a pointer id
|
|
"""
|
|
desc = xutil.get_list_short_with(id)
|
|
name, props = desc.rsplit("id=", 1)
|
|
if "pointer" in props:
|
|
state = FLOATING
|
|
if "master" in props:
|
|
state = MASTER
|
|
elif "slave" in props:
|
|
state = SLAVE
|
|
return Pointer(name.strip(), props.split(maxsplit=1)[0], state)
|
|
else:
|
|
raise TypeError(f"id[{id}] is not a pointer id")
|
|
|
|
|
|
def get_ids_iter():
|
|
"""xinput id generator
|
|
|
|
Yields:
|
|
int: id of xinput devices
|
|
"""
|
|
ids = xutil.get_ids()
|
|
for id in ids:
|
|
yield id
|
|
|
|
|
|
def get_pointer_iter(is_short=True):
|
|
"""xinput pointers generator
|
|
|
|
Args:
|
|
is_short (bool, optional): if True generates short type pointers.
|
|
Defaults to True.
|
|
|
|
Yields:
|
|
Pointer: xinput pointers
|
|
"""
|
|
for id in get_ids_iter():
|
|
if is_short:
|
|
try:
|
|
yield get_short_pointer(id)
|
|
except TypeError as e:
|
|
# ignore if the id is not pointer
|
|
pass
|
|
except e:
|
|
# TODO: logging
|
|
pass
|
|
else:
|
|
pass # TODO
|
|
|
|
|
|
def get_pointers(is_short=True):
|
|
"""Wraps pointers in `xinput --list` in Pointer class
|
|
|
|
Creation of the pointer is done by getting the list description of
|
|
each id. if the is_short arg is True, then short list description will be
|
|
used which will provide the class `name`, `is_master` and `id` values.
|
|
|
|
Getting this pointers is done by first calling `xinput --list --id-only` to
|
|
get ids and then execute `xinput --list {id}` to get the description with
|
|
less-complicated output compare to iterating over `xinput --list --short`
|
|
line by line (--short option has some special characters that cause overhead
|
|
to the system for processing them individually and per-case).
|
|
"""
|
|
pointers = []
|
|
for pointer in get_pointer_iter(is_short):
|
|
pointers.append(pointer)
|
|
return pointers
|
|
|
|
|
|
def create_touch_master():
|
|
"""_summary_
|
|
|
|
Raises:
|
|
SystemError: If creation of touch pointer failed
|
|
|
|
Returns:
|
|
Pointer: pointer object corresponding to `touch` master
|
|
"""
|
|
touch = None
|
|
xutil.create_master("touch")
|
|
id = xutil.get_xi_id_by_name("touch pointer")
|
|
if id:
|
|
try:
|
|
touch = get_short_pointer(id)
|
|
except:
|
|
raise SystemError(
|
|
"touch pointer is not available. cannot create touch pointer"
|
|
)
|
|
else:
|
|
raise SystemError(
|
|
"touch pointer is not available. cannot create touch pointer"
|
|
)
|
|
|
|
# TODO configure cursor bitmap
|
|
return touch
|
|
|
|
|
|
def get_pointers_categorized():
|
|
"""Categorized Pointers
|
|
|
|
Categories:
|
|
1. VCore: Pointer
|
|
2. Touch Master: Pointer
|
|
3. eGalax: Pointer | None
|
|
4. Other non-masters: List[Pinter]
|
|
|
|
Raises:
|
|
SystemError: If creation of touch pointer failed
|
|
|
|
Returns:
|
|
|
|
"""
|
|
v_core = None
|
|
touch = None
|
|
e_galax = None
|
|
pointers = []
|
|
# filter pointers
|
|
for pointer in get_pointer_iter():
|
|
if pointer.name == "Virtual core pointer":
|
|
v_core = pointer
|
|
elif "eGalax" in pointer.name:
|
|
e_galax = pointer
|
|
elif pointer.name == "touch pointer":
|
|
touch = pointer
|
|
elif not pointer.master:
|
|
pointers.append(pointer)
|
|
|
|
if not touch:
|
|
touch = create_touch_master()
|
|
|
|
return v_core, touch, e_galax, pointers
|
|
|