mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-01-08 05:50:14 +01:00
proto: Define new ei_stylus protocol and implementation
Co-authored-by: Jason Gerecke <jason.gerecke@wacom.com>
This commit is contained in:
parent
3f48d11958
commit
bea231c4bf
33 changed files with 4176 additions and 9 deletions
|
|
@ -6,6 +6,7 @@
|
|||
Copyright © 2010-2011 Intel Corporation
|
||||
Copyright © 2012-2013 Collabora, Ltd.
|
||||
Copyright © 2023 Red Hat, Inc.
|
||||
Copyright © 2025 Wacom Co., Ltd.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
|
|
@ -752,8 +753,9 @@
|
|||
any relative movement on this region for that movement to match the same
|
||||
*physical* movement on another region.
|
||||
|
||||
It is an EIS implementation bug to advertise the touch and/or absolute pointer capability
|
||||
on a device_type.virtual device without advertising an ei_region for this device.
|
||||
It is an EIS implementation bug to advertise the touch, absolute pointer, and/or
|
||||
stylus capabilities on a device_type.virtual device without advertising an ei_region
|
||||
for this device.
|
||||
|
||||
This event is optional and sent immediately after object creation. Where a device
|
||||
has multiple regions, this event is sent once for each region.
|
||||
|
|
@ -781,6 +783,7 @@
|
|||
- "ei_button"
|
||||
- "ei_keyboard"
|
||||
- "ei_touchscreen"
|
||||
- "ei_stylus"
|
||||
The interface version is equal or less to the client-supported
|
||||
version in ei_handshake.interface_version for the respective interface.
|
||||
|
||||
|
|
@ -1584,4 +1587,529 @@
|
|||
<arg name="touchid" type="uint32"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="ei_stylus" version="1">
|
||||
<description summary="stylus object">
|
||||
Interface for stylus requests and events.
|
||||
|
||||
A stylus is an absolute pointing tool commonly used for writing, drawing,
|
||||
and other tasks traditionally accomplished with a pen or pencil. This
|
||||
interface represents the various semantics and properties common to these
|
||||
kinds of tools. An ei_device may use this interface alone or in
|
||||
combination with other interfaces to emulate tools with additional
|
||||
features. For example, a tool with physical buttons may be emulated by
|
||||
creating an ei_device that has both this and an ei_button interface.
|
||||
|
||||
When adding this interface to an ei_device, the server and client are
|
||||
required to negotiate tool capabilities. Negotiation is performed by the
|
||||
server first sending ei_stylus.tool_capabilities prior to ei_device.done
|
||||
and then the client responding with ei_stylus.bind_tool_capabilities
|
||||
prior to starting emulation for the first time.
|
||||
|
||||
This interface may be used on both ei_device.device_type.virtual and
|
||||
ei_device.device_type.physical devices. As an interface with absolute
|
||||
motion, virtual devices must declare an arbitrary set of regions that
|
||||
are be valid for motion events. For physical devices, the server must
|
||||
send an ei_device.dimensions that reflects the size of the active area
|
||||
of the stylus' digitizer. This size **must not** include any
|
||||
"[out-of-bounds][OOB]" margin that may exist (e.g. a digitizer with a
|
||||
404 x 229 mm active area and 2mm margin on all sides should have a
|
||||
declared size of only 400 x 225 mm).
|
||||
|
||||
Implementations are free to decide how they handle multiple styli. For
|
||||
example, a sender that is capable of distinguishing two styli (e.g. by
|
||||
serial number) may choose to use a unique ei_device object for each
|
||||
stylus, making it possible for the receiver to keep track of which tool
|
||||
is in use. Senders are not obligated to do this; it is equally valid for
|
||||
them to discard any distinguishing information that they may (or may not)
|
||||
have and use a single ei_device for all styli. Similarly, receivers are
|
||||
free to choose whether to use or discard information about the source
|
||||
ei_device after processing.
|
||||
|
||||
This interface is only provided once per device and where a client
|
||||
requests ei_stylus.release the interface does not get re-initialized. An
|
||||
EIS implementation may adjust the behavior of the device (including
|
||||
removing the device) if the interface is released.
|
||||
|
||||
Note that for a client to receive objects of this type, it must announce
|
||||
support for the interface in ei_handshake.interface_version.
|
||||
|
||||
### Protocol States
|
||||
|
||||
This protocol is stateful and relies on ei_device.frame to delimit state
|
||||
changes. Only those properties, axes, and other values that have changed
|
||||
from one frame to the next are required to be sent.
|
||||
|
||||
This documentation may use various phrases to describe the major
|
||||
proximity states of the protocol. For clarity, these phrases are defined
|
||||
below:
|
||||
|
||||
- **Out of proximity**: Initial state of an ei_stylus object. This state
|
||||
indicates that a stylus tool is unable to be sensed by a digitizer.
|
||||
Its location and other properties are unknown an invalid in this
|
||||
state. This state can only be transitioned out of by sending a frame
|
||||
containing ei_stylus.proximity_in.
|
||||
|
||||
- **Entering proximity**: State of the ei_stylus object for the duration
|
||||
of the frame containing ei_stylus.proximity_in. This state indicates
|
||||
that a stylus has just come near enough to a digitizer for its
|
||||
location and other properties to become known and valid. This is a
|
||||
transient state that automatically advances to "in proximity" once the
|
||||
frame has finished processing.
|
||||
|
||||
- **In proximity**: State of the ei_stylus object during normal
|
||||
operation. This state indicates that the stylus is remaining near
|
||||
enough to its digitizer for location and other properties to remain
|
||||
valid. This state is transitioned out of by sending a frame containing
|
||||
ei_stylus.proximity_out.
|
||||
|
||||
- **Leaving proximity**: State of the ei_stylus for the duration of the
|
||||
frame containing ei_stylus.proximity_out. This state indicates that
|
||||
the stylus has just moved far enough from its digitizer for its
|
||||
location and other properties to no longer be known or valid. This is
|
||||
a transient state that automatically advances to "out of proximity"
|
||||
once the frame has finished processing. Some stylus hardware/drivers
|
||||
may provide a final update of the last-known valid location and other
|
||||
properties as a stylus leaves proximity. This protocol allows such a
|
||||
final update to be sent in this state.
|
||||
|
||||
### Logical Contact
|
||||
|
||||
This protocol uses the concept of "logical contact" to represent when a
|
||||
stylus is making intentional contact with its digitizer. Logical
|
||||
contact is a heuristic and often flagged by hardware drivers based on
|
||||
things like the state of a hardware "tip switch", the level of pressure
|
||||
compared to a threshold, etc. It is important to note that physical
|
||||
contact does *not* necessarily imply logical contact; some physical
|
||||
contacts are unintentional and some imperfect tools may indicate
|
||||
physical contact even while hovering (e.g. by always sending some small
|
||||
non-zero pressure value).
|
||||
|
||||
### Stylus Buttons
|
||||
|
||||
This protocol does not define notifications or events for the state of
|
||||
buttons that exist on it. Instead, it is expected that implementations
|
||||
ensure that the parent ei_device declares both this and an ei_button
|
||||
interface. Button requests should be routed through the button interface
|
||||
and be part of the same ei_device.frame that contains the coincident
|
||||
stylus requests.
|
||||
|
||||
[OOB]: https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html#out-of-bounds-motion-events
|
||||
</description>
|
||||
|
||||
<!-- ei_stylus client requests version 1 -->
|
||||
|
||||
<enum name="capability" since="1">
|
||||
<description summary="capability type">
|
||||
This enum denotes capability types for the ei_stylus.
|
||||
|
||||
A capability describes a particular type of data that may be reported
|
||||
by a device or tool. Each capability is a bit flag that may be set in
|
||||
a mask describing a full set of capabilities.
|
||||
</description>
|
||||
<entry name="erase" value="1" summary="the tool may act as an eraser"/>
|
||||
<entry name="pressure" value="2" summary="pressure data may be reported"/>
|
||||
<entry name="distance" value="4" summary="distance data may be reported"/>
|
||||
<entry name="tilt" value="8" summary="tilt data may be reported"/>
|
||||
<entry name="rotation" value="16" summary="rotation data may be reported"/>
|
||||
<entry name="airbrush_flow" value="32" summary="airbrush_flow data may be reported"/>
|
||||
</enum>
|
||||
|
||||
<request name="release" since="1">
|
||||
<description summary="stylus removal request">
|
||||
Notification that the client is no longer interested in this stylus
|
||||
object. The EIS implementation will release any resources related to
|
||||
this object and send the ei_stylus.destroyed event once complete.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="bind_tool_capabilities" since="1" context-type="sender">
|
||||
<description summary="stylus tool capability bind request">
|
||||
Request to bind to a given set of tool capabilities. This is used
|
||||
by clients to describe which subset of server-supported capabilities
|
||||
may be sent by this particular stylus.
|
||||
|
||||
Clients are required to send this in response to the
|
||||
ei_stylus.tool_capabilities event. It is required to be sent prior to
|
||||
the first ei_device.start_emulating request. It is a protocol violation
|
||||
to not provide this feedback back to the server. It is a protocol
|
||||
violation to include capabilities that were not present in the server
|
||||
event.
|
||||
|
||||
It is a protocol violation to send requests or events for unbound
|
||||
capabilities.
|
||||
</description>
|
||||
<arg name="capabilities" type="uint32" summary="A mask of 'capability' flags that the client wishes to handle"/>
|
||||
</request>
|
||||
|
||||
<request name="proximity_in" since="1" context-type="sender">
|
||||
<description summary="sylus proximity in request">
|
||||
Notification that a stylus is entering proximity of its digitizer. The
|
||||
stylus object transitions from an "out of proximity" state to
|
||||
"entering proximity" for the duration of the ei_device.frame that
|
||||
contains this request. After the frame has been processed, the
|
||||
object automatically transitions to an "in proximity" state.
|
||||
|
||||
The frame containing this request is required to also contain
|
||||
ei_stylus.motion.
|
||||
|
||||
It is a protocol violation to send this request while the stylus object
|
||||
is already in or entering proximity. It is a protocol violation to send
|
||||
ei_stylus.proximity_in and ei_device.proximity_out in the same
|
||||
frame.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="proximity_out" since="1" context-type="sender">
|
||||
<description summary="stylus proximity out request">
|
||||
Notification that the the stylus is leaving proximity of its
|
||||
digitizer. The stylus object transitions from an "in proximity" state
|
||||
to "leaving proximity" for the duration of the ei_device.frame that
|
||||
contains this request. After the frame has been processed, the object
|
||||
automatically transitions to an "out of proximity" state.
|
||||
|
||||
Once a stylus is "out of proximity", all other state information
|
||||
(e.g. tool type, up/down/erase state, axis values) is considered
|
||||
invalid and must be cleared on both the sending and receiving side.
|
||||
|
||||
The frame containing this request may contain updates of the stylus
|
||||
state (location, tilt, etc.) that represents its final known valid
|
||||
properties. It should not contain events that attempt to explicitly
|
||||
reset state.
|
||||
|
||||
It is a protocol violation to send this request while the stylus object
|
||||
is already leaving or out of proximity. It is a protocol violation to
|
||||
send ei_stylus.proximity_in and ei_device.proximity_out in the same
|
||||
frame.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="erase_start" since="1" context-type="sender">
|
||||
<description summary="erase start request">
|
||||
Notification that the stylus's eraser feature has been activated.
|
||||
|
||||
Physical styli often include some kind of eraser feature, activated by
|
||||
flipping the tool over or holding a button down. These button-activated
|
||||
tools in particular may start or stop erasing without ever leaving
|
||||
proximity.
|
||||
|
||||
The default state for tools is "not erasing".
|
||||
|
||||
This request may only be sent while the stylus is entering or in
|
||||
proximity. It is a protocol violation to send this request at any
|
||||
other time. It is a protocol violation to for ei_stylus.erase_start and
|
||||
ei_stylus.erase_stop to share the same ei_device.frame. It is a client
|
||||
bug to send this request when the ei_stylus.capability.erase capability
|
||||
is not bound. The EIS implementation may ignore unbound requests and/or
|
||||
disconnect the client.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="erase_stop" since="1" context-type="sender">
|
||||
<description summary="erase stop request">
|
||||
Notification that the stylus's eraser feature has been deactivated.
|
||||
|
||||
Physical styli often include some kind of eraser feature, activated by
|
||||
flipping the tool over or holding a button down. These button-activated
|
||||
tools in particular may start or stop erasing without ever leaving
|
||||
proximity.
|
||||
|
||||
The default state for tools is "not erasing".
|
||||
|
||||
This request may only be sent while the stylus is in or leaving
|
||||
proximity. It is a protocol violation to send this request at any
|
||||
other time. It is a protocol violation to for ei_stylus.erase_start and
|
||||
ei_stylus.erase_stop to share the same ei_device.frame. It is a client
|
||||
bug to send this request when the ei_stylus.capability.erase capability
|
||||
is not bound. The EIS implementation may ignore unbound requests and/or
|
||||
disconnect the client.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="down" since="1" context-type="sender">
|
||||
<description summary="stylus down request">
|
||||
Notification that the stylus has come into logical contact with its
|
||||
digitizer.
|
||||
|
||||
Senders are required to use this request to signal logical contact.
|
||||
Receivers are free to treat the stylus as "up" in the absence of this
|
||||
event, regardless of other axis values that may be present (e.g.
|
||||
pressure, distance).
|
||||
|
||||
This request may only be sent while the stylus is entering or in
|
||||
proximity. It is a protocol violation to send this request at any other
|
||||
time. It is a protocol violation to for ei_stylus.down and ei_stylus.up
|
||||
to share the same ei_device.frame.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="up" since="1" context-type="sender">
|
||||
<description summary="stylus up request">
|
||||
Notification that the stylus has left logical contact with its
|
||||
digitizer.
|
||||
|
||||
Senders are required to generate this request to signal the loss of
|
||||
logical contact. Receivers are free to treat the stylus as "down" in
|
||||
the absence of this event, regardless of other axis values that may be
|
||||
present (e.g. pressure, distance).
|
||||
|
||||
This request may only be sent while the stylus is in or leaving
|
||||
proximity. It is a protocol violation to send this request at any other
|
||||
time. It is a protocol violation to for ei_stylus.down and ei_stylus.up
|
||||
to share the same ei_device.frame.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="motion" since="1" context-type="sender">
|
||||
<description summary="stylus motion request">
|
||||
Notification that the stylus has been moved to the given absolute
|
||||
coordinates. The interpretation of values depends on if the device is
|
||||
physical (mm) or virtual (pixels). Fractional pixels are allowed.
|
||||
|
||||
Valid `(x, y)` locations are those that exist inside of the
|
||||
ei_device.dimension (for physical devices) or one of the device's
|
||||
ei_device.region (for virtual devices). It is a client bug to send a
|
||||
location that exists outside of these locations. The EIS implementation
|
||||
may clamp out-of-range values and/or disconnect the client.
|
||||
|
||||
This request is required to be in the same frame as
|
||||
ei_stylus.proximity_in. It may also be sent while the stylus is in or
|
||||
leaving proximity. It is a protocol violation to send this request at
|
||||
any other time.
|
||||
</description>
|
||||
<arg name="x" type="float" summary="The x position of the stylus in mm or logical pixels."/>
|
||||
<arg name="y" type="float" summary="The y position of the stylus in mm or logical pixels."/>
|
||||
</request>
|
||||
|
||||
<request name="pressure" since="1" context-type="sender">
|
||||
<description summary="stylus pressure request">
|
||||
Notification of the relative amount of pressure exerted on the stylus.
|
||||
|
||||
The valid range for pressure is `0.0 <= pressure <= 1.0`. It is a
|
||||
client bug to send values outside of this range. The EIS implementation
|
||||
may clamp out-of-range values and/or disconnect the client.
|
||||
|
||||
The value `pressure = 0.0` indicates the stylus is experiencing
|
||||
"minimum" or "no" pressure, and `pressure = 1.0` indicates the stylus
|
||||
is measuring some arbitrary "maximum pressure".
|
||||
|
||||
This request may only be sent while the stylus is entering, in, or
|
||||
leaving proximity. It is a protocol violation to send this request at
|
||||
any other time.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Non-zero pressure does not imply logical contact, but logical
|
||||
> contact _does_ imply a non-zero pressure. If a client has bound the
|
||||
> pressure capability, it is a bug to not ensure `pressure > 0.0`
|
||||
> when sending ei_stylus.down. The EIS implementation may correct
|
||||
> illegal values and/or disconnect the client.
|
||||
</description>
|
||||
<arg name="pressure" type="float" summary="The tip pressure as a normalized value."/>
|
||||
</request>
|
||||
|
||||
<request name="distance" since="1" context-type="sender">
|
||||
<description summary="stylus distance request">
|
||||
Notification of the relative distance between the stylus and its
|
||||
digitizer.
|
||||
|
||||
The valid range for distance is `0.0 <= distance <= 1.0`. It is a
|
||||
client bug to send values outside of this range. The EIS implementation
|
||||
may clamp out-of-range values and/or disconnect the client.
|
||||
|
||||
The value `distance = 0.0` indicates the stylus is in physical contact
|
||||
with the digitizer and `distance = 1.0` indicates the stylus is at some
|
||||
arbitrary "maximum distance".
|
||||
|
||||
This request may only be sent while the stylus is entering, in, or
|
||||
leaving proximity. It is a protocol violation to send this request at
|
||||
any other time.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Physical contact does not imply logical contact, but logical
|
||||
> contact _does_ imply physical contact. If a client has bound the
|
||||
> distance capability, it is a bug to not ensure that `d = 0.0` when
|
||||
> sending ei_stylus.down. The EIS implementation may correct illegal
|
||||
> values and/or disconnect the client.
|
||||
</description>
|
||||
<arg name="distance" type="float" summary="The tip-to-digitizer distance as a normalized value."/>
|
||||
</request>
|
||||
|
||||
<request name="tilt" since="1" context-type="sender">
|
||||
<description summary="stylus tilt request">
|
||||
Notification of the stylus's tilt angles in degrees.
|
||||
|
||||
The valid range for each tilt angle is `-90.0 <= tilt_[xy] <=
|
||||
+90.0`. It is a client bug to send values outside of this range. The
|
||||
EIS implementation may clamp out-of-range values and/or disconnect
|
||||
the client.
|
||||
|
||||
Each tilt angle is measured relative to the digitizer's Z axis. The pair
|
||||
`(tilt_x = 0, tilt_y = 0)` indicates the stylus is being held parallel
|
||||
to the Z axis, while `(tilt_x = 90, tilt_y = 0)` and `(tilt_x = 0,
|
||||
tilt_y = 90)` indicate the stylus parallel to the +X and +Y axes,
|
||||
respectively.
|
||||
|
||||
This request may only be sent while the stylus is entering, in, or
|
||||
leaving proximity. It is a protocol violation to send this request at
|
||||
any other time.
|
||||
</description>
|
||||
<arg name="tilt_x" type="float" summary="The angle in degrees of the stylus along the digitizer X axis."/>
|
||||
<arg name="tilt_y" type="float" summary="The angle in degrees of the stylus along the digitizer Y axis."/>
|
||||
</request>
|
||||
|
||||
<request name="rotation" since="1" context-type="sender">
|
||||
<description summary="stylus rotation request">
|
||||
Notification of the stylus's barrel rotation angle in degrees.
|
||||
|
||||
The valid range for barrel rotation is `0.0 <= rotation < 360.0`.
|
||||
It is a client bug to send values outside of this range. The EIS
|
||||
implementation may reduce out-of-range values modulo 360 and/or
|
||||
disconnect the client.
|
||||
|
||||
The value `rotation = 0.0` indicates the stylus is being held at its
|
||||
neutral rotation angle. Angles increase in value as the stylus is
|
||||
rotated clockwise while held.
|
||||
|
||||
This request may only be sent while the stylus is entering, in, or
|
||||
leaving proximity. It is a protocol violation to send this request at
|
||||
any other time.
|
||||
</description>
|
||||
<arg name="rotation" type="float" summary="The angle in degrees of the stylus about its own Z axis."/>
|
||||
</request>
|
||||
|
||||
<request name="airbrush_flow" since="1" context-type="sender">
|
||||
<description summary="stylus airbrush flow request">
|
||||
Notification of the relative position of an airbrush stylus's flow
|
||||
control.
|
||||
|
||||
The valid range for airbrush flow is `0.0 <= flow <= 1.0`. It is
|
||||
a client bug to send values outside of this range. The EIS
|
||||
implementation may clamp out-of-range values and/or disconnect the
|
||||
client.
|
||||
|
||||
The value `flow = 0.0` indicates the airbrush flow control is fully
|
||||
"off" and `flow = 1.0` indicates the control is fully "on".
|
||||
|
||||
This request may only be sent while the stylus is entering, in, or
|
||||
leaving proximity. It is a protocol violation to send this request at
|
||||
any other time.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Many platforms report the airbrush flow control through a generic
|
||||
> "tangential pressure" or "slider" property. These generic properties
|
||||
> may contain other types of data when non-airbrush tools are in use.
|
||||
> Developers should take care to not report other types of data with
|
||||
> this request.
|
||||
</description>
|
||||
<arg name="flow" type="float" summary="The position of an airbrush flow control present on the tool, as a normalized value."/>
|
||||
</request>
|
||||
|
||||
<!-- ei_stylus events version 1 -->
|
||||
|
||||
<event name="destroyed" type="destructor" since="1">
|
||||
<description summary="stylus removal notification">
|
||||
This object has been removed and a client should release all associated
|
||||
resources.
|
||||
|
||||
This object will be destroyed by the EIS implementation immediately
|
||||
after this event is sent and as such the client must not attempt to use
|
||||
it after that point.
|
||||
</description>
|
||||
<arg name="serial" type="uint32" summary="This event's serial number."/>
|
||||
</event>
|
||||
|
||||
<event name="tool_capabilities" since="1">
|
||||
<description summary="stylus tool capabilities event">
|
||||
See the ei_stylus.bind_tool_capabilities request for more details.
|
||||
|
||||
The server sends this event after attaching the ei_stylus interface
|
||||
to an ei_device. This event describes the set of capabilities that
|
||||
the tool supports. For sender contexts, the client must confirm
|
||||
(and optionally narrow down) the capabilities with the
|
||||
ei_stylus.bind_tool_capabilities request before the device will
|
||||
send events.
|
||||
</description>
|
||||
<arg name="capabilities" type="uint32" summary="A mask of 'capability' flags for the events available through this interface"/>
|
||||
</event>
|
||||
|
||||
<event name="proximity_in" since="1" context-type="receiver">
|
||||
<description summary="sylus proximity in event">
|
||||
See the ei_stylus.proximity_in request for more details.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="proximity_out" since="1" context-type="receiver">
|
||||
<description summary="stylus proximity out event">
|
||||
See the ei_stylus.proximity_out request for more details.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="erase_start" since="1" context-type="receiver">
|
||||
<description summary="erase start event">
|
||||
See the ei_stylus.erase_start request for more details.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="erase_stop" since="1" context-type="receiver">
|
||||
<description summary="erase stop event">
|
||||
See the ei_stylus.erase_stop request for more details.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="down" since="1" context-type="receiver">
|
||||
<description summary="stylus down event">
|
||||
See the ei_stylus.down request for more details.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="up" since="1" context-type="receiver">
|
||||
<description summary="stylus up event">
|
||||
See the ei_stylus.up request for more details.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="motion" since="1" context-type="receiver">
|
||||
<description summary="stylus motion event">
|
||||
See the ei_stylus.motion request for more details.
|
||||
</description>
|
||||
<arg name="x" type="float" summary="The x position of the stylus in mm or logical pixels."/>
|
||||
<arg name="y" type="float" summary="The y position of the stylus in mm or logical pixels."/>
|
||||
</event>
|
||||
|
||||
<event name="pressure" since="1" context-type="receiver">
|
||||
<description summary="stylus pressure event">
|
||||
See the ei_stylus.pressure request for more details.
|
||||
</description>
|
||||
<arg name="pressure" type="float" summary="The tip pressure as a normalized value."/>
|
||||
</event>
|
||||
|
||||
<event name="distance" since="1" context-type="receiver">
|
||||
<description summary="stylus distance event">
|
||||
See the ei_stylus.distance request for more details.
|
||||
</description>
|
||||
<arg name="distance" type="float" summary="The tip-to-digitizer distance as a normalized value."/>
|
||||
</event>
|
||||
|
||||
<event name="tilt" since="1" context-type="receiver">
|
||||
<description summary="stylus tilt event">
|
||||
See the ei_stylus.tilt request for more details.
|
||||
</description>
|
||||
<arg name="tilt_x" type="float" summary="The angle in degrees of the stylus along the digitizer X axis."/>
|
||||
<arg name="tilt_y" type="float" summary="The angle in degrees of the stylus along the digitizer Y axis."/>
|
||||
</event>
|
||||
|
||||
<event name="rotation" since="1" context-type="receiver">
|
||||
<description summary="stylus rotation event">
|
||||
See the ei_stylus.rotation request for more details.
|
||||
</description>
|
||||
<arg name="rotation" type="float" summary="The angle in degrees of the stylus about its own Z axis."/>
|
||||
</event>
|
||||
|
||||
<event name="airbrush_flow" since="1" context-type="receiver">
|
||||
<description summary="stylus slider event">
|
||||
See the ei_stylus.airbrush_flow request for more details.
|
||||
</description>
|
||||
<arg name="flow" type="float" summary="The position of an airbrush flow control present on the tool, as a normalized value."/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ ei_device_destroy(struct ei_device *device)
|
|||
ei_button_unref(device->button);
|
||||
ei_touchscreen_unref(device->touchscreen);
|
||||
ei_keyboard_unref(device->keyboard);
|
||||
ei_stylus_unref(device->stylus);
|
||||
ei_seat_unref(seat);
|
||||
free(device->name);
|
||||
free(device->pending_region_mapping_id);
|
||||
|
|
@ -255,13 +256,16 @@ handle_msg_done(struct ei_device *device)
|
|||
mask_add(device->capabilities, EI_DEVICE_CAP_KEYBOARD);
|
||||
if (device->touchscreen)
|
||||
mask_add(device->capabilities, EI_DEVICE_CAP_TOUCH);
|
||||
if (device->stylus)
|
||||
mask_add(device->capabilities, EI_DEVICE_CAP_STYLUS);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_BUTTON) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_SCROLL)) {
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_SCROLL) &&
|
||||
!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
log_debug(ei, "Rejecting device %#" PRIx64 " '%s' with no known capabilities",
|
||||
ei_device_get_id(device), ei_device_get_name(device));
|
||||
ei_device_close(device);
|
||||
|
|
@ -273,7 +277,7 @@ handle_msg_done(struct ei_device *device)
|
|||
ei_queue_device_added_event(device);
|
||||
ei_device_done(device);
|
||||
log_debug(ei,
|
||||
"Added device %#" PRIx64 " '%s' caps: %s%s%s%s%s%s seat: %s",
|
||||
"Added device %#" PRIx64 " '%s' caps: %s%s%s%s%s%s%s seat: %s",
|
||||
ei_device_get_id(device), ei_device_get_name(device),
|
||||
ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) ? "p" : "",
|
||||
ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) ? "a" : "",
|
||||
|
|
@ -281,6 +285,7 @@ handle_msg_done(struct ei_device *device)
|
|||
ei_device_has_capability(device, EI_DEVICE_CAP_TOUCH) ? "t" : "",
|
||||
ei_device_has_capability(device, EI_DEVICE_CAP_BUTTON) ? "b" : "",
|
||||
ei_device_has_capability(device, EI_DEVICE_CAP_SCROLL) ? "s" : "",
|
||||
ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS) ? "y" : "",
|
||||
ei_seat_get_name(ei_device_get_seat(device)));
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -466,6 +471,13 @@ handle_msg_interface(struct ei_device *device, object_id_t id, const char *name,
|
|||
"Duplicate ei_touchscreen interface object on device");
|
||||
|
||||
device->touchscreen = ei_touchscreen_new(device, id, version);
|
||||
} else if (streq(name, EI_STYLUS_INTERFACE_NAME)) {
|
||||
DISCONNECT_IF_INVALID_VERSION(ei, ei_stylus, id, version);
|
||||
if (device->stylus)
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Duplicate ei_stylus interface object on device");
|
||||
|
||||
device->stylus = ei_stylus_new(device, id, version);
|
||||
} else {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Unsupported interface '%s' on device", name);
|
||||
|
|
@ -913,6 +925,286 @@ ei_device_get_touchscreen_interface(struct ei_device *device)
|
|||
return &touchscreen_interface;
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_tool_capabilities(struct ei_stylus *stylus, uint32_t capability)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus tool capabilities event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_NEW) {
|
||||
ei_queue_stylus_tool_capabilities_event(device, capability);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus tool capabilities");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_proximity_in(struct ei_stylus *stylus)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus proximity in event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_proximity_in_event(device);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus proximity in");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_proximity_out(struct ei_stylus *stylus)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus proximity out event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_proximity_out_event(device);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus proximity out");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_erase_start(struct ei_stylus *stylus)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus erase start event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_erase_start_event(device);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus erase start");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_erase_stop(struct ei_stylus *stylus)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus erase stop event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_erase_stop_event(device);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus erase stop");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_down(struct ei_stylus *stylus)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus down event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_down_event(device);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus down");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_up(struct ei_stylus *stylus)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus up event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_up_event(device);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus up");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_motion(struct ei_stylus *stylus, float x, float y)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus motion event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_motion_event(device, x, y);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus motion");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_pressure(struct ei_stylus *stylus, float pressure)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus pressure event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_pressure_event(device, pressure);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus pressure");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_distance(struct ei_stylus *stylus, float distance)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus distance event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_distance_event(device, distance);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus distance");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_tilt(struct ei_stylus *stylus, float tilt_x, float tilt_y)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus tilt event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_tilt_event(device, tilt_x, tilt_y);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus tilt");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_rotation(struct ei_stylus *stylus, float rotation)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus rotation event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_rotation_event(device, rotation);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus rotation");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_airbrush_flow(struct ei_stylus *stylus, float flow)
|
||||
{
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_SENDER_CONTEXT(device);
|
||||
|
||||
if (!ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus airbrush_flow event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EI_DEVICE_STATE_EMULATING) {
|
||||
ei_queue_stylus_airbrush_flow_event(device, flow);
|
||||
return NULL;
|
||||
}
|
||||
return maybe_error_on_device_state(device, "stylus airbrush_flow");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
handle_msg_stylus_destroy(struct ei_stylus *stylus, uint32_t serial)
|
||||
{
|
||||
struct ei *ei = ei_stylus_get_context(stylus);
|
||||
ei_update_serial(ei, serial);
|
||||
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
ei_stylus_unref(steal(&device->stylus));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct ei_stylus_interface stylus_interface = {
|
||||
.destroyed = handle_msg_stylus_destroy,
|
||||
.airbrush_flow = handle_msg_stylus_airbrush_flow,
|
||||
.rotation = handle_msg_stylus_rotation,
|
||||
.tilt = handle_msg_stylus_tilt,
|
||||
.distance = handle_msg_stylus_distance,
|
||||
.pressure = handle_msg_stylus_pressure,
|
||||
.motion = handle_msg_stylus_motion,
|
||||
.up = handle_msg_stylus_up,
|
||||
.down = handle_msg_stylus_down,
|
||||
.erase_start = handle_msg_stylus_erase_start,
|
||||
.erase_stop = handle_msg_stylus_erase_stop,
|
||||
.proximity_out = handle_msg_stylus_proximity_out,
|
||||
.proximity_in = handle_msg_stylus_proximity_in,
|
||||
.tool_capabilities = handle_msg_stylus_tool_capabilities,
|
||||
};
|
||||
|
||||
const struct ei_stylus_interface *
|
||||
ei_device_get_stylus_interface(struct ei_device *device)
|
||||
{
|
||||
return &stylus_interface;
|
||||
}
|
||||
|
||||
struct ei_device *
|
||||
ei_device_new(struct ei_seat *seat, object_id_t deviceid, uint32_t version)
|
||||
{
|
||||
|
|
@ -1058,6 +1350,8 @@ ei_device_send_release(struct ei_device *device)
|
|||
ei_scroll_request_release(device->scroll);
|
||||
if (device->button)
|
||||
ei_button_request_release(device->button);
|
||||
if (device->stylus)
|
||||
ei_stylus_request_release(device->stylus);
|
||||
|
||||
int rc = ei_device_request_release(device);
|
||||
if (rc)
|
||||
|
|
@ -1118,6 +1412,7 @@ ei_device_removed_by_server(struct ei_device *device)
|
|||
ei_touchscreen_unref(steal(&device->touchscreen));
|
||||
ei_scroll_unref(steal(&device->scroll));
|
||||
ei_button_unref(steal(&device->button));
|
||||
ei_stylus_unref(steal(&device->stylus));
|
||||
|
||||
ei_unregister_object(ei, &device->proto_object);
|
||||
ei_queue_device_removed_event(device);
|
||||
|
|
@ -1194,6 +1489,7 @@ ei_device_has_capability(struct ei_device *device,
|
|||
case EI_DEVICE_CAP_TOUCH:
|
||||
case EI_DEVICE_CAP_BUTTON:
|
||||
case EI_DEVICE_CAP_SCROLL:
|
||||
case EI_DEVICE_CAP_STYLUS:
|
||||
return mask_all(device->capabilities, cap);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1812,6 +2108,376 @@ ei_touch_cancel(struct ei_touch *touch)
|
|||
ei_send_touch_up(touch->device, touch->tracking_id);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_bind_tool_capabilities(struct ei_device *device, uint32_t capabilities)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = false;
|
||||
|
||||
int rc = ei_stylus_request_bind_tool_capabilities(device->stylus, capabilities);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_bind_tool_capabilities(struct ei_device *device, uint32_t capabilities)
|
||||
{
|
||||
// TODO: If/when libei-device.c gets something equivalent to the
|
||||
// EIS_DEVICE_STATE_AWAITING_READY state, this should be updated
|
||||
// to match it.
|
||||
if (device->state != EI_DEVICE_STATE_PAUSED) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not paused", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_bind_tool_capabilities(device, capabilities);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_motion(struct ei_device *device, float x, float y)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_motion(device->stylus, x, y);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_motion(struct ei_device *device, float x, float y)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ei_device_in_region(device, x, y))
|
||||
return;
|
||||
|
||||
ei_send_stylus_motion(device, x, y);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_pressure(struct ei_device *device, float pressure)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_pressure(device->stylus, pressure);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_pressure(struct ei_device *device, float pressure)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_pressure(device, pressure);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_distance(struct ei_device *device, float distance)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_distance(device->stylus, distance);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_distance(struct ei_device *device, float distance)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_distance(device, distance);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_tilt(struct ei_device *device, float tilt_x, float tilt_y)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_tilt(device->stylus, tilt_x, tilt_y);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_tilt(struct ei_device *device, float tilt_x, float tilt_y)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_tilt(device, tilt_x, tilt_y);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_rotation(struct ei_device *device, float rotation)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_rotation(device->stylus, rotation);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_rotation(struct ei_device *device, float rotation)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_rotation(device, rotation);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_airbrush_flow(struct ei_device *device, float flow)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_airbrush_flow(device->stylus, flow);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_airbrush_flow(struct ei_device *device, float flow)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_airbrush_flow(device, flow);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_erase_start(struct ei_device *device)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_erase_start(device->stylus);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_erase_start(struct ei_device *device)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_erase_start(device);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_erase_stop(struct ei_device *device)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_erase_stop(device->stylus);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_erase_stop(struct ei_device *device)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_erase_stop(device);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_up(struct ei_device *device)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_up(device->stylus);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_up(struct ei_device *device)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_up(device);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_down(struct ei_device *device)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_down(device->stylus);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_down(struct ei_device *device)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_down(device);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_proximity_out(struct ei_device *device)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_proximity_out(device->stylus);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_proximity_out(struct ei_device *device)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_proximity_out(device);
|
||||
}
|
||||
|
||||
static int
|
||||
ei_send_stylus_proximity_in(struct ei_device *device)
|
||||
{
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
if (ei->state == EI_STATE_NEW || ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
int rc = ei_stylus_request_proximity_in(device->stylus);
|
||||
if (rc)
|
||||
ei_disconnect(ei);
|
||||
return rc;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_stylus_proximity_in(struct ei_device *device)
|
||||
{
|
||||
if (device->state != EI_DEVICE_STATE_EMULATING) {
|
||||
log_bug_client(ei_device_get_context(device),
|
||||
"%s: device is not emulating", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ei_send_stylus_proximity_in(device);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_device_frame(struct ei_device *device, uint64_t time)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "libei-pointer.h"
|
||||
#include "libei-keyboard.h"
|
||||
#include "libei-touchscreen.h"
|
||||
#include "libei-stylus.h"
|
||||
|
||||
enum ei_device_state {
|
||||
/* Before the DeviceAddedDone was received */
|
||||
|
|
@ -65,6 +66,7 @@ struct ei_device {
|
|||
struct ei_button *button;
|
||||
struct ei_keyboard *keyboard;
|
||||
struct ei_touchscreen *touchscreen;
|
||||
struct ei_stylus *stylus;
|
||||
|
||||
struct list link;
|
||||
enum ei_device_state state;
|
||||
|
|
@ -123,6 +125,7 @@ OBJECT_DECLARE_GETTER(ei_device, scroll_interface, const struct ei_scroll_interf
|
|||
OBJECT_DECLARE_GETTER(ei_device, button_interface, const struct ei_button_interface *);
|
||||
OBJECT_DECLARE_GETTER(ei_device, keyboard_interface, const struct ei_keyboard_interface *);
|
||||
OBJECT_DECLARE_GETTER(ei_device, touchscreen_interface, const struct ei_touchscreen_interface *);
|
||||
OBJECT_DECLARE_GETTER(ei_device, stylus_interface, const struct ei_stylus_interface *);
|
||||
OBJECT_DECLARE_SETTER(ei_device, type, enum ei_device_type);
|
||||
OBJECT_DECLARE_SETTER(ei_device, name, const char*);
|
||||
OBJECT_DECLARE_SETTER(ei_device, seat, const char*);
|
||||
|
|
|
|||
|
|
@ -65,6 +65,19 @@ ei_event_type_to_string(enum ei_event_type type)
|
|||
CASE_RETURN_STRING(EI_EVENT_TOUCH_DOWN);
|
||||
CASE_RETURN_STRING(EI_EVENT_TOUCH_UP);
|
||||
CASE_RETURN_STRING(EI_EVENT_TOUCH_MOTION);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_PROXIMITY_IN);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_PROXIMITY_OUT);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_DOWN);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_UP);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_MOTION);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_PRESSURE);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_DISTANCE);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_TILT);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_ROTATION);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_AIRBRUSH_FLOW);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_TOOL_CAPABILITIES);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_ERASE_START);
|
||||
CASE_RETURN_STRING(EI_EVENT_STYLUS_ERASE_STOP);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
@ -98,6 +111,19 @@ ei_event_destroy(struct ei_event *event)
|
|||
case EI_EVENT_TOUCH_DOWN:
|
||||
case EI_EVENT_TOUCH_UP:
|
||||
case EI_EVENT_TOUCH_MOTION:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EI_EVENT_STYLUS_DOWN:
|
||||
case EI_EVENT_STYLUS_UP:
|
||||
case EI_EVENT_STYLUS_MOTION:
|
||||
case EI_EVENT_STYLUS_PRESSURE:
|
||||
case EI_EVENT_STYLUS_DISTANCE:
|
||||
case EI_EVENT_STYLUS_TILT:
|
||||
case EI_EVENT_STYLUS_ROTATION:
|
||||
case EI_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
case EI_EVENT_STYLUS_TOOL_CAPABILITIES:
|
||||
case EI_EVENT_STYLUS_ERASE_START:
|
||||
case EI_EVENT_STYLUS_ERASE_STOP:
|
||||
break;
|
||||
case EI_EVENT_DEVICE_ADDED:
|
||||
if (ei->interface_versions.ei_device >= EI_DEVICE_REQUEST_READY_SINCE_VERSION)
|
||||
|
|
@ -377,6 +403,117 @@ ei_event_touch_get_is_cancel(struct ei_event *event)
|
|||
return event->touch.is_cancel;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
ei_event_stylus_get_capability(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_TOOL_CAPABILITIES);
|
||||
|
||||
return event->stylus.capability;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_event_stylus_get_is_prox(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_PROXIMITY_IN,
|
||||
EI_EVENT_STYLUS_PROXIMITY_OUT);
|
||||
|
||||
return event->stylus.is_prox;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_event_stylus_get_is_down(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_DOWN,
|
||||
EI_EVENT_STYLUS_UP);
|
||||
|
||||
return event->stylus.is_down;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
ei_event_stylus_get_is_erase(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_ERASE_START,
|
||||
EI_EVENT_STYLUS_ERASE_STOP);
|
||||
|
||||
return event->stylus.is_erase;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_x(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_MOTION);
|
||||
|
||||
return event->stylus.x;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_y(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_MOTION);
|
||||
|
||||
return event->stylus.y;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_pressure(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_PRESSURE);
|
||||
|
||||
return event->stylus.pressure;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_distance(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_DISTANCE);
|
||||
|
||||
return event->stylus.distance;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_tilt_x(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_TILT);
|
||||
|
||||
return event->stylus.tilt_x;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_tilt_y(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_TILT);
|
||||
|
||||
return event->stylus.tilt_y;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_rotation(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_ROTATION);
|
||||
|
||||
return event->stylus.rotation;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
ei_event_stylus_get_flow(struct ei_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EI_EVENT_STYLUS_AIRBRUSH_FLOW);
|
||||
|
||||
return event->stylus.flow;
|
||||
}
|
||||
|
||||
_public_ uint64_t
|
||||
ei_event_get_time(struct ei_event *event)
|
||||
{
|
||||
|
|
@ -392,6 +529,19 @@ ei_event_get_time(struct ei_event *event)
|
|||
EI_EVENT_TOUCH_DOWN,
|
||||
EI_EVENT_TOUCH_UP,
|
||||
EI_EVENT_TOUCH_MOTION,
|
||||
EI_EVENT_STYLUS_PROXIMITY_IN,
|
||||
EI_EVENT_STYLUS_PROXIMITY_OUT,
|
||||
EI_EVENT_STYLUS_DOWN,
|
||||
EI_EVENT_STYLUS_UP,
|
||||
EI_EVENT_STYLUS_MOTION,
|
||||
EI_EVENT_STYLUS_PRESSURE,
|
||||
EI_EVENT_STYLUS_DISTANCE,
|
||||
EI_EVENT_STYLUS_TILT,
|
||||
EI_EVENT_STYLUS_ROTATION,
|
||||
EI_EVENT_STYLUS_AIRBRUSH_FLOW,
|
||||
EI_EVENT_STYLUS_ERASE_STOP,
|
||||
EI_EVENT_STYLUS_ERASE_START,
|
||||
EI_EVENT_STYLUS_TOOL_CAPABILITIES,
|
||||
EI_EVENT_FRAME);
|
||||
|
||||
return event->timestamp;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ struct ei_event {
|
|||
struct {
|
||||
struct ei_pingpong *pingpong;
|
||||
} sync;
|
||||
struct {
|
||||
uint32_t capability;
|
||||
bool is_prox, is_down, is_erase;
|
||||
float x, y, pressure, distance, rotation, flow;
|
||||
float tilt_x, tilt_y;
|
||||
} stylus;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ ei_handshake_initialize(struct ei_handshake *setup, uint32_t version)
|
|||
ei_handshake_request_interface_version(setup, EI_BUTTON_INTERFACE_NAME, v->ei_button);
|
||||
ei_handshake_request_interface_version(setup, EI_KEYBOARD_INTERFACE_NAME, v->ei_keyboard);
|
||||
ei_handshake_request_interface_version(setup, EI_TOUCHSCREEN_INTERFACE_NAME, v->ei_touchscreen);
|
||||
ei_handshake_request_interface_version(setup, EI_STYLUS_INTERFACE_NAME, v->ei_stylus);
|
||||
}
|
||||
|
||||
ei_handshake_request_finish(setup);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "libei-region.h"
|
||||
#include "libei-scroll.h"
|
||||
#include "libei-seat.h"
|
||||
#include "libei-stylus.h"
|
||||
#include "libei-touchscreen.h"
|
||||
|
||||
struct ei_backend_interface {
|
||||
|
|
@ -77,6 +78,7 @@ struct ei_interface_versions {
|
|||
uint32_t ei_button;
|
||||
uint32_t ei_keyboard;
|
||||
uint32_t ei_touchscreen;
|
||||
uint32_t ei_stylus;
|
||||
};
|
||||
|
||||
struct ei_unsent {
|
||||
|
|
@ -246,6 +248,45 @@ ei_queue_touch_cancel_event(struct ei_device *device, uint32_t touchid);
|
|||
void
|
||||
ei_sync_event_send_done(struct ei_event *e);
|
||||
|
||||
void
|
||||
ei_queue_stylus_tool_capabilities_event(struct ei_device *device, uint32_t capability);
|
||||
|
||||
void
|
||||
ei_queue_stylus_proximity_in_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_stylus_proximity_out_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_stylus_down_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_stylus_up_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_stylus_motion_event(struct ei_device *device, float x, float y);
|
||||
|
||||
void
|
||||
ei_queue_stylus_pressure_event(struct ei_device *device, float p);
|
||||
|
||||
void
|
||||
ei_queue_stylus_distance_event(struct ei_device *device, float d);
|
||||
|
||||
void
|
||||
ei_queue_stylus_tilt_event(struct ei_device *device, float tilt_x, float tilt_y);
|
||||
|
||||
void
|
||||
ei_queue_stylus_rotation_event(struct ei_device *device, float r);
|
||||
|
||||
void
|
||||
ei_queue_stylus_airbrush_flow_event(struct ei_device *device, float s);
|
||||
|
||||
void
|
||||
ei_queue_stylus_erase_start_event(struct ei_device *device);
|
||||
|
||||
void
|
||||
ei_queue_stylus_erase_stop_event(struct ei_device *device);
|
||||
|
||||
_printf_(6, 7) void
|
||||
ei_log_msg(struct ei *ei,
|
||||
enum ei_log_priority priority,
|
||||
|
|
|
|||
|
|
@ -247,6 +247,8 @@ ei_seat_has_capability(struct ei_seat *seat,
|
|||
return seat->capabilities.map[EI_SCROLL_INTERFACE_INDEX] != 0;
|
||||
case EI_DEVICE_CAP_BUTTON:
|
||||
return seat->capabilities.map[EI_BUTTON_INTERFACE_INDEX] != 0;
|
||||
case EI_DEVICE_CAP_STYLUS:
|
||||
return seat->capabilities.map[EI_STYLUS_INTERFACE_INDEX] != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -281,6 +283,8 @@ ei_seat_cap_mask(struct ei_seat *seat, enum ei_device_capability cap)
|
|||
return seat->capabilities.map[EI_BUTTON_INTERFACE_INDEX];
|
||||
case EI_DEVICE_CAP_SCROLL:
|
||||
return seat->capabilities.map[EI_SCROLL_INTERFACE_INDEX];
|
||||
case EI_DEVICE_CAP_STYLUS:
|
||||
return seat->capabilities.map[EI_STYLUS_INTERFACE_INDEX];
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
87
src/libei-stylus.c
Normal file
87
src/libei-stylus.c
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2023 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util-bits.h"
|
||||
#include "util-macros.h"
|
||||
#include "util-mem.h"
|
||||
#include "util-io.h"
|
||||
#include "util-strings.h"
|
||||
#include "util-version.h"
|
||||
|
||||
#include "libei-private.h"
|
||||
#include "ei-proto.h"
|
||||
|
||||
static void
|
||||
ei_stylus_destroy(struct ei_stylus *stylus)
|
||||
{
|
||||
struct ei *ei = ei_stylus_get_context(stylus);
|
||||
ei_unregister_object(ei, &stylus->proto_object);
|
||||
}
|
||||
|
||||
OBJECT_IMPLEMENT_REF(ei_stylus);
|
||||
OBJECT_IMPLEMENT_UNREF_CLEANUP(ei_stylus);
|
||||
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(ei_stylus);
|
||||
static
|
||||
OBJECT_IMPLEMENT_PARENT(ei_stylus, ei_device);
|
||||
OBJECT_IMPLEMENT_GETTER_AS_REF(ei_stylus, proto_object, const struct brei_object*);
|
||||
|
||||
struct ei_device *
|
||||
ei_stylus_get_device(struct ei_stylus *stylus)
|
||||
{
|
||||
return ei_stylus_parent(stylus);
|
||||
}
|
||||
|
||||
struct ei*
|
||||
ei_stylus_get_context(struct ei_stylus *stylus)
|
||||
{
|
||||
return ei_device_get_context(ei_stylus_get_device(stylus));
|
||||
}
|
||||
|
||||
const struct ei_stylus_interface *
|
||||
ei_stylus_get_interface(struct ei_stylus *stylus) {
|
||||
struct ei_device *device = ei_stylus_get_device(stylus);
|
||||
return ei_device_get_stylus_interface(device);
|
||||
}
|
||||
|
||||
struct ei_stylus *
|
||||
ei_stylus_new(struct ei_device *device, object_id_t id, uint32_t version)
|
||||
{
|
||||
struct ei_stylus *stylus = ei_stylus_create(&device->object);
|
||||
struct ei *ei = ei_device_get_context(device);
|
||||
|
||||
stylus->proto_object.id = id;
|
||||
stylus->proto_object.implementation = stylus;
|
||||
stylus->proto_object.interface = &ei_stylus_proto_interface;
|
||||
stylus->proto_object.version = version;
|
||||
ei_register_object(ei, &stylus->proto_object);
|
||||
|
||||
return stylus; /* ref owned by caller */
|
||||
}
|
||||
49
src/libei-stylus.h
Normal file
49
src/libei-stylus.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2023 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util-object.h"
|
||||
#include "util-list.h"
|
||||
#include "brei-shared.h"
|
||||
|
||||
struct ei;
|
||||
struct ei_device;
|
||||
struct ei_stylus;
|
||||
|
||||
/* This is a protocol-only object, not exposed in the API */
|
||||
struct ei_stylus {
|
||||
struct object object;
|
||||
struct brei_object proto_object;
|
||||
};
|
||||
|
||||
OBJECT_DECLARE_GETTER(ei_stylus, context, struct ei*);
|
||||
OBJECT_DECLARE_GETTER(ei_stylus, device, struct ei_device*);
|
||||
OBJECT_DECLARE_GETTER(ei_stylus, proto_object, const struct brei_object*);
|
||||
OBJECT_DECLARE_GETTER(ei_stylus, interface, const struct ei_stylus_interface *);
|
||||
OBJECT_DECLARE_REF(ei_stylus);
|
||||
OBJECT_DECLARE_UNREF(ei_stylus);
|
||||
|
||||
struct ei_stylus *
|
||||
ei_stylus_new(struct ei_device *device, object_id_t id, uint32_t version);
|
||||
172
src/libei.c
172
src/libei.c
|
|
@ -134,6 +134,7 @@ ei_create_context(bool is_sender, void *user_data)
|
|||
.ei_button = VERSION_V(1),
|
||||
.ei_keyboard = VERSION_V(1),
|
||||
.ei_touchscreen = VERSION_V(2),
|
||||
.ei_stylus = VERSION_V(1),
|
||||
};
|
||||
/* This must be v1 until the server tells us otherwise */
|
||||
ei->handshake = ei_handshake_new(ei, VERSION_V(1));
|
||||
|
|
@ -245,6 +246,19 @@ update_event_timestamp(struct ei_event *event, uint64_t time)
|
|||
case EI_EVENT_TOUCH_DOWN:
|
||||
case EI_EVENT_TOUCH_UP:
|
||||
case EI_EVENT_TOUCH_MOTION:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EI_EVENT_STYLUS_DOWN:
|
||||
case EI_EVENT_STYLUS_UP:
|
||||
case EI_EVENT_STYLUS_MOTION:
|
||||
case EI_EVENT_STYLUS_PRESSURE:
|
||||
case EI_EVENT_STYLUS_DISTANCE:
|
||||
case EI_EVENT_STYLUS_TILT:
|
||||
case EI_EVENT_STYLUS_ROTATION:
|
||||
case EI_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
case EI_EVENT_STYLUS_TOOL_CAPABILITIES:
|
||||
case EI_EVENT_STYLUS_ERASE_START:
|
||||
case EI_EVENT_STYLUS_ERASE_STOP:
|
||||
if (event->timestamp != 0) {
|
||||
log_bug(ei_event_get_context(event),
|
||||
"Unexpected timestamp for event of type: %s",
|
||||
|
|
@ -280,6 +294,19 @@ queue_event(struct ei *ei, struct ei_event *event)
|
|||
case EI_EVENT_TOUCH_DOWN:
|
||||
case EI_EVENT_TOUCH_UP:
|
||||
case EI_EVENT_TOUCH_MOTION:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EI_EVENT_STYLUS_DOWN:
|
||||
case EI_EVENT_STYLUS_UP:
|
||||
case EI_EVENT_STYLUS_MOTION:
|
||||
case EI_EVENT_STYLUS_PRESSURE:
|
||||
case EI_EVENT_STYLUS_DISTANCE:
|
||||
case EI_EVENT_STYLUS_TILT:
|
||||
case EI_EVENT_STYLUS_ROTATION:
|
||||
case EI_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
case EI_EVENT_STYLUS_TOOL_CAPABILITIES:
|
||||
case EI_EVENT_STYLUS_ERASE_START:
|
||||
case EI_EVENT_STYLUS_ERASE_STOP:
|
||||
prefix = "pending ";
|
||||
queue = &device->pending_event_queue;
|
||||
break;
|
||||
|
|
@ -626,6 +653,151 @@ ei_queue_touch_cancel_event(struct ei_device *device, uint32_t touchid)
|
|||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_tool_capabilities_event(struct ei_device *device, uint32_t capability)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_TOOL_CAPABILITIES;
|
||||
e->stylus.capability = capability;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_proximity_in_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_PROXIMITY_IN;
|
||||
e->stylus.is_prox = true;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_proximity_out_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_PROXIMITY_OUT;
|
||||
e->stylus.is_prox = false;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_erase_start_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_ERASE_START;
|
||||
e->stylus.is_erase = true;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_erase_stop_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_ERASE_STOP;
|
||||
e->stylus.is_erase = false;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_down_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_DOWN;
|
||||
e->stylus.is_down = true;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_up_event(struct ei_device *device)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_UP;
|
||||
e->stylus.is_down = false;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_motion_event(struct ei_device *device, float x, float y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_MOTION;
|
||||
e->stylus.x = x;
|
||||
e->stylus.y = y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_pressure_event(struct ei_device *device, float pressure)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_PRESSURE;
|
||||
e->stylus.pressure = pressure;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_distance_event(struct ei_device *device, float distance)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_DISTANCE;
|
||||
e->stylus.distance = distance;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_tilt_event(struct ei_device *device, float tilt_x, float tilt_y)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_TILT;
|
||||
e->stylus.tilt_x = tilt_x;
|
||||
e->stylus.tilt_y = tilt_y;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_rotation_event(struct ei_device *device, float rotation)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_ROTATION;
|
||||
e->stylus.rotation = rotation;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
void
|
||||
ei_queue_stylus_airbrush_flow_event(struct ei_device *device, float flow)
|
||||
{
|
||||
struct ei_event *e = ei_event_new_for_device(device);
|
||||
|
||||
e->type = EI_EVENT_STYLUS_AIRBRUSH_FLOW;
|
||||
e->stylus.flow = flow;
|
||||
|
||||
queue_event(ei_device_get_context(device), e);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_disconnect(struct ei *ei)
|
||||
{
|
||||
|
|
|
|||
295
src/libei.h
295
src/libei.h
|
|
@ -215,6 +215,28 @@ struct ei_region;
|
|||
*/
|
||||
struct ei_touch;
|
||||
|
||||
/**
|
||||
* @struct ei_stylus
|
||||
*
|
||||
* A single stylus initiated by a sender context.
|
||||
*
|
||||
* @see ei_device_stylus_new
|
||||
* @see ei_stylus_bind_tool_capabilities
|
||||
* @see ei_stylus_proximity_in
|
||||
* @see ei_stylus_proximity_out
|
||||
* @see ei_stylus_erase_start
|
||||
* @see ei_stylus_erase_stop
|
||||
* @see ei_stylus_down
|
||||
* @see ei_stylus_up
|
||||
* @see ei_stylus_motion
|
||||
* @see ei_stylus_pressure
|
||||
* @see ei_stylus_distance
|
||||
* @see ei_stylus_tilt
|
||||
* @see ei_stylus_rotation
|
||||
* @see ei_stylus_airbrush_flow
|
||||
*/
|
||||
struct ei_stylus;
|
||||
|
||||
/**
|
||||
* @struct ei_ping
|
||||
*
|
||||
|
|
@ -300,6 +322,10 @@ enum ei_device_capability {
|
|||
* The device can send button events
|
||||
*/
|
||||
EI_DEVICE_CAP_BUTTON = (1 << 5),
|
||||
/**
|
||||
* The device can send stylus events
|
||||
*/
|
||||
EI_DEVICE_CAP_STYLUS = (1 << 7),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -591,6 +617,59 @@ enum ei_event_type {
|
|||
* See ei_device_touch_new() and ei_touch_motion() for the sender context API.
|
||||
*/
|
||||
EI_EVENT_TOUCH_MOTION,
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_TOOL_CAPABILITIES = 1000,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_PROXIMITY_IN,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_PROXIMITY_OUT,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_ERASE_START,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_ERASE_STOP,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_DOWN,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_UP,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_MOTION,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_PRESSURE,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_DISTANCE,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_TILT,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_ROTATION,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EI_EVENT_STYLUS_AIRBRUSH_FLOW,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1957,6 +2036,118 @@ ei_touch_get_user_data(struct ei_touch *touch);
|
|||
struct ei_device *
|
||||
ei_touch_get_device(struct ei_touch *touch);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
struct ei_stylus *
|
||||
ei_device_stylus_new(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_bind_tool_capabilities(struct ei_device *device, uint32_t capabilitiy);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_proximity_in(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_proximity_out(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_erase_start(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_erase_stop(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_down(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_up(struct ei_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_motion(struct ei_device *device, float x, float y);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_pressure(struct ei_device *device, float p);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_distance(struct ei_device *device, float d);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_tilt(struct ei_device *device, float tilt_x, float tilt_y);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_rotation(struct ei_device *device, float r);
|
||||
|
||||
/**
|
||||
* @ingroup libei-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
ei_device_stylus_airbrush_flow(struct ei_device *device, float s);
|
||||
|
||||
/**
|
||||
* Return the seat from this event.
|
||||
*
|
||||
|
|
@ -2220,6 +2411,110 @@ ei_event_touch_get_y(struct ei_event *event);
|
|||
bool
|
||||
ei_event_touch_get_is_cancel(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
bool
|
||||
ei_event_stylus_get_is_prox(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
bool
|
||||
ei_event_stylus_get_is_erase(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_stylus_get_capability(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
uint32_t
|
||||
ei_event_stylus_get_code(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
bool
|
||||
ei_event_stylus_get_is_down(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_x(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_y(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_pressure(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_distance(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_tilt_x(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_tilt_y(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_rotation(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libei-receiver
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
ei_event_stylus_get_flow(struct ei_event *event);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -529,6 +529,7 @@ eis_client_new(struct eis *eis, int fd)
|
|||
.ei_button = VERSION_V(1),
|
||||
.ei_keyboard = VERSION_V(1),
|
||||
.ei_touchscreen = VERSION_V(2),
|
||||
.ei_stylus = VERSION_V(1),
|
||||
};
|
||||
struct source *s = source_new(fd, client_dispatch, client);
|
||||
int rc = sink_add_source(eis->sink, s);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ struct eis_client_interface_versions {
|
|||
uint32_t ei_button;
|
||||
uint32_t ei_keyboard;
|
||||
uint32_t ei_touchscreen;
|
||||
uint32_t ei_stylus;
|
||||
};
|
||||
|
||||
struct eis_client {
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ eis_device_destroy(struct eis_device *device)
|
|||
eis_pointer_unref(device->pointer);
|
||||
eis_touchscreen_unref(device->touchscreen);
|
||||
eis_keyboard_unref(device->keyboard);
|
||||
eis_stylus_unref(device->stylus);
|
||||
|
||||
free(device->name);
|
||||
}
|
||||
|
|
@ -739,6 +740,299 @@ eis_device_get_touchscreen_interface(struct eis_device *device)
|
|||
return &touchscreen_interface;
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_bind_tool_capabilities(struct eis_stylus *stylus, uint32_t capability)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus tool capabilities event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_AWAITING_READY) {
|
||||
eis_queue_stylus_bind_tool_capabilities_event(device, capability);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus tool capabilities");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_proximity_in(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus proximity in event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_proximity_in_event(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus proximity in");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_proximity_out(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus proximity out event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_proximity_out_event(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus proximity out");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_erase_start(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus erase start event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_erase_start_event(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus erase start");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_erase_stop(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus erase stop event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_erase_stop_event(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus erase stop");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_down(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus down event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_down_event(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus down");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_up(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus up event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_up_event(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus up");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_motion(struct eis_stylus *stylus, float x, float y)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus motion event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_motion_event(device, x, y);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus motion");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_pressure(struct eis_stylus *stylus, float pressure)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus pressure event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_pressure_event(device, pressure);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus pressure");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_distance(struct eis_stylus *stylus, float distance)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus distance event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_distance_event(device, distance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus distance");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_tilt(struct eis_stylus *stylus, float tilt_x, float tilt_y)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus tilt event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_tilt_event(device, tilt_x, tilt_y);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus tilt");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_rotation(struct eis_stylus *stylus, float rotation)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus rotation event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_rotation_event(device, rotation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus rotation");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_airbrush_flow(struct eis_stylus *stylus, float flow)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
|
||||
DISCONNECT_IF_RECEIVER_CONTEXT(device);
|
||||
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
return brei_result_new(EIS_CONNECTION_DISCONNECT_REASON_PROTOCOL,
|
||||
"Stylus airbrush_flow event for non-stylus device");
|
||||
}
|
||||
|
||||
if (device->state == EIS_DEVICE_STATE_EMULATING) {
|
||||
eis_queue_stylus_airbrush_flow_event(device, flow);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maybe_error_on_device_state(device, "stylus airbrush_flow");
|
||||
}
|
||||
|
||||
static struct brei_result *
|
||||
client_msg_stylus_release(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_device *device = eis_stylus_get_device(stylus);
|
||||
eis_stylus_event_destroyed(device->stylus,
|
||||
eis_client_get_next_serial(eis_device_get_client(device)));
|
||||
eis_stylus_unref(steal(&device->stylus));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct eis_stylus_interface stylus_interface = {
|
||||
.release = client_msg_stylus_release,
|
||||
.airbrush_flow = client_msg_stylus_airbrush_flow,
|
||||
.rotation = client_msg_stylus_rotation,
|
||||
.tilt = client_msg_stylus_tilt,
|
||||
.distance = client_msg_stylus_distance,
|
||||
.pressure = client_msg_stylus_pressure,
|
||||
.motion = client_msg_stylus_motion,
|
||||
.up = client_msg_stylus_up,
|
||||
.down = client_msg_stylus_down,
|
||||
.erase_stop = client_msg_stylus_erase_stop,
|
||||
.erase_start = client_msg_stylus_erase_start,
|
||||
.proximity_out = client_msg_stylus_proximity_out,
|
||||
.proximity_in = client_msg_stylus_proximity_in,
|
||||
.bind_tool_capabilities = client_msg_stylus_bind_tool_capabilities,
|
||||
};
|
||||
|
||||
const struct eis_stylus_interface *
|
||||
eis_device_get_stylus_interface(struct eis_device *device)
|
||||
{
|
||||
return &stylus_interface;
|
||||
}
|
||||
|
||||
_public_ struct eis_device *
|
||||
eis_seat_new_device(struct eis_seat *seat)
|
||||
{
|
||||
|
|
@ -809,6 +1103,7 @@ eis_device_configure_capability(struct eis_device *device, enum eis_device_capab
|
|||
case EIS_DEVICE_CAP_TOUCH:
|
||||
case EIS_DEVICE_CAP_BUTTON:
|
||||
case EIS_DEVICE_CAP_SCROLL:
|
||||
case EIS_DEVICE_CAP_STYLUS:
|
||||
mask_add(device->capabilities, cap);
|
||||
break;
|
||||
}
|
||||
|
|
@ -936,6 +1231,19 @@ eis_device_add(struct eis_device *device)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
device->stylus = eis_stylus_new(device);
|
||||
rc = eis_device_event_interface(device, eis_stylus_get_id(device->stylus),
|
||||
EIS_STYLUS_INTERFACE_NAME,
|
||||
eis_stylus_get_version(device->stylus));
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
// FIXME: This should not use a hardcoded value -- it should offer
|
||||
// whatever capabilities the server implementation wants!
|
||||
eis_device_stylus_tool_capabilities(device, 63);
|
||||
}
|
||||
|
||||
rc = eis_device_event_done(device);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
|
@ -991,6 +1299,10 @@ eis_device_remove(struct eis_device *device)
|
|||
eis_keyboard_event_destroyed(device->keyboard, eis_client_get_next_serial(client));
|
||||
eis_keyboard_unref(steal(&device->keyboard));
|
||||
}
|
||||
if (device->stylus) {
|
||||
eis_stylus_event_destroyed(device->stylus, eis_client_get_next_serial(client));
|
||||
eis_stylus_unref(steal(&device->stylus));
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_NEW)
|
||||
eis_device_event_destroyed(device, eis_client_get_next_serial(client));
|
||||
|
|
@ -1018,6 +1330,7 @@ eis_device_has_capability(struct eis_device *device,
|
|||
case EIS_DEVICE_CAP_TOUCH:
|
||||
case EIS_DEVICE_CAP_BUTTON:
|
||||
case EIS_DEVICE_CAP_SCROLL:
|
||||
case EIS_DEVICE_CAP_STYLUS:
|
||||
return mask_all(device->capabilities, cap);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1476,3 +1789,235 @@ eis_device_keyboard_send_xkb_modifiers(struct eis_device *device, uint32_t depre
|
|||
eis_client_get_next_serial(eis_device_get_client(device)),
|
||||
depressed, locked, latched, group);
|
||||
}
|
||||
|
||||
_public_ struct eis_stylus *
|
||||
eis_device_stylus_new(struct eis_device *device)
|
||||
{
|
||||
struct eis_stylus *stylus = eis_stylus_new(device);
|
||||
|
||||
return stylus;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_tool_capabilities(struct eis_device *device, uint32_t capability)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_NEW)
|
||||
return;
|
||||
|
||||
device->send_frame_event = false;
|
||||
|
||||
eis_stylus_event_tool_capabilities(device->stylus, capability);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_proximity_in(struct eis_device *device)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_proximity_in(device->stylus);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_proximity_out(struct eis_device *device)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_proximity_out(device->stylus);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_erase_start(struct eis_device *device)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_erase_start(device->stylus);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_erase_stop(struct eis_device *device)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_erase_stop(device->stylus);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_down(struct eis_device *device)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_down(device->stylus);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_up(struct eis_device *device)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_up(device->stylus);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_motion(struct eis_device *device, float x, float y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
if (!eis_device_in_region(device, x, y))
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_motion(device->stylus, x, y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_pressure(struct eis_device *device, float pressure)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_pressure(device->stylus, pressure);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_distance(struct eis_device *device, float distance)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_distance(device->stylus, distance);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_tilt(struct eis_device *device, float tilt_x, float tilt_y)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_tilt(device->stylus, tilt_x, tilt_y);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_rotation(struct eis_device *device, float rotation)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_rotation(device->stylus, rotation);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_device_stylus_airbrush_flow(struct eis_device *device, float flow)
|
||||
{
|
||||
if (!eis_device_has_capability(device, EIS_DEVICE_CAP_STYLUS)) {
|
||||
log_bug_client(eis_device_get_context(device),
|
||||
"%s: device is not a stylus device", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->state != EIS_DEVICE_STATE_EMULATING)
|
||||
return;
|
||||
|
||||
device->send_frame_event = true;
|
||||
|
||||
eis_stylus_event_airbrush_flow(device->stylus, flow);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ struct eis_device {
|
|||
struct eis_button *button;
|
||||
struct eis_keyboard *keyboard;
|
||||
struct eis_touchscreen *touchscreen;
|
||||
struct eis_stylus *stylus;
|
||||
|
||||
char *name;
|
||||
enum eis_device_state state;
|
||||
|
|
@ -117,6 +118,7 @@ OBJECT_DECLARE_GETTER(eis_device, scroll_interface, const struct eis_scroll_inte
|
|||
OBJECT_DECLARE_GETTER(eis_device, button_interface, const struct eis_button_interface *);
|
||||
OBJECT_DECLARE_GETTER(eis_device, keyboard_interface, const struct eis_keyboard_interface *);
|
||||
OBJECT_DECLARE_GETTER(eis_device, touchscreen_interface, const struct eis_touchscreen_interface *);
|
||||
OBJECT_DECLARE_GETTER(eis_device, stylus_interface, const struct eis_stylus_interface *);
|
||||
|
||||
void
|
||||
eis_device_set_client_keymap(struct eis_device *device,
|
||||
|
|
|
|||
|
|
@ -57,6 +57,19 @@ eis_event_destroy(struct eis_event *event)
|
|||
case EIS_EVENT_TOUCH_MOTION:
|
||||
case EIS_EVENT_TOUCH_UP:
|
||||
case EIS_EVENT_FRAME:
|
||||
case EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EIS_EVENT_STYLUS_ERASE_START:
|
||||
case EIS_EVENT_STYLUS_ERASE_STOP:
|
||||
case EIS_EVENT_STYLUS_DOWN:
|
||||
case EIS_EVENT_STYLUS_UP:
|
||||
case EIS_EVENT_STYLUS_MOTION:
|
||||
case EIS_EVENT_STYLUS_PRESSURE:
|
||||
case EIS_EVENT_STYLUS_DISTANCE:
|
||||
case EIS_EVENT_STYLUS_TILT:
|
||||
case EIS_EVENT_STYLUS_ROTATION:
|
||||
case EIS_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
handled = true;
|
||||
break;
|
||||
case EIS_EVENT_PONG:
|
||||
|
|
@ -192,6 +205,19 @@ eis_event_get_time(struct eis_event *event)
|
|||
EIS_EVENT_TOUCH_DOWN,
|
||||
EIS_EVENT_TOUCH_UP,
|
||||
EIS_EVENT_TOUCH_MOTION,
|
||||
EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES,
|
||||
EIS_EVENT_STYLUS_PROXIMITY_IN,
|
||||
EIS_EVENT_STYLUS_PROXIMITY_OUT,
|
||||
EIS_EVENT_STYLUS_ERASE_START,
|
||||
EIS_EVENT_STYLUS_ERASE_STOP,
|
||||
EIS_EVENT_STYLUS_DOWN,
|
||||
EIS_EVENT_STYLUS_UP,
|
||||
EIS_EVENT_STYLUS_MOTION,
|
||||
EIS_EVENT_STYLUS_PRESSURE,
|
||||
EIS_EVENT_STYLUS_DISTANCE,
|
||||
EIS_EVENT_STYLUS_TILT,
|
||||
EIS_EVENT_STYLUS_ROTATION,
|
||||
EIS_EVENT_STYLUS_AIRBRUSH_FLOW,
|
||||
EIS_EVENT_FRAME);
|
||||
|
||||
return event->timestamp;
|
||||
|
|
@ -217,6 +243,7 @@ eis_event_seat_has_capability(struct eis_event *event, enum eis_device_capabilit
|
|||
case EIS_DEVICE_CAP_TOUCH:
|
||||
case EIS_DEVICE_CAP_BUTTON:
|
||||
case EIS_DEVICE_CAP_SCROLL:
|
||||
case EIS_DEVICE_CAP_STYLUS:
|
||||
return mask_all(event->bind.capabilities, cap);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -430,3 +457,114 @@ eis_event_touch_get_is_cancel(struct eis_event *event)
|
|||
|
||||
return event->touch.is_cancel;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
eis_event_stylus_get_is_prox(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EIS_EVENT_STYLUS_PROXIMITY_IN,
|
||||
EIS_EVENT_STYLUS_PROXIMITY_OUT);
|
||||
|
||||
return event->stylus.is_prox;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
eis_event_stylus_get_is_erase(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EIS_EVENT_STYLUS_ERASE_START,
|
||||
EIS_EVENT_STYLUS_ERASE_STOP);
|
||||
|
||||
return event->stylus.is_erase;
|
||||
}
|
||||
|
||||
_public_ uint32_t
|
||||
eis_event_stylus_get_capability(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES);
|
||||
|
||||
return event->stylus.capability;
|
||||
}
|
||||
|
||||
_public_ bool
|
||||
eis_event_stylus_get_is_down(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0,
|
||||
EIS_EVENT_STYLUS_DOWN,
|
||||
EIS_EVENT_STYLUS_UP);
|
||||
|
||||
return event->stylus.is_down;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_x(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_MOTION);
|
||||
|
||||
return event->stylus.x;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_y(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_MOTION);
|
||||
|
||||
return event->stylus.y;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_pressure(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_PRESSURE);
|
||||
|
||||
return event->stylus.pressure;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_distance(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_DISTANCE);
|
||||
|
||||
return event->stylus.distance;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_tilt_x(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_TILT);
|
||||
|
||||
return event->stylus.tilt_x;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_tilt_y(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_TILT);
|
||||
|
||||
return event->stylus.tilt_y;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_rotation(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_ROTATION);
|
||||
|
||||
return event->stylus.rotation;
|
||||
}
|
||||
|
||||
_public_ float
|
||||
eis_event_stylus_get_flow(struct eis_event *event)
|
||||
{
|
||||
require_event_type(event, 0.0,
|
||||
EIS_EVENT_STYLUS_AIRBRUSH_FLOW);
|
||||
|
||||
return event->stylus.flow;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,12 @@ struct eis_event {
|
|||
struct {
|
||||
struct eis_callback *callback;
|
||||
} sync;
|
||||
struct {
|
||||
uint32_t capability;
|
||||
float x, y, pressure, distance, rotation, flow;
|
||||
float tilt_x, tilt_y;
|
||||
bool is_prox, is_down, is_erase;
|
||||
} stylus;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ client_msg_finish(struct eis_handshake *setup)
|
|||
SEND_INTERFACE_VERSION(EIS_SCROLL, ei_scroll);
|
||||
SEND_INTERFACE_VERSION(EIS_KEYBOARD, ei_keyboard);
|
||||
SEND_INTERFACE_VERSION(EIS_TOUCHSCREEN, ei_touchscreen);
|
||||
SEND_INTERFACE_VERSION(EIS_STYLUS, ei_stylus);
|
||||
|
||||
#undef SEND_INTERFACE_VERSION
|
||||
|
||||
|
|
@ -237,6 +238,7 @@ client_msg_interface_version(struct eis_handshake *setup, const char *name, uint
|
|||
VERSION_ENTRY(ei_scroll),
|
||||
VERSION_ENTRY(ei_keyboard),
|
||||
VERSION_ENTRY(ei_touchscreen),
|
||||
VERSION_ENTRY(ei_stylus),
|
||||
#undef VERSION_ENTRY
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#include "libeis-region.h"
|
||||
#include "libeis-scroll.h"
|
||||
#include "libeis-seat.h"
|
||||
#include "libeis-stylus.h"
|
||||
#include "libeis-touchscreen.h"
|
||||
|
||||
struct eis_backend_interface {
|
||||
|
|
@ -163,6 +164,45 @@ eis_queue_touch_cancel_event(struct eis_device *device, uint32_t touchid);
|
|||
void
|
||||
eis_sync_event_send_done(struct eis_event *e);
|
||||
|
||||
void
|
||||
eis_queue_stylus_bind_tool_capabilities_event(struct eis_device *device, uint32_t capability);
|
||||
|
||||
void
|
||||
eis_queue_stylus_proximity_in_event(struct eis_device *device);
|
||||
|
||||
void
|
||||
eis_queue_stylus_proximity_out_event(struct eis_device *device);
|
||||
|
||||
void
|
||||
eis_queue_stylus_erase_start_event(struct eis_device *device);
|
||||
|
||||
void
|
||||
eis_queue_stylus_erase_stop_event(struct eis_device *device);
|
||||
|
||||
void
|
||||
eis_queue_stylus_down_event(struct eis_device *device);
|
||||
|
||||
void
|
||||
eis_queue_stylus_up_event(struct eis_device *device);
|
||||
|
||||
void
|
||||
eis_queue_stylus_motion_event(struct eis_device *device, float x, float y);
|
||||
|
||||
void
|
||||
eis_queue_stylus_pressure_event(struct eis_device *device, float p);
|
||||
|
||||
void
|
||||
eis_queue_stylus_distance_event(struct eis_device *device, float d);
|
||||
|
||||
void
|
||||
eis_queue_stylus_tilt_event(struct eis_device *device, float tilt_x, float tilt_y);
|
||||
|
||||
void
|
||||
eis_queue_stylus_rotation_event(struct eis_device *device, float r);
|
||||
|
||||
void
|
||||
eis_queue_stylus_airbrush_flow_event(struct eis_device *device, float s);
|
||||
|
||||
_printf_(6, 7) void
|
||||
eis_log_msg(struct eis *eis,
|
||||
enum eis_log_priority priority,
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@ client_msg_bind(struct eis_seat *seat, uint64_t caps)
|
|||
capabilities |= EIS_DEVICE_CAP_BUTTON;
|
||||
if (caps & bit(EIS_SCROLL_INTERFACE_INDEX))
|
||||
capabilities |= EIS_DEVICE_CAP_SCROLL;
|
||||
if (caps & bit(EIS_STYLUS_INTERFACE_INDEX))
|
||||
capabilities |= EIS_DEVICE_CAP_STYLUS;
|
||||
|
||||
eis_seat_bind(seat, capabilities);
|
||||
|
||||
|
|
@ -221,6 +223,14 @@ eis_seat_add(struct eis_seat *seat)
|
|||
mask_add(seat->capabilities.proto_mask, mask);
|
||||
}
|
||||
|
||||
if (seat->capabilities.c_mask & EIS_DEVICE_CAP_STYLUS &&
|
||||
client->interface_versions.ei_stylus > 0) {
|
||||
uint64_t mask = bit(EIS_STYLUS_INTERFACE_INDEX);
|
||||
eis_seat_event_capability(seat, mask,
|
||||
EIS_STYLUS_INTERFACE_NAME);
|
||||
mask_add(seat->capabilities.proto_mask, mask);
|
||||
}
|
||||
|
||||
eis_seat_event_done(seat);
|
||||
}
|
||||
|
||||
|
|
@ -313,6 +323,7 @@ eis_seat_configure_capability(struct eis_seat *seat,
|
|||
case EIS_DEVICE_CAP_TOUCH:
|
||||
case EIS_DEVICE_CAP_BUTTON:
|
||||
case EIS_DEVICE_CAP_SCROLL:
|
||||
case EIS_DEVICE_CAP_STYLUS:
|
||||
mask_add(seat->capabilities.c_mask, cap);
|
||||
break;
|
||||
}
|
||||
|
|
@ -329,6 +340,7 @@ eis_seat_has_capability(struct eis_seat *seat,
|
|||
case EIS_DEVICE_CAP_TOUCH:
|
||||
case EIS_DEVICE_CAP_BUTTON:
|
||||
case EIS_DEVICE_CAP_SCROLL:
|
||||
case EIS_DEVICE_CAP_STYLUS:
|
||||
return mask_all(seat->capabilities.c_mask, cap);
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
107
src/libeis-stylus.c
Normal file
107
src/libeis-stylus.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2023 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util-bits.h"
|
||||
#include "util-macros.h"
|
||||
#include "util-mem.h"
|
||||
#include "util-io.h"
|
||||
#include "util-strings.h"
|
||||
#include "util-version.h"
|
||||
|
||||
#include "libeis-private.h"
|
||||
#include "eis-proto.h"
|
||||
|
||||
static void
|
||||
eis_stylus_destroy(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_client * client = eis_stylus_get_client(stylus);
|
||||
eis_client_unregister_object(client, &stylus->proto_object);
|
||||
}
|
||||
|
||||
OBJECT_IMPLEMENT_REF(eis_stylus);
|
||||
OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_stylus);
|
||||
OBJECT_IMPLEMENT_GETTER_AS_REF(eis_stylus, proto_object, const struct brei_object *);
|
||||
|
||||
static
|
||||
OBJECT_IMPLEMENT_CREATE(eis_stylus);
|
||||
static
|
||||
OBJECT_IMPLEMENT_PARENT(eis_stylus, eis_device);
|
||||
|
||||
uint32_t
|
||||
eis_stylus_get_version(struct eis_stylus *stylus)
|
||||
{
|
||||
return stylus->proto_object.version;
|
||||
}
|
||||
|
||||
object_id_t
|
||||
eis_stylus_get_id(struct eis_stylus *stylus)
|
||||
{
|
||||
return stylus->proto_object.id;
|
||||
}
|
||||
|
||||
struct eis_device *
|
||||
eis_stylus_get_device(struct eis_stylus *stylus)
|
||||
{
|
||||
return eis_stylus_parent(stylus);
|
||||
}
|
||||
|
||||
struct eis_client*
|
||||
eis_stylus_get_client(struct eis_stylus *stylus)
|
||||
{
|
||||
return eis_device_get_client(eis_stylus_get_device(stylus));
|
||||
}
|
||||
|
||||
struct eis*
|
||||
eis_stylus_get_context(struct eis_stylus *stylus)
|
||||
{
|
||||
struct eis_client *client = eis_stylus_get_client(stylus);
|
||||
return eis_client_get_context(client);
|
||||
}
|
||||
|
||||
const struct eis_stylus_interface *
|
||||
eis_stylus_get_interface(struct eis_stylus *stylus) {
|
||||
return eis_device_get_stylus_interface(eis_stylus_get_device(stylus));
|
||||
}
|
||||
|
||||
struct eis_stylus *
|
||||
eis_stylus_new(struct eis_device *device)
|
||||
{
|
||||
struct eis_stylus *stylus = eis_stylus_create(&device->object);
|
||||
struct eis_client *client = eis_device_get_client(device);
|
||||
|
||||
stylus->proto_object.id = eis_client_get_new_id(client);
|
||||
stylus->proto_object.implementation = stylus;
|
||||
stylus->proto_object.interface = &eis_stylus_proto_interface;
|
||||
stylus->proto_object.version = client->interface_versions.ei_stylus;
|
||||
list_init(&stylus->proto_object.link);
|
||||
|
||||
eis_client_register_object(client, &stylus->proto_object);
|
||||
|
||||
return stylus; /* ref owned by caller */
|
||||
}
|
||||
51
src/libeis-stylus.h
Normal file
51
src/libeis-stylus.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util-object.h"
|
||||
#include "brei-shared.h"
|
||||
#include "libeis-client.h"
|
||||
|
||||
struct eis;
|
||||
struct eis_client;
|
||||
|
||||
/* This is a protocol-only object, not exposed in the API */
|
||||
struct eis_stylus {
|
||||
struct object object;
|
||||
struct brei_object proto_object;
|
||||
};
|
||||
|
||||
OBJECT_DECLARE_GETTER(eis_stylus, context, struct eis *);
|
||||
OBJECT_DECLARE_GETTER(eis_stylus, device, struct eis_device *);
|
||||
OBJECT_DECLARE_GETTER(eis_stylus, client, struct eis_client *);
|
||||
OBJECT_DECLARE_GETTER(eis_stylus, id, object_id_t);
|
||||
OBJECT_DECLARE_GETTER(eis_stylus, version, uint32_t);
|
||||
OBJECT_DECLARE_GETTER(eis_stylus, proto_object, const struct brei_object *);
|
||||
OBJECT_DECLARE_GETTER(eis_stylus, interface, const struct eis_stylus_interface *);
|
||||
OBJECT_DECLARE_REF(eis_stylus);
|
||||
OBJECT_DECLARE_UNREF(eis_stylus);
|
||||
|
||||
struct eis_stylus *
|
||||
eis_stylus_new(struct eis_device *device);
|
||||
158
src/libeis.c
158
src/libeis.c
|
|
@ -154,6 +154,19 @@ eis_event_type_to_string(enum eis_event_type type)
|
|||
CASE_RETURN_STRING(EIS_EVENT_TOUCH_DOWN);
|
||||
CASE_RETURN_STRING(EIS_EVENT_TOUCH_UP);
|
||||
CASE_RETURN_STRING(EIS_EVENT_TOUCH_MOTION);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_PROXIMITY_IN);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_PROXIMITY_OUT);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_ERASE_START);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_ERASE_STOP);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_DOWN);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_UP);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_MOTION);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_PRESSURE);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_DISTANCE);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_TILT);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_ROTATION);
|
||||
CASE_RETURN_STRING(EIS_EVENT_STYLUS_AIRBRUSH_FLOW);
|
||||
CASE_RETURN_STRING(EIS_EVENT_FRAME);
|
||||
}
|
||||
|
||||
|
|
@ -175,6 +188,19 @@ update_event_timestamp(struct eis_event *event, uint64_t time)
|
|||
case EIS_EVENT_TOUCH_DOWN:
|
||||
case EIS_EVENT_TOUCH_UP:
|
||||
case EIS_EVENT_TOUCH_MOTION:
|
||||
case EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EIS_EVENT_STYLUS_ERASE_START:
|
||||
case EIS_EVENT_STYLUS_ERASE_STOP:
|
||||
case EIS_EVENT_STYLUS_DOWN:
|
||||
case EIS_EVENT_STYLUS_UP:
|
||||
case EIS_EVENT_STYLUS_MOTION:
|
||||
case EIS_EVENT_STYLUS_PRESSURE:
|
||||
case EIS_EVENT_STYLUS_DISTANCE:
|
||||
case EIS_EVENT_STYLUS_TILT:
|
||||
case EIS_EVENT_STYLUS_ROTATION:
|
||||
case EIS_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
if (event->timestamp != 0) {
|
||||
log_bug(eis_event_get_context(event),
|
||||
"Unexpected timestamp for event of type: %s",
|
||||
|
|
@ -211,6 +237,19 @@ eis_queue_event(struct eis_event *event)
|
|||
case EIS_EVENT_TOUCH_DOWN:
|
||||
case EIS_EVENT_TOUCH_UP:
|
||||
case EIS_EVENT_TOUCH_MOTION:
|
||||
case EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EIS_EVENT_STYLUS_ERASE_START:
|
||||
case EIS_EVENT_STYLUS_ERASE_STOP:
|
||||
case EIS_EVENT_STYLUS_DOWN:
|
||||
case EIS_EVENT_STYLUS_UP:
|
||||
case EIS_EVENT_STYLUS_MOTION:
|
||||
case EIS_EVENT_STYLUS_PRESSURE:
|
||||
case EIS_EVENT_STYLUS_DISTANCE:
|
||||
case EIS_EVENT_STYLUS_TILT:
|
||||
case EIS_EVENT_STYLUS_ROTATION:
|
||||
case EIS_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
prefix = "pending ";
|
||||
queue = &device->pending_event_queue;
|
||||
break;
|
||||
|
|
@ -474,6 +513,125 @@ eis_queue_touch_cancel_event(struct eis_device *device, uint32_t touchid)
|
|||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_bind_tool_capabilities_event(struct eis_device *device, uint32_t capability)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES;
|
||||
e->stylus.capability = capability;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_proximity_in_event(struct eis_device *device)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_PROXIMITY_IN;
|
||||
e->stylus.is_prox = true;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_proximity_out_event(struct eis_device *device)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_PROXIMITY_OUT;
|
||||
e->stylus.is_prox = false;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_erase_start_event(struct eis_device *device)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_ERASE_START;
|
||||
e->stylus.is_erase = true;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_erase_stop_event(struct eis_device *device)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_ERASE_STOP;
|
||||
e->stylus.is_erase = false;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_down_event(struct eis_device *device)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_DOWN;
|
||||
e->stylus.is_down = true;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_up_event(struct eis_device *device)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_UP;
|
||||
e->stylus.is_down = false;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_motion_event(struct eis_device *device, float x, float y)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_MOTION;
|
||||
e->stylus.x = x;
|
||||
e->stylus.y = y;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_pressure_event(struct eis_device *device, float pressure)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_PRESSURE;
|
||||
e->stylus.pressure = pressure;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_distance_event(struct eis_device *device, float distance)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_DISTANCE;
|
||||
e->stylus.distance = distance;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_tilt_event(struct eis_device *device, float tilt_x, float tilt_y)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_TILT;
|
||||
e->stylus.tilt_x = tilt_x;
|
||||
e->stylus.tilt_y = tilt_y;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_rotation_event(struct eis_device *device, float rotation)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_ROTATION;
|
||||
e->stylus.rotation = rotation;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
void
|
||||
eis_queue_stylus_airbrush_flow_event(struct eis_device *device, float flow)
|
||||
{
|
||||
struct eis_event *e = eis_event_new_for_device(device);
|
||||
e->type = EIS_EVENT_STYLUS_AIRBRUSH_FLOW;
|
||||
e->stylus.flow = flow;
|
||||
eis_queue_event(e);
|
||||
}
|
||||
|
||||
_public_ struct eis_event*
|
||||
eis_get_event(struct eis *eis)
|
||||
{
|
||||
|
|
|
|||
256
src/libeis.h
256
src/libeis.h
|
|
@ -226,6 +226,7 @@ enum eis_device_capability {
|
|||
EIS_DEVICE_CAP_TOUCH = (1 << 3),
|
||||
EIS_DEVICE_CAP_SCROLL = (1 << 4),
|
||||
EIS_DEVICE_CAP_BUTTON = (1 << 5),
|
||||
EIS_DEVICE_CAP_STYLUS = (1 << 7),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -396,6 +397,59 @@ enum eis_event_type {
|
|||
* properties).
|
||||
*/
|
||||
EIS_EVENT_TOUCH_MOTION,
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES = 1000,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_PROXIMITY_IN,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_PROXIMITY_OUT,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_ERASE_START,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_ERASE_STOP,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_DOWN,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_UP,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_MOTION,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_PRESSURE,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_DISTANCE,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_TILT,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_ROTATION,
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
EIS_EVENT_STYLUS_AIRBRUSH_FLOW,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1678,6 +1732,104 @@ eis_touch_get_user_data(struct eis_touch *touch);
|
|||
struct eis_device *
|
||||
eis_touch_get_device(struct eis_touch *touch);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
struct eis_stylus *
|
||||
eis_device_stylus_new(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_tool_capabilities(struct eis_device *device, uint32_t capability);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_proximity_in(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_proximity_out(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_erase_start(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_erase_stop(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_down(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_up(struct eis_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_motion(struct eis_device *device, float x, float y);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_pressure(struct eis_device *device, float p);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_distance(struct eis_device *device, float d);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_tilt(struct eis_device *device, float tilt_x, float tilt_y);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_rotation(struct eis_device *device, float r);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-receiver
|
||||
* TODO
|
||||
*/
|
||||
void
|
||||
eis_device_stylus_airbrush_flow(struct eis_device *device, float s);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
|
|
@ -1869,6 +2021,110 @@ eis_event_touch_get_y(struct eis_event *event);
|
|||
bool
|
||||
eis_event_touch_get_is_cancel(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
bool
|
||||
eis_event_stylus_get_is_prox(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
bool
|
||||
eis_event_stylus_get_is_erase(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
uint32_t
|
||||
eis_event_stylus_get_code(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
uint32_t
|
||||
eis_event_stylus_get_capability(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
bool
|
||||
eis_event_stylus_get_is_down(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_x(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_y(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_pressure(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_distance(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_tilt_x(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_tilt_y(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_rotation(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup libeis-sender
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
float
|
||||
eis_event_stylus_get_flow(struct eis_event *event);
|
||||
|
||||
/**
|
||||
* @returns a timestamp for the current time to pass into
|
||||
* eis_device_frame().
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ if build_libei
|
|||
'libei-scroll.c',
|
||||
'libei-seat.c',
|
||||
'libei-socket.c',
|
||||
'libei-stylus.c',
|
||||
'libei-touchscreen.c',
|
||||
) + [brei_proto_headers, ei_proto_headers, ei_proto_sources]
|
||||
|
||||
|
|
@ -121,6 +122,7 @@ if build_libeis
|
|||
'libeis-scroll.c',
|
||||
'libeis-seat.c',
|
||||
'libeis-socket.c',
|
||||
'libeis-stylus.c',
|
||||
'libeis-touchscreen.c',
|
||||
'libeis.c',
|
||||
) + [brei_proto_headers, eis_proto_headers, eis_proto_sources]
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ struct peck {
|
|||
struct eis_device *eis_button;
|
||||
struct eis_device *eis_scroll;
|
||||
struct eis_device *eis_touch;
|
||||
struct eis_device *eis_stylus;
|
||||
|
||||
struct ei_seat *ei_seat;
|
||||
struct ei_device *ei_pointer;
|
||||
|
|
@ -83,6 +84,7 @@ struct peck {
|
|||
struct ei_device *ei_button;
|
||||
struct ei_device *ei_scroll;
|
||||
struct ei_device *ei_touch;
|
||||
struct ei_device *ei_stylus;
|
||||
|
||||
uint64_t now;
|
||||
|
||||
|
|
@ -174,6 +176,7 @@ peck_destroy(struct peck *peck)
|
|||
eis_device_unref(peck->eis_touch);
|
||||
eis_device_unref(peck->eis_button);
|
||||
eis_device_unref(peck->eis_scroll);
|
||||
eis_device_unref(peck->eis_stylus);
|
||||
eis_seat_unref(peck->eis_seat);
|
||||
|
||||
ei_device_unref(peck->ei_pointer);
|
||||
|
|
@ -182,6 +185,7 @@ peck_destroy(struct peck *peck)
|
|||
ei_device_unref(peck->ei_touch);
|
||||
ei_device_unref(peck->ei_button);
|
||||
ei_device_unref(peck->ei_scroll);
|
||||
ei_device_unref(peck->ei_stylus);
|
||||
ei_seat_unref(peck->ei_seat);
|
||||
|
||||
ei_unref(peck->ei);
|
||||
|
|
@ -351,6 +355,13 @@ peck_eis_get_default_touch(struct peck *peck)
|
|||
return peck->eis_touch;
|
||||
};
|
||||
|
||||
struct eis_device *
|
||||
peck_eis_get_default_stylus(struct peck *peck)
|
||||
{
|
||||
munit_assert_ptr_not_null(peck->eis_stylus);
|
||||
return peck->eis_stylus;
|
||||
};
|
||||
|
||||
struct ei_seat *
|
||||
peck_ei_get_default_seat(struct peck *peck)
|
||||
{
|
||||
|
|
@ -400,6 +411,13 @@ peck_ei_get_default_touch(struct peck *peck)
|
|||
return peck->ei_touch;
|
||||
};
|
||||
|
||||
struct ei_device *
|
||||
peck_ei_get_default_stylus(struct peck *peck)
|
||||
{
|
||||
munit_assert_ptr_not_null(peck->ei_stylus);
|
||||
return peck->ei_stylus;
|
||||
};
|
||||
|
||||
/* Ensures that device frames in tests always have an ascending and fixed
|
||||
* interval. Every time this is called it adds 10ms to the time offset.
|
||||
*/
|
||||
|
|
@ -708,12 +726,14 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
|
|||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_CLOSE_DEVICE);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES);
|
||||
break;
|
||||
case PECK_EIS_BEHAVIOR_ADD_DEVICES:
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_STYLUS);
|
||||
break;
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_BIND_SEAT:
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_CLOSE_DEVICE:
|
||||
|
|
@ -725,7 +745,9 @@ peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
|
|||
case PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE:
|
||||
case PECK_EIS_BEHAVIOR_ADD_KEYBOARD:
|
||||
case PECK_EIS_BEHAVIOR_ADD_TOUCH:
|
||||
case PECK_EIS_BEHAVIOR_ADD_STYLUS:
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_DEVICE_READY:
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES:
|
||||
flag_set(peck->eis_behavior, behavior);
|
||||
break;
|
||||
case PECK_EIS_BEHAVIOR_REJECT_CLIENT:
|
||||
|
|
@ -766,12 +788,14 @@ peck_disable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
|
|||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_CLOSE_DEVICE);
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING);
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING);
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES);
|
||||
break;
|
||||
case PECK_EIS_BEHAVIOR_ADD_DEVICES:
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER);
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE);
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD);
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_TOUCH);
|
||||
peck_disable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_STYLUS);
|
||||
break;
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_BIND_SEAT:
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_CLOSE_DEVICE:
|
||||
|
|
@ -783,11 +807,13 @@ peck_disable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior)
|
|||
case PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE:
|
||||
case PECK_EIS_BEHAVIOR_ADD_KEYBOARD:
|
||||
case PECK_EIS_BEHAVIOR_ADD_TOUCH:
|
||||
case PECK_EIS_BEHAVIOR_ADD_STYLUS:
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_DEVICE_READY:
|
||||
case PECK_EIS_BEHAVIOR_REJECT_CLIENT:
|
||||
case PECK_EIS_BEHAVIOR_ACCEPT_CLIENT:
|
||||
case PECK_EIS_BEHAVIOR_RESUME_DEVICE:
|
||||
case PECK_EIS_BEHAVIOR_SUSPEND_DEVICE:
|
||||
case PECK_EIS_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES:
|
||||
flag_clear(peck->eis_behavior, behavior);
|
||||
break;
|
||||
}
|
||||
|
|
@ -817,6 +843,7 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
|
|||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_BUTTON);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_SCROLL);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_STYLUS);
|
||||
break;
|
||||
case PECK_EI_BEHAVIOR_AUTOSTART:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER:
|
||||
|
|
@ -825,10 +852,12 @@ peck_enable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
|
|||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_BUTTON:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_SCROLL:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_STYLUS:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_FRAME:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_SYNC:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_RESUMED:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_PAUSED:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES:
|
||||
flag_set(peck->ei_behavior, behavior);
|
||||
break;
|
||||
}
|
||||
|
|
@ -845,6 +874,7 @@ peck_disable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
|
|||
case PECK_EI_BEHAVIOR_AUTOSEAT:
|
||||
flag_clear(peck->ei_behavior, behavior);
|
||||
break;
|
||||
//FIXME: Shouldn't these be /disable/ ?
|
||||
case PECK_EI_BEHAVIOR_AUTODEVICES:
|
||||
peck_disable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
|
||||
peck_disable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSEAT);
|
||||
|
|
@ -858,6 +888,7 @@ peck_disable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
|
|||
peck_disable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH);
|
||||
peck_disable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_BUTTON);
|
||||
peck_disable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_SCROLL);
|
||||
peck_disable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_ADDED_STYLUS);
|
||||
break;
|
||||
case PECK_EI_BEHAVIOR_AUTOSTART:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_POINTER:
|
||||
|
|
@ -866,10 +897,12 @@ peck_disable_ei_behavior(struct peck *peck, enum peck_ei_behavior behavior)
|
|||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_BUTTON:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_SCROLL:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_ADDED_STYLUS:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_FRAME:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_SYNC:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_RESUMED:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_PAUSED:
|
||||
case PECK_EI_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES:
|
||||
flag_clear(peck->ei_behavior, behavior);
|
||||
break;
|
||||
}
|
||||
|
|
@ -886,6 +919,7 @@ peck_create_eis_seat(struct peck *peck, struct eis_client *client)
|
|||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_TOUCH);
|
||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_SCROLL);
|
||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_STYLUS);
|
||||
|
||||
log_debug(peck, "EIS adding seat: '%s'\n", eis_seat_get_name(seat));
|
||||
eis_seat_add(seat);
|
||||
|
|
@ -972,6 +1006,27 @@ peck_eis_create_touch(struct peck *peck, struct eis_seat *seat, const char *name
|
|||
return device;
|
||||
}
|
||||
|
||||
static inline struct eis_device *
|
||||
peck_eis_create_stylus(struct peck *peck, struct eis_seat *seat, const char *name)
|
||||
{
|
||||
struct eis_device *device = eis_seat_new_device(seat);
|
||||
_unref_(eis_region) *region = eis_device_new_region(device);
|
||||
|
||||
eis_region_set_offset(region, 0, 0);
|
||||
eis_region_set_size(region, 1920, 1080);
|
||||
|
||||
eis_device_configure_name(device, name);
|
||||
eis_device_configure_capability(device, EIS_DEVICE_CAP_STYLUS);
|
||||
eis_device_configure_capability(device, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_region_add(region);
|
||||
eis_device_add(device);
|
||||
|
||||
// FIXME: Configure capabilities from PECK_EIS_BEHAVIOR_*
|
||||
// once eis_device_add is updated with a method to do so.
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static inline void
|
||||
peck_handle_eis_seat_bind(struct peck *peck, struct eis_event *e)
|
||||
{
|
||||
|
|
@ -1055,13 +1110,35 @@ peck_handle_eis_seat_bind(struct peck *peck, struct eis_event *e)
|
|||
}
|
||||
}
|
||||
|
||||
if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_STYLUS)) {
|
||||
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_ADD_STYLUS) && !peck->eis_stylus) {
|
||||
// FIXME: This may need to be updated once the ability to announce
|
||||
// and bind capabilities is available
|
||||
log_debug(peck, "EIS creating default stylus\n");
|
||||
_unref_(eis_device) *stylus = peck_eis_create_stylus(peck, seat, "default stylus");
|
||||
|
||||
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_RESUME_DEVICE))
|
||||
eis_device_resume(stylus);
|
||||
|
||||
peck->eis_stylus = eis_device_ref(stylus);
|
||||
}
|
||||
} else {
|
||||
if (peck->eis_stylus) {
|
||||
log_debug(peck, "EIS removing default stylus\n");
|
||||
|
||||
_unref_(eis_device) *stylus = steal(&peck->eis_stylus);
|
||||
eis_device_remove(stylus);
|
||||
}
|
||||
}
|
||||
|
||||
/* Removing all caps means removing the seat */
|
||||
if (!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_POINTER) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_POINTER_ABSOLUTE) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_KEYBOARD) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_BUTTON) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_SCROLL) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_TOUCH))
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_TOUCH) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_STYLUS))
|
||||
eis_seat_remove(seat);
|
||||
}
|
||||
|
||||
|
|
@ -1081,8 +1158,12 @@ peck_eis_device_remove(struct peck *peck, struct eis_device *device)
|
|||
peck->eis_button = eis_device_unref(device);
|
||||
if (device == peck->eis_scroll)
|
||||
peck->eis_scroll = eis_device_unref(device);
|
||||
if (device == peck->eis_stylus)
|
||||
peck->eis_stylus = eis_device_unref(device);
|
||||
}
|
||||
|
||||
static uint32_t offered_caps;
|
||||
|
||||
bool
|
||||
_peck_dispatch_eis(struct peck *peck, int lineno)
|
||||
{
|
||||
|
|
@ -1148,6 +1229,10 @@ _peck_dispatch_eis(struct peck *peck, int lineno)
|
|||
if (flag_is_set(peck->eis_behavior, PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING))
|
||||
process_event = tristate_yes;
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES:
|
||||
if (flag_is_set(peck->eis_behavior, PECK_EI_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES))
|
||||
process_event = tristate_yes;
|
||||
break;
|
||||
case EIS_EVENT_POINTER_MOTION:
|
||||
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case EIS_EVENT_BUTTON_BUTTON:
|
||||
|
|
@ -1159,6 +1244,18 @@ _peck_dispatch_eis(struct peck *peck, int lineno)
|
|||
case EIS_EVENT_TOUCH_DOWN:
|
||||
case EIS_EVENT_TOUCH_UP:
|
||||
case EIS_EVENT_TOUCH_MOTION:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EIS_EVENT_STYLUS_ERASE_START:
|
||||
case EIS_EVENT_STYLUS_ERASE_STOP:
|
||||
case EIS_EVENT_STYLUS_DOWN:
|
||||
case EIS_EVENT_STYLUS_UP:
|
||||
case EIS_EVENT_STYLUS_MOTION:
|
||||
case EIS_EVENT_STYLUS_PRESSURE:
|
||||
case EIS_EVENT_STYLUS_DISTANCE:
|
||||
case EIS_EVENT_STYLUS_TILT:
|
||||
case EIS_EVENT_STYLUS_ROTATION:
|
||||
case EIS_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
need_frame = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1202,6 +1299,9 @@ _peck_dispatch_eis(struct peck *peck, int lineno)
|
|||
last_timestamp = timestamp;
|
||||
break;
|
||||
}
|
||||
case EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES:
|
||||
uint32_t bound_caps = eis_event_stylus_get_capability(e);
|
||||
munit_assert_int(offered_caps & bound_caps, ==, bound_caps);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1241,6 +1341,10 @@ peck_check_ei_added(struct peck *peck, struct ei_event *e)
|
|||
flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_ADDED_SCROLL))
|
||||
return tristate_yes;
|
||||
|
||||
if (ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS) &
|
||||
flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_ADDED_STYLUS))
|
||||
return tristate_yes;
|
||||
|
||||
return tristate_unset;
|
||||
}
|
||||
|
||||
|
|
@ -1308,6 +1412,10 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
case EI_EVENT_DEVICE_START_EMULATING:
|
||||
case EI_EVENT_DEVICE_STOP_EMULATING:
|
||||
break;
|
||||
case EI_EVENT_STYLUS_TOOL_CAPABILITIES:
|
||||
if (flag_is_set(peck->ei_behavior, PECK_EI_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES))
|
||||
process_event = tristate_yes;
|
||||
break;
|
||||
case EI_EVENT_POINTER_MOTION:
|
||||
case EI_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case EI_EVENT_BUTTON_BUTTON:
|
||||
|
|
@ -1320,6 +1428,18 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
case EI_EVENT_TOUCH_DOWN:
|
||||
case EI_EVENT_TOUCH_UP:
|
||||
case EI_EVENT_TOUCH_MOTION:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EIS_EVENT_STYLUS_ERASE_START:
|
||||
case EIS_EVENT_STYLUS_ERASE_STOP:
|
||||
case EIS_EVENT_STYLUS_DOWN:
|
||||
case EIS_EVENT_STYLUS_UP:
|
||||
case EIS_EVENT_STYLUS_MOTION:
|
||||
case EIS_EVENT_STYLUS_PRESSURE:
|
||||
case EIS_EVENT_STYLUS_DISTANCE:
|
||||
case EIS_EVENT_STYLUS_TILT:
|
||||
case EIS_EVENT_STYLUS_ROTATION:
|
||||
case EIS_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
need_frame = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1355,7 +1475,8 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
EI_DEVICE_CAP_KEYBOARD,
|
||||
EI_DEVICE_CAP_TOUCH,
|
||||
EI_DEVICE_CAP_BUTTON,
|
||||
EI_DEVICE_CAP_SCROLL, NULL);
|
||||
EI_DEVICE_CAP_SCROLL,
|
||||
EI_DEVICE_CAP_STYLUS, NULL);
|
||||
break;
|
||||
}
|
||||
case EI_EVENT_DEVICE_ADDED:
|
||||
|
|
@ -1373,6 +1494,8 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
peck->ei_button = ei_device_ref(device);
|
||||
if (!peck->ei_scroll && ei_device_has_capability(device, EI_DEVICE_CAP_SCROLL))
|
||||
peck->ei_scroll = ei_device_ref(device);
|
||||
if (!peck->ei_scroll && ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS))
|
||||
peck->ei_stylus = ei_device_ref(device);
|
||||
break;
|
||||
}
|
||||
case EI_EVENT_DEVICE_RESUMED:
|
||||
|
|
@ -1386,6 +1509,9 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
case EI_EVENT_DEVICE_PAUSED:
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
case EI_EVENT_STYLUS_TOOL_CAPABILITIES:
|
||||
offered_caps = ei_event_stylus_get_capability(e);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1656,6 +1782,19 @@ peck_ei_event_type_name(enum ei_event_type type)
|
|||
CASE_STRING(TOUCH_DOWN);
|
||||
CASE_STRING(TOUCH_UP);
|
||||
CASE_STRING(TOUCH_MOTION);
|
||||
CASE_STRING(STYLUS_TOOL_CAPABILITIES);
|
||||
CASE_STRING(STYLUS_PROXIMITY_IN);
|
||||
CASE_STRING(STYLUS_PROXIMITY_OUT);
|
||||
CASE_STRING(STYLUS_ERASE_START);
|
||||
CASE_STRING(STYLUS_ERASE_STOP);
|
||||
CASE_STRING(STYLUS_DOWN);
|
||||
CASE_STRING(STYLUS_UP);
|
||||
CASE_STRING(STYLUS_MOTION);
|
||||
CASE_STRING(STYLUS_PRESSURE);
|
||||
CASE_STRING(STYLUS_DISTANCE);
|
||||
CASE_STRING(STYLUS_TILT);
|
||||
CASE_STRING(STYLUS_ROTATION);
|
||||
CASE_STRING(STYLUS_AIRBRUSH_FLOW);
|
||||
}
|
||||
#undef CASE_STRING
|
||||
assert(!"Unhandled ei event type");
|
||||
|
|
@ -1695,6 +1834,19 @@ peck_eis_event_type_name(enum eis_event_type type)
|
|||
CASE_STRING(TOUCH_UP);
|
||||
CASE_STRING(TOUCH_MOTION);
|
||||
CASE_STRING(FRAME);
|
||||
CASE_STRING(STYLUS_BIND_TOOL_CAPABILITIES);
|
||||
CASE_STRING(STYLUS_PROXIMITY_IN);
|
||||
CASE_STRING(STYLUS_PROXIMITY_OUT);
|
||||
CASE_STRING(STYLUS_ERASE_START);
|
||||
CASE_STRING(STYLUS_ERASE_STOP);
|
||||
CASE_STRING(STYLUS_DOWN);
|
||||
CASE_STRING(STYLUS_UP);
|
||||
CASE_STRING(STYLUS_MOTION);
|
||||
CASE_STRING(STYLUS_PRESSURE);
|
||||
CASE_STRING(STYLUS_DISTANCE);
|
||||
CASE_STRING(STYLUS_TILT);
|
||||
CASE_STRING(STYLUS_ROTATION);
|
||||
CASE_STRING(STYLUS_AIRBRUSH_FLOW);
|
||||
}
|
||||
#undef CASE_STRING
|
||||
assert(!"Unhandled EIS event type");
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@ enum peck_eis_behavior {
|
|||
*/
|
||||
PECK_EIS_BEHAVIOR_HANDLE_START_EMULATING,
|
||||
PECK_EIS_BEHAVIOR_HANDLE_STOP_EMULATING,
|
||||
/**
|
||||
* Handle stylus capability events. This behavior is enabled by default.
|
||||
*/
|
||||
PECK_EIS_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES,
|
||||
|
||||
/**
|
||||
* Create default devices
|
||||
|
|
@ -105,6 +109,7 @@ enum peck_eis_behavior {
|
|||
PECK_EIS_BEHAVIOR_ADD_POINTER_ABSOLUTE,
|
||||
PECK_EIS_BEHAVIOR_ADD_KEYBOARD,
|
||||
PECK_EIS_BEHAVIOR_ADD_TOUCH,
|
||||
PECK_EIS_BEHAVIOR_ADD_STYLUS,
|
||||
|
||||
PECK_EIS_BEHAVIOR_RESUME_DEVICE,
|
||||
PECK_EIS_BEHAVIOR_SUSPEND_DEVICE,
|
||||
|
|
@ -136,6 +141,7 @@ enum peck_ei_behavior {
|
|||
PECK_EI_BEHAVIOR_HANDLE_ADDED_TOUCH,
|
||||
PECK_EI_BEHAVIOR_HANDLE_ADDED_BUTTON,
|
||||
PECK_EI_BEHAVIOR_HANDLE_ADDED_SCROLL,
|
||||
PECK_EI_BEHAVIOR_HANDLE_ADDED_STYLUS,
|
||||
|
||||
PECK_EI_BEHAVIOR_HANDLE_RESUMED,
|
||||
PECK_EI_BEHAVIOR_HANDLE_PAUSED,
|
||||
|
|
@ -148,6 +154,10 @@ enum peck_ei_behavior {
|
|||
* Handle sync events. This behavior is enabled by default.
|
||||
*/
|
||||
PECK_EI_BEHAVIOR_HANDLE_SYNC,
|
||||
/**
|
||||
* Handle stylus capability events.
|
||||
*/
|
||||
PECK_EI_BEHAVIOR_HANDLE_STYLUS_CAPABILITIES,
|
||||
};
|
||||
|
||||
struct peck;
|
||||
|
|
@ -252,6 +262,9 @@ peck_eis_get_default_button(struct peck *peck);
|
|||
struct eis_device *
|
||||
peck_eis_get_default_scroll(struct peck *peck);
|
||||
|
||||
struct eis_device *
|
||||
peck_eis_get_default_stylus(struct peck *peck);
|
||||
|
||||
struct ei_seat *
|
||||
peck_ei_get_default_seat(struct peck *peck);
|
||||
|
||||
|
|
@ -273,6 +286,9 @@ peck_ei_get_default_pointer_absolute(struct peck *peck);
|
|||
struct ei_device *
|
||||
peck_ei_get_default_touch(struct peck *peck);
|
||||
|
||||
struct ei_device *
|
||||
peck_ei_get_default_stylus(struct peck *peck);
|
||||
|
||||
uint64_t
|
||||
peck_ei_now(struct peck *peck);
|
||||
|
||||
|
|
|
|||
|
|
@ -1503,6 +1503,143 @@ MUNIT_TEST(test_ei_device_multitouch)
|
|||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
// FIXME: This may need to be updated once the ability to announce
|
||||
// and bind capabilities is available.
|
||||
MUNIT_TEST(test_ei_device_stylus)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new();
|
||||
struct ei_device *device = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_STYLUS);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
device = peck_ei_get_default_stylus(peck);
|
||||
|
||||
ei_device_stylus_proximity_in(device);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_motion(device, 0.1 , 0.2);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_pressure(device, 0.3);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_distance(device, 0.0);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_tilt(device, 0.4, 0.5);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_rotation(device, 0.6);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_airbrush_flow(device, 0.7);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_erase_start(device);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_erase_stop(device);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
|
||||
ei_device_stylus_proximity_out(device);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
_unref_(eis_event) *proximity_in =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_PROXIMITY_IN);
|
||||
munit_assert_true(eis_event_stylus_get_is_prox(proximity_in));
|
||||
|
||||
_unref_(eis_event) *motion =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_MOTION);
|
||||
munit_assert_double_equal(eis_event_stylus_get_x(motion), 0.1, 2 /* precision */);
|
||||
munit_assert_double_equal(eis_event_stylus_get_y(motion), 0.2, 2 /* precision */);
|
||||
|
||||
_unref_(eis_event) *pressure =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_PRESSURE);
|
||||
munit_assert_double_equal(eis_event_stylus_get_pressure(pressure), 0.3, 2 /* precision */);
|
||||
|
||||
_unref_(eis_event) *distance =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_DISTANCE);
|
||||
munit_assert_double_equal(eis_event_stylus_get_distance(distance), 0.0, 2 /* precision */);
|
||||
|
||||
_unref_(eis_event) *tilt =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_TILT);
|
||||
munit_assert_double_equal(eis_event_stylus_get_tilt_x(tilt), 0.4, 2 /* precision */);
|
||||
munit_assert_double_equal(eis_event_stylus_get_tilt_y(tilt), 0.5, 2 /* precision */);
|
||||
|
||||
_unref_(eis_event) *rotation =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_ROTATION);
|
||||
munit_assert_double_equal(eis_event_stylus_get_rotation(rotation), 0.6, 2 /* precision */);
|
||||
|
||||
_unref_(eis_event) *airbrush_flow =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_AIRBRUSH_FLOW);
|
||||
munit_assert_double_equal(eis_event_stylus_get_flow(airbrush_flow), 0.7, 2 /* precision */);
|
||||
|
||||
_unref_(eis_event) *erase_start =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_ERASE_START);
|
||||
munit_assert_true(eis_event_stylus_get_is_erase(erase_start));
|
||||
|
||||
_unref_(eis_event) *erase_stop =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_ERASE_STOP);
|
||||
munit_assert_false(eis_event_stylus_get_is_erase(erase_stop));
|
||||
|
||||
_unref_(eis_event) *proximity_out =
|
||||
peck_eis_next_event(eis, EIS_EVENT_STYLUS_PROXIMITY_OUT);
|
||||
munit_assert_false(eis_event_stylus_get_is_prox(proximity_out));
|
||||
|
||||
peck_assert_no_eis_events(eis);
|
||||
}
|
||||
|
||||
with_client(peck) {
|
||||
/* We know our default device has one region */
|
||||
struct ei_region *r = ei_device_get_region(device, 0);
|
||||
uint32_t maxx = ei_region_get_x(r) + ei_region_get_width(r);
|
||||
uint32_t maxy = ei_region_get_y(r) + ei_region_get_height(r);
|
||||
|
||||
/* outside of stylus range, expect to be discarded */
|
||||
ei_device_stylus_motion(device, maxx + 1, maxy/2);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
ei_device_stylus_motion(device, maxx/2 , maxy + 1);
|
||||
ei_device_frame(device, peck_ei_now(peck));
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
peck_assert_no_eis_events(eis);
|
||||
|
||||
/* Don't auto-handle the DEVICE_CLOSED event */
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_HANDLE_SYNC);
|
||||
}
|
||||
|
||||
with_client(peck) {
|
||||
ei_device_close(device);
|
||||
/* motion after remove must not trigger an event */
|
||||
with_nonfatal_ei_bug(peck)
|
||||
ei_device_stylus_motion(device, 100, 200);
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_server(peck) {
|
||||
_unref_(eis_event) *stop =
|
||||
peck_eis_next_event(eis, EIS_EVENT_DEVICE_STOP_EMULATING);
|
||||
_unref_(eis_event) *closed =
|
||||
peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED);
|
||||
peck_assert_no_eis_events(eis);
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
#if HAVE_MEMFD_CREATE
|
||||
MUNIT_TEST(test_ei_keymap_invalid)
|
||||
{
|
||||
|
|
@ -2893,6 +3030,153 @@ MUNIT_TEST(test_passive_ei_device_multitouch)
|
|||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
// FIXME: This may need to be updated once the ability to announce
|
||||
// and bind capabilities is available.
|
||||
MUNIT_TEST(test_passive_ei_device_stylus)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new_context("mode", PECK_EI_RECEIVER);
|
||||
struct eis_device *device = NULL;
|
||||
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
|
||||
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_STYLUS);
|
||||
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
uint32_t sequence = 123;
|
||||
|
||||
with_server(peck) {
|
||||
struct eis_device *device = peck_eis_get_default_stylus(peck);
|
||||
eis_device_start_emulating(device, sequence);
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_unref_(ei_event) *start =
|
||||
peck_ei_next_event(ei, EI_EVENT_DEVICE_START_EMULATING);
|
||||
munit_assert_uint(ei_event_emulating_get_sequence(start), ==, sequence);
|
||||
}
|
||||
|
||||
with_server(peck) {
|
||||
device = peck_eis_get_default_stylus(peck);
|
||||
|
||||
eis_device_stylus_proximity_in(device);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_motion(device, 0.1 , 0.2);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_pressure(device, 0.3);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_distance(device, 0.0);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_tilt(device, 0.4, 0.5);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_rotation(device, 0.6);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_airbrush_flow(device, 0.7);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_erase_start(device);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_erase_stop(device);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
|
||||
eis_device_stylus_proximity_out(device);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_unref_(ei_event) *proximity_in =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_PROXIMITY_IN);
|
||||
munit_assert_true(ei_event_stylus_get_is_prox(proximity_in));
|
||||
|
||||
_unref_(ei_event) *motion =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_MOTION);
|
||||
munit_assert_double_equal(ei_event_stylus_get_x(motion), 0.1, 2 /* precision */);
|
||||
munit_assert_double_equal(ei_event_stylus_get_y(motion), 0.2, 2 /* precision */);
|
||||
|
||||
_unref_(ei_event) *pressure =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_PRESSURE);
|
||||
munit_assert_double_equal(ei_event_stylus_get_pressure(pressure), 0.3, 2 /* precision */);
|
||||
|
||||
_unref_(ei_event) *distance =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_DISTANCE);
|
||||
munit_assert_double_equal(ei_event_stylus_get_distance(distance), 0.0, 2 /* precision */);
|
||||
|
||||
_unref_(ei_event) *tilt =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_TILT);
|
||||
munit_assert_double_equal(ei_event_stylus_get_tilt_x(tilt), 0.4, 2 /* precision */);
|
||||
munit_assert_double_equal(ei_event_stylus_get_tilt_y(tilt), 0.5, 2 /* precision */);
|
||||
|
||||
_unref_(ei_event) *rotation =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_ROTATION);
|
||||
munit_assert_double_equal(ei_event_stylus_get_rotation(rotation), 0.6, 2 /* precision */);
|
||||
|
||||
_unref_(ei_event) *airbrush_flow =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_AIRBRUSH_FLOW);
|
||||
munit_assert_double_equal(ei_event_stylus_get_flow(airbrush_flow), 0.7, 2 /* precision */);
|
||||
|
||||
_unref_(ei_event) *erase_start =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_ERASE_START);
|
||||
munit_assert_true(ei_event_stylus_get_is_erase(erase_start));
|
||||
|
||||
_unref_(ei_event) *erase_stop =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_ERASE_STOP);
|
||||
munit_assert_false(ei_event_stylus_get_is_erase(erase_stop));
|
||||
|
||||
_unref_(ei_event) *proximity_out =
|
||||
peck_ei_next_event(ei, EI_EVENT_STYLUS_PROXIMITY_OUT);
|
||||
munit_assert_false(ei_event_stylus_get_is_prox(proximity_out));
|
||||
|
||||
peck_assert_no_ei_events(ei);
|
||||
}
|
||||
|
||||
with_server(peck) {
|
||||
/* We know our default device has one region */
|
||||
struct eis_region *r = eis_device_get_region(device, 0);
|
||||
uint32_t maxx = eis_region_get_x(r) + eis_region_get_width(r);
|
||||
uint32_t maxy = eis_region_get_y(r) + eis_region_get_height(r);
|
||||
|
||||
/* outside of stylus range, expect to be discarded */
|
||||
eis_device_stylus_motion(device, maxx + 1, maxy/2);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
eis_device_stylus_motion(device, maxx/2 , maxy + 1);
|
||||
eis_device_frame(device, peck_eis_now(peck));
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
peck_assert_no_ei_events(ei);
|
||||
}
|
||||
|
||||
with_server(peck) {
|
||||
eis_device_remove(device);
|
||||
/* motion after remove must not trigger an event */
|
||||
eis_device_stylus_motion(device, 100, 200);
|
||||
}
|
||||
|
||||
peck_dispatch_until_stable(peck);
|
||||
|
||||
with_client(peck) {
|
||||
_unref_(ei_event) *stop =
|
||||
peck_ei_next_event(ei, EI_EVENT_DEVICE_STOP_EMULATING);
|
||||
_unref_(ei_event) *closed =
|
||||
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
|
||||
peck_assert_no_ei_events(ei);
|
||||
}
|
||||
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MUNIT_TEST(test_passive_ei_frame_timestamp)
|
||||
{
|
||||
_unref_(peck) *peck = peck_new_context("mode", PECK_EI_RECEIVER);
|
||||
|
|
|
|||
|
|
@ -295,6 +295,29 @@ print_pong_event(struct ei_event *event)
|
|||
printf(" id: %#" PRIx64 "\n", ei_ping_get_id(ping));
|
||||
}
|
||||
|
||||
static void
|
||||
print_stylus_event(struct ei_event *event)
|
||||
{
|
||||
print_device(event);
|
||||
|
||||
bool down = ei_event_stylus_get_is_down(event);
|
||||
bool prox = ei_event_stylus_get_is_prox(event);
|
||||
bool erase = ei_event_stylus_get_is_erase(event);
|
||||
|
||||
uint32_t capability = ei_event_stylus_get_capability(event);
|
||||
|
||||
float x = ei_event_stylus_get_x(event);
|
||||
float y = ei_event_stylus_get_y(event);
|
||||
float p = ei_event_stylus_get_pressure(event);
|
||||
float d = ei_event_stylus_get_distance(event);
|
||||
float r = ei_event_stylus_get_rotation(event);
|
||||
float s = ei_event_stylus_get_flow(event);
|
||||
float tilt_x = ei_event_stylus_get_tilt_x(event);
|
||||
float tilt_y = ei_event_stylus_get_tilt_y(event);
|
||||
|
||||
printf(" stylus: [down - %s, prox - %s, erase - %s]\n[x - %f, y - %f, p - %f, d - %f, r - %f, s - %f, tilt_x - %f, tilt_y - %f]\n[Capability - %u]", truefalse(down), truefalse(prox), truefalse(erase), x, y, p, d, r, s, tilt_x, tilt_y, capability);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
enum {
|
||||
|
|
@ -455,6 +478,21 @@ int main(int argc, char **argv)
|
|||
case EI_EVENT_PONG:
|
||||
print_pong_event(e);
|
||||
break;
|
||||
case EI_EVENT_STYLUS_TOOL_CAPABILITIES:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
case EI_EVENT_STYLUS_ERASE_START:
|
||||
case EI_EVENT_STYLUS_ERASE_STOP:
|
||||
case EI_EVENT_STYLUS_DOWN:
|
||||
case EI_EVENT_STYLUS_UP:
|
||||
case EI_EVENT_STYLUS_MOTION:
|
||||
case EI_EVENT_STYLUS_PRESSURE:
|
||||
case EI_EVENT_STYLUS_DISTANCE:
|
||||
case EI_EVENT_STYLUS_TILT:
|
||||
case EI_EVENT_STYLUS_ROTATION:
|
||||
case EI_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
print_stylus_event(e);
|
||||
break;
|
||||
case EI_EVENT_SYNC:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,12 +300,14 @@ int main(int argc, char **argv)
|
|||
_unref_(ei_device) *kbd = NULL;
|
||||
_unref_(ei_device) *abs = NULL;
|
||||
_unref_(ei_device) *touch = NULL;
|
||||
_unref_(ei_device) *stylus = NULL;
|
||||
|
||||
bool stop = false;
|
||||
bool have_ptr = false;
|
||||
bool have_kbd = false;
|
||||
bool have_abs = false;
|
||||
bool have_touch = false;
|
||||
bool have_stylus = false;
|
||||
struct ei_seat *default_seat = NULL;
|
||||
|
||||
uint32_t sequence = 0;
|
||||
|
|
@ -344,7 +346,8 @@ int main(int argc, char **argv)
|
|||
EI_DEVICE_CAP_POINTER_ABSOLUTE,
|
||||
EI_DEVICE_CAP_TOUCH,
|
||||
EI_DEVICE_CAP_BUTTON,
|
||||
EI_DEVICE_CAP_SCROLL, NULL);
|
||||
EI_DEVICE_CAP_SCROLL,
|
||||
EI_DEVICE_CAP_STYLUS, NULL);
|
||||
break;
|
||||
}
|
||||
case EI_EVENT_SEAT_REMOVED:
|
||||
|
|
@ -376,6 +379,11 @@ int main(int argc, char **argv)
|
|||
touch = ei_device_ref(device);
|
||||
handle_regions(device);
|
||||
}
|
||||
if (ei_device_has_capability(device, EI_DEVICE_CAP_STYLUS)) {
|
||||
colorprint("New stylus device: %s\n", ei_device_get_name(device));
|
||||
stylus = ei_device_ref(device);
|
||||
handle_regions(device);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_DEVICE_RESUMED:
|
||||
|
|
@ -403,6 +411,12 @@ int main(int argc, char **argv)
|
|||
colorprint("Touch device was resumed\n");
|
||||
have_touch = true;
|
||||
}
|
||||
if (ei_event_get_device(e) == stylus) {
|
||||
if (!receiver)
|
||||
ei_device_start_emulating(stylus, ++sequence);
|
||||
colorprint("Stylus device was resumed\n");
|
||||
have_stylus = true;
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_DEVICE_PAUSED:
|
||||
if (ei_event_get_device(e) == ptr) {
|
||||
|
|
@ -421,6 +435,10 @@ int main(int argc, char **argv)
|
|||
colorprint("Touch device was paused\n");
|
||||
have_touch = false;
|
||||
}
|
||||
if (ei_event_get_device(e) == stylus) {
|
||||
colorprint("Stylus device was paused\n");
|
||||
have_stylus = false;
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_DEVICE_REMOVED:
|
||||
{
|
||||
|
|
@ -498,6 +516,71 @@ int main(int argc, char **argv)
|
|||
colorprint("touch up %u\n", ei_event_touch_get_id(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EI_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
{
|
||||
colorprint("stylus proximity %s\n",
|
||||
ei_event_get_type(e) == EI_EVENT_STYLUS_PROXIMITY_OUT ? "out" : "in");
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_DOWN:
|
||||
case EI_EVENT_STYLUS_UP:
|
||||
{
|
||||
colorprint("stylus %s\n",
|
||||
ei_event_get_type(e) == EI_EVENT_STYLUS_DOWN ? "down" : "up");
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_TOOL_CAPABILITIES:
|
||||
{
|
||||
colorprint("stylus capability 0x%08x\n",
|
||||
ei_event_stylus_get_capability(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_ERASE_START:
|
||||
case EI_EVENT_STYLUS_ERASE_STOP:
|
||||
{
|
||||
colorprint("stylus erase %s\n",
|
||||
ei_event_get_type(e) == EI_EVENT_STYLUS_ERASE_STOP ? "stop" : "start");
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_PRESSURE:
|
||||
{
|
||||
colorprint("stylus pressure %.2f\n",
|
||||
ei_event_stylus_get_pressure(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_DISTANCE:
|
||||
{
|
||||
colorprint("stylus distance %.2f\n",
|
||||
ei_event_stylus_get_distance(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_ROTATION:
|
||||
{
|
||||
colorprint("stylus rotation %.2f\n",
|
||||
ei_event_stylus_get_rotation(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
{
|
||||
colorprint("stylus airbrush %.2f\n",
|
||||
ei_event_stylus_get_flow(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_TILT:
|
||||
{
|
||||
colorprint("stylus tilt | x - %.2f y - %.2f\n",
|
||||
ei_event_stylus_get_tilt_x(e),
|
||||
ei_event_stylus_get_tilt_y(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_STYLUS_MOTION:
|
||||
{
|
||||
colorprint("stylus motion | x - %.2f y - %.2f\n",
|
||||
ei_event_stylus_get_x(e),
|
||||
ei_event_stylus_get_y(e));
|
||||
}
|
||||
break;
|
||||
case EI_EVENT_SYNC:
|
||||
{
|
||||
colorprint("sync\n");
|
||||
|
|
@ -585,6 +668,78 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
if (have_stylus) {
|
||||
static int counter = 0;
|
||||
|
||||
switch (counter++ % 13) {
|
||||
case 0:
|
||||
colorprint("sending stylus prox in event\n");
|
||||
ei_device_stylus_proximity_in(stylus);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
colorprint("sending stylus down event\n");
|
||||
ei_device_stylus_down(stylus);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 3:
|
||||
colorprint("sending stylus motion event\n");
|
||||
ei_device_stylus_motion(stylus, 10, 10);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 4:
|
||||
colorprint("sending stylus tilt event\n");
|
||||
ei_device_stylus_tilt(stylus, 15, 15);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 5:
|
||||
colorprint("sending stylus pressure event\n");
|
||||
ei_device_stylus_pressure(stylus, 20);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 6:
|
||||
colorprint("sending stylus distance event\n");
|
||||
ei_device_stylus_distance(stylus, 25);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 7:
|
||||
colorprint("sending stylus rotation event\n");
|
||||
ei_device_stylus_rotation(stylus, 5);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 8:
|
||||
colorprint("sending stylus airbrush event\n");
|
||||
ei_device_stylus_airbrush_flow(stylus, 30);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 9:
|
||||
colorprint("sending stylus erase start event\n");
|
||||
ei_device_stylus_erase_start(stylus);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 10:
|
||||
colorprint("sending stylus erase stop event\n");
|
||||
ei_device_stylus_erase_stop(stylus);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 11:
|
||||
colorprint("sending stylus up event\n");
|
||||
ei_device_stylus_up(stylus);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
case 12:
|
||||
colorprint("sending stylus prox out event\n");
|
||||
ei_device_stylus_proximity_out(stylus);
|
||||
ei_device_frame(stylus, now);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -597,13 +752,16 @@ int main(int argc, char **argv)
|
|||
ei_device_close(abs);
|
||||
if (touch)
|
||||
ei_device_close(touch);
|
||||
if (stylus)
|
||||
ei_device_close(stylus);
|
||||
if (default_seat) {
|
||||
ei_seat_bind_capabilities(default_seat, EI_DEVICE_CAP_POINTER,
|
||||
EI_DEVICE_CAP_KEYBOARD,
|
||||
EI_DEVICE_CAP_POINTER_ABSOLUTE,
|
||||
EI_DEVICE_CAP_TOUCH,
|
||||
EI_DEVICE_CAP_BUTTON,
|
||||
EI_DEVICE_CAP_SCROLL, NULL);
|
||||
EI_DEVICE_CAP_SCROLL,
|
||||
EI_DEVICE_CAP_STYLUS, NULL);
|
||||
ei_seat_unref(default_seat);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libeis.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
|
@ -124,6 +125,7 @@ eis_demo_client_destroy(struct eis_demo_client *democlient)
|
|||
eis_device_unref(democlient->abs);
|
||||
eis_device_unref(democlient->kbd);
|
||||
eis_device_unref(democlient->touchscreen);
|
||||
eis_device_unref(democlient->stylus);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -315,6 +317,22 @@ add_device(struct eis_demo_server *server, struct eis_client *client,
|
|||
device = steal(&touchscreen);
|
||||
break;
|
||||
}
|
||||
case EIS_DEVICE_CAP_STYLUS:
|
||||
{
|
||||
struct eis_device *stylus = eis_seat_new_device(seat);
|
||||
eis_device_configure_name(stylus, "test stylus");
|
||||
eis_device_configure_capability(stylus, EIS_DEVICE_CAP_STYLUS);
|
||||
_unref_(eis_region) *region = eis_device_new_region(stylus);
|
||||
eis_region_set_mapping_id(region, "demo region");
|
||||
eis_region_set_size(region, 1920, 1080);
|
||||
eis_region_set_offset(region, 0, 0);
|
||||
eis_region_add(region);
|
||||
colorprint("Creating stylus device %s for %s\n", eis_device_get_name(stylus),
|
||||
eis_client_get_name(client));
|
||||
eis_device_add(stylus);
|
||||
device = steal(&stylus);
|
||||
break;
|
||||
}
|
||||
case EIS_DEVICE_CAP_BUTTON:
|
||||
case EIS_DEVICE_CAP_SCROLL:
|
||||
/* Mixed in with pointer/abs - good enough for a demo server */
|
||||
|
|
@ -371,6 +389,7 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server,
|
|||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_TOUCH);
|
||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_SCROLL);
|
||||
eis_seat_configure_capability(seat, EIS_DEVICE_CAP_STYLUS);
|
||||
eis_seat_add(seat);
|
||||
/* Note: we don't have a ref to this seat ourselves anywhere */
|
||||
break;
|
||||
|
|
@ -436,12 +455,23 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server,
|
|||
}
|
||||
}
|
||||
|
||||
if (eis_event_seat_has_capability(e, EIS_DEVICE_CAP_STYLUS)) {
|
||||
if (!democlient->stylus)
|
||||
democlient->stylus = add_device(server, client, seat, EIS_DEVICE_CAP_STYLUS);
|
||||
} else {
|
||||
if (democlient->stylus) {
|
||||
eis_device_remove(democlient->stylus);
|
||||
democlient->stylus = eis_device_unref(democlient->stylus);
|
||||
}
|
||||
}
|
||||
|
||||
/* Special "Feature", if all caps are unbound remove the seat.
|
||||
* This is a demo server after all, so let's demo this. */
|
||||
if (!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_POINTER) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_POINTER_ABSOLUTE) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_KEYBOARD) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_TOUCH))
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_TOUCH) &&
|
||||
!eis_event_seat_has_capability(e, EIS_DEVICE_CAP_STYLUS))
|
||||
eis_seat_remove(seat);
|
||||
|
||||
break;
|
||||
|
|
@ -479,6 +509,9 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server,
|
|||
if (democlient->touchscreen == device)
|
||||
democlient->touchscreen = NULL;
|
||||
|
||||
if (democlient->stylus == device)
|
||||
democlient->stylus = NULL;
|
||||
|
||||
eis_device_unref(device);
|
||||
}
|
||||
break;
|
||||
|
|
@ -551,6 +584,71 @@ eis_demo_server_printf_handle_event(struct eis_demo_server *server,
|
|||
colorprint("touch up %u\n", eis_event_touch_get_id(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_IN:
|
||||
case EIS_EVENT_STYLUS_PROXIMITY_OUT:
|
||||
{
|
||||
colorprint("stylus proximity %s\n",
|
||||
eis_event_get_type(e) == EIS_EVENT_STYLUS_PROXIMITY_OUT ? "out" : "in");
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_DOWN:
|
||||
case EIS_EVENT_STYLUS_UP:
|
||||
{
|
||||
colorprint("stylus %s\n",
|
||||
eis_event_get_type(e) == EIS_EVENT_STYLUS_DOWN ? "down" : "up");
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_BIND_TOOL_CAPABILITIES:
|
||||
{
|
||||
colorprint("stylus bind capability 0x%08x\n",
|
||||
eis_event_stylus_get_capability(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_ERASE_START:
|
||||
case EIS_EVENT_STYLUS_ERASE_STOP:
|
||||
{
|
||||
colorprint("stylus erase %s\n",
|
||||
eis_event_get_type(e) == EIS_EVENT_STYLUS_ERASE_STOP ? "stop" : "start");
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_PRESSURE:
|
||||
{
|
||||
colorprint("stylus pressure %.2f\n",
|
||||
eis_event_stylus_get_pressure(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_DISTANCE:
|
||||
{
|
||||
colorprint("stylus distance %.2f\n",
|
||||
eis_event_stylus_get_distance(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_ROTATION:
|
||||
{
|
||||
colorprint("stylus rotation %.2f\n",
|
||||
eis_event_stylus_get_rotation(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_AIRBRUSH_FLOW:
|
||||
{
|
||||
colorprint("stylus airbrush %.2f\n",
|
||||
eis_event_stylus_get_flow(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_TILT:
|
||||
{
|
||||
colorprint("stylus tilt | x - %.2f y - %.2f\n",
|
||||
eis_event_stylus_get_tilt_x(e),
|
||||
eis_event_stylus_get_tilt_y(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_STYLUS_MOTION:
|
||||
{
|
||||
colorprint("stylus motion | x - %.2f y - %.2f\n",
|
||||
eis_event_stylus_get_x(e),
|
||||
eis_event_stylus_get_y(e));
|
||||
}
|
||||
break;
|
||||
case EIS_EVENT_FRAME:
|
||||
{
|
||||
colorprint("frame timestamp: %" PRIu64 "\n",
|
||||
|
|
@ -744,6 +842,7 @@ int main(int argc, char **argv)
|
|||
struct eis_device *kbd = democlient->kbd;
|
||||
struct eis_device *abs = democlient->abs;
|
||||
struct eis_device *touchscreen = democlient->touchscreen;
|
||||
struct eis_device *stylus = democlient->stylus;
|
||||
if (ptr) {
|
||||
colorprint("sending motion event\n");
|
||||
eis_device_pointer_motion(ptr, -1, 1);
|
||||
|
|
@ -816,6 +915,102 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
if (stylus) {
|
||||
static int counter = 0;
|
||||
|
||||
switch (counter++ % 13) {
|
||||
case 0:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus prox in\n");
|
||||
eis_device_stylus_proximity_in(stylus);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus down\n");
|
||||
eis_device_stylus_down(stylus);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus motion\n");
|
||||
eis_device_stylus_motion(stylus, 10, 10);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus tilt\n");
|
||||
eis_device_stylus_tilt(stylus, 15, 15);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus pressure\n");
|
||||
eis_device_stylus_pressure(stylus, 5);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus distance\n");
|
||||
eis_device_stylus_distance(stylus, 20);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus rotation\n");
|
||||
eis_device_stylus_rotation(stylus, 25);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus airbrush\n");
|
||||
eis_device_stylus_airbrush_flow(stylus, 30);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus erase start\n");
|
||||
eis_device_stylus_erase_start(stylus);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus erase stop\n");
|
||||
eis_device_stylus_erase_stop(stylus);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus up\n");
|
||||
eis_device_stylus_up(stylus);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
if (stylus) { /* NULL if client was disconnected internally already */
|
||||
colorprint("sending stylus prox out\n");
|
||||
eis_device_stylus_proximity_out(stylus);
|
||||
eis_device_frame(stylus, now);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ struct eis_demo_client {
|
|||
struct eis_device *abs;
|
||||
struct eis_device *touchscreen;
|
||||
struct eis_touch *touch;
|
||||
struct eis_device *stylus;
|
||||
};
|
||||
|
||||
struct eis_demo_server {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue