mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-27 20:50:07 +01:00
tablet: Handle button-events
Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
e5f7ec9d53
commit
5561e4502d
5 changed files with 233 additions and 3 deletions
|
|
@ -31,6 +31,11 @@
|
|||
#define tablet_unset_status(tablet_,s_) ((tablet_)->status &= ~(s_))
|
||||
#define tablet_has_status(tablet_,s_) (!!((tablet_)->status & (s_)))
|
||||
|
||||
#define tablet_get_pressed_buttons(tablet_,field_) \
|
||||
((tablet_)->button_state.field_ & ~((tablet_)->prev_button_state.field_))
|
||||
#define tablet_get_released_buttons(tablet_,field_) \
|
||||
((tablet_)->prev_button_state.field_ & ~((tablet_)->button_state.field_))
|
||||
|
||||
static void
|
||||
tablet_process_absolute(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -110,6 +115,37 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_update_button(struct tablet_dispatch *tablet,
|
||||
uint32_t evcode,
|
||||
uint32_t enable)
|
||||
{
|
||||
uint32_t button, *flags;
|
||||
|
||||
/* XXX: This really depends on the expected buttons fitting in the mask */
|
||||
if (evcode >= BTN_MISC && evcode <= BTN_TASK) {
|
||||
flags = &tablet->button_state.pad_buttons;
|
||||
button = evcode - BTN_MISC;
|
||||
} else if (evcode >= BTN_TOUCH && evcode <= BTN_STYLUS2) {
|
||||
flags = &tablet->button_state.stylus_buttons;
|
||||
button = evcode - BTN_TOUCH;
|
||||
} else {
|
||||
log_info("Unhandled button %s (%#x)\n",
|
||||
libevdev_event_code_get_name(EV_KEY, evcode), evcode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
(*flags) |= 1 << button;
|
||||
tablet_set_status(tablet, TABLET_BUTTONS_PRESSED);
|
||||
} else {
|
||||
(*flags) &= ~(1 << button);
|
||||
tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
|
||||
}
|
||||
|
||||
assert(button < 32);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_process_key(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -128,7 +164,11 @@ tablet_process_key(struct tablet_dispatch *tablet,
|
|||
/* These codes have an equivalent libinput_tool value */
|
||||
tablet_update_tool(tablet, e->code, e->value);
|
||||
break;
|
||||
case BTN_TOUCH:
|
||||
case BTN_STYLUS:
|
||||
case BTN_STYLUS2:
|
||||
default:
|
||||
tablet_update_button(tablet, e->code, e->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -186,12 +226,68 @@ tablet_notify_tool(struct tablet_dispatch *tablet,
|
|||
tablet_notify_tool_update(base, time, new_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_notify_button_mask(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
uint32_t time,
|
||||
uint32_t buttons,
|
||||
uint32_t button_base,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct libinput_device *base = &device->base;
|
||||
int32_t num_button = 0;
|
||||
|
||||
while (buttons) {
|
||||
int enabled;
|
||||
|
||||
num_button++;
|
||||
enabled = (buttons & 1);
|
||||
buttons >>= 1;
|
||||
|
||||
if (!enabled)
|
||||
continue;
|
||||
|
||||
tablet_notify_button(base,
|
||||
time,
|
||||
num_button + button_base - 1,
|
||||
state);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_notify_buttons(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
uint32_t time,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
uint32_t pad_buttons, stylus_buttons;
|
||||
|
||||
if (state == LIBINPUT_BUTTON_STATE_PRESSED) {
|
||||
pad_buttons = tablet_get_pressed_buttons(tablet, pad_buttons);
|
||||
stylus_buttons =
|
||||
tablet_get_pressed_buttons(tablet, stylus_buttons);
|
||||
} else {
|
||||
pad_buttons = tablet_get_released_buttons(tablet, pad_buttons);
|
||||
stylus_buttons =
|
||||
tablet_get_released_buttons(tablet, stylus_buttons);
|
||||
}
|
||||
|
||||
tablet_notify_button_mask(tablet, device, time,
|
||||
pad_buttons, BTN_MISC, state);
|
||||
tablet_notify_button_mask(tablet, device, time,
|
||||
stylus_buttons, BTN_TOUCH, state);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_flush(struct tablet_dispatch *tablet,
|
||||
struct evdev_device *device,
|
||||
uint32_t time)
|
||||
{
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
|
||||
/* Release all stylus buttons */
|
||||
tablet->button_state.stylus_buttons = 0;
|
||||
tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
|
||||
|
||||
/* FIXME: This behavior is not ideal and this memset should be
|
||||
* removed */
|
||||
memset(&tablet->changed_axes, 0, sizeof(tablet->changed_axes));
|
||||
|
|
@ -210,10 +306,27 @@ tablet_flush(struct tablet_dispatch *tablet,
|
|||
}
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_BUTTONS_RELEASED)) {
|
||||
tablet_notify_buttons(tablet, device, time,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tablet_unset_status(tablet, TABLET_BUTTONS_RELEASED);
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_BUTTONS_PRESSED)) {
|
||||
tablet_notify_buttons(tablet, device, time,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tablet_unset_status(tablet, TABLET_BUTTONS_PRESSED);
|
||||
}
|
||||
|
||||
if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
|
||||
tablet_notify_proximity_out(&device->base, time);
|
||||
tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
|
||||
}
|
||||
|
||||
/* Update state */
|
||||
memcpy(&tablet->prev_button_state,
|
||||
&tablet->button_state,
|
||||
sizeof(tablet->button_state));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -31,7 +31,14 @@ enum tablet_status {
|
|||
TABLET_NONE = 0,
|
||||
TABLET_AXES_UPDATED = 1 << 0,
|
||||
TABLET_TOOL_UPDATED = 1 << 1,
|
||||
TABLET_TOOL_LEAVING_PROXIMITY = 1 << 2
|
||||
TABLET_TOOL_LEAVING_PROXIMITY = 1 << 2,
|
||||
TABLET_BUTTONS_PRESSED = 1 << 3,
|
||||
TABLET_BUTTONS_RELEASED = 1 << 4
|
||||
};
|
||||
|
||||
struct button_state {
|
||||
uint32_t pad_buttons; /* bitmask of evcode - BTN_MISC */
|
||||
uint32_t stylus_buttons; /* bitmask of evcode - BTN_TOUCH */
|
||||
};
|
||||
|
||||
struct tablet_dispatch {
|
||||
|
|
@ -41,6 +48,9 @@ struct tablet_dispatch {
|
|||
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
|
||||
double axes[LIBINPUT_TABLET_AXIS_CNT];
|
||||
|
||||
struct button_state button_state;
|
||||
struct button_state prev_button_state;
|
||||
|
||||
enum libinput_tool_type current_tool_type;
|
||||
uint32_t current_tool_serial;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -219,6 +219,11 @@ tablet_notify_proximity_out(struct libinput_device *device,
|
|||
uint32_t time);
|
||||
|
||||
void
|
||||
tablet_notify_button(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
int32_t button,
|
||||
enum libinput_button_state state);
|
||||
void
|
||||
touch_notify_frame(struct libinput_device *device,
|
||||
uint32_t time);
|
||||
#endif /* LIBINPUT_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ struct libinput_event_touch {
|
|||
|
||||
struct libinput_event_tablet {
|
||||
struct libinput_event base;
|
||||
uint32_t button;
|
||||
enum libinput_button_state state;
|
||||
uint32_t seat_button_count;
|
||||
uint32_t time;
|
||||
double *axes;
|
||||
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
|
||||
|
|
@ -202,6 +205,7 @@ libinput_event_get_pointer_event(struct libinput_event *event)
|
|||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -231,6 +235,7 @@ libinput_event_get_keyboard_event(struct libinput_event *event)
|
|||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -260,6 +265,7 @@ libinput_event_get_touch_event(struct libinput_event *event)
|
|||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -288,6 +294,7 @@ libinput_event_get_tablet_event(struct libinput_event *event)
|
|||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
return (struct libinput_event_tablet *) event;
|
||||
}
|
||||
|
||||
|
|
@ -316,6 +323,7 @@ libinput_event_get_device_notify_event(struct libinput_event *event)
|
|||
case LIBINPUT_EVENT_TABLET_AXIS:
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
|
||||
case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
|
||||
case LIBINPUT_EVENT_TABLET_BUTTON:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -532,6 +540,24 @@ libinput_event_tablet_get_time(struct libinput_event_tablet *event)
|
|||
return event->time;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_tablet_get_button(struct libinput_event_tablet *event)
|
||||
{
|
||||
return event->button;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_button_state
|
||||
libinput_event_tablet_get_button_state(struct libinput_event_tablet *event)
|
||||
{
|
||||
return event->state;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_tablet_get_seat_button_count(struct libinput_event_tablet *event)
|
||||
{
|
||||
return event->seat_button_count;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_tool_type
|
||||
libinput_tool_get_type(struct libinput_tool *tool)
|
||||
{
|
||||
|
|
@ -1223,6 +1249,35 @@ tablet_notify_proximity_out(struct libinput_device *device,
|
|||
&proximity_out_update_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
tablet_notify_button(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
int32_t button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct libinput_event_tablet *button_event;
|
||||
int32_t seat_button_count;
|
||||
|
||||
button_event = zalloc(sizeof *button_event);
|
||||
if (!button_event)
|
||||
return;
|
||||
|
||||
seat_button_count = update_seat_button_count(device->seat,
|
||||
button,
|
||||
state);
|
||||
|
||||
*button_event = (struct libinput_event_tablet) {
|
||||
.time = time,
|
||||
.button = button,
|
||||
.state = state,
|
||||
.seat_button_count = seat_button_count,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
LIBINPUT_EVENT_TABLET_BUTTON,
|
||||
&button_event->base);
|
||||
}
|
||||
|
||||
static void
|
||||
libinput_post_event(struct libinput *libinput,
|
||||
struct libinput_event *event)
|
||||
|
|
|
|||
|
|
@ -269,7 +269,8 @@ enum libinput_event_type {
|
|||
* was held down on the stylus are sent before the initial proximity out
|
||||
* event.
|
||||
*/
|
||||
LIBINPUT_EVENT_TABLET_PROXIMITY_OUT
|
||||
LIBINPUT_EVENT_TABLET_PROXIMITY_OUT,
|
||||
LIBINPUT_EVENT_TABLET_BUTTON
|
||||
};
|
||||
|
||||
struct libinput;
|
||||
|
|
@ -299,7 +300,8 @@ struct libinput_event_touch;
|
|||
*
|
||||
* Tablet event representing an axis update, button press, or tool update. Valid
|
||||
* event types for this event are @ref LIBINPUT_EVENT_TABLET_AXIS, @ref
|
||||
* LIBINPUT_EVENT_TABLET_TOOL_UPDATE and @ref LIBINPUT_EVENT_TABLET_TOOL_UPDATE.
|
||||
* LIBINPUT_EVENT_TABLET_TOOL_UPDATE, @ref LIBINPUT_EVENT_TABLET_TOOL_UPDATE and
|
||||
* @ref LIBINPUT_EVENT_TABLET_BUTTON.
|
||||
*/
|
||||
struct libinput_event_tablet;
|
||||
|
||||
|
|
@ -932,6 +934,51 @@ libinput_event_tablet_get_y_transformed(struct libinput_event_tablet *event,
|
|||
struct libinput_tool *
|
||||
libinput_event_tablet_get_tool(struct libinput_event_tablet *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Return the button that triggered this event.
|
||||
* For tablet events that are not of type LIBINPUT_EVENT_TABLET_BUTTON, this
|
||||
* function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* LIBINPUT_EVENT_TABLET_BUTTON.
|
||||
*
|
||||
* @param event The libinput tablet event
|
||||
* @return the button triggering this event
|
||||
*/
|
||||
uint32_t
|
||||
libinput_event_tablet_get_button(struct libinput_event_tablet *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Return the button state of the event.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* LIBINPUT_EVENT_TABLET_BUTTON.
|
||||
*
|
||||
* @param event The libinput tablet event
|
||||
* @return the button state triggering this event
|
||||
*/
|
||||
enum libinput_button_state
|
||||
libinput_event_tablet_get_button_state(struct libinput_event_tablet *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* For the button of a LIBINPUT_EVENT_TABLET_BUTTON event, return the total
|
||||
* number of buttons pressed on all devices on the associated seat after the
|
||||
* the event was triggered.
|
||||
*
|
||||
" @note It is an application bug to call this function for events other than
|
||||
* LIBINPUT_EVENT_TABLET_BUTTON. For other events, this function returns 0.
|
||||
*
|
||||
* @return the seat wide pressed button count for the key of this event
|
||||
*/
|
||||
uint32_t
|
||||
libinput_event_tablet_get_seat_button_count(struct libinput_event_tablet *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue