diff --git a/retro-gtk/retro-core-view.c b/retro-gtk/retro-core-view.c index 5772045c4d50f917f81c6db9a1adc3bcfe423d9d..2866082700b4f4327bb69f8df82609df47bf495a 100644 --- a/retro-gtk/retro-core-view.c +++ b/retro-gtk/retro-core-view.c @@ -6,6 +6,7 @@ #include "retro-gl-display.h" #include "retro-controller-codes.h" #include "retro-core-view-controller.h" +#include "retro-input-private.h" #include "retro-pa-player.h" struct _RetroCoreView @@ -18,6 +19,7 @@ struct _RetroCoreView gboolean can_grab_pointer; gboolean snap_pointer_to_borders; GHashTable *key_state; + GHashTable *keyval_state; RetroKeyJoypadMapping *key_joypad_mapping; GHashTable *mouse_button_state; GdkScreen *grabbed_screen; @@ -185,6 +187,7 @@ retro_core_view_on_key_press_event (GtkWidget *source, retro_core_view_ungrab (self); set_input_pressed (self->key_state, event->hardware_keycode); + set_input_pressed (self->keyval_state, event->keyval); return FALSE; } @@ -200,6 +203,7 @@ retro_core_view_on_key_release_event (GtkWidget *source, g_return_val_if_fail (event != NULL, FALSE); set_input_released (self->key_state, event->hardware_keycode); + set_input_released (self->keyval_state, event->keyval); return FALSE; } @@ -338,6 +342,22 @@ retro_core_view_get_mouse_button_state (RetroCoreView *self, return get_input_state (self->mouse_button_state, button); } +static gboolean +retro_core_view_get_keyboard_key_state (RetroCoreView *self, + guint16 key) +{ + guint16 keyval; + + g_return_val_if_fail (RETRO_IS_CORE_VIEW (self), FALSE); + + if (key >= RETRO_KEYBOARD_KEY_LAST) + return FALSE; + + keyval = retro_keyboard_key_to_val_converter (key); + + return get_input_state (self->keyval_state, keyval); +} + static void retro_core_view_finalize (GObject *object) { @@ -348,6 +368,7 @@ retro_core_view_finalize (GObject *object) g_object_unref (self->sensitive_binding); g_object_unref (self->audio_player); g_hash_table_unref (self->key_state); + g_hash_table_unref (self->keyval_state); g_object_unref (self->key_joypad_mapping); g_hash_table_unref (self->mouse_button_state); g_clear_object (&self->grabbed_screen); @@ -467,6 +488,7 @@ retro_core_view_init (RetroCoreView *self) self->audio_player = retro_pa_player_new (); self->key_state = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); + self->keyval_state = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); self->key_joypad_mapping = retro_key_joypad_mapping_new_default (); self->mouse_button_state = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); @@ -603,7 +625,8 @@ retro_core_view_get_key_joypad_mapping (RetroCoreView *self) * * Creates a new #RetroController exposing @self as the specified controller * type. The valid controller types are RETRO_CONTROLLER_TYPE_JOYPAD, - * RETRO_CONTROLLER_TYPE_MOUSE and RETRO_CONTROLLER_TYPE_POINTER. + * RETRO_CONTROLLER_TYPE_MOUSE, RETRO_CONTROLLER_TYPE_KEYBOARD and + * RETRO_CONTROLLER_TYPE_POINTER. * * Returns: (transfer full): a new #RetroController */ @@ -694,6 +717,11 @@ retro_core_view_get_input_state (RetroCoreView *self, default: return 0; } + case RETRO_CONTROLLER_TYPE_KEYBOARD: + if (!retro_input_get_keyboard (input, &id)) + return 0; + + return retro_core_view_get_keyboard_key_state (self, id) ? G_MAXINT16 : 0; case RETRO_CONTROLLER_TYPE_POINTER: if (!retro_input_get_pointer (input, &id)) return 0; @@ -737,6 +765,7 @@ retro_core_view_get_controller_capabilities (RetroCoreView *self) return 1 << RETRO_CONTROLLER_TYPE_JOYPAD | 1 << RETRO_CONTROLLER_TYPE_MOUSE | + 1 << RETRO_CONTROLLER_TYPE_KEYBOARD | 1 << RETRO_CONTROLLER_TYPE_POINTER; } diff --git a/retro-gtk/retro-input-private.h b/retro-gtk/retro-input-private.h index ce3497c089ed1f390d523a97905264f5e1fca8d0..5b817e84a0bea55f60a1f9bb2cd773bba656bc97 100644 --- a/retro-gtk/retro-input-private.h +++ b/retro-gtk/retro-input-private.h @@ -8,12 +8,14 @@ #endif #include "retro-input.h" +#include "retro-keyboard-key.h" G_BEGIN_DECLS typedef struct _RetroInputAny RetroInputAny; typedef struct _RetroInputJoypad RetroInputJoypad; typedef struct _RetroInputMouse RetroInputMouse; +typedef struct _RetroInputKeyboard RetroInputKeyboard; typedef struct _RetroInputLightgun RetroInputLightgun; typedef struct _RetroInputAnalog RetroInputAnalog; typedef struct _RetroInputPointer RetroInputPointer; @@ -34,6 +36,11 @@ struct _RetroInputMouse { RetroMouseId id; }; +struct _RetroInputKeyboard { + RetroControllerType type; + RetroKeyboardKey key; +}; + struct _RetroInputLightgun { RetroControllerType type; RetroLightgunId id; @@ -54,6 +61,7 @@ union _RetroInput { RetroInputAny any; RetroInputJoypad joypad; RetroInputMouse mouse; + RetroInputKeyboard keyboard; RetroInputLightgun lightgun; RetroInputAnalog analog; RetroInputPointer pointer; @@ -64,6 +72,9 @@ void retro_input_init (RetroInput *self, guint id, guint index); +gboolean retro_input_get_keyboard (RetroInput *self, + RetroKeyboardKey *key); + G_END_DECLS #endif /* RETRO_INPUT_PRIVATE_H */ diff --git a/retro-gtk/retro-input.c b/retro-gtk/retro-input.c index cfd99e469679f281698c0190fcc62cfa3ae9bfab..ab29a23df5a7398242c20f5467b380c935a96e61 100644 --- a/retro-gtk/retro-input.c +++ b/retro-gtk/retro-input.c @@ -156,6 +156,33 @@ retro_input_get_mouse (RetroInput *self, return TRUE; } +/** + * retro_input_get_keyboard: + * @self: a #RetroInput + * @key: (out): return location for the key + * + * Gets the keyboard key of %self, if any. + * + * Returns: whether the key was retrieved + */ +gboolean +retro_input_get_keyboard (RetroInput *self, + RetroKeyboardKey *key) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (key != NULL, FALSE); + + if (self->any.type != RETRO_CONTROLLER_TYPE_KEYBOARD) + return FALSE; + + if (self->keyboard.key >= RETRO_KEYBOARD_KEY_LAST) + return FALSE; + + *key = self->keyboard.key; + + return TRUE; +} + /** * retro_input_get_lightgun: * @self: a #RetroInput diff --git a/retro-gtk/retro-keyboard-key.c b/retro-gtk/retro-keyboard-key.c index e43056bac0ad2dec0d597452be8d7161199b1237..d78c9364a36ceb9a78bbabfe9cf267ebe8b84f6f 100644 --- a/retro-gtk/retro-keyboard-key.c +++ b/retro-gtk/retro-keyboard-key.c @@ -166,3 +166,140 @@ retro_keyboard_key_converter (guint keyval) return RETRO_KEYBOARD_KEY_UNKNOWN; } } + +guint +retro_keyboard_key_to_val_converter (RetroKeyboardKey key) +{ + /* + * US-ASCII codes + * + * Both GDK_KEY_* and RETRO_KEYBOARD_KEY_* start with the US-ASCII codes, + * implementing common letters, digits and symbols. + */ + if (key >= 0x20 && key < 0x80) + return key; + + /* + * Function keys + * + * Both GDK_KEY_F* and RETRO_KEYBOARD_KEY_F* implement function keys 1—15 in a + * consecutive manner. GDK_KEY_F* actually implements more function keys but + * RETRO_KEYBOARD_KEY_F* doesn't. + */ + if (key >= RETRO_KEYBOARD_KEY_F1 && key <= RETRO_KEYBOARD_KEY_F15) + return GDK_KEY_F1 + (key - RETRO_KEYBOARD_KEY_F1); + + /* + * Keypad digits + * + * Both GDK_KEY_KP_* and RETRO_KEYBOARD_KEY_KP* implement keypad digits 0–9 in + * a consecutive manner. + */ + if (key >= RETRO_KEYBOARD_KEY_KP0 && key <= RETRO_KEYBOARD_KEY_KP9) + return GDK_KEY_KP_0 + (key - RETRO_KEYBOARD_KEY_KP0); + + /* + * Various keys + * + * FIXME: The following keys are unimplemented because I couldn't find the + * right GDK_KEY_* equivalent: + * - RETRO_KEYBOARD_KEY_MODE + * - RETRO_KEYBOARD_KEY_COMPOSE + * - RETRO_KEYBOARD_KEY_POWER + */ + switch (key) { + case RETRO_KEYBOARD_KEY_BACKSPACE: + return GDK_KEY_BackSpace; + case RETRO_KEYBOARD_KEY_TAB: + return GDK_KEY_Tab; + case RETRO_KEYBOARD_KEY_CLEAR: + return GDK_KEY_Clear; + case RETRO_KEYBOARD_KEY_RETURN: + return GDK_KEY_Return; + case RETRO_KEYBOARD_KEY_PAUSE: + return GDK_KEY_Pause; + case RETRO_KEYBOARD_KEY_ESCAPE: + return GDK_KEY_Escape; + case RETRO_KEYBOARD_KEY_DELETE: + return GDK_KEY_Delete; + + case RETRO_KEYBOARD_KEY_UP: + return GDK_KEY_Up; + case RETRO_KEYBOARD_KEY_DOWN: + return GDK_KEY_Down; + case RETRO_KEYBOARD_KEY_LEFT: + return GDK_KEY_Left; + case RETRO_KEYBOARD_KEY_RIGHT: + return GDK_KEY_Right; + case RETRO_KEYBOARD_KEY_INSERT: + return GDK_KEY_Insert; + case RETRO_KEYBOARD_KEY_HOME: + return GDK_KEY_Home; + case RETRO_KEYBOARD_KEY_END: + return GDK_KEY_End; + case RETRO_KEYBOARD_KEY_PAGEUP: + return GDK_KEY_Page_Up; + case RETRO_KEYBOARD_KEY_PAGEDOWN: + return GDK_KEY_Page_Down; + + case RETRO_KEYBOARD_KEY_KP_PERIOD: + return GDK_KEY_KP_Decimal; + case RETRO_KEYBOARD_KEY_KP_DIVIDE: + return GDK_KEY_KP_Divide; + case RETRO_KEYBOARD_KEY_KP_MULTIPLY: + return GDK_KEY_KP_Multiply; + case RETRO_KEYBOARD_KEY_KP_MINUS: + return GDK_KEY_KP_Subtract; + case RETRO_KEYBOARD_KEY_KP_PLUS: + return GDK_KEY_KP_Add; + case RETRO_KEYBOARD_KEY_KP_ENTER: + return GDK_KEY_KP_Enter; + case RETRO_KEYBOARD_KEY_KP_EQUALS: + return GDK_KEY_KP_Equal; + + case RETRO_KEYBOARD_KEY_NUMLOCK: + return GDK_KEY_Num_Lock; + case RETRO_KEYBOARD_KEY_CAPSLOCK: + return GDK_KEY_Caps_Lock; + case RETRO_KEYBOARD_KEY_SCROLLOCK: + return GDK_KEY_Scroll_Lock; + case RETRO_KEYBOARD_KEY_RSHIFT: + return GDK_KEY_Shift_R; + case RETRO_KEYBOARD_KEY_LSHIFT: + return GDK_KEY_Shift_L; + case RETRO_KEYBOARD_KEY_RCTRL: + return GDK_KEY_Control_R; + case RETRO_KEYBOARD_KEY_LCTRL: + return GDK_KEY_Control_L; + case RETRO_KEYBOARD_KEY_RALT: + return GDK_KEY_Alt_R; + case RETRO_KEYBOARD_KEY_LALT: + return GDK_KEY_Alt_L; + case RETRO_KEYBOARD_KEY_RMETA: + return GDK_KEY_Meta_R; + case RETRO_KEYBOARD_KEY_LMETA: + return GDK_KEY_Meta_L; + case RETRO_KEYBOARD_KEY_RSUPER: + return GDK_KEY_Super_R; + case RETRO_KEYBOARD_KEY_LSUPER: + return GDK_KEY_Super_L; + + case RETRO_KEYBOARD_KEY_HELP: + return GDK_KEY_Help; + case RETRO_KEYBOARD_KEY_PRINT: + return GDK_KEY_Print; + case RETRO_KEYBOARD_KEY_SYSREQ: + return GDK_KEY_Sys_Req; + case RETRO_KEYBOARD_KEY_BREAK: + return GDK_KEY_Break; + case RETRO_KEYBOARD_KEY_MENU: + return GDK_KEY_Menu; + case RETRO_KEYBOARD_KEY_EURO: + return GDK_KEY_EuroSign; + case RETRO_KEYBOARD_KEY_UNDO: + return GDK_KEY_Undo; + + default: + return GDK_KEY_VoidSymbol; + } +} diff --git a/retro-gtk/retro-keyboard-key.h b/retro-gtk/retro-keyboard-key.h index f9ce061c778086fc79656c334e629d347ed585d6..115a1a2ce15949b468b0faaa3cace2ec694026bb 100644 --- a/retro-gtk/retro-keyboard-key.h +++ b/retro-gtk/retro-keyboard-key.h @@ -170,6 +170,7 @@ typedef enum { RetroKeyboardModifierKey retro_keyboard_modifier_key_converter (guint keyval, GdkModifierType modifiers); RetroKeyboardKey retro_keyboard_key_converter (guint keyval); +guint retro_keyboard_key_to_val_converter (RetroKeyboardKey key); G_END_DECLS