mirror of
				https://github.com/Ryujinx/SDL.git
				synced 2025-11-04 14:24:53 +00:00 
			
		
		
		
	Implemented full evdev keyboard text support
This is based on the Linux kernel driver, and has fallback mapping tables in case we aren't connected to a virtual terminal.
This commit is contained in:
		
							parent
							
								
									49292705a9
								
							
						
					
					
						commit
						e0a40fb6a9
					
				
							
								
								
									
										2
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -23348,7 +23348,7 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
 | 
			
		|||
        fi
 | 
			
		||||
        # Set up files for evdev input
 | 
			
		||||
        if test x$use_input_events = xyes; then
 | 
			
		||||
            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev.c"
 | 
			
		||||
            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev*.c"
 | 
			
		||||
        fi
 | 
			
		||||
        ;;
 | 
			
		||||
    *-*-cygwin* | *-*-mingw32*)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3123,7 +3123,7 @@ case "$host" in
 | 
			
		|||
        fi
 | 
			
		||||
        # Set up files for evdev input
 | 
			
		||||
        if test x$use_input_events = xyes; then
 | 
			
		||||
            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev.c"
 | 
			
		||||
            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_evdev*.c"
 | 
			
		||||
        fi       
 | 
			
		||||
        ;;
 | 
			
		||||
    *-*-cygwin* | *-*-mingw32*)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,27 +30,21 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include "SDL_evdev.h"
 | 
			
		||||
#include "SDL_evdev_kbd.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <limits.h>             /* For the definition of PATH_MAX */
 | 
			
		||||
#include <linux/input.h>
 | 
			
		||||
#ifdef SDL_INPUT_LINUXKD
 | 
			
		||||
#include <linux/kd.h>
 | 
			
		||||
#include <linux/keyboard.h>
 | 
			
		||||
#include <linux/vt.h>
 | 
			
		||||
#include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "SDL.h"
 | 
			
		||||
#include "SDL_assert.h"
 | 
			
		||||
#include "SDL_endian.h"
 | 
			
		||||
#include "../../core/linux/SDL_udev.h"
 | 
			
		||||
#include "SDL_scancode.h"
 | 
			
		||||
#include "../../events/SDL_events_c.h"
 | 
			
		||||
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
 | 
			
		||||
#include "../../core/linux/SDL_udev.h"
 | 
			
		||||
 | 
			
		||||
/* These are not defined in older Linux kernel headers */
 | 
			
		||||
#ifndef SYN_DROPPED
 | 
			
		||||
| 
						 | 
				
			
			@ -62,28 +56,25 @@
 | 
			
		|||
#define ABS_MT_POSITION_Y   0x36
 | 
			
		||||
#define ABS_MT_TRACKING_ID  0x39
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef K_OFF
 | 
			
		||||
#define K_OFF 0x04
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct SDL_evdevlist_item
 | 
			
		||||
{
 | 
			
		||||
    char *path;
 | 
			
		||||
    int fd;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /* TODO: use this for every device, not just touchscreen */
 | 
			
		||||
    int out_of_sync;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /* TODO: expand on this to have data for every possible class (mouse,
 | 
			
		||||
       keyboard, touchpad, etc.). Also there's probably some things in here we
 | 
			
		||||
       can pull out to the SDL_evdevlist_item i.e. name */
 | 
			
		||||
    int is_touchscreen;
 | 
			
		||||
    struct {
 | 
			
		||||
        char* name;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        int min_x, max_x, range_x;
 | 
			
		||||
        int min_y, max_y, range_y;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        int max_slots;
 | 
			
		||||
        int current_slot;
 | 
			
		||||
        struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -97,18 +88,17 @@ typedef struct SDL_evdevlist_item
 | 
			
		|||
            int x, y;
 | 
			
		||||
        } * slots;
 | 
			
		||||
    } * touchscreen_data;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    struct SDL_evdevlist_item *next;
 | 
			
		||||
} SDL_evdevlist_item;
 | 
			
		||||
 | 
			
		||||
typedef struct SDL_EVDEV_PrivateData
 | 
			
		||||
{
 | 
			
		||||
    int ref_count;
 | 
			
		||||
    int num_devices;
 | 
			
		||||
    SDL_evdevlist_item *first;
 | 
			
		||||
    SDL_evdevlist_item *last;
 | 
			
		||||
    int num_devices;
 | 
			
		||||
    int ref_count;
 | 
			
		||||
    int console_fd;
 | 
			
		||||
    int old_kb_mode;
 | 
			
		||||
    SDL_EVDEV_keyboard_state *kbd;
 | 
			
		||||
} SDL_EVDEV_PrivateData;
 | 
			
		||||
 | 
			
		||||
#define _THIS SDL_EVDEV_PrivateData *_this
 | 
			
		||||
