snegg.ei module

Wrapper module around the libei C library. This is a thin API wrapper with most of the semantics of the underlying C library preserved. See the libei documentation for details on each API.

Warning

Most objects in this module are refcounted and automatically destroy the underlying C object when the Python reference is dropped. This may cause all sub-objects in the underlying C object to be destroyed as well. Care must be taken to preserve the Python object across multiple invocations.

class snegg.ei.ButtonEvent(button: int, is_press: bool)

Bases: object

button: int
is_press: bool
exception snegg.ei.ConnectionError(message: str, errno: Optional[int] = None)

Bases: Exception

class snegg.ei.Context(cobject, name: str)

Bases: CObjectWrapper

Represents a libei context. Use Sender or Receiver to create a context.

Logging of the libei context is hooked into Python’s logging module as the ei logger.

Warning

This context is refcounted and automatically destroys the underlying C object when the reference is dropped. This may cause all sub-objects in the underlying C object to be destroyed.

dispatch() None

Dispatch internally pending events. This method must be called immediately after fd has input pending. After calling dispatch(), events may be available in events.

property events: Iterator[Event]

Return an iterator over the currently pending events. The events will be automatically cleaned up when the references are dropped. This can cause subtle bugs, in particular this example code never prints events:

if len(ei.events) > 0:   # consumes and discards all events
    for e in ei.events:  # always [] because no events are waiting
        print(e)

The events returned by the first call to ei.events are iterated on and cleaned up by len() - on the second call to ei.events no further events are pending.

Do this instead:

events = ei.events
if len(events) > 0:
    for e in events:
        print(e)
property fd: IO

Return the file descriptor to monitor (e.g. using select). When this file descriptor has events pending, immediately call dispatch().

property name: str

This EI client’s name. Note that the name may or may not be honored by the EIS implementation. For example in the case of a client going through an XDG Desktop Portal, the app-id may be used instead.

property now: int

Return a CLOCK_MONOTONIC timestamp in microseconds

class snegg.ei.Device(cobject)

Bases: CObjectWrapper

button_button(button: int, is_press: bool) Device

Send a button event. The button number must be one of those defined in linux/input-event-codes.h.

This function does nothing if the device is not currently emulating.

Returns self for easy chaining of events.

property capabilities: tuple[snegg.ei.DeviceCapability]

The list of capabilities on this device. This is always a subset of the capabilities requested in Seat.bind().

close()

Close this device and indicate that this client is no longer interested in it. This typically results in the device being removed from the seat, never to be seen again.

property device_type: DeviceType
frame(timestamp: Optional[int] = None) Device

Send a frame event. If the timestamp is None is is replaced with the timestamp returned by Context.now().

property height: int

The height of the device if the attr:device_type is DeviceType.PHYSICAL, otherwise zero

keyboard_key(key: int, is_press: bool) Device

Send a key event. The key must be one of those defined in linux/input-event-codes.h.

This function does nothing if the device is not currently emulating.

Returns self for easy chaining of events.

property name: str

The name of this device as assigned by the EIS implementation.

pointer_motion(dx: float, dy: float) Device

Send a relative motion event with the given delta. The deltas are in logical pixels or mm, depending on the device_type.

This function does nothing if the device is not currently emulating.

Returns self for easy chaining of events.

pointer_motion_absolute(x: float, y: float) Device

Send a absolute motion event with the given position. The position is in logical pixels or mm, depending on the device_type.

This function does nothing if the device is not currently emulating.

Returns self for easy chaining of events.

property regions: tuple[snegg.ei.Region]

Return the set of regions available on this device. The set of regions is constant for the lifetime of the device.

property seat: Seat

Return the seat this device is attached to. The seat is constant for the lifetime of the device.

start_emulating(sequence: Optional[int] = None) Device

Start emulating events on this device. If the sequence is None, a random (but monotonically increasing) number is assigned to this sequence.

Returns self for easy chaining of events.

stop_emulating() Device

Stop the current emulation sequence.

Returns self for easy chaining of events.

touch_new() Touch

Create a new touch event. This touch does nothing until Touch.down() is called.

This function does nothing if the device is not currently emulating.

Returns self for easy chaining of events.

property width: int

The width of the device if the attr:device_type is DeviceType.PHYSICAL, otherwise zero

