diff --git a/Makefile.common b/Makefile.common index 9b692fe951..dc0f40198c 100644 --- a/Makefile.common +++ b/Makefile.common @@ -505,6 +505,7 @@ ifeq ($(HAVE_MENU_COMMON), 1) OBJ += menu/menu_driver.o \ menu/menu_content.o \ menu/menu_input.o \ + menu/menu_event.o \ menu/menu_entries.o \ menu/menu_navigation.o \ menu/menu_setting.o \ diff --git a/griffin/griffin.c b/griffin/griffin.c index 9fca97f2c0..03fe237977 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -888,6 +888,7 @@ MENU #ifdef HAVE_MENU #include "../menu/menu_driver.c" #include "../menu/menu_input.c" +#include "../menu/menu_event.c" #include "../menu/menu_entries.c" #include "../menu/menu_setting.c" #include "../menu/menu_cbs.c" diff --git a/menu/menu_event.c b/menu/menu_event.c new file mode 100644 index 0000000000..8e1dbc3e20 --- /dev/null +++ b/menu/menu_event.c @@ -0,0 +1,229 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2016 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include "widgets/menu_entry.h" +#include "widgets/menu_input_dialog.h" + +#include "menu_event.h" + +#include "menu_driver.h" +#include "menu_input.h" +#include "menu_animation.h" +#include "menu_display.h" +#include "menu_navigation.h" + +#include "../configuration.h" + +static int menu_event_pointer(unsigned *action) +{ + const struct retro_keybind *binds[MAX_USERS] = {NULL}; + menu_input_t *menu_input = menu_input_get_ptr(); + unsigned fb_width = menu_display_get_width(); + unsigned fb_height = menu_display_get_height(); + int pointer_device = + menu_driver_ctl(RARCH_MENU_CTL_IS_SET_TEXTURE, NULL) ? + RETRO_DEVICE_POINTER : RARCH_DEVICE_POINTER_SCREEN; + int pointer_x = + input_driver_state(binds, 0, pointer_device, + 0, RETRO_DEVICE_ID_POINTER_X); + int pointer_y = + input_driver_state(binds, 0, pointer_device, + 0, RETRO_DEVICE_ID_POINTER_Y); + + menu_input->pointer.pressed[0] = input_driver_state(binds, + 0, pointer_device, + 0, RETRO_DEVICE_ID_POINTER_PRESSED); + menu_input->pointer.pressed[1] = input_driver_state(binds, + 0, pointer_device, + 1, RETRO_DEVICE_ID_POINTER_PRESSED); + menu_input->pointer.back = input_driver_state(binds, 0, pointer_device, + 0, RARCH_DEVICE_ID_POINTER_BACK); + + menu_input->pointer.x = ((pointer_x + 0x7fff) * (int)fb_width) / 0xFFFF; + menu_input->pointer.y = ((pointer_y + 0x7fff) * (int)fb_height) / 0xFFFF; + + return 0; +} + +unsigned menu_event(retro_input_t input, + retro_input_t trigger_input) +{ + menu_animation_ctx_delta_t delta; + float delta_time; + unsigned ret = MENU_ACTION_NOOP; + static bool initial_held = true; + static bool first_held = false; + bool set_scroll = false; + bool mouse_enabled = false; + size_t new_scroll_accel = 0; + settings_t *settings = config_get_ptr(); + menu_input_t *menu_input = menu_input_get_ptr(); + + if (!menu_input) + return 0; + + if (input.state) + { + if (!first_held) + { + /* don't run anything first frame, only capture held inputs + * for old_input_state. */ + + first_held = true; + menu_input->delay.timer = initial_held ? 12 : 6; + menu_input->delay.count = 0; + } + + if (menu_input->delay.count >= menu_input->delay.timer) + { + retro_input_t input_repeat = {0}; + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_UP); + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_DOWN); + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_LEFT); + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_RIGHT); + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_B); + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_A); + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_L); + BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_R); + + set_scroll = true; + first_held = false; + trigger_input.state |= input.state & input_repeat.state; + + menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SCROLL_ACCEL, + &new_scroll_accel); + + new_scroll_accel = MIN(new_scroll_accel + 1, 64); + } + + initial_held = false; + } + else + { + set_scroll = true; + first_held = false; + initial_held = true; + } + + if (set_scroll) + menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SCROLL_ACCEL, + &new_scroll_accel); + + menu_animation_ctl(MENU_ANIMATION_CTL_DELTA_TIME, &delta_time); + + delta.current = delta_time; + + if (menu_animation_ctl(MENU_ANIMATION_CTL_IDEAL_DELTA_TIME_GET, &delta)) + menu_input->delay.count += delta.ideal; + + if (menu_input_dialog_get_display_kb()) + { + static unsigned ti_char = 64; + static bool ti_next = false; + + if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN)) + { + if (ti_char > 32) + ti_char--; + if (! ti_next) + input_keyboard_event(true, '\x7f', '\x7f', 0, RETRO_DEVICE_KEYBOARD); + input_keyboard_event(true, ti_char, ti_char, 0, RETRO_DEVICE_KEYBOARD); + ti_next = false; + } + + if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP)) + { + if (ti_char < 125) + ti_char++; + if (! ti_next) + input_keyboard_event(true, '\x7f', '\x7f', 0, RETRO_DEVICE_KEYBOARD); + input_keyboard_event(true, ti_char, ti_char, 0, RETRO_DEVICE_KEYBOARD); + ti_next = false; + } + + if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A)) + { + ti_char = 64; + ti_next = true; + } + + if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B)) + { + input_keyboard_event(true, '\x7f', '\x7f', 0, RETRO_DEVICE_KEYBOARD); + ti_char = 64; + ti_next = false; + } + + /* send return key to close keyboard input window */ + if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START)) + input_keyboard_event(true, '\n', '\n', 0, RETRO_DEVICE_KEYBOARD); + + trigger_input.state = 0; + } + + if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP)) + ret = MENU_ACTION_UP; + else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN)) + ret = MENU_ACTION_DOWN; + else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT)) + ret = MENU_ACTION_LEFT; + else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT)) + ret = MENU_ACTION_RIGHT; + else if (trigger_input.state & (UINT64_C(1) << settings->menu_scroll_up_btn)) + ret = MENU_ACTION_SCROLL_UP; + else if (trigger_input.state & (UINT64_C(1) << settings->menu_scroll_down_btn)) + ret = MENU_ACTION_SCROLL_DOWN; + else if (trigger_input.state & (UINT64_C(1) << settings->menu_cancel_btn)) + ret = MENU_ACTION_CANCEL; + else if (trigger_input.state & (UINT64_C(1) << settings->menu_ok_btn)) + ret = MENU_ACTION_OK; + else if (trigger_input.state & (UINT64_C(1) << settings->menu_search_btn)) + ret = MENU_ACTION_SEARCH; + else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y)) + ret = MENU_ACTION_SCAN; + else if (trigger_input.state & (UINT64_C(1) << settings->menu_default_btn)) + ret = MENU_ACTION_START; + else if (trigger_input.state & (UINT64_C(1) << settings->menu_info_btn)) + ret = MENU_ACTION_INFO; + else if (trigger_input.state & (UINT64_C(1) << RARCH_MENU_TOGGLE)) + ret = MENU_ACTION_TOGGLE; + + mouse_enabled = settings->menu.mouse.enable; +#ifdef HAVE_OVERLAY + if (!mouse_enabled) + mouse_enabled = !(settings->input.overlay_enable + && input_overlay_is_alive(NULL)); +#endif + + if (!mouse_enabled) + menu_input->mouse.ptr = 0; + + if (settings->menu.pointer.enable) + menu_event_pointer(&ret); + else + memset(&menu_input->pointer, 0, sizeof(menu_input->pointer)); + + return ret; +} diff --git a/menu/menu_event.h b/menu/menu_event.h new file mode 100644 index 0000000000..1cef678b44 --- /dev/null +++ b/menu/menu_event.h @@ -0,0 +1,35 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2016 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef _MENU_EVENT_H +#define _MENU_EVENT_H + +#include + +RETRO_BEGIN_DECLS + +/* Send input code to menu for one frame. + * + * TODO/FIXME - needs to be overhauled so we can send multiple + * events per frame if we want to, and we shouldn't send the + * entire button state either but do a separate event per button + * state. + */ +unsigned menu_event(retro_input_t input, retro_input_t trigger_state); + +RETRO_END_DECLS + +#endif diff --git a/menu/menu_input.c b/menu/menu_input.c index 339b76c3cb..01f584782d 100644 --- a/menu/menu_input.c +++ b/menu/menu_input.c @@ -48,35 +48,7 @@ enum menu_mouse_action MENU_MOUSE_ACTION_HORIZ_WHEEL_DOWN }; -typedef struct menu_input -{ - struct - { - unsigned ptr; - } mouse; - - struct - { - int16_t x; - int16_t y; - int16_t dx; - int16_t dy; - float accel; - bool pressed[2]; - bool back; - unsigned ptr; - } pointer; - - - /* Used for key repeat */ - struct - { - float timer; - float count; - } delay; -} menu_input_t; - -static menu_input_t *menu_input_get_ptr(void) +menu_input_t *menu_input_get_ptr(void) { static menu_input_t menu_input_state; return &menu_input_state; @@ -150,37 +122,6 @@ bool menu_input_ctl(enum menu_input_ctl_state state, void *data) return true; } -static int menu_event_pointer(unsigned *action) -{ - const struct retro_keybind *binds[MAX_USERS] = {NULL}; - menu_input_t *menu_input = menu_input_get_ptr(); - unsigned fb_width = menu_display_get_width(); - unsigned fb_height = menu_display_get_height(); - int pointer_device = - menu_driver_ctl(RARCH_MENU_CTL_IS_SET_TEXTURE, NULL) ? - RETRO_DEVICE_POINTER : RARCH_DEVICE_POINTER_SCREEN; - int pointer_x = - input_driver_state(binds, 0, pointer_device, - 0, RETRO_DEVICE_ID_POINTER_X); - int pointer_y = - input_driver_state(binds, 0, pointer_device, - 0, RETRO_DEVICE_ID_POINTER_Y); - - menu_input->pointer.pressed[0] = input_driver_state(binds, - 0, pointer_device, - 0, RETRO_DEVICE_ID_POINTER_PRESSED); - menu_input->pointer.pressed[1] = input_driver_state(binds, - 0, pointer_device, - 1, RETRO_DEVICE_ID_POINTER_PRESSED); - menu_input->pointer.back = input_driver_state(binds, 0, pointer_device, - 0, RARCH_DEVICE_ID_POINTER_BACK); - - menu_input->pointer.x = ((pointer_x + 0x7fff) * (int)fb_width) / 0xFFFF; - menu_input->pointer.y = ((pointer_y + 0x7fff) * (int)fb_height) / 0xFFFF; - - return 0; -} - static int menu_input_mouse_post_iterate(uint64_t *input_mouse, menu_file_list_cbs_t *cbs, unsigned action) { @@ -534,163 +475,3 @@ void menu_input_post_iterate(int *ret, unsigned action) *ret |= menu_input_pointer_post_iterate(cbs, &entry, action); } -unsigned menu_event(retro_input_t input, - retro_input_t trigger_input) -{ - menu_animation_ctx_delta_t delta; - float delta_time; - unsigned ret = MENU_ACTION_NOOP; - static bool initial_held = true; - static bool first_held = false; - bool set_scroll = false; - bool mouse_enabled = false; - size_t new_scroll_accel = 0; - settings_t *settings = config_get_ptr(); - menu_input_t *menu_input = menu_input_get_ptr(); - - if (!menu_input) - return 0; - - if (input.state) - { - if (!first_held) - { - /* don't run anything first frame, only capture held inputs - * for old_input_state. */ - - first_held = true; - menu_input->delay.timer = initial_held ? 12 : 6; - menu_input->delay.count = 0; - } - - if (menu_input->delay.count >= menu_input->delay.timer) - { - retro_input_t input_repeat = {0}; - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_UP); - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_DOWN); - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_LEFT); - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_RIGHT); - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_B); - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_A); - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_L); - BIT32_SET(input_repeat.state, RETRO_DEVICE_ID_JOYPAD_R); - - set_scroll = true; - first_held = false; - trigger_input.state |= input.state & input_repeat.state; - - menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SCROLL_ACCEL, - &new_scroll_accel); - - new_scroll_accel = MIN(new_scroll_accel + 1, 64); - } - - initial_held = false; - } - else - { - set_scroll = true; - first_held = false; - initial_held = true; - } - - if (set_scroll) - menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SCROLL_ACCEL, - &new_scroll_accel); - - menu_animation_ctl(MENU_ANIMATION_CTL_DELTA_TIME, &delta_time); - - delta.current = delta_time; - - if (menu_animation_ctl(MENU_ANIMATION_CTL_IDEAL_DELTA_TIME_GET, &delta)) - menu_input->delay.count += delta.ideal; - - if (menu_input_dialog_get_display_kb()) - { - static unsigned ti_char = 64; - static bool ti_next = false; - - if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN)) - { - if (ti_char > 32) - ti_char--; - if (! ti_next) - input_keyboard_event(true, '\x7f', '\x7f', 0, RETRO_DEVICE_KEYBOARD); - input_keyboard_event(true, ti_char, ti_char, 0, RETRO_DEVICE_KEYBOARD); - ti_next = false; - } - - if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP)) - { - if (ti_char < 125) - ti_char++; - if (! ti_next) - input_keyboard_event(true, '\x7f', '\x7f', 0, RETRO_DEVICE_KEYBOARD); - input_keyboard_event(true, ti_char, ti_char, 0, RETRO_DEVICE_KEYBOARD); - ti_next = false; - } - - if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A)) - { - ti_char = 64; - ti_next = true; - } - - if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B)) - { - input_keyboard_event(true, '\x7f', '\x7f', 0, RETRO_DEVICE_KEYBOARD); - ti_char = 64; - ti_next = false; - } - - /* send return key to close keyboard input window */ - if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START)) - input_keyboard_event(true, '\n', '\n', 0, RETRO_DEVICE_KEYBOARD); - - trigger_input.state = 0; - } - - if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP)) - ret = MENU_ACTION_UP; - else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN)) - ret = MENU_ACTION_DOWN; - else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT)) - ret = MENU_ACTION_LEFT; - else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT)) - ret = MENU_ACTION_RIGHT; - else if (trigger_input.state & (UINT64_C(1) << settings->menu_scroll_up_btn)) - ret = MENU_ACTION_SCROLL_UP; - else if (trigger_input.state & (UINT64_C(1) << settings->menu_scroll_down_btn)) - ret = MENU_ACTION_SCROLL_DOWN; - else if (trigger_input.state & (UINT64_C(1) << settings->menu_cancel_btn)) - ret = MENU_ACTION_CANCEL; - else if (trigger_input.state & (UINT64_C(1) << settings->menu_ok_btn)) - ret = MENU_ACTION_OK; - else if (trigger_input.state & (UINT64_C(1) << settings->menu_search_btn)) - ret = MENU_ACTION_SEARCH; - else if (trigger_input.state & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y)) - ret = MENU_ACTION_SCAN; - else if (trigger_input.state & (UINT64_C(1) << settings->menu_default_btn)) - ret = MENU_ACTION_START; - else if (trigger_input.state & (UINT64_C(1) << settings->menu_info_btn)) - ret = MENU_ACTION_INFO; - else if (trigger_input.state & (UINT64_C(1) << RARCH_MENU_TOGGLE)) - ret = MENU_ACTION_TOGGLE; - - mouse_enabled = settings->menu.mouse.enable; -#ifdef HAVE_OVERLAY - if (!mouse_enabled) - mouse_enabled = !(settings->input.overlay_enable - && input_overlay_is_alive(NULL)); -#endif - - if (!mouse_enabled) - menu_input->mouse.ptr = 0; - - if (settings->menu.pointer.enable) - menu_event_pointer(&ret); - else - memset(&menu_input->pointer, 0, sizeof(menu_input->pointer)); - - return ret; -} diff --git a/menu/menu_input.h b/menu/menu_input.h index 50d4527610..50c03563d5 100644 --- a/menu/menu_input.h +++ b/menu/menu_input.h @@ -79,6 +79,34 @@ enum menu_input_ctl_state MENU_INPUT_CTL_DEINIT }; +typedef struct menu_input +{ + struct + { + unsigned ptr; + } mouse; + + struct + { + int16_t x; + int16_t y; + int16_t dx; + int16_t dy; + float accel; + bool pressed[2]; + bool back; + unsigned ptr; + } pointer; + + + /* Used for key repeat */ + struct + { + float timer; + float count; + } delay; +} menu_input_t; + typedef struct menu_input_ctx_hitbox { int32_t x1; @@ -87,15 +115,6 @@ typedef struct menu_input_ctx_hitbox int32_t y2; } menu_input_ctx_hitbox_t; -/* Send input code to menu for one frame. - * - * TODO/FIXME - needs to be overhauled so we can send multiple - * events per frame if we want to, and we shouldn't send the - * entire button state either but do a separate event per button - * state. - */ -unsigned menu_event(retro_input_t input, retro_input_t trigger_state); - void menu_input_post_iterate(int *ret, unsigned action); int16_t menu_input_pointer_state(enum menu_input_pointer_state state); @@ -106,6 +125,8 @@ bool menu_input_mouse_check_vector_inside_hitbox(menu_input_ctx_hitbox_t *hitbox bool menu_input_ctl(enum menu_input_ctl_state state, void *data); +menu_input_t *menu_input_get_ptr(void); + RETRO_END_DECLS #endif diff --git a/runloop.c b/runloop.c index 18f2cca2ab..8fb884ac72 100644 --- a/runloop.c +++ b/runloop.c @@ -44,6 +44,7 @@ #ifdef HAVE_MENU #include "menu/menu_display.h" #include "menu/menu_driver.h" +#include "menu/menu_event.h" #include "menu/widgets/menu_dialog.h" #endif