Skip to content

Commit 8869e4a

Browse files
authored
Merge pull request #150 from ardera/develop
improve input handling
2 parents 133600c + ca62469 commit 8869e4a

File tree

9 files changed

+1443
-105
lines changed

9 files changed

+1443
-105
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ set(FLUTTER_PI_SRC
110110
src/collection.c
111111
src/cursor.c
112112
src/keyboard.c
113+
src/user_input.c
113114
src/plugins/services.c
114115
)
115116

@@ -163,7 +164,7 @@ target_compile_options(flutter-pi PRIVATE
163164
${LIBINPUT_CFLAGS}
164165
${LIBUDEV_CFLAGS}
165166
${LIBXKBCOMMON_CFLAGS}
166-
$<$<CONFIG:DEBUG>:-O0 -ggdb>
167+
$<$<CONFIG:DEBUG>:-O0 -ggdb -DDEBUG>
167168
)
168169

169170
if (BUILD_TEXT_INPUT_PLUGIN)

include/collection.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <stdlib.h>
66
#include <errno.h>
77
#include <stdbool.h>
8+
#include <stdint.h>
9+
#include <assert.h>
810

911
#include <pthread.h>
1012

@@ -404,4 +406,25 @@ static inline void *memdup(const void *restrict src, const size_t n) {
404406
#define BMAP_CLEAR(p_bmap, i_bit) ((p_bmap)[(i_bit) / sizeof(*(p_bmap))] &= ~(1 << ((i_bit) & (sizeof(*(p_bmap)) - 1))))
405407
#define BMAP_ZERO(p_bmap, n_bits) (memset((p_bmap), 0, (((n_bits) - 1) / 8) + 1))
406408

409+
#define min(a, b) ((a) < (b) ? (a) : (b))
410+
#define max(a, b) ((a) > (b) ? (a) : (b))
411+
412+
/**
413+
* @brief Get the current time of the system monotonic clock.
414+
* @returns time in nanoseconds.
415+
*/
416+
static inline uint64_t get_monotonic_time(void) {
417+
struct timespec time;
418+
clock_gettime(CLOCK_MONOTONIC, &time);
419+
return time.tv_nsec + time.tv_sec*1000000000ull;
420+
}
421+
422+
#ifdef DEBUG
423+
#define DEBUG_ASSERT(__cond) assert(__cond)
424+
#define DEBUG_ASSERT_MSG(__cond, __msg) assert((__msg, (__cond))
425+
#else
426+
#define DEBUG_ASSERT(__cond) do {} while (false)
427+
#define DEBUG_ASSERT_MSG(__cond, __msg) do {} while (false)
428+
#endif
429+
407430
#endif

include/flutter-pi.h

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef _FLUTTERPI_H
22
#define _FLUTTERPI_H
33

4+
#define LOG_FLUTTERPI_ERROR(...) fprintf(stderr, "[flutter-pi] " __VA_ARGS__)
5+
46
#include <limits.h>
57
#include <linux/input.h>
68
#include <stdbool.h>
@@ -211,11 +213,17 @@ struct libudev {
211213
.skewY = 0, .scaleY = 1, .transY = 0, \
212214
.pers0 = -sin(((double) (deg))/180.0*M_PI), .pers1 = 0, .pers2 = cos(((double) (deg))/180.0*M_PI)})
213215

216+
/**
217+
* A flutter transformation that rotates any coords around the z-axis, counter-clockwise.
218+
*/
214219
#define FLUTTER_ROTZ_TRANSFORMATION(deg) ((FlutterTransformation) \
215220
{.scaleX = cos(((double) (deg))/180.0*M_PI), .skewX = -sin(((double) (deg))/180.0*M_PI), .transX = 0, \
216221
.skewY = sin(((double) (deg))/180.0*M_PI), .scaleY = cos(((double) (deg))/180.0*M_PI), .transY = 0, \
217222
.pers0 = 0, .pers1 = 0, .pers2 = 1})
218223

224+
/**
225+
* A transformation that is the result of multiplying a with b.
226+
*/
219227
#define FLUTTER_MULTIPLIED_TRANSFORMATIONS(a, b) ((FlutterTransformation) \
220228
{.scaleX = a.scaleX * b.scaleX + a.skewX * b.skewY + a.transX * b.pers0, \
221229
.skewX = a.scaleX * b.skewX + a.skewX * b.scaleY + a.transX * b.pers1, \
@@ -227,12 +235,24 @@ struct libudev {
227235
.pers1 = a.pers0 * b.skewX + a.pers1 * b.scaleY + a.pers2 * b.pers1, \
228236
.pers2 = a.pers0 * b.transX + a.pers1 * b.transY + a.pers2 * b.pers2})
229237

238+
/**
239+
* A transformation that is the result of adding a with b.
240+
*/
230241
#define FLUTTER_ADDED_TRANSFORMATIONS(a, b) ((FlutterTransformation) \
231242
{.scaleX = a.scaleX + b.scaleX, .skewX = a.skewX + b.skewX, .transX = a.transX + b.transX, \
232243
.skewY = a.skewY + b.skewY, .scaleY = a.scaleY + b.scaleY, .transY = a.transY + b.transY, \
233244
.pers0 = a.pers0 + b.pers0, .pers1 = a.pers1 + b.pers1, .pers2 = a.pers2 + b.pers2 \
234245
})
235246

247+
/**
248+
* A transformation that is the result of transponating a.
249+
*/
250+
#define FLUTTER_TRANSPONATED_TRANSFORMATION(a) ((FlutterTransformation) \
251+
{.scaleX = a.scaleX, .skewX = a.skewY, .transX = a.pers0, \
252+
.skewY = a.skewX, .scaleY = a.scaleY, .transY = a.pers1, \
253+
.pers0 = a.transX, .pers1 = a.transY, .pers2 = a.pers2, \
254+
})
255+
236256
static inline void apply_flutter_transformation(
237257
const FlutterTransformation t,
238258
double *px,
@@ -392,21 +412,8 @@ struct flutterpi {
392412
struct compositor *compositor;
393413

394414
/// IO
395-
struct {
396-
bool use_paths;
397-
bool disable_text_input;
398-
399-
glob_t input_devices_glob;
400-
# ifndef BUILD_WITHOUT_UDEV_SUPPORT
401-
struct libudev libudev;
402-
# endif
403-
struct libinput *libinput;
404-
sd_event_source *libinput_event_source;
405-
struct keyboard_config *keyboard_config;
406-
407-
int64_t next_unused_flutter_device_id;
408-
double cursor_x, cursor_y;
409-
} input;
415+
sd_event_source *user_input_event_source;
416+
struct user_input *user_input;
410417

411418
/// flutter stuff
412419
struct {
@@ -453,14 +460,6 @@ struct platform_message {
453460

454461
extern struct flutterpi flutterpi;
455462

456-
struct input_device_data {
457-
int64_t flutter_device_id_offset;
458-
struct keyboard_state *keyboard_state;
459-
double x, y;
460-
int64_t buttons;
461-
uint64_t timestamp;
462-
};
463-
464463
int flutterpi_fill_view_properties(
465464
bool has_orientation,
466465
enum device_orientation orientation,

include/keyboard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include <xkbcommon/xkbcommon.h>
55

6+
#define LOG_KEYBOARD_ERROR(...) fprintf(stderr, "[keyboard] " __VA_ARGS__)
7+
68
struct keyboard_config {
79
struct xkb_context *context;
810
struct xkb_keymap *default_keymap;

include/user_input.h

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#ifndef USER_INPUT_H_
2+
#define USER_INPUT_H_
3+
4+
#include <xkbcommon/xkbcommon.h>
5+
#include <flutter_embedder.h>
6+
7+
#define LOG_USER_INPUT_ERROR(...) fprintf(stderr, "[user input] " __VA_ARGS__)
8+
#define MAX_COLLECTED_FLUTTER_POINTER_EVENTS 64
9+
10+
#define FLUTTER_POINTER_EVENT(_phase, _timestamp, _x, _y, _device, _signal_kind, _scroll_delta_x, _scroll_delta_y, _device_kind, _buttons) \
11+
(FlutterPointerEvent) { \
12+
.struct_size = sizeof(FlutterPointerEvent), \
13+
.phase = (_phase), \
14+
.timestamp = (_timestamp), \
15+
.x = (_x), .y = (_y), \
16+
.device = (_device), \
17+
.signal_kind = (_signal_kind), \
18+
.scroll_delta_x = (_scroll_delta_x), \
19+
.scroll_delta_y = (_scroll_delta_y), \
20+
.device_kind = (_device_kind), \
21+
.buttons = (_buttons) \
22+
}
23+
24+
#define FLUTTER_POINTER_TOUCH_ADD_EVENT(_timestamp, _x, _y, _device_id) \
25+
FLUTTER_POINTER_EVENT(kAdd, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindTouch, 0)
26+
27+
#define FLUTTER_POINTER_TOUCH_REMOVE_EVENT(_timestamp, _x, _y, _device_id) \
28+
FLUTTER_POINTER_EVENT(kRemove, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindTouch, 0)
29+
30+
#define FLUTTER_POINTER_TOUCH_MOVE_EVENT(_timestamp, _x, _y, _device_id) \
31+
FLUTTER_POINTER_EVENT(kMove, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindTouch, 0)
32+
33+
#define FLUTTER_POINTER_TOUCH_DOWN_EVENT(_timestamp, _x, _y, _device_id) \
34+
FLUTTER_POINTER_EVENT(kDown, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindTouch, 0)
35+
36+
#define FLUTTER_POINTER_TOUCH_UP_EVENT(_timestamp, _x, _y, _device_id) \
37+
FLUTTER_POINTER_EVENT(kUp, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindTouch, 0)
38+
39+
#define FLUTTER_POINTER_MOUSE_BUTTON_EVENT(_phase, _timestamp, _x, _y, _device_id, _buttons) \
40+
FLUTTER_POINTER_EVENT(_phase, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindMouse, _buttons)
41+
42+
#define FLUTTER_POINTER_MOUSE_ADD_EVENT(_timestamp, _x, _y, _device_id, _buttons) \
43+
FLUTTER_POINTER_EVENT(kAdd, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindMouse, _buttons)
44+
45+
#define FLUTTER_POINTER_MOUSE_REMOVE_EVENT(_timestamp, _x, _y, _device_id, _buttons) \
46+
FLUTTER_POINTER_EVENT(kRemove, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindMouse, _buttons)
47+
48+
#define FLUTTER_POINTER_REMOVE_EVENT(_timestamp, _x, _y, _device, _buttons) \
49+
FLUTTER_POINTER_EVENT(kRemove, _timestamp, _x, _y, _device_id, kFlutterPointerSignalKindNone, 0.0, 0.0, kFlutterPointerDeviceKindMouse, _buttons)
50+
51+
#define FLUTTER_POINTER_MOUSE_MOVE_EVENT(_timestamp, _x, _y, _device_id, _buttons) \
52+
FLUTTER_POINTER_EVENT( \
53+
(_buttons) & kFlutterPointerButtonMousePrimary ? kMove : kHover, \
54+
_timestamp, \
55+
_x, _y, \
56+
_device_id, \
57+
kFlutterPointerSignalKindNone, \
58+
0.0, 0.0, \
59+
kFlutterPointerDeviceKindMouse, \
60+
_buttons\
61+
)
62+
63+
typedef void (*flutter_pointer_event_callback_t)(void *userdata, const FlutterPointerEvent *events, size_t n_events);
64+
65+
typedef void (*utf8_character_callback_t)(void *userdata, uint8_t *character);
66+
67+
typedef void (*xkb_keysym_callback_t)(void *userdata, xkb_keysym_t keysym);
68+
69+
typedef void (*gtk_keyevent_callback_t)(
70+
void *userdata,
71+
uint32_t unicode_scalar_values,
72+
uint32_t key_code,
73+
uint32_t scan_code,
74+
uint32_t modifiers,
75+
bool is_down
76+
);
77+
78+
typedef void (*set_cursor_enabled_callback_t)(void *userdata, bool enabled);
79+
80+
typedef void (*move_cursor_callback_t)(void *userdata, unsigned int x, unsigned int y);
81+
82+
struct user_input_interface {
83+
flutter_pointer_event_callback_t on_flutter_pointer_event;
84+
utf8_character_callback_t on_utf8_character;
85+
xkb_keysym_callback_t on_xkb_keysym;
86+
gtk_keyevent_callback_t on_gtk_keyevent;
87+
set_cursor_enabled_callback_t on_set_cursor_enabled;
88+
move_cursor_callback_t on_move_cursor;
89+
};
90+
91+
struct user_input;
92+
93+
/**
94+
* @brief Create a new user input instance. Will try to load the default keyboard config from /etc/default/keyboard
95+
* and create a udev-backed libinput instance.
96+
*/
97+
struct user_input *user_input_new(
98+
const struct user_input_interface *interface,
99+
void *userdata,
100+
const FlutterTransformation *display_to_view_transform,
101+
const FlutterTransformation *view_to_display_transform,
102+
unsigned int display_width,
103+
unsigned int display_height
104+
);
105+
106+
/**
107+
* @brief Destroy this user input instance and free all allocated memory. This will not remove any input devices
108+
* added to flutter and won't invoke any callbacks in the user input interface at all.
109+
*/
110+
void user_input_destroy(struct user_input *input);
111+
112+
/**
113+
* @brief Set a 3x3 matrix and display width / height so user_input can transform any device coordinates into
114+
* proper flutter view coordinates. (For example to account for a rotated display)
115+
* Will also transform absolute & relative mouse movements.
116+
*
117+
* @param display_to_view_transform will be copied internally.
118+
*/
119+
void user_input_set_transform(
120+
struct user_input *input,
121+
const FlutterTransformation *display_to_view_transform,
122+
const FlutterTransformation *view_to_display_transform,
123+
unsigned int display_width,
124+
unsigned int display_height
125+
);
126+
127+
/**
128+
* @brief Returns a filedescriptor used for input event notification. The returned
129+
* filedescriptor should be listened to with EPOLLIN | EPOLLRDHUP | EPOLLPRI or equivalent.
130+
* When the fd becomes ready, @ref user_input_on_fd_ready should be called not long after it
131+
* became ready. (libinput somehow relies on that)
132+
*/
133+
int user_input_get_fd(struct user_input *input);
134+
135+
/**
136+
* @brief Should be called when the fd returned by @ref user_input_get_fd becomes ready.
137+
* The user_input_interface callbacks will be called inside this function.
138+
*/
139+
int user_input_on_fd_ready(struct user_input *input);
140+
141+
#endif

0 commit comments

Comments
 (0)