Compare commits
8 Commits
input_even
...
input_even
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b26ad41da7 | ||
|
|
bc84a130a4 | ||
|
|
3c663e1c0f | ||
|
|
05ef36545c | ||
|
|
ac32280a43 | ||
|
|
93c49ae446 | ||
|
|
15d40b6d16 | ||
|
|
c520d9f0e7 |
@@ -14,6 +14,7 @@ src = [
|
|||||||
'src/file_handler.c',
|
'src/file_handler.c',
|
||||||
'src/fps_counter.c',
|
'src/fps_counter.c',
|
||||||
'src/frame_buffer.c',
|
'src/frame_buffer.c',
|
||||||
|
'src/input_events.c',
|
||||||
'src/input_manager.c',
|
'src/input_manager.c',
|
||||||
'src/keyboard_inject.c',
|
'src/keyboard_inject.c',
|
||||||
'src/mouse_inject.c',
|
'src/mouse_inject.c',
|
||||||
|
|||||||
76
app/src/input_events.c
Normal file
76
app/src/input_events.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include <input_events.h>
|
||||||
|
|
||||||
|
static inline uint16_t
|
||||||
|
sc_mods_state_from_sdl(uint16_t mods_state) {
|
||||||
|
return mods_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum sc_keycode
|
||||||
|
sc_keycode_from_sdl(SDL_Keycode keycode) {
|
||||||
|
return (enum sc_keycode) keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum sc_scancode
|
||||||
|
sc_scancode_from_sdl(SDL_Scancode scancode) {
|
||||||
|
return (enum sc_scancode) scancode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum sc_action
|
||||||
|
sc_action_from_sdl_keyboard_type(uint32_t type) {
|
||||||
|
assert(type == SDL_KEYDOWN || type == SDL_KEYUP);
|
||||||
|
if (type == SDL_KEYDOWN) {
|
||||||
|
return SC_ACTION_DOWN;
|
||||||
|
}
|
||||||
|
return SC_ACTION_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum sc_action
|
||||||
|
sc_action_from_sdl_mousebutton_type(uint32_t type) {
|
||||||
|
assert(type == SDL_MOUSEBUTTONDOWN || type == SDL_MOUSEBUTTONUP);
|
||||||
|
if (type == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
return SC_ACTION_DOWN;
|
||||||
|
}
|
||||||
|
return SC_ACTION_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum sc_mouse_button
|
||||||
|
sc_mouse_button_from_sdl(uint8_t button) {
|
||||||
|
if (button >= SDL_BUTTON_LEFT && button <= SDL_BUTTON_X2) {
|
||||||
|
// SC_MOUSE_BUTTON_* constants are initialized from SDL_BUTTON(index)
|
||||||
|
return SDL_BUTTON(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SC_MOUSE_BUTTON_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t
|
||||||
|
sc_mouse_buttons_state_from_sdl(uint32_t buttons_state) {
|
||||||
|
assert(buttons_state < 0x100); // fits in uint8_t
|
||||||
|
return buttons_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_key_event_from_sdl(struct sc_key_event *event,
|
||||||
|
const SDL_KeyboardEvent *sdl) {
|
||||||
|
event->action = sc_action_from_sdl_keyboard_type(sdl->type);
|
||||||
|
event->keycode = sc_keycode_from_sdl(sdl->keysym.sym);
|
||||||
|
event->scancode = sc_scancode_from_sdl(sdl->keysym.scancode);
|
||||||
|
event->repeat = sdl->repeat;
|
||||||
|
event->mods_state = sc_mods_state_from_sdl(sdl->keysym.mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_text_event_from_sdl(struct sc_text_event *event,
|
||||||
|
const SDL_TextInputEvent *sdl) {
|
||||||
|
event->text = sdl->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_mouse_click_event_from_sdl(struct sc_mouse_click_event *event,
|
||||||
|
const SDL_MouseButtonEvent *sdl,
|
||||||
|
const SDL_Window *window,
|
||||||
|
struct sc_size screen_size) {
|
||||||
|
event->action = sc_action_from_sdl_mousebutton_type(sdl->type);
|
||||||
|
event->button = sc_mouse_button_from_sdl(sdl->button);
|
||||||
|
event->position.screen_size = screen_size;
|
||||||
|
}
|
||||||
@@ -10,37 +10,9 @@
|
|||||||
|
|
||||||
#include "coords.h"
|
#include "coords.h"
|
||||||
|
|
||||||
/* The representation of input events in scrcpy is very close to the SDL API,
|
/* The values are purposely the same as the SDL constants, so that the
|
||||||
* for simplicity.
|
|
||||||
*
|
|
||||||
* This scrcpy input events API is designed to be consumed by input event
|
|
||||||
* processors (sc_key_processor and sc_mouse_processor, see app/src/trait/).
|
|
||||||
*
|
|
||||||
* One major semantic difference between SDL input events and scrcpy input
|
|
||||||
* events is their frame of reference (for mouse and touch events): SDL events
|
|
||||||
* coordinates are expressed in SDL window coordinates (the visible UI), while
|
|
||||||
* scrcpy events are expressed in device frame coordinates.
|
|
||||||
*
|
|
||||||
* In particular, the window may be visually scaled or rotated (with --rotation
|
|
||||||
* or MOD+Left/Right), but this does not impact scrcpy input events (contrary
|
|
||||||
* to SDL input events). This allows to abstract these display details from the
|
|
||||||
* input event processors (and to make them independent from the "screen").
|
|
||||||
*
|
|
||||||
* For many enums below, the values are purposely the same as the SDL
|
|
||||||
* constants (though not all SDL values are represented), so that the
|
|
||||||
* implementation to convert from the SDL version to the scrcpy version is
|
* implementation to convert from the SDL version to the scrcpy version is
|
||||||
* straightforward.
|
* straightforward */
|
||||||
*
|
|
||||||
* In practice, there are 3 levels of input events:
|
|
||||||
* 1. SDL input events (as received from SDL)
|
|
||||||
* 2. scrcpy input events (this API)
|
|
||||||
* 3. the key/mouse processors input events (Android API or HID events)
|
|
||||||
*
|
|
||||||
* An input event is first received (1), then (if accepted) converted to an
|
|
||||||
* scrcpy input event (2), then submitted to the relevant key/mouse processor,
|
|
||||||
* which (if accepted) is converted to an Android event (to be sent to the
|
|
||||||
* server) or to an HID event (to be sent over USB/AOA directly).
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum sc_mod {
|
enum sc_mod {
|
||||||
SC_MOD_LSHIFT = KMOD_LSHIFT,
|
SC_MOD_LSHIFT = KMOD_LSHIFT,
|
||||||
@@ -58,8 +30,8 @@ enum sc_mod {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum sc_action {
|
enum sc_action {
|
||||||
SC_ACTION_DOWN, // key or button pressed
|
SC_ACTION_DOWN = 1, // key or button pressed
|
||||||
SC_ACTION_UP, // key or button released
|
SC_ACTION_UP = 2, // key or button released
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sc_keycode {
|
enum sc_keycode {
|
||||||
@@ -365,9 +337,37 @@ struct sc_mouse_scroll_event {
|
|||||||
|
|
||||||
struct sc_mouse_motion_event {
|
struct sc_mouse_motion_event {
|
||||||
struct sc_position position;
|
struct sc_position position;
|
||||||
|
int32_t xrel;
|
||||||
|
int32_t yrel;
|
||||||
uint8_t buttons_state; // bitwise-OR of sc_mouse_button values
|
uint8_t buttons_state; // bitwise-OR of sc_mouse_button values
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//enum sc_mouse_event_type {
|
||||||
|
// SC_MOUSE_EVENT_TYPE_CLICK,
|
||||||
|
// SC_MOUSE_EVENT_TYPE_MOVE,
|
||||||
|
// SC_MOUSE_EVENT_TYPE_SCROLL,
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//struct sc_mouse_event {
|
||||||
|
// enum sc_mouse_event_type type;
|
||||||
|
// struct sc_position position;
|
||||||
|
// uint8_t buttons_state; // bitwise-OR of sc_mouse_button values
|
||||||
|
// union {
|
||||||
|
// struct {
|
||||||
|
// enum sc_action action;
|
||||||
|
// enum sc_mouse_button button;
|
||||||
|
// } click;
|
||||||
|
// struct {
|
||||||
|
// int32_t xrel;
|
||||||
|
// int32_t yrel;
|
||||||
|
// } move;
|
||||||
|
// struct {
|
||||||
|
// int32_t h;
|
||||||
|
// int32_t v;
|
||||||
|
// } scroll;
|
||||||
|
// };
|
||||||
|
//};
|
||||||
|
|
||||||
struct sc_touch_event {
|
struct sc_touch_event {
|
||||||
struct sc_position position;
|
struct sc_position position;
|
||||||
enum sc_touch_action action;
|
enum sc_touch_action action;
|
||||||
@@ -375,4 +375,30 @@ struct sc_touch_event {
|
|||||||
float pressure;
|
float pressure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//void
|
||||||
|
//sc_key_event_from_sdl(struct sc_key_event *event, const SDL_KeyboardEvent *sdl);
|
||||||
|
//
|
||||||
|
//void
|
||||||
|
//sc_text_event_from_sdl(struct sc_text_event *event,
|
||||||
|
// const SDL_TextInputEvent *sdl);
|
||||||
|
//
|
||||||
|
//void
|
||||||
|
//sc_mouse_click_event_from_sdl(struct sc_mouse_click_event *event,
|
||||||
|
// const SDL_MouseButtonEvent *sdl,
|
||||||
|
// const SDL_Window *window,
|
||||||
|
// struct sc_size screen_size);
|
||||||
|
//
|
||||||
|
//void
|
||||||
|
//sc_mouse_wheel_event_from_sdl(struct sc_mouse_wheel_event *event,
|
||||||
|
// const SDL_MouseWheelEvent *sdl);
|
||||||
|
//
|
||||||
|
//void
|
||||||
|
//sc_mouse_motion_event_from_sdl(struct sc_mouse_motion_event *event,
|
||||||
|
// const SDL_MouseMotionEvent *sdl);
|
||||||
|
//
|
||||||
|
//void
|
||||||
|
//sc_touch_event_from_sdl(struct sc_touch_event *event,
|
||||||
|
// const SDL_TouchFingerEvent *sdl);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -63,21 +63,36 @@ sc_mouse_button_from_sdl(uint8_t button) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t
|
static inline uint8_t
|
||||||
sc_mouse_buttons_state_from_sdl(uint32_t buttons_state,
|
sc_mouse_buttons_state_from_sdl(uint32_t buttons_state) {
|
||||||
bool forward_all_clicks) {
|
|
||||||
assert(buttons_state < 0x100); // fits in uint8_t
|
assert(buttons_state < 0x100); // fits in uint8_t
|
||||||
|
return buttons_state;
|
||||||
uint8_t mask = SC_MOUSE_BUTTON_LEFT;
|
|
||||||
if (forward_all_clicks) {
|
|
||||||
mask |= SC_MOUSE_BUTTON_RIGHT
|
|
||||||
| SC_MOUSE_BUTTON_MIDDLE
|
|
||||||
| SC_MOUSE_BUTTON_X1
|
|
||||||
| SC_MOUSE_BUTTON_X2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buttons_state & mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void
|
||||||
|
//sc_key_event_from_sdl(struct sc_key_event *event,
|
||||||
|
// const SDL_KeyboardEvent *sdl) {
|
||||||
|
// event->action = sc_action_from_sdl_keyboard_type(sdl->type);
|
||||||
|
// event->keycode = sc_keycode_from_sdl(sdl->keysym.sym);
|
||||||
|
// event->scancode = sc_scancode_from_sdl(sdl->keysym.scancode);
|
||||||
|
// event->repeat = sdl->repeat;
|
||||||
|
// event->mods_state = sc_mods_state_from_sdl(sdl->keysym.mod);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void
|
||||||
|
//sc_text_event_from_sdl(struct sc_text_event *event,
|
||||||
|
// const SDL_TextInputEvent *sdl) {
|
||||||
|
// event->text = sdl->text;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void
|
||||||
|
//sc_mouse_click_event_from_sdl(struct sc_mouse_click_event *event,
|
||||||
|
// const SDL_MouseButtonEvent *sdl,
|
||||||
|
// struct sc_size screen_size) {
|
||||||
|
// event->action = sc_action_from_sdl_mousebutton_type(sdl->type);
|
||||||
|
// event->button = sc_mouse_button_from_sdl(sdl->button);
|
||||||
|
// event->position.screen_size = screen_size;
|
||||||
|
//}
|
||||||
|
|
||||||
#define SC_SDL_SHORTCUT_MODS_MASK (KMOD_CTRL | KMOD_ALT | KMOD_GUI)
|
#define SC_SDL_SHORTCUT_MODS_MASK (KMOD_CTRL | KMOD_ALT | KMOD_GUI)
|
||||||
|
|
||||||
static inline uint16_t
|
static inline uint16_t
|
||||||
@@ -159,72 +174,85 @@ input_manager_init(struct input_manager *im, struct controller *controller,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
send_keycode(struct controller *controller, enum android_keycode keycode,
|
send_keycode(struct controller *controller, enum android_keycode keycode,
|
||||||
enum sc_action action, const char *name) {
|
int actions, const char *name) {
|
||||||
// send DOWN event
|
// send DOWN event
|
||||||
struct control_msg msg;
|
struct control_msg msg;
|
||||||
msg.type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
msg.type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
||||||
msg.inject_keycode.action = action == SC_ACTION_DOWN
|
|
||||||
? AKEY_EVENT_ACTION_DOWN
|
|
||||||
: AKEY_EVENT_ACTION_UP;
|
|
||||||
msg.inject_keycode.keycode = keycode;
|
msg.inject_keycode.keycode = keycode;
|
||||||
msg.inject_keycode.metastate = 0;
|
msg.inject_keycode.metastate = 0;
|
||||||
msg.inject_keycode.repeat = 0;
|
msg.inject_keycode.repeat = 0;
|
||||||
|
|
||||||
if (!controller_push_msg(controller, &msg)) {
|
if (actions & SC_ACTION_DOWN) {
|
||||||
LOGW("Could not request 'inject %s'", name);
|
msg.inject_keycode.action = AKEY_EVENT_ACTION_DOWN;
|
||||||
return;
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
|
LOGW("Could not request 'inject %s (DOWN)'", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actions & SC_ACTION_UP) {
|
||||||
|
msg.inject_keycode.action = AKEY_EVENT_ACTION_UP;
|
||||||
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
|
LOGW("Could not request 'inject %s (UP)'", name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_home(struct controller *controller, enum sc_action action) {
|
action_home(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_HOME, action, "HOME");
|
send_keycode(controller, AKEYCODE_HOME, actions, "HOME");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_back(struct controller *controller, enum sc_action action) {
|
action_back(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_BACK, action, "BACK");
|
send_keycode(controller, AKEYCODE_BACK, actions, "BACK");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_app_switch(struct controller *controller, enum sc_action action) {
|
action_app_switch(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_APP_SWITCH, action, "APP_SWITCH");
|
send_keycode(controller, AKEYCODE_APP_SWITCH, actions, "APP_SWITCH");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_power(struct controller *controller, enum sc_action action) {
|
action_power(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_POWER, action, "POWER");
|
send_keycode(controller, AKEYCODE_POWER, actions, "POWER");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_volume_up(struct controller *controller, enum sc_action action) {
|
action_volume_up(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_VOLUME_UP, action, "VOLUME_UP");
|
send_keycode(controller, AKEYCODE_VOLUME_UP, actions, "VOLUME_UP");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_volume_down(struct controller *controller, enum sc_action action) {
|
action_volume_down(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_VOLUME_DOWN, action, "VOLUME_DOWN");
|
send_keycode(controller, AKEYCODE_VOLUME_DOWN, actions, "VOLUME_DOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
action_menu(struct controller *controller, enum sc_action action) {
|
action_menu(struct controller *controller, int actions) {
|
||||||
send_keycode(controller, AKEYCODE_MENU, action, "MENU");
|
send_keycode(controller, AKEYCODE_MENU, actions, "MENU");
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn the screen on if it was off, press BACK otherwise
|
// turn the screen on if it was off, press BACK otherwise
|
||||||
// If the screen is off, it is turned on only on ACTION_DOWN
|
// If the screen is off, it is turned on only on ACTION_DOWN
|
||||||
static void
|
static void
|
||||||
press_back_or_turn_screen_on(struct controller *controller,
|
press_back_or_turn_screen_on(struct controller *controller, int actions) {
|
||||||
enum sc_action action) {
|
|
||||||
struct control_msg msg;
|
struct control_msg msg;
|
||||||
msg.type = CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON;
|
msg.type = CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON;
|
||||||
msg.back_or_screen_on.action = action == SC_ACTION_DOWN
|
|
||||||
? AKEY_EVENT_ACTION_DOWN
|
|
||||||
: AKEY_EVENT_ACTION_UP;
|
|
||||||
|
|
||||||
if (!controller_push_msg(controller, &msg)) {
|
if (actions & SC_ACTION_DOWN) {
|
||||||
LOGW("Could not request 'press back or turn screen on'");
|
msg.back_or_screen_on.action = AKEY_EVENT_ACTION_DOWN;
|
||||||
return;
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
|
LOGW("Could not request 'press back or turn screen on'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actions & SC_ACTION_UP) {
|
||||||
|
msg.back_or_screen_on.action = AKEY_EVENT_ACTION_UP;
|
||||||
|
if (!controller_push_msg(controller, &msg)) {
|
||||||
|
LOGW("Could not request 'press back or turn screen on'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,7 +656,6 @@ input_manager_process_key(struct input_manager *im,
|
|||||||
static void
|
static void
|
||||||
input_manager_process_mouse_motion(struct input_manager *im,
|
input_manager_process_mouse_motion(struct input_manager *im,
|
||||||
const SDL_MouseMotionEvent *event) {
|
const SDL_MouseMotionEvent *event) {
|
||||||
|
|
||||||
uint32_t mask = SDL_BUTTON_LMASK;
|
uint32_t mask = SDL_BUTTON_LMASK;
|
||||||
if (im->forward_all_clicks) {
|
if (im->forward_all_clicks) {
|
||||||
mask |= SDL_BUTTON_MMASK | SDL_BUTTON_RMASK;
|
mask |= SDL_BUTTON_MMASK | SDL_BUTTON_RMASK;
|
||||||
@@ -648,12 +675,12 @@ input_manager_process_mouse_motion(struct input_manager *im,
|
|||||||
.point = screen_convert_window_to_frame_coords(im->screen,
|
.point = screen_convert_window_to_frame_coords(im->screen,
|
||||||
event->x, event->y),
|
event->x, event->y),
|
||||||
},
|
},
|
||||||
.buttons_state =
|
.xrel = event->xrel,
|
||||||
sc_mouse_buttons_state_from_sdl(event->state,
|
.yrel = event->yrel,
|
||||||
im->forward_all_clicks),
|
.buttons_state = sc_mouse_buttons_state_from_sdl(event->state),
|
||||||
};
|
};
|
||||||
|
|
||||||
im->mp->ops->process_mouse_motion(im->mp, &evt);
|
im->mp->ops->process_mouse_motion(im->mp, event);
|
||||||
|
|
||||||
if (im->vfinger_down) {
|
if (im->vfinger_down) {
|
||||||
struct sc_point mouse =
|
struct sc_point mouse =
|
||||||
@@ -685,7 +712,7 @@ input_manager_process_touch(struct input_manager *im,
|
|||||||
.pressure = event->pressure,
|
.pressure = event->pressure,
|
||||||
};
|
};
|
||||||
|
|
||||||
im->mp->ops->process_touch(im->mp, &evt);
|
im->mp->ops->process_touch(im->mp, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -755,12 +782,10 @@ input_manager_process_mouse_button(struct input_manager *im,
|
|||||||
},
|
},
|
||||||
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
.action = sc_action_from_sdl_mousebutton_type(event->type),
|
||||||
.button = sc_mouse_button_from_sdl(event->button),
|
.button = sc_mouse_button_from_sdl(event->button),
|
||||||
.buttons_state =
|
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state),
|
||||||
sc_mouse_buttons_state_from_sdl(sdl_buttons_state,
|
|
||||||
im->forward_all_clicks),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
im->mp->ops->process_mouse_click(im->mp, &evt);
|
im->mp->ops->process_mouse_button(im->mp, event);
|
||||||
|
|
||||||
// Pinch-to-zoom simulation.
|
// Pinch-to-zoom simulation.
|
||||||
//
|
//
|
||||||
@@ -806,7 +831,7 @@ input_manager_process_mouse_wheel(struct input_manager *im,
|
|||||||
.vscroll = event->y,
|
.vscroll = event->y,
|
||||||
};
|
};
|
||||||
|
|
||||||
im->mp->ops->process_mouse_scroll(im->mp, &evt);
|
im->mp->ops->process_mouse_wheel(im->mp, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -12,13 +12,20 @@
|
|||||||
/** Downcast key processor to sc_keyboard_inject */
|
/** Downcast key processor to sc_keyboard_inject */
|
||||||
#define DOWNCAST(KP) container_of(KP, struct sc_keyboard_inject, key_processor)
|
#define DOWNCAST(KP) container_of(KP, struct sc_keyboard_inject, key_processor)
|
||||||
|
|
||||||
static enum android_keyevent_action
|
static bool
|
||||||
convert_keycode_action(enum sc_action action) {
|
convert_keycode_action(enum sc_action from, enum android_keyevent_action *to) {
|
||||||
if (action == SC_ACTION_DOWN) {
|
static const struct sc_intmap_entry actions[] = {
|
||||||
return AKEY_EVENT_ACTION_DOWN;
|
{SC_ACTION_DOWN, AKEY_EVENT_ACTION_DOWN},
|
||||||
|
{SC_ACTION_UP, AKEY_EVENT_ACTION_UP},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from);
|
||||||
|
if (entry) {
|
||||||
|
*to = entry->value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
assert(action == SC_ACTION_UP);
|
|
||||||
return AKEY_EVENT_ACTION_UP;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -250,12 +257,15 @@ convert_input_key(const struct sc_key_event *event, struct control_msg *msg,
|
|||||||
enum sc_key_inject_mode key_inject_mode, uint32_t repeat) {
|
enum sc_key_inject_mode key_inject_mode, uint32_t repeat) {
|
||||||
msg->type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
msg->type = CONTROL_MSG_TYPE_INJECT_KEYCODE;
|
||||||
|
|
||||||
|
if (!convert_keycode_action(event->action, &msg->inject_keycode.action)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!convert_keycode(event->keycode, &msg->inject_keycode.keycode,
|
if (!convert_keycode(event->keycode, &msg->inject_keycode.keycode,
|
||||||
event->mods_state, key_inject_mode)) {
|
event->mods_state, key_inject_mode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->inject_keycode.action = convert_keycode_action(event->action);
|
|
||||||
msg->inject_keycode.repeat = repeat;
|
msg->inject_keycode.repeat = repeat;
|
||||||
msg->inject_keycode.metastate = convert_meta_state(event->mods_state);
|
msg->inject_keycode.metastate = convert_meta_state(event->mods_state);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "mouse_inject.h"
|
#include "mouse_inject.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
|
|
||||||
#include "android/input.h"
|
#include "android/input.h"
|
||||||
#include "control_msg.h"
|
#include "control_msg.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "input_events.h"
|
|
||||||
#include "util/intmap.h"
|
#include "util/intmap.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
@@ -15,138 +15,209 @@
|
|||||||
static enum android_motionevent_buttons
|
static enum android_motionevent_buttons
|
||||||
convert_mouse_buttons(uint32_t state) {
|
convert_mouse_buttons(uint32_t state) {
|
||||||
enum android_motionevent_buttons buttons = 0;
|
enum android_motionevent_buttons buttons = 0;
|
||||||
if (state & SC_MOUSE_BUTTON_LEFT) {
|
if (state & SDL_BUTTON_LMASK) {
|
||||||
buttons |= AMOTION_EVENT_BUTTON_PRIMARY;
|
buttons |= AMOTION_EVENT_BUTTON_PRIMARY;
|
||||||
}
|
}
|
||||||
if (state & SC_MOUSE_BUTTON_RIGHT) {
|
if (state & SDL_BUTTON_RMASK) {
|
||||||
buttons |= AMOTION_EVENT_BUTTON_SECONDARY;
|
buttons |= AMOTION_EVENT_BUTTON_SECONDARY;
|
||||||
}
|
}
|
||||||
if (state & SC_MOUSE_BUTTON_MIDDLE) {
|
if (state & SDL_BUTTON_MMASK) {
|
||||||
buttons |= AMOTION_EVENT_BUTTON_TERTIARY;
|
buttons |= AMOTION_EVENT_BUTTON_TERTIARY;
|
||||||
}
|
}
|
||||||
if (state & SC_MOUSE_BUTTON_X1) {
|
if (state & SDL_BUTTON_X1MASK) {
|
||||||
buttons |= AMOTION_EVENT_BUTTON_BACK;
|
buttons |= AMOTION_EVENT_BUTTON_BACK;
|
||||||
}
|
}
|
||||||
if (state & SC_MOUSE_BUTTON_X2) {
|
if (state & SDL_BUTTON_X2MASK) {
|
||||||
buttons |= AMOTION_EVENT_BUTTON_FORWARD;
|
buttons |= AMOTION_EVENT_BUTTON_FORWARD;
|
||||||
}
|
}
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum android_motionevent_action
|
static bool
|
||||||
convert_mouse_action(enum sc_action action) {
|
convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) {
|
||||||
if (action == SC_ACTION_DOWN) {
|
static const struct sc_intmap_entry actions[] = {
|
||||||
return AMOTION_EVENT_ACTION_DOWN;
|
{SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN},
|
||||||
|
{SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from);
|
||||||
|
if (entry) {
|
||||||
|
*to = entry->value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
assert(action == SC_ACTION_UP);
|
|
||||||
return AMOTION_EVENT_ACTION_UP;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum android_motionevent_action
|
static bool
|
||||||
convert_touch_action(enum sc_touch_action action) {
|
convert_touch_action(SDL_EventType from, enum android_motionevent_action *to) {
|
||||||
switch (action) {
|
static const struct sc_intmap_entry actions[] = {
|
||||||
case SC_TOUCH_ACTION_MOVE:
|
{SDL_FINGERMOTION, AMOTION_EVENT_ACTION_MOVE},
|
||||||
return AMOTION_EVENT_ACTION_MOVE;
|
{SDL_FINGERDOWN, AMOTION_EVENT_ACTION_DOWN},
|
||||||
case SC_TOUCH_ACTION_DOWN:
|
{SDL_FINGERUP, AMOTION_EVENT_ACTION_UP},
|
||||||
return AMOTION_EVENT_ACTION_DOWN;
|
};
|
||||||
default:
|
|
||||||
assert(action == SC_TOUCH_ACTION_UP);
|
const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from);
|
||||||
return AMOTION_EVENT_ACTION_UP;
|
if (entry) {
|
||||||
|
*to = entry->value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
convert_mouse_motion(const SDL_MouseMotionEvent *from, struct screen *screen,
|
||||||
|
struct control_msg *to) {
|
||||||
|
to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
|
||||||
|
to->inject_touch_event.action = AMOTION_EVENT_ACTION_MOVE;
|
||||||
|
to->inject_touch_event.pointer_id = POINTER_ID_MOUSE;
|
||||||
|
to->inject_touch_event.position.screen_size = screen->frame_size;
|
||||||
|
to->inject_touch_event.position.point =
|
||||||
|
screen_convert_window_to_frame_coords(screen, from->x, from->y);
|
||||||
|
to->inject_touch_event.pressure = 1.f;
|
||||||
|
to->inject_touch_event.buttons = convert_mouse_buttons(from->state);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
convert_touch(const SDL_TouchFingerEvent *from, struct screen *screen,
|
||||||
|
struct control_msg *to) {
|
||||||
|
to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
|
||||||
|
|
||||||
|
if (!convert_touch_action(from->type, &to->inject_touch_event.action)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
to->inject_touch_event.pointer_id = from->fingerId;
|
||||||
|
to->inject_touch_event.position.screen_size = screen->frame_size;
|
||||||
|
|
||||||
|
int dw;
|
||||||
|
int dh;
|
||||||
|
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
|
||||||
|
|
||||||
|
// SDL touch event coordinates are normalized in the range [0; 1]
|
||||||
|
int32_t x = from->x * dw;
|
||||||
|
int32_t y = from->y * dh;
|
||||||
|
to->inject_touch_event.position.point =
|
||||||
|
screen_convert_drawable_to_frame_coords(screen, x, y);
|
||||||
|
|
||||||
|
to->inject_touch_event.pressure = from->pressure;
|
||||||
|
to->inject_touch_event.buttons = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
convert_mouse_button(const SDL_MouseButtonEvent *from, struct screen *screen,
|
||||||
|
struct control_msg *to) {
|
||||||
|
to->type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT;
|
||||||
|
|
||||||
|
if (!convert_mouse_action(from->type, &to->inject_touch_event.action)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
to->inject_touch_event.pointer_id = POINTER_ID_MOUSE;
|
||||||
|
to->inject_touch_event.position.screen_size = screen->frame_size;
|
||||||
|
to->inject_touch_event.position.point =
|
||||||
|
screen_convert_window_to_frame_coords(screen, from->x, from->y);
|
||||||
|
to->inject_touch_event.pressure =
|
||||||
|
from->type == SDL_MOUSEBUTTONDOWN ? 1.f : 0.f;
|
||||||
|
to->inject_touch_event.buttons =
|
||||||
|
convert_mouse_buttons(SDL_BUTTON(from->button));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
convert_mouse_wheel(const SDL_MouseWheelEvent *from, struct screen *screen,
|
||||||
|
struct control_msg *to) {
|
||||||
|
|
||||||
|
// mouse_x and mouse_y are expressed in pixels relative to the window
|
||||||
|
int mouse_x;
|
||||||
|
int mouse_y;
|
||||||
|
SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||||
|
|
||||||
|
struct sc_position position = {
|
||||||
|
.screen_size = screen->frame_size,
|
||||||
|
.point = screen_convert_window_to_frame_coords(screen,
|
||||||
|
mouse_x, mouse_y),
|
||||||
|
};
|
||||||
|
|
||||||
|
to->type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT;
|
||||||
|
|
||||||
|
to->inject_scroll_event.position = position;
|
||||||
|
to->inject_scroll_event.hscroll = from->x;
|
||||||
|
to->inject_scroll_event.vscroll = from->y;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
|
sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp,
|
||||||
const struct sc_mouse_motion_event *event) {
|
const SDL_MouseMotionEvent *event) {
|
||||||
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
||||||
|
|
||||||
struct control_msg msg = {
|
struct control_msg msg;
|
||||||
.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,
|
if (!convert_mouse_motion(event, mi->screen, &msg)) {
|
||||||
.inject_touch_event = {
|
return;
|
||||||
.action = AMOTION_EVENT_ACTION_MOVE,
|
}
|
||||||
.pointer_id = POINTER_ID_MOUSE,
|
|
||||||
.position = event->position,
|
|
||||||
.pressure = 1.f,
|
|
||||||
.buttons = convert_mouse_buttons(event->buttons_state),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!controller_push_msg(mi->controller, &msg)) {
|
if (!controller_push_msg(mi->controller, &msg)) {
|
||||||
LOGW("Could not request 'inject mouse motion event'");
|
LOGW("Could not request 'inject mouse motion event'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
sc_mouse_processor_process_mouse_click(struct sc_mouse_processor *mp,
|
|
||||||
const struct sc_mouse_click_event *event) {
|
|
||||||
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
|
||||||
|
|
||||||
struct control_msg msg = {
|
|
||||||
.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,
|
|
||||||
.inject_touch_event = {
|
|
||||||
.action = convert_mouse_action(event->action),
|
|
||||||
.pointer_id = POINTER_ID_MOUSE,
|
|
||||||
.position = event->position,
|
|
||||||
.pressure = event->action == SC_ACTION_DOWN ? 1.f : 0.f,
|
|
||||||
.buttons = convert_mouse_buttons(event->buttons_state),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!controller_push_msg(mi->controller, &msg)) {
|
|
||||||
LOGW("Could not request 'inject mouse click event'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
|
|
||||||
const struct sc_mouse_scroll_event *event) {
|
|
||||||
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
|
||||||
|
|
||||||
struct control_msg msg = {
|
|
||||||
.type = CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
|
|
||||||
.inject_scroll_event = {
|
|
||||||
.position = event->position,
|
|
||||||
.hscroll = event->hscroll,
|
|
||||||
.vscroll = event->vscroll,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!controller_push_msg(mi->controller, &msg)) {
|
|
||||||
LOGW("Could not request 'inject mouse scroll event'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_mouse_processor_process_touch(struct sc_mouse_processor *mp,
|
sc_mouse_processor_process_touch(struct sc_mouse_processor *mp,
|
||||||
const struct sc_touch_event *event) {
|
const SDL_TouchFingerEvent *event) {
|
||||||
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
||||||
|
|
||||||
struct control_msg msg = {
|
struct control_msg msg;
|
||||||
.type = CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT,
|
if (convert_touch(event, mi->screen, &msg)) {
|
||||||
.inject_touch_event = {
|
if (!controller_push_msg(mi->controller, &msg)) {
|
||||||
.action = convert_touch_action(event->action),
|
LOGW("Could not request 'inject touch event'");
|
||||||
.pointer_id = event->pointer_id,
|
}
|
||||||
.position = event->position,
|
}
|
||||||
.pressure = event->pressure,
|
}
|
||||||
.buttons = 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!controller_push_msg(mi->controller, &msg)) {
|
static void
|
||||||
LOGW("Could not request 'inject touch event'");
|
sc_mouse_processor_process_mouse_button(struct sc_mouse_processor *mp,
|
||||||
|
const SDL_MouseButtonEvent *event) {
|
||||||
|
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
||||||
|
|
||||||
|
struct control_msg msg;
|
||||||
|
if (convert_mouse_button(event, mi->screen, &msg)) {
|
||||||
|
if (!controller_push_msg(mi->controller, &msg)) {
|
||||||
|
LOGW("Could not request 'inject mouse button event'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_mouse_processor_process_mouse_wheel(struct sc_mouse_processor *mp,
|
||||||
|
const SDL_MouseWheelEvent *event) {
|
||||||
|
struct sc_mouse_inject *mi = DOWNCAST(mp);
|
||||||
|
|
||||||
|
struct control_msg msg;
|
||||||
|
if (convert_mouse_wheel(event, mi->screen, &msg)) {
|
||||||
|
if (!controller_push_msg(mi->controller, &msg)) {
|
||||||
|
LOGW("Could not request 'inject mouse wheel event'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sc_mouse_inject_init(struct sc_mouse_inject *mi,
|
sc_mouse_inject_init(struct sc_mouse_inject *mi, struct controller *controller,
|
||||||
struct controller *controller) {
|
struct screen *screen) {
|
||||||
mi->controller = controller;
|
mi->controller = controller;
|
||||||
|
mi->screen = screen;
|
||||||
|
|
||||||
static const struct sc_mouse_processor_ops ops = {
|
static const struct sc_mouse_processor_ops ops = {
|
||||||
.process_mouse_motion = sc_mouse_processor_process_mouse_motion,
|
.process_mouse_motion = sc_mouse_processor_process_mouse_motion,
|
||||||
.process_mouse_click = sc_mouse_processor_process_mouse_click,
|
|
||||||
.process_mouse_scroll = sc_mouse_processor_process_mouse_scroll,
|
|
||||||
.process_touch = sc_mouse_processor_process_touch,
|
.process_touch = sc_mouse_processor_process_touch,
|
||||||
|
.process_mouse_button = sc_mouse_processor_process_mouse_button,
|
||||||
|
.process_mouse_wheel = sc_mouse_processor_process_mouse_wheel,
|
||||||
};
|
};
|
||||||
|
|
||||||
mi->mouse_processor.ops = &ops;
|
mi->mouse_processor.ops = &ops;
|
||||||
|
|||||||
@@ -13,9 +13,11 @@ struct sc_mouse_inject {
|
|||||||
struct sc_mouse_processor mouse_processor; // mouse processor trait
|
struct sc_mouse_processor mouse_processor; // mouse processor trait
|
||||||
|
|
||||||
struct controller *controller;
|
struct controller *controller;
|
||||||
|
struct screen *screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
sc_mouse_inject_init(struct sc_mouse_inject *mi, struct controller *controller);
|
sc_mouse_inject_init(struct sc_mouse_inject *mi, struct controller *controller,
|
||||||
|
struct screen *screen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ aoa_hid_end:
|
|||||||
kp = &s->keyboard_inject.key_processor;
|
kp = &s->keyboard_inject.key_processor;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_mouse_inject_init(&s->mouse_inject, &s->controller);
|
sc_mouse_inject_init(&s->mouse_inject, &s->controller, &s->screen);
|
||||||
mp = &s->mouse_inject.mouse_processor;
|
mp = &s->mouse_inject.mouse_processor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "input_events.h"
|
#include <SDL2/SDL_events.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mouse processor trait.
|
* Mouse processor trait.
|
||||||
@@ -21,19 +21,19 @@ struct sc_mouse_processor {
|
|||||||
struct sc_mouse_processor_ops {
|
struct sc_mouse_processor_ops {
|
||||||
void
|
void
|
||||||
(*process_mouse_motion)(struct sc_mouse_processor *mp,
|
(*process_mouse_motion)(struct sc_mouse_processor *mp,
|
||||||
const struct sc_mouse_motion_event *event);
|
const SDL_MouseMotionEvent *event);
|
||||||
|
|
||||||
void
|
|
||||||
(*process_mouse_click)(struct sc_mouse_processor *mp,
|
|
||||||
const struct sc_mouse_click_event *event);
|
|
||||||
|
|
||||||
void
|
|
||||||
(*process_mouse_scroll)(struct sc_mouse_processor *mp,
|
|
||||||
const struct sc_mouse_scroll_event *event);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
(*process_touch)(struct sc_mouse_processor *mp,
|
(*process_touch)(struct sc_mouse_processor *mp,
|
||||||
const struct sc_touch_event *event);
|
const SDL_TouchFingerEvent *event);
|
||||||
|
|
||||||
|
void
|
||||||
|
(*process_mouse_button)(struct sc_mouse_processor *mp,
|
||||||
|
const SDL_MouseButtonEvent *event);
|
||||||
|
|
||||||
|
void
|
||||||
|
(*process_mouse_wheel)(struct sc_mouse_processor *mp,
|
||||||
|
const SDL_MouseWheelEvent *event);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user