diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index c0bde0d7e..453285793 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -73,6 +73,7 @@ typedef struct SDL_evdevlist_item { char *path; int fd; + int udev_class; /* TODO: use this for every device, not just touchscreen */ SDL_bool out_of_sync; @@ -155,6 +156,15 @@ static int SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled) return 0; } +static void SDL_EVDEV_UpdateKeyboardMute(void) +{ + if (SDL_EVDEV_GetDeviceCount(SDL_UDEV_DEVICE_KEYBOARD) > 0) { + SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_TRUE); + } else { + SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_FALSE); + } +} + int SDL_EVDEV_Init(void) { if (_this == NULL) { @@ -208,6 +218,8 @@ int SDL_EVDEV_Init(void) #endif /* SDL_USE_LIBUDEV */ _this->kbd = SDL_EVDEV_kbd_init(); + + SDL_EVDEV_UpdateKeyboardMute(); } SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode; @@ -231,13 +243,13 @@ void SDL_EVDEV_Quit(void) SDL_UDEV_Quit(); #endif /* SDL_USE_LIBUDEV */ - SDL_EVDEV_kbd_quit(_this->kbd); - /* Remove existing devices */ while (_this->first != NULL) { SDL_EVDEV_device_removed(_this->first->path); } + SDL_EVDEV_kbd_quit(_this->kbd); + SDL_assert(_this->first == NULL); SDL_assert(_this->last == NULL); SDL_assert(_this->num_devices == 0); @@ -276,6 +288,19 @@ static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_cl } #endif /* SDL_USE_LIBUDEV */ +int SDL_EVDEV_GetDeviceCount(int device_class) +{ + SDL_evdevlist_item *item; + int count = 0; + + for (item = _this->first; item != NULL; item = item->next) { + if ((item->udev_class & device_class) == device_class) { + ++count; + } + } + return count; +} + void SDL_EVDEV_Poll(void) { struct input_event events[32]; @@ -864,6 +889,8 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) return SDL_OutOfMemory(); } + item->udev_class = udev_class; + if (ioctl(item->fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) { item->relative_mouse = test_bit(REL_X, relbit) && test_bit(REL_Y, relbit); item->high_res_wheel = test_bit(REL_WHEEL_HI_RES, relbit); @@ -900,6 +927,8 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) SDL_EVDEV_sync_device(item); + SDL_EVDEV_UpdateKeyboardMute(); + return _this->num_devices++; } @@ -926,6 +955,7 @@ static int SDL_EVDEV_device_removed(const char *dev_path) close(item->fd); SDL_free(item->path); SDL_free(item); + SDL_EVDEV_UpdateKeyboardMute(); _this->num_devices--; return 0; } diff --git a/src/core/linux/SDL_evdev.h b/src/core/linux/SDL_evdev.h index ba58b91aa..b0c6c7ef0 100644 --- a/src/core/linux/SDL_evdev.h +++ b/src/core/linux/SDL_evdev.h @@ -30,6 +30,7 @@ struct input_event; extern int SDL_EVDEV_Init(void); extern void SDL_EVDEV_Quit(void); +extern int SDL_EVDEV_GetDeviceCount(int device_class); extern void SDL_EVDEV_Poll(void); extern Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event); diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c index 2754e51e4..a58129dea 100644 --- a/src/core/linux/SDL_evdev_kbd.c +++ b/src/core/linux/SDL_evdev_kbd.c @@ -84,6 +84,7 @@ static fn_handler_fn *fn_handler[] = { struct SDL_EVDEV_keyboard_state { int console_fd; + SDL_bool muted; int old_kbd_mode; unsigned short **key_maps; unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ @@ -332,20 +333,6 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE); } - /* Allow inhibiting keyboard mute with env. variable for debugging etc. */ - if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) { - /* Mute the keyboard so keystrokes only generate evdev events - * and do not leak through to the console - */ - ioctl(kbd->console_fd, KDSKBMODE, K_OFF); - - /* Make sure to restore keyboard if application fails to call - * SDL_Quit before exit or fatal signal is raised. - */ - if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) { - kbd_register_emerg_cleanup(kbd); - } - } return kbd; } @@ -355,12 +342,9 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) return; } - kbd_unregister_emerg_cleanup(); + SDL_EVDEV_kbd_set_muted(state, SDL_FALSE); if (state->console_fd >= 0) { - /* Restore the original keyboard mode */ - ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode); - close(state->console_fd); state->console_fd = -1; } @@ -378,6 +362,39 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) SDL_free(state); } +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +{ + if (state == NULL) { + return; + } + + if (muted == state->muted) { + return; + } + + if (muted) { + /* Allow inhibiting keyboard mute with env. variable for debugging etc. */ + if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) { + /* Mute the keyboard so keystrokes only generate evdev events + * and do not leak through to the console + */ + ioctl(state->console_fd, KDSKBMODE, K_OFF); + + /* Make sure to restore keyboard if application fails to call + * SDL_Quit before exit or fatal signal is raised. + */ + if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) { + kbd_register_emerg_cleanup(state); + } + } + } else { + kbd_unregister_emerg_cleanup(); + + /* Restore the original keyboard mode */ + ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode); + } +} + /* * Helper Functions. */ diff --git a/src/core/linux/SDL_evdev_kbd.h b/src/core/linux/SDL_evdev_kbd.h index 6d592ef28..e00ca0b14 100644 --- a/src/core/linux/SDL_evdev_kbd.h +++ b/src/core/linux/SDL_evdev_kbd.h @@ -26,6 +26,7 @@ struct SDL_EVDEV_keyboard_state; typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state; extern SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void); +extern void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted); extern void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down); extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state);