| 
						 | 
				
			
			@ -135,28 +125,6 @@ static Uint8 EVDEV_MouseButtons[] = {
 | 
			
		|||
    SDL_BUTTON_X2 + 3           /*  BTN_TASK        0x117 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Prevent keystrokes from reaching the tty */
 | 
			
		||||
static int SDL_EVDEV_mute_keyboard(int tty_fd, int* old_kb_mode)
 | 
			
		||||
{
 | 
			
		||||
    if (ioctl(tty_fd, KDGKBMODE, old_kb_mode) < 0) {
 | 
			
		||||
        return SDL_SetError("Failed to get keyboard mode during muting");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (ioctl(tty_fd, KDSKBMODE, K_OFF) < 0) {
 | 
			
		||||
        return SDL_SetError("Failed to set keyboard mode during muting");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return 0;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Restore the keyboard mode for given tty */
 | 
			
		||||
static void SDL_EVDEV_unmute_keyboard(int tty_fd, int old_kb_mode)
 | 
			
		||||
{
 | 
			
		||||
    if (ioctl(tty_fd, KDSKBMODE, old_kb_mode) < 0) {
 | 
			
		||||
        SDL_SetError("Failed to set keyboard mode during unmuting");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SDL_EVDEV_Init(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -180,25 +148,18 @@ SDL_EVDEV_Init(void)
 | 
			
		|||
            _this = NULL;
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        /* Force a scan to build the initial device list */
 | 
			
		||||
        SDL_UDEV_Scan();
 | 
			
		||||
#else
 | 
			
		||||
        /* TODO: Scan the devices manually, like a caveman */
 | 
			
		||||
#endif /* SDL_USE_LIBUDEV */
 | 
			
		||||
 | 
			
		||||
        /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
 | 
			
		||||
        _this->console_fd = open("/dev/tty", O_RDONLY);
 | 
			
		||||
 | 
			
		||||
        /* Mute the keyboard so keystrokes only generate evdev events and do not
 | 
			
		||||
           leak through to the console */
 | 
			
		||||
        if (_this->console_fd >= 0) {
 | 
			
		||||
            SDL_EVDEV_mute_keyboard(_this->console_fd, &_this->old_kb_mode);
 | 
			
		||||
        }
 | 
			
		||||
        _this->kbd = SDL_EVDEV_kbd_init();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    _this->ref_count += 1;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -208,29 +169,26 @@ SDL_EVDEV_Quit(void)
 | 
			
		|||
    if (_this == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    _this->ref_count -= 1;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    if (_this->ref_count < 1) {
 | 
			
		||||
#if SDL_USE_LIBUDEV
 | 
			
		||||
        SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
 | 
			
		||||
        SDL_UDEV_Quit();
 | 
			
		||||
#endif /* SDL_USE_LIBUDEV */
 | 
			
		||||
       
 | 
			
		||||
        if (_this->console_fd >= 0) {
 | 
			
		||||
            SDL_EVDEV_unmute_keyboard(_this->console_fd, _this->old_kb_mode);
 | 
			
		||||
            close(_this->console_fd);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        SDL_EVDEV_kbd_quit(_this->kbd);
 | 
			
		||||
 | 
			
		||||
        /* Remove existing devices */
 | 
			
		||||
        while(_this->first != NULL) {
 | 
			
		||||
            SDL_EVDEV_device_removed(_this->first->path);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        SDL_assert(_this->first == NULL);
 | 
			
		||||
        SDL_assert(_this->last == NULL);
 | 
			
		||||
        SDL_assert(_this->num_devices == 0);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        SDL_free(_this);
 | 
			
		||||
        _this = NULL;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -243,7 +201,7 @@ void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
 | 
			
		|||
    if (dev_path == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    switch(udev_event) {
 | 
			
		||||
    case SDL_UDEV_DEVICEADDED:
 | 
			
		||||
        if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
 | 
			
		||||
| 
						 | 
				
			
			@ -261,89 +219,6 @@ void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
 | 
			
		|||
}
 | 
			
		||||
#endif /* SDL_USE_LIBUDEV */
 | 
			
		||||
 | 
			
		||||
#ifdef SDL_INPUT_LINUXKD
 | 
			
		||||
/* this logic is pulled from kbd_keycode() in drivers/tty/vt/keyboard.c in the
 | 
			
		||||
   Linux kernel source */
 | 
			
		||||
static void SDL_EVDEV_do_text_input(unsigned short keycode)
 | 
			
		||||
{
 | 
			
		||||
    char shift_state;
 | 
			
		||||
    int locks_state;
 | 
			
		||||
    struct kbentry kbe;
 | 
			
		||||
    unsigned char type;
 | 
			
		||||
    char text[2] = { 0 };
 | 
			
		||||
    
 | 
			
		||||
    if (_this->console_fd < 0)
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    shift_state = TIOCL_GETSHIFTSTATE;
 | 
			
		||||
    if (ioctl(_this->console_fd, TIOCLINUX, &shift_state) < 0) {
 | 
			
		||||
        /* TODO: error */
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kbe.kb_table = shift_state;
 | 
			
		||||
    kbe.kb_index = keycode;
 | 
			
		||||
    
 | 
			
		||||
    if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
 | 
			
		||||
        /* TODO: error */
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (kbe.kb_value == K_HOLE || kbe.kb_value == K_NOSUCHMAP) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kbe.kb_value ^= 0xf000;
 | 
			
		||||
 | 
			
		||||
    type = KTYP(kbe.kb_value);
 | 
			
		||||
    
 | 
			
		||||
    if (type < 0xf0) {
 | 
			
		||||
        /* 
 | 
			
		||||
         * FIXME: keysyms with a type below 0xf0 represent a unicode character
 | 
			
		||||
         * which requires special handling due to dead characters, diacritics,
 | 
			
		||||
         * etc. For perfect input a proper way to deal with such characters
 | 
			
		||||
         * should be implemented.
 | 
			
		||||
         *
 | 
			
		||||
         * For reference, the only place I was able to find out about this
 | 
			
		||||
         * special 0xf0 value was in an unused? couple of patches listed below.
 | 
			
		||||
         *
 | 
			
		||||
         * http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-keyboard.diff
 | 
			
		||||
         * http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-console.diff
 | 
			
		||||
         */
 | 
			
		||||
        
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    type -= 0xf0;
 | 
			
		||||
    
 | 
			
		||||
    /* if type is KT_LETTER then it can be affected by Caps Lock */
 | 
			
		||||
    if (type == KT_LETTER) {
 | 
			
		||||
        type = KT_LATIN;
 | 
			
		||||
    
 | 
			
		||||
        if (ioctl(_this->console_fd, KDGKBLED, &locks_state) < 0) {
 | 
			
		||||
            /* TODO: error */
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (locks_state & K_CAPSLOCK) {
 | 
			
		||||
            kbe.kb_table = shift_state ^ (1 << KG_SHIFT);
 | 
			
		||||
            
 | 
			
		||||
            if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
 | 
			
		||||
                /* TODO: error */
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /* TODO: convert values >= 0x80 from ISO-8859-1? to UTF-8 */
 | 
			
		||||
    if (type != KT_LATIN || KVAL(kbe.kb_value) >= 0x80)
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    *text = KVAL(kbe.kb_value);
 | 
			
		||||
    SDL_SendKeyboardText(text);
 | 
			
		||||
}
 | 
			
		||||
#endif /* SDL_INPUT_LINUXKD */
 | 
			
		||||
 | 
			
		||||
void 
 | 
			
		||||
SDL_EVDEV_Poll(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -375,7 +250,7 @@ SDL_EVDEV_Poll(void)
 | 
			
		|||
                    events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                switch (events[i].type) {
 | 
			
		||||
                case EV_KEY:
 | 
			
		||||
                    if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -395,11 +270,9 @@ SDL_EVDEV_Poll(void)
 | 
			
		|||
                            SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
 | 
			
		||||
                        } else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
 | 
			
		||||
                            SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
 | 
			
		||||
#ifdef SDL_INPUT_LINUXKD
 | 
			
		||||
                            SDL_EVDEV_do_text_input(events[i].code);
 | 
			
		||||
#endif /* SDL_INPUT_LINUXKD */
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    SDL_EVDEV_kbd_keycode(_this->kbd, events[i].code, events[i].value);
 | 
			
		||||
                    break;
 | 
			
		||||
                case EV_ABS:
 | 
			
		||||
                    switch(events[i].code) {
 | 
			
		||||
| 
						 | 
				
			
			@ -471,13 +344,13 @@ SDL_EVDEV_Poll(void)
 | 
			
		|||
                    case SYN_REPORT:
 | 
			
		||||
                        if (!item->is_touchscreen) /* FIXME: temp hack */
 | 
			
		||||
                            break;
 | 
			
		||||
                            
 | 
			
		||||
 | 
			
		||||
                        for(j = 0; j < item->touchscreen_data->max_slots; j++) {
 | 
			
		||||
                            norm_x = (float)(item->touchscreen_data->slots[j].x - item->touchscreen_data->min_x) /
 | 
			
		||||
                                (float)item->touchscreen_data->range_x;
 | 
			
		||||
                            norm_y = (float)(item->touchscreen_data->slots[j].y - item->touchscreen_data->min_y) /
 | 
			
		||||
                                (float)item->touchscreen_data->range_y;
 | 
			
		||||
                        
 | 
			
		||||
 | 
			
		||||
                            switch(item->touchscreen_data->slots[j].delta) {
 | 
			
		||||
                            case EVDEV_TOUCH_SLOTDELTA_DOWN:
 | 
			
		||||
                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, 1.0f);
 | 
			
		||||
| 
						 | 
				
			
			@ -496,7 +369,7 @@ SDL_EVDEV_Poll(void)
 | 
			
		|||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        
 | 
			
		||||
 | 
			
		||||
                        if (item->out_of_sync)
 | 
			
		||||
                            item->out_of_sync = 0;
 | 
			
		||||
                        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -539,26 +412,26 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 | 
			
		|||
    int ret, i;
 | 
			
		||||
    char name[64];
 | 
			
		||||
    struct input_absinfo abs_info;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    if (!item->is_touchscreen)
 | 
			
		||||
        return 0;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
 | 
			
		||||
    if (item->touchscreen_data == NULL)
 | 
			
		||||
        return SDL_OutOfMemory();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        SDL_free(item->touchscreen_data);
 | 
			
		||||
        return SDL_SetError("Failed to get evdev touchscreen name");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    item->touchscreen_data->name = SDL_strdup(name);
 | 
			
		||||
    if (item->touchscreen_data->name == NULL) {
 | 
			
		||||
        SDL_free(item->touchscreen_data);
 | 
			
		||||
        return SDL_OutOfMemory();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        SDL_free(item->touchscreen_data->name);
 | 
			
		||||
| 
						 | 
				
			
			@ -568,7 +441,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 | 
			
		|||
    item->touchscreen_data->min_x = abs_info.minimum;
 | 
			
		||||
    item->touchscreen_data->max_x = abs_info.maximum;
 | 
			
		||||
    item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        SDL_free(item->touchscreen_data->name);
 | 
			
		||||
| 
						 | 
				
			
			@ -578,7 +451,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 | 
			
		|||
    item->touchscreen_data->min_y = abs_info.minimum;
 | 
			
		||||
    item->touchscreen_data->max_y = abs_info.maximum;
 | 
			
		||||
    item->touchscreen_data->range_y = abs_info.maximum - abs_info.minimum;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        SDL_free(item->touchscreen_data->name);
 | 
			
		||||
| 
						 | 
				
			
			@ -586,7 +459,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 | 
			
		|||
        return SDL_SetError("Failed to get evdev touchscreen limits");
 | 
			
		||||
    }
 | 
			
		||||
    item->touchscreen_data->max_slots = abs_info.maximum + 1;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    item->touchscreen_data->slots = SDL_calloc(
 | 
			
		||||
        item->touchscreen_data->max_slots,
 | 
			
		||||
        sizeof(*item->touchscreen_data->slots));
 | 
			
		||||
| 
						 | 
				
			
			@ -595,11 +468,11 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 | 
			
		|||
        SDL_free(item->touchscreen_data);
 | 
			
		||||
        return SDL_OutOfMemory();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < item->touchscreen_data->max_slots; i++) {
 | 
			
		||||
        item->touchscreen_data->slots[i].tracking_id = -1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
 | 
			
		||||
        item->touchscreen_data->name);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -608,7 +481,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
 | 
			
		|||
        SDL_free(item->touchscreen_data);
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif /* SDL_USE_LIBUDEV */
 | 
			
		||||
| 
						 | 
				
			
			@ -617,7 +490,7 @@ static void
 | 
			
		|||
SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
 | 
			
		||||
    if (!item->is_touchscreen)
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    SDL_DelTouch(item->fd);
 | 
			
		||||
    SDL_free(item->touchscreen_data->slots);
 | 
			
		||||
    SDL_free(item->touchscreen_data->name);
 | 
			
		||||
| 
						 | 
				
			
			@ -641,21 +514,21 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
 | 
			
		|||
    __u32* mt_req_code;
 | 
			
		||||
    __s32* mt_req_values;
 | 
			
		||||
    size_t mt_req_size;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /* TODO: sync devices other than touchscreen */
 | 
			
		||||
    if (!item->is_touchscreen)
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    mt_req_size = sizeof(*mt_req_code) +
 | 
			
		||||
        sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    mt_req_code = SDL_calloc(1, mt_req_size);
 | 
			
		||||
    if (mt_req_code == NULL) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    mt_req_values = (__s32*)mt_req_code + 1;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    *mt_req_code = ABS_MT_TRACKING_ID;
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -682,7 +555,7 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
 | 
			
		|||
            item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    *mt_req_code = ABS_MT_POSITION_X;
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -700,7 +573,7 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    *mt_req_code = ABS_MT_POSITION_Y;
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -718,14 +591,14 @@ SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        SDL_free(mt_req_code);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    item->touchscreen_data->current_slot = abs_info.value;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    SDL_free(mt_req_code);
 | 
			
		||||
 | 
			
		||||
#endif /* EVIOCGMTSLOTS */
 | 
			
		||||
| 
						 | 
				
			
			@ -744,7 +617,7 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
 | 
			
		|||
            return -1;  /* already have this one */
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
 | 
			
		||||
    if (item == NULL) {
 | 
			
		||||
        return SDL_OutOfMemory();
 | 
			
		||||
| 
						 | 
				
			
			@ -755,33 +628,33 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
 | 
			
		|||
        SDL_free(item);
 | 
			
		||||
        return SDL_SetError("Unable to open %s", dev_path);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    item->path = SDL_strdup(dev_path);
 | 
			
		||||
    if (item->path == NULL) {
 | 
			
		||||
        close(item->fd);
 | 
			
		||||
        SDL_free(item);
 | 
			
		||||
        return SDL_OutOfMemory();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
 | 
			
		||||
        item->is_touchscreen = 1;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
 | 
			
		||||
            close(item->fd);
 | 
			
		||||
            SDL_free(item);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    if (_this->last == NULL) {
 | 
			
		||||
        _this->first = _this->last = item;
 | 
			
		||||
    } else {
 | 
			
		||||
        _this->last->next = item;
 | 
			
		||||
        _this->last = item;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    SDL_EVDEV_sync_device(item);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    return _this->num_devices++;
 | 
			
		||||
}
 | 
			
		||||
#endif /* SDL_USE_LIBUDEV */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										677
									
								
								src/core/linux/SDL_evdev_kbd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										677
									
								
								src/core/linux/SDL_evdev_kbd.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,677 @@
 | 
			
		|||
/*
 | 
			
		||||
  Simple DirectMedia Layer
 | 
			
		||||
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
 | 
			
		||||
 | 
			
		||||
  This software is provided 'as-is', without any express or implied
 | 
			
		||||
  warranty.  In no event will the authors be held liable for any damages
 | 
			
		||||
  arising from the use of this software.
 | 
			
		||||
 | 
			
		||||
  Permission is granted to anyone to use this software for any purpose,
 | 
			
		||||
  including commercial applications, and to alter it and redistribute it
 | 
			
		||||
  freely, subject to the following restrictions:
 | 
			
		||||
 | 
			
		||||
  1. The origin of this software must not be misrepresented; you must not
 | 
			
		||||
     claim that you wrote the original software. If you use this software
 | 
			
		||||
     in a product, an acknowledgment in the product documentation would be
 | 
			
		||||
     appreciated but is not required.
 | 
			
		||||
  2. Altered source versions must be plainly marked as such, and must not be
 | 
			
		||||
     misrepresented as being the original software.
 | 
			
		||||
  3. This notice may not be removed or altered from any source distribution.
 | 
			
		||||
*/
 | 
			
		||||
#include "../../SDL_internal.h"
 | 
			
		||||
 | 
			
		||||
#include "SDL_evdev_kbd.h"
 | 
			
		||||
 | 
			
		||||
#ifdef SDL_INPUT_LINUXKD
 | 
			
		||||
 | 
			
		||||
/* This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source */
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <linux/kd.h>
 | 
			
		||||
#include <linux/keyboard.h>
 | 
			
		||||
#include <linux/vt.h>
 | 
			
		||||
#include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
 | 
			
		||||
 | 
			
		||||
#include "../../events/SDL_events_c.h"
 | 
			
		||||
#include "SDL_evdev_kbd_default_accents.h"
 | 
			
		||||
#include "SDL_evdev_kbd_default_keymap.h"
 | 
			
		||||
 | 
			
		||||
/* These are not defined in older Linux kernel headers */
 | 
			
		||||
#ifndef K_UNICODE
 | 
			
		||||
#define K_UNICODE 0x03
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef K_OFF
 | 
			
		||||
#define K_OFF 0x04
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handler Tables.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define K_HANDLERS\
 | 
			
		||||
    k_self,     k_fn,       k_spec,       k_pad,\
 | 
			
		||||
    k_dead,     k_cons,     k_cur,        k_shift,\
 | 
			
		||||
    k_meta,     k_ascii,    k_lock,       k_lowercase,\
 | 
			
		||||
    k_slock,    k_dead2,    k_brl,        k_ignore
 | 
			
		||||
 | 
			
		||||
typedef void (k_handler_fn)(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag);
 | 
			
		||||
static k_handler_fn K_HANDLERS;
 | 
			
		||||
static k_handler_fn *k_handler[16] = { K_HANDLERS };
 | 
			
		||||
 | 
			
		||||
typedef void (fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd);
 | 
			
		||||
static void fn_enter(SDL_EVDEV_keyboard_state *kbd);
 | 
			
		||||
static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd);
 | 
			
		||||
static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd);
 | 
			
		||||
static void fn_num(SDL_EVDEV_keyboard_state *kbd);
 | 
			
		||||
static void fn_compose(SDL_EVDEV_keyboard_state *kbd);
 | 
			
		||||
 | 
			
		||||
static fn_handler_fn *fn_handler[] =
 | 
			
		||||
{
 | 
			
		||||
    NULL,       fn_enter,   NULL,       NULL,
 | 
			
		||||
    NULL,       NULL,       NULL,       fn_caps_toggle,
 | 
			
		||||
    fn_num,     NULL,       NULL,       NULL,
 | 
			
		||||
    NULL,       fn_caps_on, fn_compose, NULL,
 | 
			
		||||
    NULL,       NULL,       NULL,       fn_num
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Keyboard State
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
struct SDL_EVDEV_keyboard_state
 | 
			
		||||
{
 | 
			
		||||
    int console_fd;
 | 
			
		||||
    int old_kbd_mode;
 | 
			
		||||
    unsigned short **key_maps;
 | 
			
		||||
    unsigned char shift_down[NR_SHIFT];        /* shift state counters.. */
 | 
			
		||||
    SDL_bool dead_key_next;
 | 
			
		||||
    int npadch;                    /* -1 or number assembled on pad */
 | 
			
		||||
    struct kbdiacrs *accents;
 | 
			
		||||
    unsigned int diacr;
 | 
			
		||||
    SDL_bool rep;                    /* flag telling character repeat */
 | 
			
		||||
    unsigned char lockstate;
 | 
			
		||||
    unsigned char slockstate;
 | 
			
		||||
    unsigned char ledflagstate;
 | 
			
		||||
    char shift_state;
 | 
			
		||||
    char text[128];
 | 
			
		||||
    unsigned int text_len;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef DUMP_ACCENTS
 | 
			
		||||
static void SDL_EVDEV_dump_accents(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
 | 
			
		||||
    printf("static struct kbdiacrs default_accents = {\n");
 | 
			
		||||
    printf("    %d,\n", kbd->accents->kb_cnt);
 | 
			
		||||
    printf("    {\n");
 | 
			
		||||
    for (i = 0; i < kbd->accents->kb_cnt; ++i) {
 | 
			
		||||
        struct kbdiacr *diacr = &kbd->accents->kbdiacr[i];
 | 
			
		||||
        printf("        { 0x%.2x, 0x%.2x, 0x%.2x },\n",
 | 
			
		||||
            diacr->diacr, diacr->base, diacr->result);
 | 
			
		||||
    }
 | 
			
		||||
    while (i < 256) {
 | 
			
		||||
        printf("        { 0x00, 0x00, 0x00 },\n");
 | 
			
		||||
        ++i;
 | 
			
		||||
    }
 | 
			
		||||
    printf("    }\n");
 | 
			
		||||
    printf("};\n");
 | 
			
		||||
}
 | 
			
		||||
#endif /* DUMP_ACCENTS */
 | 
			
		||||
 | 
			
		||||
#ifdef DUMP_KEYMAP
 | 
			
		||||
static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    int i, j;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
 | 
			
		||||
        if (kbd->key_maps[i]) {
 | 
			
		||||
            printf("static unsigned short default_key_map_%d[NR_KEYS] = {", i);
 | 
			
		||||
            for (j = 0; j < NR_KEYS; ++j) {
 | 
			
		||||
                if ((j%8) == 0) {
 | 
			
		||||
                    printf("\n    ");
 | 
			
		||||
                }
 | 
			
		||||
                printf("0x%.4x, ", kbd->key_maps[i][j]);
 | 
			
		||||
            }
 | 
			
		||||
            printf("\n};\n");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    printf("\n");
 | 
			
		||||
    printf("static unsigned short *default_key_maps[MAX_NR_KEYMAPS] = {\n");
 | 
			
		||||
    for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
 | 
			
		||||
        if (kbd->key_maps[i]) {
 | 
			
		||||
            printf("    default_key_map_%d,\n", i);
 | 
			
		||||
        } else {
 | 
			
		||||
            printf("    NULL,\n");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    printf("};\n");
 | 
			
		||||
}
 | 
			
		||||
#endif /* DUMP_KEYMAP */
 | 
			
		||||
 | 
			
		||||
static int SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    int i, j;
 | 
			
		||||
 | 
			
		||||
    kbd->key_maps = (unsigned short **)SDL_calloc(MAX_NR_KEYMAPS, sizeof(unsigned short *));
 | 
			
		||||
    if (!kbd->key_maps) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
 | 
			
		||||
        struct kbentry kbe;
 | 
			
		||||
 | 
			
		||||
        kbe.kb_table = i;
 | 
			
		||||
        kbe.kb_index = 0;
 | 
			
		||||
        if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (kbe.kb_value == K_NOSUCHMAP) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        kbd->key_maps[i] = (unsigned short *)SDL_malloc(NR_KEYS * sizeof(unsigned short));
 | 
			
		||||
        if (!kbd->key_maps[i]) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (j = 0; j < NR_KEYS; ++j) {
 | 
			
		||||
            kbe.kb_table = i;
 | 
			
		||||
            kbe.kb_index = j;
 | 
			
		||||
            if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            kbd->key_maps[i][j] = (kbe.kb_value ^ 0xf000);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SDL_EVDEV_keyboard_state *
 | 
			
		||||
SDL_EVDEV_kbd_init(void)
 | 
			
		||||
{
 | 
			
		||||
    SDL_EVDEV_keyboard_state *kbd;
 | 
			
		||||
    int i;
 | 
			
		||||
    char shift_state, flag_state;
 | 
			
		||||
 | 
			
		||||
    kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
 | 
			
		||||
    if (!kbd) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kbd->npadch = -1;
 | 
			
		||||
 | 
			
		||||
    /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
 | 
			
		||||
    kbd->console_fd = open("/dev/tty", O_RDONLY);
 | 
			
		||||
 | 
			
		||||
    shift_state = TIOCL_GETSHIFTSTATE;
 | 
			
		||||
    if (ioctl(kbd->console_fd, TIOCLINUX, &shift_state) == 0) {
 | 
			
		||||
        kbd->shift_state = shift_state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
 | 
			
		||||
        kbd->ledflagstate = flag_state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kbd->accents = &default_accents;
 | 
			
		||||
    if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
 | 
			
		||||
        /* No worries, we'll use the default accent table */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kbd->key_maps = default_key_maps;
 | 
			
		||||
    if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
 | 
			
		||||
        /* Set the keyboard in UNICODE mode and load the keymaps */
 | 
			
		||||
        ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
 | 
			
		||||
 | 
			
		||||
        if (SDL_EVDEV_kbd_load_keymaps(kbd) < 0) {
 | 
			
		||||
            for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
 | 
			
		||||
                if (kbd->key_maps[i]) {
 | 
			
		||||
                    SDL_free(kbd->key_maps[i]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            SDL_free(kbd->key_maps);
 | 
			
		||||
 | 
			
		||||
            kbd->key_maps = default_key_maps;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Mute the keyboard so keystrokes only generate evdev events
 | 
			
		||||
         * and do not leak through to the console
 | 
			
		||||
         */
 | 
			
		||||
        ioctl(kbd->console_fd, KDSKBMODE, K_OFF);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef DUMP_ACCENTS
 | 
			
		||||
    SDL_EVDEV_dump_accents(kbd);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef DUMP_KEYMAP
 | 
			
		||||
    SDL_EVDEV_dump_keymap(kbd);
 | 
			
		||||
#endif
 | 
			
		||||
    return kbd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    if (!kbd) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kbd->console_fd >= 0) {
 | 
			
		||||
        /* Restore the original keyboard mode */
 | 
			
		||||
        ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
 | 
			
		||||
 | 
			
		||||
        close(kbd->console_fd);
 | 
			
		||||
        kbd->console_fd = -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kbd->key_maps && kbd->key_maps != default_key_maps) {
 | 
			
		||||
        int i;
 | 
			
		||||
        for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
 | 
			
		||||
            if (kbd->key_maps[i]) {
 | 
			
		||||
                SDL_free(kbd->key_maps[i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        SDL_free(kbd->key_maps);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_free(kbd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Helper Functions.
 | 
			
		||||
 */
 | 
			
		||||
static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c)
 | 
			
		||||
{
 | 
			
		||||
    /* c is already part of a UTF-8 sequence and safe to add as a character */
 | 
			
		||||
    if (kbd->text_len < (sizeof(kbd->text)-1)) {
 | 
			
		||||
        kbd->text[kbd->text_len++] = (char)c;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void put_utf8(SDL_EVDEV_keyboard_state *kbd, uint c)
 | 
			
		||||
{
 | 
			
		||||
    if (c < 0x80)
 | 
			
		||||
        /*  0******* */
 | 
			
		||||
        put_queue(kbd, c);
 | 
			
		||||
    else if (c < 0x800) {
 | 
			
		||||
        /* 110***** 10****** */
 | 
			
		||||
        put_queue(kbd, 0xc0 | (c >> 6));
 | 
			
		||||
        put_queue(kbd, 0x80 | (c & 0x3f));
 | 
			
		||||
    } else if (c < 0x10000) {
 | 
			
		||||
        if (c >= 0xD800 && c < 0xE000)
 | 
			
		||||
            return;
 | 
			
		||||
        if (c == 0xFFFF)
 | 
			
		||||
            return;
 | 
			
		||||
        /* 1110**** 10****** 10****** */
 | 
			
		||||
        put_queue(kbd, 0xe0 | (c >> 12));
 | 
			
		||||
        put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
 | 
			
		||||
        put_queue(kbd, 0x80 | (c & 0x3f));
 | 
			
		||||
    } else if (c < 0x110000) {
 | 
			
		||||
        /* 11110*** 10****** 10****** 10****** */
 | 
			
		||||
        put_queue(kbd, 0xf0 | (c >> 18));
 | 
			
		||||
        put_queue(kbd, 0x80 | ((c >> 12) & 0x3f));
 | 
			
		||||
        put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
 | 
			
		||||
        put_queue(kbd, 0x80 | (c & 0x3f));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * We have a combining character DIACR here, followed by the character CH.
 | 
			
		||||
 * If the combination occurs in the table, return the corresponding value.
 | 
			
		||||
 * Otherwise, if CH is a space or equals DIACR, return DIACR.
 | 
			
		||||
 * Otherwise, conclude that DIACR was not combining after all,
 | 
			
		||||
 * queue it and return CH.
 | 
			
		||||
 */
 | 
			
		||||
static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int d = kbd->diacr;
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
 | 
			
		||||
    kbd->diacr = 0;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < kbd->accents->kb_cnt; i++) {
 | 
			
		||||
        if (kbd->accents->kbdiacr[i].diacr == d &&
 | 
			
		||||
            kbd->accents->kbdiacr[i].base == ch) {
 | 
			
		||||
            return kbd->accents->kbdiacr[i].result;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ch == ' ' || ch == d)
 | 
			
		||||
        return d;
 | 
			
		||||
 | 
			
		||||
    put_utf8(kbd, d);
 | 
			
		||||
 | 
			
		||||
    return ch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
 | 
			
		||||
{
 | 
			
		||||
    return ((kbd->ledflagstate >> flag) & 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
 | 
			
		||||
{
 | 
			
		||||
    kbd->ledflagstate |= 1 << flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void clr_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
 | 
			
		||||
{
 | 
			
		||||
    kbd->ledflagstate &= ~(1 << flag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void chg_vc_kbd_lock(SDL_EVDEV_keyboard_state *kbd, int flag)
 | 
			
		||||
{
 | 
			
		||||
    kbd->lockstate ^= 1 << flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void chg_vc_kbd_slock(SDL_EVDEV_keyboard_state *kbd, int flag)
 | 
			
		||||
{
 | 
			
		||||
    kbd->slockstate ^= 1 << flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
 | 
			
		||||
{
 | 
			
		||||
    kbd->ledflagstate ^= 1 << flag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Special function handlers
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static void fn_enter(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    if (kbd->diacr) {
 | 
			
		||||
        put_utf8(kbd, kbd->diacr);
 | 
			
		||||
        kbd->diacr = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    if (kbd->rep)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    chg_vc_kbd_led(kbd, K_CAPSLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    if (kbd->rep)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    set_vc_kbd_led(kbd, K_CAPSLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fn_num(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    if (!kbd->rep)
 | 
			
		||||
        chg_vc_kbd_led(kbd, K_NUMLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fn_compose(SDL_EVDEV_keyboard_state *kbd)
 | 
			
		||||
{
 | 
			
		||||
    kbd->dead_key_next = SDL_TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Special key handlers
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static void k_ignore(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_spec(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    if (up_flag)
 | 
			
		||||
        return;
 | 
			
		||||
    if (value >= SDL_arraysize(fn_handler))
 | 
			
		||||
        return;
 | 
			
		||||
    if (fn_handler[value])
 | 
			
		||||
        fn_handler[value](kbd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_lowercase(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    if (up_flag)
 | 
			
		||||
        return;        /* no action, if this is a key release */
 | 
			
		||||
 | 
			
		||||
    if (kbd->diacr)
 | 
			
		||||
        value = handle_diacr(kbd, value);
 | 
			
		||||
 | 
			
		||||
    if (kbd->dead_key_next) {
 | 
			
		||||
        kbd->dead_key_next = SDL_FALSE;
 | 
			
		||||
        kbd->diacr = value;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    put_utf8(kbd, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_deadunicode(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    if (up_flag)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_dead(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
 | 
			
		||||
 | 
			
		||||
    k_deadunicode(kbd, ret_diacr[value], up_flag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_dead2(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    k_deadunicode(kbd, value, up_flag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_cons(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_fn(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_cur(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_pad(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    static const char pad_chars[] = "0123456789+-*/\015,.?()#";
 | 
			
		||||
 | 
			
		||||
    if (up_flag)
 | 
			
		||||
        return;        /* no action, if this is a key release */
 | 
			
		||||
 | 
			
		||||
    if (!vc_kbd_led(kbd, K_NUMLOCK)) {
 | 
			
		||||
        /* unprintable action */
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    put_queue(kbd, pad_chars[value]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    int old_state = kbd->shift_state;
 | 
			
		||||
 | 
			
		||||
    if (kbd->rep)
 | 
			
		||||
        return;
 | 
			
		||||
    /*
 | 
			
		||||
     * Mimic typewriter:
 | 
			
		||||
     * a CapsShift key acts like Shift but undoes CapsLock
 | 
			
		||||
     */
 | 
			
		||||
    if (value == KVAL(K_CAPSSHIFT)) {
 | 
			
		||||
        value = KVAL(K_SHIFT);
 | 
			
		||||
        if (!up_flag)
 | 
			
		||||
            clr_vc_kbd_led(kbd, K_CAPSLOCK);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (up_flag) {
 | 
			
		||||
        /*
 | 
			
		||||
         * handle the case that two shift or control
 | 
			
		||||
         * keys are depressed simultaneously
 | 
			
		||||
         */
 | 
			
		||||
        if (kbd->shift_down[value])
 | 
			
		||||
            kbd->shift_down[value]--;
 | 
			
		||||
    } else
 | 
			
		||||
        kbd->shift_down[value]++;
 | 
			
		||||
 | 
			
		||||
    if (kbd->shift_down[value])
 | 
			
		||||
        kbd->shift_state |= (1 << value);
 | 
			
		||||
    else
 | 
			
		||||
        kbd->shift_state &= ~(1 << value);
 | 
			
		||||
 | 
			
		||||
    /* kludge */
 | 
			
		||||
    if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) {
 | 
			
		||||
        put_utf8(kbd, kbd->npadch);
 | 
			
		||||
        kbd->npadch = -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_meta(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_ascii(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    int base;
 | 
			
		||||
 | 
			
		||||
    if (up_flag)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (value < 10) {
 | 
			
		||||
        /* decimal input of code, while Alt depressed */
 | 
			
		||||
        base = 10;
 | 
			
		||||
    } else {
 | 
			
		||||
        /* hexadecimal input of code, while AltGr depressed */
 | 
			
		||||
        value -= 10;
 | 
			
		||||
        base = 16;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kbd->npadch == -1)
 | 
			
		||||
        kbd->npadch = value;
 | 
			
		||||
    else
 | 
			
		||||
        kbd->npadch = kbd->npadch * base + value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_lock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    if (up_flag || kbd->rep)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    chg_vc_kbd_lock(kbd, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_slock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
    k_shift(kbd, value, up_flag);
 | 
			
		||||
    if (up_flag || kbd->rep)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    chg_vc_kbd_slock(kbd, value);
 | 
			
		||||
    /* try to make Alt, oops, AltGr and such work */
 | 
			
		||||
    if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) {
 | 
			
		||||
        kbd->slockstate = 0;
 | 
			
		||||
        chg_vc_kbd_slock(kbd, value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void k_brl(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char shift_final;
 | 
			
		||||
    unsigned char type;
 | 
			
		||||
    unsigned short *key_map;
 | 
			
		||||
    unsigned short keysym;
 | 
			
		||||
 | 
			
		||||
    if (!kbd) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kbd->rep = (down == 2);
 | 
			
		||||
 | 
			
		||||
    shift_final = (kbd->shift_state | kbd->slockstate) ^ kbd->lockstate;
 | 
			
		||||
    key_map = kbd->key_maps[shift_final];
 | 
			
		||||
    if (!key_map) {
 | 
			
		||||
        kbd->slockstate = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (keycode < NR_KEYS) {
 | 
			
		||||
        keysym = key_map[keycode];
 | 
			
		||||
    } else {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type = KTYP(keysym);
 | 
			
		||||
 | 
			
		||||
    if (type < 0xf0) {
 | 
			
		||||
        if (down) {
 | 
			
		||||
            put_utf8(kbd, keysym);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        type -= 0xf0;
 | 
			
		||||
 | 
			
		||||
        /* if type is KT_LETTER then it can be affected by Caps Lock */
 | 
			
		||||
        if (type == KT_LETTER) {
 | 
			
		||||
            type = KT_LATIN;
 | 
			
		||||
 | 
			
		||||
            if (vc_kbd_led(kbd, K_CAPSLOCK)) {
 | 
			
		||||
                key_map = kbd->key_maps[shift_final ^ (1 << KG_SHIFT)];
 | 
			
		||||
                if (key_map) {
 | 
			
		||||
                    keysym = key_map[keycode];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        (*k_handler[type])(kbd, keysym & 0xff, !down);
 | 
			
		||||
 | 
			
		||||
        if (type != KT_SLOCK) {
 | 
			
		||||
            kbd->slockstate = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kbd->text_len > 0) {
 | 
			
		||||
        kbd->text[kbd->text_len] = '\0';
 | 
			
		||||
        SDL_SendKeyboardText(kbd->text);
 | 
			
		||||
        kbd->text_len = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else /* !SDL_INPUT_LINUXKD */
 | 
			
		||||
 | 
			
		||||
SDL_EVDEV_keyboard_state *
 | 
			
		||||
SDL_EVDEV_kbd_init(void)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* SDL_INPUT_LINUXKD */
 | 
			
		||||
 | 
			
		||||
/* vi: set ts=4 sw=4 expandtab: */
 | 
			
		||||
							
								
								
									
										29
									
								
								src/core/linux/SDL_evdev_kbd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/core/linux/SDL_evdev_kbd.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/*
 | 
			
		||||
  Simple DirectMedia Layer
 | 
			
		||||
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
 | 
			
		||||
 | 
			
		||||
  This software is provided 'as-is', without any express or implied
 | 
			
		||||
  warranty.  In no event will the authors be held liable for any damages
 | 
			
		||||
  arising from the use of this software.
 | 
			
		||||
 | 
			
		||||
  Permission is granted to anyone to use this software for any purpose,
 | 
			
		||||
  including commercial applications, and to alter it and redistribute it
 | 
			
		||||
  freely, subject to the following restrictions:
 | 
			
		||||
 | 
			
		||||
  1. The origin of this software must not be misrepresented; you must not
 | 
			
		||||
     claim that you wrote the original software. If you use this software
 | 
			
		||||
     in a product, an acknowledgment in the product documentation would be
 | 
			
		||||
     appreciated but is not required.
 | 
			
		||||
  2. Altered source versions must be plainly marked as such, and must not be
 | 
			
		||||
     misrepresented as being the original software.
 | 
			
		||||
  3. This notice may not be removed or altered from any source distribution.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
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_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down);
 | 
			
		||||
extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state);
 | 
			
		||||
 | 
			
		||||
/* vi: set ts=4 sw=4 expandtab: */
 | 
			
		||||
							
								
								
									
										284
									
								
								src/core/linux/SDL_evdev_kbd_default_accents.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								src/core/linux/SDL_evdev_kbd_default_accents.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,284 @@
 | 
			
		|||
/*
 | 
			
		||||
  Simple DirectMedia Layer
 | 
			
		||||
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
 | 
			
		||||
 | 
			
		||||
  This software is provided 'as-is', without any express or implied
 | 
			
		||||
  warranty.  In no event will the authors be held liable for any damages
 | 
			
		||||
  arising from the use of this software.
 | 
			
		||||
 | 
			
		||||
  Permission is granted to anyone to use this software for any purpose,
 | 
			
		||||
  including commercial applications, and to alter it and redistribute it
 | 
			
		||||
  freely, subject to the following restrictions:
 | 
			
		||||
 | 
			
		||||
  1. The origin of this software must not be misrepresented; you must not
 | 
			
		||||
     claim that you wrote the original software. If you use this software
 | 
			
		||||
     in a product, an acknowledgment in the product documentation would be
 | 
			
		||||
     appreciated but is not required.
 | 
			
		||||
  2. Altered source versions must be plainly marked as such, and must not be
 | 
			
		||||
     misrepresented as being the original software.
 | 
			
		||||
  3. This notice may not be removed or altered from any source distribution.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
static struct kbdiacrs default_accents = {
 | 
			
		||||
    68,
 | 
			
		||||
    {
 | 
			
		||||
        { 0x60, 0x41, 0xc0 },
 | 
			
		||||
        { 0x60, 0x61, 0xe0 },
 | 
			
		||||
        { 0x27, 0x41, 0xc1 },
 | 
			
		||||
        { 0x27, 0x61, 0xe1 },
 | 
			
		||||
        { 0x5e, 0x41, 0xc2 },
 | 
			
		||||
        { 0x5e, 0x61, 0xe2 },
 | 
			
		||||
        { 0x7e, 0x41, 0xc3 },
 | 
			
		||||
        { 0x7e, 0x61, 0xe3 },
 | 
			
		||||
        { 0x22, 0x41, 0xc4 },
 | 
			
		||||
        { 0x22, 0x61, 0xe4 },
 | 
			
		||||
        { 0x4f, 0x41, 0xc5 },
 | 
			
		||||
        { 0x6f, 0x61, 0xe5 },
 | 
			
		||||
        { 0x30, 0x41, 0xc5 },
 | 
			
		||||
        { 0x30, 0x61, 0xe5 },
 | 
			
		||||
        { 0x41, 0x41, 0xc5 },
 | 
			
		||||
        { 0x61, 0x61, 0xe5 },
 | 
			
		||||
        { 0x41, 0x45, 0xc6 },
 | 
			
		||||
        { 0x61, 0x65, 0xe6 },
 | 
			
		||||
        { 0x2c, 0x43, 0xc7 },
 | 
			
		||||
        { 0x2c, 0x63, 0xe7 },
 | 
			
		||||
        { 0x60, 0x45, 0xc8 },
 | 
			
		||||
        { 0x60, 0x65, 0xe8 },
 | 
			
		||||
        { 0x27, 0x45, 0xc9 },
 | 
			
		||||
        { 0x27, 0x65, 0xe9 },
 | 
			
		||||
        { 0x5e, 0x45, 0xca },
 | 
			
		||||
        { 0x5e, 0x65, 0xea },
 | 
			
		||||
        { 0x22, 0x45, 0xcb },
 | 
			
		||||
        { 0x22, 0x65, 0xeb },
 | 
			
		||||
        { 0x60, 0x49, 0xcc },
 | 
			
		||||
        { 0x60, 0x69, 0xec },
 | 
			
		||||
        { 0x27, 0x49, 0xcd },
 | 
			
		||||
        { 0x27, 0x69, 0xed },
 | 
			
		||||
        { 0x5e, 0x49, 0xce },
 | 
			
		||||
        { 0x5e, 0x69, 0xee },
 | 
			
		||||
        { 0x22, 0x49, 0xcf },
 | 
			
		||||
        { 0x22, 0x69, 0xef },
 | 
			
		||||
        { 0x2d, 0x44, 0xd0 },
 | 
			
		||||
        { 0x2d, 0x64, 0xf0 },
 | 
			
		||||
        { 0x7e, 0x4e, 0xd1 },
 | 
			
		||||
        { 0x7e, 0x6e, 0xf1 },
 | 
			
		||||
        { 0x60, 0x4f, 0xd2 },
 | 
			
		||||
        { 0x60, 0x6f, 0xf2 },
 | 
			
		||||
        { 0x27, 0x4f, 0xd3 },
 | 
			
		||||
        { 0x27, 0x6f, 0xf3 },
 | 
			
		||||
        { 0x5e, 0x4f, 0xd4 },
 | 
			
		||||
        { 0x5e, 0x6f, 0xf4 },
 | 
			
		||||
        { 0x7e, 0x4f, 0xd5 },
 | 
			
		||||
        { 0x7e, 0x6f, 0xf5 },
 | 
			
		||||
        { 0x22, 0x4f, 0xd6 },
 | 
			
		||||
        { 0x22, 0x6f, 0xf6 },
 | 
			
		||||
        { 0x2f, 0x4f, 0xd8 },
 | 
			
		||||
        { 0x2f, 0x6f, 0xf8 },
 | 
			
		||||
        { 0x60, 0x55, 0xd9 },
 | 
			
		||||
        { 0x60, 0x75, 0xf9 },
 | 
			
		||||
        { 0x27, 0x55, 0xda },
 | 
			
		||||
        { 0x27, 0x75, 0xfa },
 | 
			
		||||
        { 0x5e, 0x55, 0xdb },
 | 
			
		||||
        { 0x5e, 0x75, 0xfb },
 | 
			
		||||
        { 0x22, 0x55, 0xdc },
 | 
			
		||||
        { 0x22, 0x75, 0xfc },
 | 
			
		||||
        { 0x27, 0x59, 0xdd },
 | 
			
		||||
        { 0x27, 0x79, 0xfd },
 | 
			
		||||
        { 0x54, 0x48, 0xde },
 | 
			
		||||
        { 0x74, 0x68, 0xfe },
 | 
			
		||||
        { 0x73, 0x73, 0xdf },
 | 
			
		||||
        { 0x22, 0x79, 0xff },
 | 
			
		||||
        { 0x73, 0x7a, 0xdf },
 | 
			
		||||
        { 0x69, 0x6a, 0xff },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
        { 0x00, 0x00, 0x00 },
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* vi: set ts=4 sw=4 expandtab: */
 | 
			
		||||
							
								
								
									
										4634
									
								
								src/core/linux/SDL_evdev_kbd_default_keymap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4634
									
								
								src/core/linux/SDL_evdev_kbd_default_keymap.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
		Reference in a new issue