|
|
|
@ -10,7 +10,7 @@
|
|
|
|
|
#define SC_SDL_SHORTCUT_MODS_MASK (KMOD_CTRL | KMOD_ALT | KMOD_GUI)
|
|
|
|
|
|
|
|
|
|
static inline uint16_t
|
|
|
|
|
to_sdl_mod(unsigned shortcut_mod) {
|
|
|
|
|
to_sdl_mod(uint8_t shortcut_mod) {
|
|
|
|
|
uint16_t sdl_mod = 0;
|
|
|
|
|
if (shortcut_mod & SC_SHORTCUT_MOD_LCTRL) {
|
|
|
|
|
sdl_mod |= KMOD_LCTRL;
|
|
|
|
@ -38,15 +38,18 @@ is_shortcut_mod(struct sc_input_manager *im, uint16_t sdl_mod) {
|
|
|
|
|
// keep only the relevant modifier keys
|
|
|
|
|
sdl_mod &= SC_SDL_SHORTCUT_MODS_MASK;
|
|
|
|
|
|
|
|
|
|
assert(im->sdl_shortcut_mods.count);
|
|
|
|
|
assert(im->sdl_shortcut_mods.count < SC_MAX_SHORTCUT_MODS);
|
|
|
|
|
for (unsigned i = 0; i < im->sdl_shortcut_mods.count; ++i) {
|
|
|
|
|
if (im->sdl_shortcut_mods.data[i] == sdl_mod) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// at least one shortcut mod pressed?
|
|
|
|
|
return sdl_mod & im->sdl_shortcut_mods;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
static bool
|
|
|
|
|
is_shortcut_key(struct sc_input_manager *im, SDL_Keycode keycode) {
|
|
|
|
|
return (im->sdl_shortcut_mods & KMOD_LCTRL && keycode == SDLK_LCTRL)
|
|
|
|
|
|| (im->sdl_shortcut_mods & KMOD_RCTRL && keycode == SDLK_RCTRL)
|
|
|
|
|
|| (im->sdl_shortcut_mods & KMOD_LALT && keycode == SDLK_LALT)
|
|
|
|
|
|| (im->sdl_shortcut_mods & KMOD_RALT && keycode == SDLK_RALT)
|
|
|
|
|
|| (im->sdl_shortcut_mods & KMOD_LGUI && keycode == SDLK_LGUI)
|
|
|
|
|
|| (im->sdl_shortcut_mods & KMOD_RGUI && keycode == SDLK_RGUI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -68,15 +71,7 @@ sc_input_manager_init(struct sc_input_manager *im,
|
|
|
|
|
im->legacy_paste = params->legacy_paste;
|
|
|
|
|
im->clipboard_autosync = params->clipboard_autosync;
|
|
|
|
|
|
|
|
|
|
const struct sc_shortcut_mods *shortcut_mods = params->shortcut_mods;
|
|
|
|
|
assert(shortcut_mods->count);
|
|
|
|
|
assert(shortcut_mods->count < SC_MAX_SHORTCUT_MODS);
|
|
|
|
|
for (unsigned i = 0; i < shortcut_mods->count; ++i) {
|
|
|
|
|
uint16_t sdl_mod = to_sdl_mod(shortcut_mods->data[i]);
|
|
|
|
|
assert(sdl_mod);
|
|
|
|
|
im->sdl_shortcut_mods.data[i] = sdl_mod;
|
|
|
|
|
}
|
|
|
|
|
im->sdl_shortcut_mods.count = shortcut_mods->count;
|
|
|
|
|
im->sdl_shortcut_mods = to_sdl_mod(params->shortcut_mods);
|
|
|
|
|
|
|
|
|
|
im->vfinger_down = false;
|
|
|
|
|
im->vfinger_invert_x = false;
|
|
|
|
@ -402,6 +397,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
const SDL_KeyboardEvent *event) {
|
|
|
|
|
// controller is NULL if --no-control is requested
|
|
|
|
|
bool control = im->controller;
|
|
|
|
|
bool paused = im->screen->paused;
|
|
|
|
|
|
|
|
|
|
SDL_Keycode keycode = event->keysym.sym;
|
|
|
|
|
uint16_t mod = event->keysym.mod;
|
|
|
|
@ -410,7 +406,12 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
bool shift = event->keysym.mod & KMOD_SHIFT;
|
|
|
|
|
bool repeat = event->repeat;
|
|
|
|
|
|
|
|
|
|
bool smod = is_shortcut_mod(im, mod);
|
|
|
|
|
// Either the modifier includes a shortcut modifier, or the key
|
|
|
|
|
// press/release is a modifier key.
|
|
|
|
|
// The second condition is necessary to ignore the release of the modifier
|
|
|
|
|
// key (because in this case mod is 0).
|
|
|
|
|
bool is_shortcut = is_shortcut_mod(im, mod)
|
|
|
|
|
|| is_shortcut_key(im, keycode);
|
|
|
|
|
|
|
|
|
|
if (down && !repeat) {
|
|
|
|
|
if (keycode == im->last_keycode && mod == im->last_mod) {
|
|
|
|
@ -422,51 +423,55 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The shortcut modifier is pressed
|
|
|
|
|
if (smod) {
|
|
|
|
|
if (is_shortcut) {
|
|
|
|
|
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
|
|
|
|
switch (keycode) {
|
|
|
|
|
case SDLK_h:
|
|
|
|
|
if (im->kp && !shift && !repeat) {
|
|
|
|
|
if (im->kp && !shift && !repeat && !paused) {
|
|
|
|
|
action_home(im, action);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_b: // fall-through
|
|
|
|
|
case SDLK_BACKSPACE:
|
|
|
|
|
if (im->kp && !shift && !repeat) {
|
|
|
|
|
if (im->kp && !shift && !repeat && !paused) {
|
|
|
|
|
action_back(im, action);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_s:
|
|
|
|
|
if (im->kp && !shift && !repeat) {
|
|
|
|
|
if (im->kp && !shift && !repeat && !paused) {
|
|
|
|
|
action_app_switch(im, action);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_m:
|
|
|
|
|
if (im->kp && !shift && !repeat) {
|
|
|
|
|
if (im->kp && !shift && !repeat && !paused) {
|
|
|
|
|
action_menu(im, action);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_p:
|
|
|
|
|
if (im->kp && !shift && !repeat) {
|
|
|
|
|
if (im->kp && !shift && !repeat && !paused) {
|
|
|
|
|
action_power(im, action);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_o:
|
|
|
|
|
if (control && !repeat && down) {
|
|
|
|
|
if (control && !repeat && down && !paused) {
|
|
|
|
|
enum sc_screen_power_mode mode = shift
|
|
|
|
|
? SC_SCREEN_POWER_MODE_NORMAL
|
|
|
|
|
: SC_SCREEN_POWER_MODE_OFF;
|
|
|
|
|
set_screen_power_mode(im, mode);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_z:
|
|
|
|
|
if (down && !repeat) {
|
|
|
|
|
sc_screen_set_paused(im->screen, !shift);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_DOWN:
|
|
|
|
|
if (shift) {
|
|
|
|
|
if (!repeat & down) {
|
|
|
|
|
apply_orientation_transform(im,
|
|
|
|
|
SC_ORIENTATION_FLIP_180);
|
|
|
|
|
}
|
|
|
|
|
} else if (im->kp) {
|
|
|
|
|
} else if (im->kp && !paused) {
|
|
|
|
|
// forward repeated events
|
|
|
|
|
action_volume_down(im, action);
|
|
|
|
|
}
|
|
|
|
@ -477,7 +482,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
apply_orientation_transform(im,
|
|
|
|
|
SC_ORIENTATION_FLIP_180);
|
|
|
|
|
}
|
|
|
|
|
} else if (im->kp) {
|
|
|
|
|
} else if (im->kp && !paused) {
|
|
|
|
|
// forward repeated events
|
|
|
|
|
action_volume_up(im, action);
|
|
|
|
|
}
|
|
|
|
@ -505,17 +510,17 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_c:
|
|
|
|
|
if (im->kp && !shift && !repeat && down) {
|
|
|
|
|
if (im->kp && !shift && !repeat && down && !paused) {
|
|
|
|
|
get_device_clipboard(im, SC_COPY_KEY_COPY);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_x:
|
|
|
|
|
if (im->kp && !shift && !repeat && down) {
|
|
|
|
|
if (im->kp && !shift && !repeat && down && !paused) {
|
|
|
|
|
get_device_clipboard(im, SC_COPY_KEY_CUT);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_v:
|
|
|
|
|
if (im->kp && !repeat && down) {
|
|
|
|
|
if (im->kp && !repeat && down && !paused) {
|
|
|
|
|
if (shift || im->legacy_paste) {
|
|
|
|
|
// inject the text as input events
|
|
|
|
|
clipboard_paste(im);
|
|
|
|
@ -547,7 +552,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_n:
|
|
|
|
|
if (control && !repeat && down) {
|
|
|
|
|
if (control && !repeat && down && !paused) {
|
|
|
|
|
if (shift) {
|
|
|
|
|
collapse_panels(im);
|
|
|
|
|
} else if (im->key_repeat == 0) {
|
|
|
|
@ -558,12 +563,12 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_r:
|
|
|
|
|
if (control && !shift && !repeat && down) {
|
|
|
|
|
if (control && !shift && !repeat && down && !paused) {
|
|
|
|
|
rotate_device(im);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case SDLK_k:
|
|
|
|
|
if (control && !shift && !repeat && down
|
|
|
|
|
if (control && !shift && !repeat && down && !paused
|
|
|
|
|
&& im->kp && im->kp->hid) {
|
|
|
|
|
// Only if the current keyboard is hid
|
|
|
|
|
open_hard_keyboard_settings(im);
|
|
|
|
@ -574,7 +579,7 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!im->kp) {
|
|
|
|
|
if (!im->kp || paused) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -622,7 +627,6 @@ sc_input_manager_process_key(struct sc_input_manager *im,
|
|
|
|
|
static void
|
|
|
|
|
sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
|
|
|
|
|
const SDL_MouseMotionEvent *event) {
|
|
|
|
|
|
|
|
|
|
if (event->which == SDL_TOUCH_MOUSEID) {
|
|
|
|
|
// simulated from touch events, so it's a duplicate
|
|
|
|
|
return;
|
|
|
|
@ -695,16 +699,16 @@ sc_input_manager_process_touch(struct sc_input_manager *im,
|
|
|
|
|
static void
|
|
|
|
|
sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|
|
|
|
const SDL_MouseButtonEvent *event) {
|
|
|
|
|
bool control = im->controller;
|
|
|
|
|
|
|
|
|
|
if (event->which == SDL_TOUCH_MOUSEID) {
|
|
|
|
|
// simulated from touch events, so it's a duplicate
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool control = im->controller;
|
|
|
|
|
bool paused = im->screen->paused;
|
|
|
|
|
bool down = event->type == SDL_MOUSEBUTTONDOWN;
|
|
|
|
|
if (!im->forward_all_clicks) {
|
|
|
|
|
if (control) {
|
|
|
|
|
if (control && !paused) {
|
|
|
|
|
enum sc_action action = down ? SC_ACTION_DOWN : SC_ACTION_UP;
|
|
|
|
|
|
|
|
|
|
if (im->kp && event->button == SDL_BUTTON_X1) {
|
|
|
|
@ -747,7 +751,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|
|
|
|
// otherwise, send the click event to the device
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!im->mp) {
|
|
|
|
|
if (!im->mp || paused) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -885,9 +889,10 @@ void
|
|
|
|
|
sc_input_manager_handle_event(struct sc_input_manager *im,
|
|
|
|
|
const SDL_Event *event) {
|
|
|
|
|
bool control = im->controller;
|
|
|
|
|
bool paused = im->screen->paused;
|
|
|
|
|
switch (event->type) {
|
|
|
|
|
case SDL_TEXTINPUT:
|
|
|
|
|
if (!im->kp) {
|
|
|
|
|
if (!im->kp || paused) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sc_input_manager_process_text_input(im, &event->text);
|
|
|
|
@ -899,13 +904,13 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
|
|
|
|
|
sc_input_manager_process_key(im, &event->key);
|
|
|
|
|
break;
|
|
|
|
|
case SDL_MOUSEMOTION:
|
|
|
|
|
if (!im->mp) {
|
|
|
|
|
if (!im->mp || paused) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sc_input_manager_process_mouse_motion(im, &event->motion);
|
|
|
|
|
break;
|
|
|
|
|
case SDL_MOUSEWHEEL:
|
|
|
|
|
if (!im->mp) {
|
|
|
|
|
if (!im->mp || paused) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sc_input_manager_process_mouse_wheel(im, &event->wheel);
|
|
|
|
@ -919,7 +924,7 @@ sc_input_manager_handle_event(struct sc_input_manager *im,
|
|
|
|
|
case SDL_FINGERMOTION:
|
|
|
|
|
case SDL_FINGERDOWN:
|
|
|
|
|
case SDL_FINGERUP:
|
|
|
|
|
if (!im->mp) {
|
|
|
|
|
if (!im->mp || paused) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sc_input_manager_process_touch(im, &event->tfinger);
|
|
|
|
|