class snegg.ei.DeviceCapability(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntFlag

BUTTON = 32
KEYBOARD = 4
POINTER = 1
POINTER_ABSOLUTE = 2
SCROLL = 16
TOUCH = 8
static all() int

Return the bitmask of all known capabilities

class snegg.ei.DeviceType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntEnum

PHYSICAL = 2
VIRTUAL = 1
class snegg.ei.Dimension(width: int, height: int)

Bases: object

height: int
width: int
class snegg.ei.Event(cobject)

Bases: CObjectWrapper

property button_event: ButtonEvent
property device: Optional[Device]
property emulating_sequence: int
property event_type: EventType
property key_event: KeyEvent
property keyboard_xkb_modifiers: XkbModifiersEvent
property pointer_absolute_event: PointerAbsoluteEvent
property pointer_event: PointerEvent
property scroll_discrete_event: ScrollDiscreteEvent
property scroll_event: ScrollEvent
property scroll_stop_event: ScrollStopEvent
property seat: Optional[Seat]
property time: int
property touch_event: TouchEvent
class snegg.ei.EventType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntEnum

BUTTON_BUTTON = 500
CONNECT = 1
DEVICE_ADDED = 5
DEVICE_PAUSED = 7
DEVICE_REMOVED = 6
DEVICE_RESUMED = 8
DEVICE_START_EMULATING = 200
DEVICE_STOP_EMULATING = 201
DISCONNECT = 2
FRAME = 100
KEYBOARD_KEY = 700
KEYBOARD_MODIFIERS = 9
POINTER_MOTION = 300
POINTER_MOTION_ABSOLUTE = 400
SCROLL_CANCEL = 602
SCROLL_DELTA = 600
SCROLL_DISCRETE = 603
SCROLL_STOP = 601
SEAT_ADDED = 3
SEAT_REMOVED = 4
TOUCH_DOWN = 800
TOUCH_MOTION = 802
TOUCH_UP = 801
class snegg.ei.KeyEvent(key: int, is_press: bool)

Bases: object

is_press: bool
key: int
class snegg.ei.Keymap(cobject)

Bases: CObjectWrapper

property device: Device
property fd: IO
property keymap_type: KeymapType
property size: int
class snegg.ei.KeymapType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: IntEnum

XKB = 1
class snegg.ei.PointerAbsoluteEvent(x: float, y: float)

Bases: object

x: float
y: float
class snegg.ei.PointerEvent(dx: float, dy: float)

Bases: object

dx: float
dy: float
class snegg.ei.Position(x: int, y: int)

Bases: object

x: int
y: int
class snegg.ei.Receiver(name: str)

Bases: Context

classmethod create_for_fd(fd: IO, name: Optional[str] = None)

Create a Receiver EI context for the given file descriptor. This fd must be connected to an EIS implementation ready to accept clients or a ConnectionError is raised.

If name is None a default name will be used instead.

classmethod create_for_socket(path: Optional[Path], name: Optional[str] = None)

Create a Receiver EI context for an EIS implementation on the given socket path. If the path is None the environment variable LIBEI_SOCKET is used by the underlying library.

The socket path must exist and be ready to accept clients or a ConnectionError is raised.

If name is None a default name will be used instead.

class snegg.ei.Region(cobject)

Bases: CObjectWrapper

contains(x: float, y: float) bool

Return True if the given position is within this region, or False otherwise.

For example, a region 640x480@100,100 returns True for the position 100/100 and False for the position 640/580.

convert(x: float, y: float) Union[tuple[float, float], tuple[()]]

Convert the given position to a position relative to this region’s origin and return the updated (x, y) tuple.

If the position is outside this region, the empty tuple is returned instead.

For example, a region 640x480@100,100 converts the position 100/150 to 0/50.

property dimension: Dimension
property mapping_id: Optional[str]
property physical_scale: float
property position: Position
class snegg.ei.ScrollDiscreteEvent(dx: int, dy: int)

Bases: object

dx: int
dy: int
class snegg.ei.ScrollEvent(dx: float, dy: float)

Bases: object

dx: float
dy: float
class snegg.ei.ScrollStopEvent(x: bool, y: bool)

Bases: object

x: bool
y: bool
class snegg.ei.Seat(cobject)

Bases: CObjectWrapper

bind(capabilities: Optional[tuple[snegg.ei.DeviceCapability]] = None)

Bind to the given set of capabilities. If capabilities is None, all capabilities available on this seat are bound.

This typically results in devices with any of the given capabilities to be created by the EIS implementation.

property capabilities: tuple[snegg.ei.DeviceCapability, ...]

The set of capabilities available on this seat. The capabilities are constant for the lifetime of the seat and devices within this seat may only have one or more of these capabilities.

Devices are not created by the EIS implementation until at least one capability is given in bind().

property name: str

The seat name assigned by the EIS implementation.

unbind(capabilities: Optional[tuple[snegg.ei.DeviceCapability]] = None)

Unbind the given set of capabilities. If capabilities is None, all capabilities available on this seat are bound.

This typically results in all devices with any of the given capabilities to be removed by the EIS implementation.

class snegg.ei.Sender(name: str)

Bases: Context

classmethod create_for_fd(fd: IO, name: Optional[str] = None)

Create a Sender EI context for the given file descriptor. This fd must be connected to an EIS implementation ready to accept clients or a ConnectionError is raised.

If name is None a default name will be used instead.

classmethod create_for_socket(path: Optional[Path], name: Optional[str] = None)

Create a Sender EI context for an EIS implementation on the given socket path. If the path is None the environment variable LIBEI_SOCKET is used by the underlying library.

The socket path must exist and be ready to accept clients or a ConnectionError is raised.

If name is None a default name will be used instead.

class snegg.ei.Touch(cobj)

Bases: CObjectWrapper

property device: Device
down(x: float, y: float) Device

Logically put the touch down at the given position. The position is in logical pixels or mm, depending on the device_type.

This function does nothing if the device is not currently emulating.

Returns the touch’s device for easy chaining of events.

motion(x: float, y: float) Device

Logically move the touch to the given position. The position is in logical pixels or mm, depending on the device_type.

This function does nothing if the device is not currently emulating.

Returns the touch’s device for easy chaining of events.

up() Device

Logically lift the touch.

This function does nothing if the device is not currently emulating.

Returns the touch’s device for easy chaining of events.

class snegg.ei.TouchEvent(touchid: int, x: float, y: float)

Bases: object

touchid: int
x: float
y: float
class snegg.ei.XkbModifiersEvent(depressed: int, latched: int, locked: int, group: int)

Bases: object

depressed: int
group: int
latched: int
locked: int