2012-08-13 17:50:28 +02:00
|
|
|
/*
|
|
|
|
* This software is licensed under the terms of the MIT-License
|
2017-02-11 04:52:08 +01:00
|
|
|
* See COPYING for further information.
|
2012-08-13 17:50:28 +02:00
|
|
|
* ---
|
2018-01-04 18:14:31 +01:00
|
|
|
* Copyright (c) 2011-2018, Lukas Weber <laochailan@web.de>.
|
|
|
|
* Copyright (c) 2012-2018, Andrei Alexeyev <akari@alienslab.net>.
|
2012-08-13 17:50:28 +02:00
|
|
|
*/
|
|
|
|
|
2017-11-25 20:45:11 +01:00
|
|
|
#include "taisei.h"
|
|
|
|
|
2012-08-13 17:50:28 +02:00
|
|
|
#include "events.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "global.h"
|
|
|
|
#include "video.h"
|
2012-08-15 02:41:21 +02:00
|
|
|
#include "gamepad.h"
|
2012-08-13 17:50:28 +02:00
|
|
|
|
2017-11-11 19:47:15 +01:00
|
|
|
static hrtime_t keyrepeat_paused_until;
|
2017-09-29 21:03:49 +02:00
|
|
|
static ListContainer *global_handlers;
|
|
|
|
|
|
|
|
uint32_t sdl_first_user_event;
|
|
|
|
|
|
|
|
static void events_register_default_handlers(void);
|
|
|
|
static void events_unregister_default_handlers(void);
|
|
|
|
|
|
|
|
/*
|
2018-01-12 19:26:07 +01:00
|
|
|
* Public API
|
2017-09-29 21:03:49 +02:00
|
|
|
*/
|
2017-09-18 13:19:50 +02:00
|
|
|
|
|
|
|
void events_init(void) {
|
2017-09-29 21:03:49 +02:00
|
|
|
sdl_first_user_event = SDL_RegisterEvents(NUM_TAISEI_EVENTS);
|
|
|
|
|
|
|
|
if(sdl_first_user_event == (uint32_t)-1) {
|
|
|
|
char *s =
|
|
|
|
"You have exhausted the SDL userevent pool. "
|
|
|
|
"How you managed that is beyond me, but congratulations. "
|
|
|
|
#if (LOG_DEFAULT_LEVELS_BACKTRACE & LOG_FATAL)
|
|
|
|
"Here's your prize stack trace."
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
log_fatal("%s", s);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_EventState(SDL_MOUSEMOTION, SDL_DISABLE);
|
|
|
|
|
|
|
|
events_register_default_handlers();
|
|
|
|
}
|
|
|
|
|
|
|
|
void events_shutdown(void) {
|
|
|
|
events_unregister_default_handlers();
|
2017-09-18 13:19:50 +02:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
if(global_handlers) {
|
|
|
|
log_warn(
|
|
|
|
"Someone didn't unregister their handler. "
|
|
|
|
"Clean up after yourself, I'm not your personal maid. "
|
|
|
|
"Hint: ASan or valgrind can probably determine the culprit."
|
|
|
|
);
|
2017-09-18 13:19:50 +02:00
|
|
|
}
|
2017-09-29 21:03:49 +02:00
|
|
|
#endif
|
2017-09-18 13:19:50 +02:00
|
|
|
}
|
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
static bool events_invoke_handler(SDL_Event *event, EventHandler *handler) {
|
|
|
|
assert(handler->proc != NULL);
|
|
|
|
|
|
|
|
if(!handler->event_type || handler->event_type == event->type) {
|
|
|
|
bool result = handler->proc(event, handler->arg);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-09-19 14:13:04 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
static int handler_container_prio_func(List *h) {
|
2017-09-29 21:03:49 +02:00
|
|
|
return ((EventHandler*)((ListContainer*)h)->data)->priority;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EventPriority real_priority(EventPriority prio) {
|
|
|
|
if(prio == EPRIO_DEFAULT) {
|
|
|
|
return EPRIO_DEFAULT_REMAP;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(prio < NUM_EPRIOS);
|
|
|
|
return prio;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool events_invoke_handlers(SDL_Event *event, ListContainer *h_list, EventHandler *h_array) {
|
|
|
|
// invoke handlers from two sources (a list and an array) in the correct order according to priority
|
|
|
|
// list items take precedence
|
|
|
|
//
|
|
|
|
// assumptions:
|
2018-01-12 19:26:07 +01:00
|
|
|
// h_list is sorted by priority
|
|
|
|
// h_array is in arbitrary order and terminated with a NULL-proc entry
|
2017-09-29 21:03:49 +02:00
|
|
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
if(h_list && !h_array) {
|
|
|
|
// case 1 (simplest): we have a list and no custom handlers
|
|
|
|
|
|
|
|
for(ListContainer *c = h_list; c; c = c->next) {
|
2017-11-11 18:32:22 +01:00
|
|
|
if((result = events_invoke_handler(event, (EventHandler*)c->data))) {
|
2017-09-29 21:03:49 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(h_list && h_array) {
|
|
|
|
// case 2 (suboptimal): we have both a list and a disordered array; need to do some actual work
|
|
|
|
// if you want to optimize this be my guest
|
|
|
|
|
|
|
|
ListContainer *merged_list = NULL;
|
|
|
|
ListContainer *prevc = NULL;
|
|
|
|
|
|
|
|
// copy the list
|
|
|
|
for(ListContainer *c = h_list; c; c = c->next) {
|
|
|
|
ListContainer *newc = calloc(1, sizeof(ListContainer));
|
|
|
|
newc->data = c->data;
|
|
|
|
newc->prev = prevc;
|
|
|
|
|
|
|
|
if(prevc) {
|
|
|
|
prevc->next = newc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!merged_list) {
|
|
|
|
merged_list = newc;
|
|
|
|
}
|
|
|
|
|
|
|
|
prevc = newc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// merge the array into the list copy, respecting priority
|
|
|
|
for(EventHandler *h = h_array; h->proc; ++h) {
|
2018-01-09 20:52:20 +01:00
|
|
|
list_insert_at_priority_tail(
|
2017-09-29 21:03:49 +02:00
|
|
|
&merged_list,
|
2017-11-21 15:45:01 +01:00
|
|
|
list_wrap_container(h),
|
2017-09-29 21:03:49 +02:00
|
|
|
real_priority(h->priority),
|
|
|
|
handler_container_prio_func
|
2017-11-21 15:45:01 +01:00
|
|
|
);
|
2017-09-29 21:03:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// iterate over the merged list
|
|
|
|
for(ListContainer *c = merged_list; c; c = c->next) {
|
2017-11-11 18:32:22 +01:00
|
|
|
if((result = events_invoke_handler(event, (EventHandler*)c->data))) {
|
2017-09-29 21:03:49 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-24 07:16:25 +01:00
|
|
|
list_free_all(&merged_list);
|
2017-09-29 21:03:49 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!h_list && h_array) {
|
|
|
|
// case 3 (unlikely): we don't have a list for some reason (no global handlers?), but there are custom handlers
|
|
|
|
|
|
|
|
for(EventHandler *h = h_array; h->proc; ++h) {
|
2017-11-11 18:32:22 +01:00
|
|
|
if((result = events_invoke_handler(event, h))) {
|
2017-09-29 21:03:49 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// case 4 (unlikely): huh? okay then
|
|
|
|
return result;
|
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
void events_register_handler(EventHandler *handler) {
|
|
|
|
assert(handler->proc != NULL);
|
|
|
|
EventHandler *handler_alloc = malloc(sizeof(EventHandler));
|
|
|
|
memcpy(handler_alloc, handler, sizeof(EventHandler));
|
2017-02-04 03:56:40 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
if(handler_alloc->priority == EPRIO_DEFAULT) {
|
|
|
|
handler_alloc->priority = EPRIO_DEFAULT_REMAP;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(handler_alloc->priority > EPRIO_DEFAULT);
|
2018-01-09 20:52:20 +01:00
|
|
|
list_insert_at_priority_tail(
|
2017-12-24 07:16:25 +01:00
|
|
|
&global_handlers,
|
|
|
|
list_wrap_container(handler_alloc),
|
2017-11-21 15:45:01 +01:00
|
|
|
handler_alloc->priority,
|
|
|
|
handler_container_prio_func
|
|
|
|
);
|
2017-09-29 21:03:49 +02:00
|
|
|
|
|
|
|
log_debug("Registered handler: %p %u", *(void**)&handler_alloc->proc, handler_alloc->priority);
|
|
|
|
}
|
|
|
|
|
|
|
|
void events_unregister_handler(EventHandlerProc proc) {
|
|
|
|
ListContainer *next;
|
|
|
|
for(ListContainer *c = global_handlers; c; c = next) {
|
|
|
|
EventHandler *h = c->data;
|
|
|
|
next = c->next;
|
|
|
|
|
|
|
|
if(h->proc == proc) {
|
|
|
|
free(c->data);
|
2017-11-21 15:45:01 +01:00
|
|
|
free(list_unlink(&global_handlers, c));
|
2017-09-29 21:03:49 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-02-04 05:51:00 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
static void events_apply_flags(EventFlags flags) {
|
|
|
|
if(flags & EFLAG_TEXT) {
|
2017-02-04 05:51:00 +01:00
|
|
|
if(!SDL_IsTextInputActive()) {
|
|
|
|
SDL_StartTextInput();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(SDL_IsTextInputActive()) {
|
|
|
|
SDL_StopTextInput();
|
|
|
|
}
|
|
|
|
}
|
2017-02-04 03:56:40 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
TaiseiEvent type;
|
|
|
|
|
|
|
|
for(type = TE_MENU_FIRST; type <= TE_MENU_LAST; ++type) {
|
|
|
|
SDL_EventState(MAKE_TAISEI_EVENT(type), (bool)(flags & EFLAG_MENU));
|
|
|
|
}
|
|
|
|
|
|
|
|
for(type = TE_GAME_FIRST; type <= TE_GAME_LAST; ++type) {
|
|
|
|
SDL_EventState(MAKE_TAISEI_EVENT(type), (bool)(flags & EFLAG_GAME));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void events_poll(EventHandler *handlers, EventFlags flags) {
|
|
|
|
SDL_Event event;
|
|
|
|
events_apply_flags(flags);
|
2018-01-16 12:51:19 +01:00
|
|
|
events_emit(TE_FRAME, 0, NULL, NULL);
|
2017-09-29 21:03:49 +02:00
|
|
|
|
2012-08-13 17:50:28 +02:00
|
|
|
while(SDL_PollEvent(&event)) {
|
2017-09-29 21:03:49 +02:00
|
|
|
events_invoke_handlers(&event, global_handlers, handlers);
|
|
|
|
}
|
|
|
|
}
|
2017-09-18 13:19:50 +02:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
void events_emit(TaiseiEvent type, int32_t code, void *data1, void *data2) {
|
|
|
|
assert(TAISEI_EVENT_VALID(type));
|
|
|
|
uint32_t sdltype = MAKE_TAISEI_EVENT(type);
|
|
|
|
assert(IS_TAISEI_EVENT(sdltype));
|
2017-09-18 13:19:50 +02:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
if(!SDL_EventState(sdltype, SDL_QUERY)) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-13 06:44:39 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
SDL_Event event = { 0 };
|
|
|
|
event.type = sdltype;
|
|
|
|
event.user.code = code;
|
|
|
|
event.user.data1 = data1;
|
|
|
|
event.user.data2 = data2;
|
2017-09-19 14:13:04 +02:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
SDL_PushEvent(&event);
|
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
void events_pause_keyrepeat(void) {
|
2017-11-11 19:47:15 +01:00
|
|
|
// workaround for SDL bug
|
|
|
|
// https://bugzilla.libsdl.org/show_bug.cgi?id=3287
|
|
|
|
keyrepeat_paused_until = time_get() + 0.25;
|
2017-09-29 21:03:49 +02:00
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
/*
|
2018-01-12 19:26:07 +01:00
|
|
|
* Default handlers
|
2017-09-29 21:03:49 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
static bool events_handler_quit(SDL_Event *event, void *arg);
|
|
|
|
static bool events_handler_keyrepeat_workaround(SDL_Event *event, void *arg);
|
2017-09-30 04:38:16 +02:00
|
|
|
static bool events_handler_clipboard(SDL_Event *event, void *arg);
|
2017-09-29 21:03:49 +02:00
|
|
|
static bool events_handler_hotkeys(SDL_Event *event, void *arg);
|
|
|
|
static bool events_handler_key_down(SDL_Event *event, void *arg);
|
|
|
|
static bool events_handler_key_up(SDL_Event *event, void *arg);
|
2017-09-30 04:38:16 +02:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
|
|
|
|
static EventHandler default_handlers[] = {
|
2018-01-12 19:26:07 +01:00
|
|
|
{ .proc = events_handler_quit, .priority = EPRIO_SYSTEM, .event_type = SDL_QUIT },
|
|
|
|
{ .proc = events_handler_keyrepeat_workaround, .priority = EPRIO_CAPTURE, .event_type = 0 },
|
|
|
|
{ .proc = events_handler_clipboard, .priority = EPRIO_CAPTURE, .event_type = SDL_KEYDOWN },
|
|
|
|
{ .proc = events_handler_hotkeys, .priority = EPRIO_HOTKEYS, .event_type = SDL_KEYDOWN },
|
|
|
|
{ .proc = events_handler_key_down, .priority = EPRIO_TRANSLATION, .event_type = SDL_KEYDOWN },
|
|
|
|
{ .proc = events_handler_key_up, .priority = EPRIO_TRANSLATION, .event_type = SDL_KEYUP },
|
2017-09-29 21:03:49 +02:00
|
|
|
|
|
|
|
{NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void events_register_default_handlers(void) {
|
|
|
|
for(EventHandler *h = default_handlers; h->proc; ++h) {
|
|
|
|
events_register_handler(h);
|
|
|
|
}
|
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
static void events_unregister_default_handlers(void) {
|
|
|
|
for(EventHandler *h = default_handlers; h->proc; ++h) {
|
|
|
|
events_unregister_handler(h->proc);
|
|
|
|
}
|
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
static bool events_handler_quit(SDL_Event *event, void *arg) {
|
2018-05-19 04:01:16 +02:00
|
|
|
taisei_quit();
|
|
|
|
return true;
|
2017-09-29 21:03:49 +02:00
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
static bool events_handler_keyrepeat_workaround(SDL_Event *event, void *arg) {
|
2017-11-11 19:47:15 +01:00
|
|
|
hrtime_t timenow = time_get();
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-11-11 19:47:15 +01:00
|
|
|
if(event->type != SDL_KEYDOWN) {
|
|
|
|
uint32_t te = TAISEI_EVENT(event->type);
|
|
|
|
|
|
|
|
if(te < TE_MENU_FIRST || te > TE_MENU_LAST) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(timenow < keyrepeat_paused_until) {
|
|
|
|
log_debug(
|
|
|
|
"Prevented a potentially bogus key repeat (%f remaining). "
|
|
|
|
"This is an SDL bug. See https://bugzilla.libsdl.org/show_bug.cgi?id=3287",
|
|
|
|
(double)(keyrepeat_paused_until - timenow)
|
|
|
|
);
|
2017-09-29 21:03:49 +02:00
|
|
|
return true;
|
|
|
|
}
|
2017-02-04 05:51:00 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
return false;
|
|
|
|
}
|
2017-02-04 05:51:00 +01:00
|
|
|
|
2017-09-30 04:38:16 +02:00
|
|
|
static bool events_handler_clipboard(SDL_Event *event, void *arg) {
|
|
|
|
if(!SDL_IsTextInputActive()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(event->key.keysym.mod & KMOD_CTRL && event->key.keysym.scancode == SDL_SCANCODE_V) {
|
|
|
|
if(SDL_HasClipboardText()) {
|
|
|
|
memset(event, 0, sizeof(SDL_Event));
|
|
|
|
event->type = MAKE_TAISEI_EVENT(TE_CLIPBOARD_PASTE);
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
static bool events_handler_key_down(SDL_Event *event, void *arg) {
|
|
|
|
SDL_Scancode scan = event->key.keysym.scancode;
|
|
|
|
bool repeat = event->key.repeat;
|
|
|
|
|
|
|
|
/*
|
2018-01-12 19:26:07 +01:00
|
|
|
* Emit menu events
|
2017-09-29 21:03:49 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
struct eventmap_s { int scancode; TaiseiEvent event; } menu_event_map[] = {
|
|
|
|
// order matters
|
|
|
|
// handle all the hardcoded controls first to prevent accidentally overriding them with unusable ones
|
|
|
|
|
|
|
|
{ SDL_SCANCODE_DOWN, TE_MENU_CURSOR_DOWN },
|
|
|
|
{ SDL_SCANCODE_UP, TE_MENU_CURSOR_UP },
|
|
|
|
{ SDL_SCANCODE_RIGHT, TE_MENU_CURSOR_RIGHT },
|
|
|
|
{ SDL_SCANCODE_LEFT, TE_MENU_CURSOR_LEFT },
|
|
|
|
{ SDL_SCANCODE_RETURN, TE_MENU_ACCEPT },
|
|
|
|
{ SDL_SCANCODE_ESCAPE, TE_MENU_ABORT },
|
|
|
|
|
|
|
|
{ config_get_int(CONFIG_KEY_DOWN), TE_MENU_CURSOR_DOWN },
|
|
|
|
{ config_get_int(CONFIG_KEY_UP), TE_MENU_CURSOR_UP },
|
|
|
|
{ config_get_int(CONFIG_KEY_RIGHT), TE_MENU_CURSOR_RIGHT },
|
|
|
|
{ config_get_int(CONFIG_KEY_LEFT), TE_MENU_CURSOR_LEFT },
|
|
|
|
{ config_get_int(CONFIG_KEY_SHOT), TE_MENU_ACCEPT },
|
|
|
|
{ config_get_int(CONFIG_KEY_BOMB), TE_MENU_ABORT },
|
|
|
|
|
|
|
|
{SDL_SCANCODE_UNKNOWN, -1}
|
|
|
|
};
|
|
|
|
|
|
|
|
if(!repeat || transition.state == TRANS_IDLE) {
|
|
|
|
for(struct eventmap_s *m = menu_event_map; m->scancode != SDL_SCANCODE_UNKNOWN; ++m) {
|
|
|
|
if(scan == m->scancode) {
|
2017-10-22 01:47:02 +02:00
|
|
|
events_emit(m->event, 0, (void*)(intptr_t)INDEV_KEYBOARD, NULL);
|
2017-02-04 05:51:00 +01:00
|
|
|
break;
|
|
|
|
}
|
2017-09-29 21:03:49 +02:00
|
|
|
}
|
|
|
|
}
|
2017-02-04 05:51:00 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
/*
|
2018-01-12 19:26:07 +01:00
|
|
|
* Emit game events
|
2017-09-29 21:03:49 +02:00
|
|
|
*/
|
2017-02-04 18:17:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
if(!repeat) {
|
|
|
|
if(scan == config_get_int(CONFIG_KEY_PAUSE) || scan == SDL_SCANCODE_ESCAPE) {
|
|
|
|
events_emit(TE_GAME_PAUSE, 0, NULL, NULL);
|
|
|
|
} else {
|
|
|
|
int key = config_key_from_scancode(scan);
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
if(key >= 0) {
|
2017-10-22 01:47:02 +02:00
|
|
|
events_emit(TE_GAME_KEY_DOWN, key, (void*)(intptr_t)INDEV_KEYBOARD, NULL);
|
2017-09-29 21:03:49 +02:00
|
|
|
}
|
2012-08-13 17:50:28 +02:00
|
|
|
}
|
|
|
|
}
|
2017-09-29 21:03:49 +02:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool events_handler_key_up(SDL_Event *event, void *arg) {
|
|
|
|
SDL_Scancode scan = event->key.keysym.scancode;
|
|
|
|
|
|
|
|
/*
|
2018-01-12 19:26:07 +01:00
|
|
|
* Emit game events
|
2017-09-29 21:03:49 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
int key = config_key_from_scancode(scan);
|
|
|
|
|
|
|
|
if(key >= 0) {
|
2017-10-22 01:47:02 +02:00
|
|
|
events_emit(TE_GAME_KEY_UP, key, (void*)(intptr_t)INDEV_KEYBOARD, NULL);
|
2017-09-29 21:03:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2012-08-13 17:50:28 +02:00
|
|
|
}
|
2017-03-06 01:25:59 +01:00
|
|
|
|
2017-09-29 21:03:49 +02:00
|
|
|
static bool events_handler_hotkeys(SDL_Event *event, void *arg) {
|
|
|
|
if(event->key.repeat) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Scancode scan = event->key.keysym.scancode;
|
|
|
|
SDL_Keymod mod = event->key.keysym.mod;
|
|
|
|
|
|
|
|
if(scan == config_get_int(CONFIG_KEY_SCREENSHOT)) {
|
|
|
|
video_take_screenshot();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((scan == SDL_SCANCODE_RETURN && (mod & KMOD_ALT)) || scan == config_get_int(CONFIG_KEY_FULLSCREEN)) {
|
|
|
|
config_set_int(CONFIG_FULLSCREEN, !config_get_int(CONFIG_FULLSCREEN));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-03-06 01:25:59 +01:00
|
|
|
}
|