From 4052dab476c13bb0fcf9cc83d30ba06609481642 Mon Sep 17 00:00:00 2001 From: Cyril Hrubis Date: Tue, 16 Aug 2011 01:26:02 +0200 Subject: [PATCH] First version of GFXprim input events. --- include/GP.h | 7 +- include/core/GP_Common.h | 8 + include/input/GP_Event.h | 399 ++++++++++++++++----- .../input/GP_InputDriverSDL.h | 22 +- libs/input/GP_Event.c | 273 +++++++++++++- libs/input/GP_InputDriverSDL.c | 138 +++++++ libs/input/Makefile | 1 + tests/SDL/Makefile | 2 +- tests/SDL/input.c | 182 ++++++++++ 9 files changed, 931 insertions(+), 101 deletions(-) copy libs/input/GP_Event.c => include/input/GP_InputDriverSDL.h (82%) create mode 100644 libs/input/GP_InputDriverSDL.c create mode 100644 tests/SDL/input.c diff --git a/include/GP.h b/include/GP.h index 90777f3f..14acffc1 100644 --- a/include/GP.h +++ b/include/GP.h @@ -16,10 +16,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * + * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos * * * * * - * Copyright (C) 2009-2010 Cyril Hrubis * + * Copyright (C) 2009-2011 Cyril Hrubis * * * *****************************************************************************/ @@ -38,4 +38,7 @@ /* backends */ #include "backends/GP_Backend.h" +/* input and events */ +#include "input/GP_Event.h" + #endif /* GP_H */ diff --git a/include/core/GP_Common.h b/include/core/GP_Common.h index 39b9ea95..23e5527f 100644 --- a/include/core/GP_Common.h +++ b/include/core/GP_Common.h @@ -50,6 +50,14 @@ }) /* + * Returns absolute value. + */ +#define GP_ABS(a) ({ \ + typeof(a) _a = a; \ + _a > 0 ? _a : -_a; \ +}) + +/* * The standard likely() and unlikely() used in Kernel */ #ifndef likely diff --git a/include/input/GP_Event.h b/include/input/GP_Event.h index f2531d65..dff17afe 100644 --- a/include/input/GP_Event.h +++ b/include/input/GP_Event.h @@ -16,110 +16,331 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * * - * * - * Copyright (C) 2009-2010 Cyril Hrubis * + * Copyright (C) 2009-2011 Cyril Hrubis * * * *****************************************************************************/ /* - This interface is modeled after linux input event system. + Gfxprim event layer. + + Events are lowlever interfaace to input devices (human interface). + + - Events are notifications that something has changed, eg. button pressed + - Each event carries some information about global state */ #ifndef GP_EVENT_H #define GP_EVENT_H -/* events */ - -typedef enum GP_EventType { - GP_EVENT_KEY = 0x01, /* key up/down event */ - GP_EVENT_REL = 0x02, /* relative XY event */ - GP_EVENT_ABS = 0x03, /* absolute XY value */ -} GP_EventType; - -/* subevents */ - -typedef enum GP_EventKeyType { - GP_KEY_UP = 0x00, - GP_KEY_DOWN = 0x01, -} GP_EventKeyType; - -typedef enum GP_EventRelType { - GP_REL_MOVE = 0x00, - GP_REL_BTN_UP = 0x01, - GP_REL_BTN_DOWN = 0x02, - GP_REL_WHEEL = 0x03, -} GP_EventRelType; - -typedef enum GP_EventAbsType { - GP_ABS_MOVE = 0x00, - GP_ABS_PEN_UP = 0x01, - GP_ABS_PEN_DOWN = 0x02, -} GP_EventAbsType; - -/* data structures */ - -typedef struct GP_EventAbs { - /* event type */ - GP_EventType type; - /* device id */ - int dev_id; - /* possition */ - int x; - int y; - /* size */ - int w; - int h; -} GP_EventAbs; - -typedef struct GP_EventRel { - GP_EventType type; - /* device id */ - int dev_id; - /* possition */ - int x; - int y; - /* relative movement */ - int rx; - int ry; - int rwheel; - /* size */ - int w; - int h; -} GP_EventRel; - -typedef struct GP_EventKey { - /* event type */ - GP_EventType type; - /* device id */ - int dev_id; - /* key */ - int key; -} GP_EventKey; +#include +#include + +#define GP_EVENT_QUEUE_SIZE 32 + +enum GP_EventType { + GP_EV_KEY = 1, /* key/button press event */ + GP_EV_REL = 2, /* relative event */ + GP_EV_ABS = 3, /* absolute event */ + GP_EV_MAX = 3, /* maximum, greater values are free */ +}; + +enum GP_EventKeyCode { + GP_EV_KEY_UP = 0, + GP_EV_KEY_DOWN = 1, + GP_EV_KEY_REPEAT = 2, +}; + +/* + * This is 1:1 to linux kernel input subsystem. + */ +enum GP_EventKeyValue { + GP_KEY_ESC = 1, + GP_KEY_1 = 2, + GP_KEY_2 = 3, + GP_KEY_3 = 4, + GP_KEY_4 = 5, + GP_KEY_5 = 6, + GP_KEY_6 = 7, + GP_KEY_7 = 8, + GP_KEY_8 = 9, + GP_KEY_9 = 10, + GP_KEY_0 = 11, + GP_KEY_MINUS = 12, + GP_KEY_EQUAL = 13, + GP_KEY_BACKSPACE = 14, + GP_KEY_TAB = 15, + GP_KEY_Q = 16, + GP_KEY_W = 17, + GP_KEY_E = 18, + GP_KEY_R = 19, + GP_KEY_T = 20, + GP_KEY_Y = 21, + GP_KEY_U = 22, + GP_KEY_I = 23, + GP_KEY_O = 24, + GP_KEY_P = 25, + GP_KEY_LEFT_BRACE = 26, + GP_KEY_RIGHT_BRACE = 27, + GP_KEY_ENTER = 28, + GP_KEY_LEFT_CTRL = 29, + GP_KEY_A = 30, + GP_KEY_S = 31, + GP_KEY_D = 32, + GP_KEY_F = 33, + GP_KEY_G = 34, + GP_KEY_H = 35, + GP_KEY_J = 36, + GP_KEY_K = 37, + GP_KEY_L = 38, + GP_KEY_SEMICOLON = 39, + GP_KEY_APOSTROPHE = 40, + GP_KEY_GRAVE = 41, + GP_KEY_LEFT_SHIFT = 42, + GP_KEY_BACKSLASH = 43, + GP_KEY_Z = 44, + GP_KEY_X = 45, + GP_KEY_C = 46, + GP_KEY_V = 47, + GP_KEY_B = 48, + GP_KEY_N = 49, + GP_KEY_M = 50, + GP_KEY_COMMA = 51, + GP_KEY_DOT = 52, + GP_KEY_SLASH = 53, + GP_KEY_RIGHT_SHIFT = 54, + GP_KEY_KP_ASTERISK = 55, + GP_KEY_LEFT_ALT = 56, + GP_KEY_SPACE = 57, + GP_KEY_CAPS_LOCK = 58, + GP_KEY_F1 = 59, + GP_KEY_F2 = 60, + GP_KEY_F3 = 61, + GP_KEY_F4 = 62, + GP_KEY_F5 = 63, + GP_KEY_F6 = 64, + GP_KEY_F7 = 65, + GP_KEY_F8 = 66, + GP_KEY_F9 = 67, + GP_KEY_F10 = 68, + GP_KEY_NUM_LOCK = 69, + GP_KEY_SCROLL_LOCK = 70, + GP_KEY_KP_7 = 71, + GP_KEY_KP_8 = 72, + GP_KEY_KP_9 = 73, + GP_KEY_KP_MINUS = 74, + GP_KEY_KP_4 = 75, + GP_KEY_KP_5 = 76, + GP_KEY_KP_6 = 77, + GP_KEY_KP_PLUS = 78, + GP_KEY_KP_1 = 79, + GP_KEY_KP_2 = 80, + GP_KEY_KP_3 = 81, + GP_KEY_KP_0 = 82, + GP_KEY_KP_DOT = 83, + + GP_KEY_F11 = 87, + GP_KEY_F12 = 88, + + GP_KEY_KP_ENTER = 96, + GP_KEY_RIGHT_CTRL = 97, + GP_KEY_KP_SLASH = 98, + GP_KEY_SYSRQ = 99, + GP_KEY_RIGHT_ALT = 100, + + GP_KEY_HOME = 102, + GP_KEY_UP = 103, + GP_KEY_PAGE_UP = 104, + GP_KEY_LEFT = 105, + GP_KEY_RIGHT = 106, + GP_KEY_END = 107, + GP_KEY_DOWN = 108, + GP_KEY_PAGE_DOWN = 109, + GP_KEY_INSERT = 110, + GP_KEY_DELETE = 111, + + GP_KEY_KP_EQUAL = 117, + GP_KEY_KP_PLUS_MINUS = 118, + GP_KEY_PAUSE = 119, + + GP_KEY_KP_COMMA = 121, + + GP_KEY_LEFT_META = 125, + GP_KEY_RIGHT_META = 126, + GP_KEY_COMPOSE = 127, -typedef union GP_EventPtr { - GP_EventAbs *abs; - GP_EventRel *rel; - GP_EventKey *key; -} GP_EventPtr; + GP_KEY_F13 = 183, + GP_KEY_F14 = 184, + GP_KEY_F15 = 185, + GP_KEY_F16 = 186, + GP_KEY_F17 = 187, + GP_KEY_F18 = 188, + GP_KEY_F19 = 189, + GP_KEY_F20 = 190, + GP_KEY_F21 = 191, + GP_KEY_F22 = 192, + GP_KEY_F23 = 193, + GP_KEY_F24 = 194, -typedef struct GP_Time { - long sec; - long usec; -} GP_Time; + /* Common Buttons */ + GP_BTN_0 = 0x100, + GP_BTN_1 = 0x101, + GP_BTN_2 = 0x102, + GP_BTN_3 = 0x103, + GP_BTN_4 = 0x104, + GP_BTN_5 = 0x105, + GP_BTN_6 = 0x106, + GP_BTN_7 = 0x107, + GP_BTN_8 = 0x108, + GP_BTN_9 = 0x109, + + /* Mouse Buttons */ + GP_BTN_LEFT = 0x110, + GP_BTN_RIGHT = 0x111, + GP_BTN_MIDDLE = 0x112, + GP_BTN_SIDE = 0x113, + GP_BTN_EXTRA = 0x114, + GP_BTN_FORWARD = 0x115, + GP_BTN_BACK = 0x116, + GP_BTN_TASK = 0x117, +}; + +enum GP_EventRelCode { + GP_EV_REL_POS = 0, + GP_EV_REL_WHEEL = 1, +}; + +enum GP_EventAbsCode { + GP_EV_ABS_POS = 0, +}; + +struct GP_EventPosRel { + int32_t rx; + int32_t ry; +}; + +struct GP_EventPosAbs { + uint32_t x, x_max; /* the x is between 0 and x_max */ + uint32_t y, y_max; + uint32_t pressure, pressure_max; +}; + +struct GP_EventKey { + uint32_t key; + char ascii; +}; + +union GP_EventValue { + /* generic one integer value */ + int32_t val; + /* key */ + struct GP_EventKey key; + /* possition */ + struct GP_EventPosRel rel; + struct GP_EventPosAbs abs; +}; typedef struct GP_Event { - /* GP_EventType */ - int type; - /* GP_Event???Type */ - int stype; - /* time */ - GP_Time time; - /* event data */ - GP_EventPtr data; + /* event */ + uint16_t type; + uint32_t code; + union GP_EventValue val; + + /* input device id */ + uint32_t dev_id; + + /* event timestamp */ + struct timeval time; + + /* + * Cursor possition, possition on screen accumulated + * from all pointer devices + */ + uint32_t cursor_x; + uint32_t cursor_y; + + /* + * Bitmap of pressed keys including mouse buttons + * accumulated for all input devices. + */ + uint8_t keys_pressed[36]; } GP_Event; +/* + * Sets global screen size. + */ +void GP_EventSetScreenSize(uint32_t w, uint32_t h); + +/* + * Sets global cursor possition, doesn't generate event. + * + * Use for initial cursor placement. + */ +void GP_EventSetScreenCursor(uint32_t x, uint32_t y); + +/* + * Returns number of queued events. + */ +uint32_t GP_EventQueued(void); + +/* + * Dump event into stdout. + */ +void GP_EventDump(struct GP_Event *ev); + +/* + * Returns human-readable key name. + */ +const char *GP_EventKeyName(enum GP_EventKeyValue key); + +/* + * Fills event and returns true. Retuns false if queue is empty. + */ +int GP_EventGet(struct GP_Event *ev); + +/* + * Inject event that moves cursor by rx and ry. + */ +void GP_EventPushRel(int32_t rx, int32_t ry, struct timeval *time); + +/* + * Inject absolute event. + */ +void GP_EventPushAbs(uint32_t x, uint32_t y, uint32_t pressure, + uint32_t x_max, uint32_t y_max, uint32_t pressure_max, + struct timeval *time); + +/* + * Inject event that changes key state. + */ +void GP_EventPushKey(uint32_t key, uint8_t code, struct timeval *time); + +/* + * Inject common event. + */ +void GP_EventPush(uint16_t type, uint32_t code, int32_t value, + struct timeval *time); + +/* + * Helpers for setting/getting key bits. + */ +static inline void GP_EventSetKey(struct GP_Event *ev, + uint32_t key) +{ + ev->keys_pressed[(key)/8] |= 1<<((key)%8); +} + +static inline int GP_EventGetKey(struct GP_Event *ev, + uint32_t key) +{ + return !!(ev->keys_pressed[(key)/8] & ~(1<<((key)%8))); +} + +static inline void GP_EventResetKey(struct GP_Event *ev, + uint32_t key) +{ + ev->keys_pressed[(key)/8] |= 1<<((key)%8); +} + #endif /* GP_EVENT_H */ diff --git a/libs/input/GP_Event.c b/include/input/GP_InputDriverSDL.h similarity index 82% copy from libs/input/GP_Event.c copy to include/input/GP_InputDriverSDL.h index fdbeb21e..01269a9d 100644 --- a/libs/input/GP_Event.c +++ b/include/input/GP_InputDriverSDL.h @@ -16,12 +16,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * * - * * - * Copyright (C) 2009-2010 Cyril Hrubis * + * Copyright (C) 2009-2011 Cyril Hrubis * * * *****************************************************************************/ -#include "GP_Event.h" +/* + + + */ + +#ifndef GP_INPUT_DRIVER_SDL_H +#define GP_INPUT_DRIVER_SDL_H + +#include +#include + +/* + * Converts SDL event to GFXprim evevt and puts it into the queue. + */ +void GP_InputDriverSDLEventPut(SDL_Event *ev); +#endif /* GP_INPUT_DRIVER_SDL_H */ diff --git a/libs/input/GP_Event.c b/libs/input/GP_Event.c index fdbeb21e..5e87a045 100644 --- a/libs/input/GP_Event.c +++ b/libs/input/GP_Event.c @@ -16,12 +16,277 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * * - * * - * Copyright (C) 2009-2010 Cyril Hrubis * + * Copyright (C) 2009-2011 Cyril Hrubis * * * *****************************************************************************/ +#include +#include +#include + +#include "GP_Common.h" #include "GP_Event.h" +/* Screen size for clipping the cursor possition */ +static uint32_t screen_w = 0, screen_h = 0; + +/* Event queue */ +static uint32_t queue_first = 0, queue_last = 0; +static struct GP_Event event_queue[GP_EVENT_QUEUE_SIZE]; + +/* Global input state */ +static struct GP_Event cur_state = {.cursor_x = 0, .cursor_y = 0}; + +static char *key_names[] = { + "Reserved", "Escape", "1", "2", "3", + "4", "5", "6", "7", "8", + "9", "0", "Minus", "Equal", "BackSpace", + "Tab", "Q", "W", "E", "R", + "T", "Y", "U", "I", "O", + "P", "LeftBrace", "RightBrace", "Enter", "LeftCtrl", + "A", "S", "D", "F", "G", + "H", "J", "K", "L", "Semicolon", + "Apostrophe", "Grave", "LeftShift", "BackSlash", "Z", + "X", "C", "V", "B", "N", + "M", "Comma", "Dot", "Slash", "RightShift", + "KP Asterisk", "LeftAlt", "Space", "CapsLock", "F1", + "F2", "F3", "F4", "F5", "F6", + "F7", "F8", "F9", "F10", "NumLock", + "ScrollLock", "KP 7", "KP 8", "KP 9", "KP Minus", + "KP 4", "KP 5", "KP 6", "KP Plus", "KP 1", + "KP 2", "KP 3", "KP 0", "KP Dot", "?", + "?", "?", "F11", "F12", "?", + "?", "?", "?", "?", "?", + "?", "KP Enter", "RightCtrl", "KP Slash", "SysRq", + "RightAlt", "?", "Home", "Up", "PageUp", + "Left", "Right", "End", "Down", "PageDown", + "Insert", "Delete", "?", "?", "?", + "?", "?", "KP Equal", "KP PlusMinus", "Pause", + "?", "KP Comma", "?", "?", "?", + "LeftMeta", "RightMeta", "Compose", +}; + +static uint16_t key_names_size = sizeof(key_names)/sizeof(void*); + +void GP_EventSetScreenSize(uint32_t w, uint32_t h) +{ + screen_w = w; + screen_h = h; + + /* clip cursor */ + if (cur_state.cursor_x >= w) + cur_state.cursor_x = w - 1; + + if (cur_state.cursor_y >= h) + cur_state.cursor_y = h - 1; +} + +void GP_EventSetScreenCursor(uint32_t x, uint32_t y) +{ + cur_state.cursor_x = x; + cur_state.cursor_y = y; +} + +uint32_t GP_EventQueued(void) +{ + if (queue_first <= queue_last) + return queue_last - queue_first; + + return GP_EVENT_QUEUE_SIZE - (queue_last - queue_first); +} + +int GP_EventGet(struct GP_Event *ev) +{ + if (queue_first == queue_last) + return 0; + + *ev = event_queue[queue_first]; + + queue_first = (queue_first + 1) % GP_EVENT_QUEUE_SIZE; + + return 1; +} + +const char *GP_EventKeyName(enum GP_EventKeyValue key) +{ + if (key < key_names_size) + return key_names[key]; + + switch (key) { + case GP_BTN_LEFT: + return "LeftButton"; + case GP_BTN_RIGHT: + return "RightButton"; + case GP_BTN_MIDDLE: + return "MiddleButton"; + default: + return "Unknown"; + }; + +} + +static void dump_rel(struct GP_Event *ev) +{ + printf("EVENT REL "); + + switch (ev->code) { + case GP_EV_REL_POS: + printf("POSSITION %u %u\n", ev->cursor_x, ev->cursor_y); + break; + case GP_EV_REL_WHEEL: + printf("WHEEL %i\n", ev->val.val); + break; + } +} + +static void dump_key(struct GP_Event *ev) +{ + const char *name = GP_EventKeyName(ev->val.key.key); + + if (ev->val.key.key < key_names_size) + name = key_names[ev->val.key.key]; + + printf("EVENT KEY %i (Key%s) %s\n", + ev->val.key.key, name, ev->code ? "down" : "up"); + +} + +void GP_EventDump(struct GP_Event *ev) +{ + switch (ev->type) { + case GP_EV_KEY: + dump_key(ev); + break; + case GP_EV_REL: + dump_rel(ev); + break; + case GP_EV_ABS: + printf("EVENT ABS\n"); + break; + } +} + +static void event_put(struct GP_Event *ev) +{ + uint32_t next = (queue_last + 1) % GP_EVENT_QUEUE_SIZE; + + if (next == queue_first) { + fprintf(stderr, "Event queue full, dropping event\n"); + return; + } + + event_queue[queue_last] = *ev; + queue_last = next; +} + +static void set_time(struct timeval *time) +{ + if (time == NULL) + gettimeofday(&cur_state.time, NULL); + else + cur_state.time = *time; +} + +static uint32_t clip_rel(uint32_t val, uint32_t max, int32_t rel) +{ + if (rel < 0) { + if (val < GP_ABS(rel)) + return 0; + else + return val + rel; + } + + if (val + rel >= max) + return max - 1; + + return val + rel; +} + +void GP_EventPushRel(int32_t rx, int32_t ry, struct timeval *time) +{ + /* event header */ + cur_state.type = GP_EV_REL; + cur_state.code = GP_EV_REL_POS; + + cur_state.val.rel.rx = rx; + cur_state.val.rel.ry = ry; + + set_time(time); + + /* move the global cursor */ + cur_state.cursor_x = clip_rel(cur_state.cursor_x, screen_w, rx); + cur_state.cursor_y = clip_rel(cur_state.cursor_y, screen_h, ry); + + /* put it into queue */ + event_put(&cur_state); +} + +void GP_EventPushAbs(uint32_t x, uint32_t y, uint32_t pressure, + uint32_t x_max, uint32_t y_max, uint32_t pressure_max, + struct timeval *time) +{ + /* event header */ + cur_state.type = GP_EV_ABS; + cur_state.code = GP_EV_REL_POS; + cur_state.val.abs.x = x; + cur_state.val.abs.y = y; + cur_state.val.abs.pressure = pressure; + cur_state.val.abs.x_max = x_max; + cur_state.val.abs.y_max = y_max; + cur_state.val.abs.pressure_max = pressure_max; + + set_time(time); + + /* set global cursor */ + cur_state.cursor_x = x * screen_w / x_max; + cur_state.cursor_y = y * screen_h / y_max; + + /* put it into queue */ + event_put(&cur_state); +} + +void GP_EventPushKey(uint32_t key, uint8_t code, struct timeval *time) +{ + switch (code) { + case GP_EV_KEY_UP: + GP_EventResetKey(&cur_state, key); + break; + case GP_EV_KEY_DOWN: + GP_EventSetKey(&cur_state, key); + break; + case GP_EV_KEY_REPEAT: + break; + default: + fprintf(stderr, "Invalid key event code %u\n", code); + return; + } + + /* event header */ + cur_state.type = GP_EV_KEY; + cur_state.code = code; + cur_state.val.key.key = key; + //TODO cur_state.val.key.ascii + + set_time(time); + + /* put it into queue */ + event_put(&cur_state); +} + +void GP_EventPush(uint16_t type, uint32_t code, int32_t value, + struct timeval *time) +{ + switch (type) { + case GP_EV_KEY: + GP_EventPushKey(code, value, time); + break; + default: + cur_state.type = type; + cur_state.code = code; + cur_state.val.val = value; + + set_time(time); + + event_put(&cur_state); + } +} diff --git a/libs/input/GP_InputDriverSDL.c b/libs/input/GP_InputDriverSDL.c new file mode 100644 index 00000000..3e7f5d14 --- /dev/null +++ b/libs/input/GP_InputDriverSDL.c @@ -0,0 +1,138 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2011 Cyril Hrubis * + * * + *****************************************************************************/ + + +#include "GP_Event.h" +#include "GP_InputDriverSDL.h" + +/* SDL ascii mapped keys */ +static uint16_t keysym_table1[] = { + 0, 0, 0, 0, + 0, 0, 0, GP_KEY_BACKSPACE, + GP_KEY_TAB, 0, 0, 0, + GP_KEY_ENTER, 0, 0, 0, + 0, 0, GP_KEY_PAUSE, 0, + 0, 0, 0, 0, + 0, 0, GP_KEY_ESC, 0, + 0, 0, 0, GP_KEY_SPACE, + 0, 0, 0, 0, + 0, 0, GP_KEY_APOSTROPHE, 0, + 0, 0, 0, GP_KEY_COMMA, + GP_KEY_MINUS, GP_KEY_DOT, GP_KEY_SLASH, GP_KEY_0, + GP_KEY_1, GP_KEY_2, GP_KEY_3, GP_KEY_4, + GP_KEY_5, GP_KEY_6, GP_KEY_7, GP_KEY_8, + GP_KEY_9, 0, GP_KEY_SEMICOLON, 0, + GP_KEY_EQUAL, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, GP_KEY_LEFT_BRACE, GP_KEY_BACKSLASH, + GP_KEY_RIGHT_BRACE, 0, 0, GP_KEY_GRAVE, + GP_KEY_A, GP_KEY_B, GP_KEY_C, GP_KEY_D, + GP_KEY_E, GP_KEY_F, GP_KEY_G, GP_KEY_H, + GP_KEY_I, GP_KEY_J, GP_KEY_K, GP_KEY_L, + GP_KEY_M, GP_KEY_N, GP_KEY_O, GP_KEY_P, + GP_KEY_Q, GP_KEY_R, GP_KEY_S, GP_KEY_T, + GP_KEY_U, GP_KEY_V, GP_KEY_W, GP_KEY_X, + GP_KEY_Y, GP_KEY_Z, 0, 0, + 0, 0, GP_KEY_DELETE, +}; + +static const uint16_t keysym_table1_size = sizeof(keysym_table1)/2; + +/* keypad and function keys starting at 256 */ +static uint16_t keysym_table2[] = { + GP_KEY_KP_0, GP_KEY_KP_1, GP_KEY_KP_2, GP_KEY_KP_3, + GP_KEY_KP_4, GP_KEY_KP_5, GP_KEY_KP_6, GP_KEY_KP_7, + GP_KEY_KP_8, GP_KEY_KP_9, GP_KEY_KP_DOT, GP_KEY_KP_SLASH, + GP_KEY_KP_ASTERISK, GP_KEY_KP_MINUS, GP_KEY_KP_PLUS, GP_KEY_KP_ENTER, + GP_KEY_KP_EQUAL, GP_KEY_UP, GP_KEY_DOWN, GP_KEY_RIGHT, + GP_KEY_LEFT, GP_KEY_INSERT, GP_KEY_HOME, GP_KEY_END, + GP_KEY_PAGE_UP, GP_KEY_PAGE_DOWN, GP_KEY_F1, GP_KEY_F2, + GP_KEY_F3, GP_KEY_F4, GP_KEY_F5, GP_KEY_F6, + GP_KEY_F7, GP_KEY_F8, GP_KEY_F9, GP_KEY_F10, + GP_KEY_F11, GP_KEY_F12, GP_KEY_F13, GP_KEY_F14, + GP_KEY_F15, 0, 0, 0, + GP_KEY_NUM_LOCK, GP_KEY_CAPS_LOCK, GP_KEY_SCROLL_LOCK, GP_KEY_RIGHT_SHIFT, + GP_KEY_LEFT_SHIFT, GP_KEY_RIGHT_CTRL, GP_KEY_LEFT_CTRL, GP_KEY_RIGHT_ALT, + GP_KEY_LEFT_ALT, 0, 0, GP_KEY_LEFT_META, + GP_KEY_RIGHT_META, 0, 0, 0, + GP_KEY_SYSRQ, 0, 0, GP_KEY_COMPOSE, +}; + +static const uint16_t keysym_table2_size = sizeof(keysym_table2)/2; + +void GP_InputDriverSDLEventPut(SDL_Event *ev) +{ + uint16_t keysym; + uint32_t key = 0; + + switch (ev->type) { + case SDL_MOUSEMOTION: + GP_EventPushRel(ev->motion.xrel, ev->motion.yrel, NULL); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + switch (ev->button.button) { + case 1: + key = GP_BTN_LEFT; + break; + case 2: + key = GP_BTN_MIDDLE; + break; + case 3: + key = GP_BTN_RIGHT; + break; + default: + return; + } + + GP_EventPush(GP_EV_KEY, key, ev->button.state, NULL); + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + keysym = ev->key.keysym.sym; + + if (keysym > 0 && keysym <= keysym_table1_size) + key = keysym_table1[keysym - 1]; + + if (keysym > 255 && keysym <= 255 + keysym_table2_size) + key = keysym_table2[keysym - 256]; + + if (key == 0) { + fprintf(stderr, "Unmapped SDL keysym %u\n", keysym); + return; + } + + printf("*** KEYSYM %u KEY %u\n", keysym, key); + + GP_EventPushKey(key, ev->key.state, NULL); + break; + case SDL_VIDEORESIZE: + break; + case SDL_QUIT: + break; + } +} diff --git a/libs/input/Makefile b/libs/input/Makefile index 0dcb2086..afadcd17 100644 --- a/libs/input/Makefile +++ b/libs/input/Makefile @@ -1,5 +1,6 @@ TOPDIR=../.. CSOURCES=$(shell ls *.c) +INCLUDE=core LIBNAME=input include $(TOPDIR)/include.mk include $(TOPDIR)/lib.mk diff --git a/tests/SDL/Makefile b/tests/SDL/Makefile index e186c7af..0c908f2f 100644 --- a/tests/SDL/Makefile +++ b/tests/SDL/Makefile @@ -6,7 +6,7 @@ INCLUDE=core gfx SDL backends LDLIBS+=-lGP -L$(TOPDIR)/build/ -lGP_SDL -lSDL APPS=pixeltest fileview fonttest linetest randomshapetest shapetest sierpinsky\ - symbolstest textaligntest trianglefps + symbolstest textaligntest trianglefps input include $(TOPDIR)/include.mk include $(TOPDIR)/app.mk diff --git a/tests/SDL/input.c b/tests/SDL/input.c new file mode 100644 index 00000000..7ff2dc5a --- /dev/null +++ b/tests/SDL/input.c @@ -0,0 +1,182 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * + * * + * * + * Copyright (C) 2009-2010 Cyril Hrubis * + * * + *****************************************************************************/ + +#include +#include +#include + +#include "GP.h" +#include "GP_SDL.h" + +/* The surface used as a display (in fact it is a software surface). */ +SDL_Surface *display = NULL; +GP_Context context; + +/* Timer used for refreshing the display */ +SDL_TimerID timer; + +/* An event used for signaling that the timer was triggered. */ +SDL_UserEvent timer_event; + +/* Values for color pixels in display format. */ +GP_Pixel red_pixel, green_pixel, blue_pixel, white_pixel; + +Uint32 timer_callback(__attribute__((unused)) Uint32 interval, + __attribute__((unused)) void *param) +{ + timer_event.type = SDL_USEREVENT; + SDL_PushEvent((SDL_Event *) &timer_event); + return 30; +} + +void draw_pixel(void) +{ +// GP_Color pixel, conv; + int x = random() % 320; + int y = random() % 240; + +// pixel = GP_GetPixel(&context, x, y); + + GP_PutPixel(&context, x, y, green_pixel); + + /* TODO: we cannot switch like this + we need either to convert blue + and others into Context format + at the very beginning, or make + a copy to convert it and match + agains what we get from GP_GetPixel + + if (pixel == blue) { + GP_PutPixel(&context, x, y, green); + } + else if (pixel == red) { + GP_PutPixel(&context, x, y, white); + } + else { + if (x < 160) { + GP_PutPixel(&context, x, y, blue); + } else { + GP_PutPixel(&context, x, y, red); + } + } */ +} + +void draw_pixels(void) +{ + SDL_LockSurface(display); + + /* Draw some pixels (exact number is not important). */ + int i; + for (i = 0; i < 30; i++) + draw_pixel(); + + SDL_UnlockSurface(display); +} + +void event_loop(void) +{ + SDL_Event event; + + while (SDL_WaitEvent(&event) > 0) { + GP_InputDriverSDLEventPut(&event); + + while (GP_EventQueued()) { + GP_Event ev; + + GP_EventGet(&ev); + GP_EventDump(&ev); + + if (ev.type == GP_EV_KEY && + ev.val.key.key == GP_KEY_ESC) + exit(0); + } + } +} + +int main(int argc, char **argv) +{ + int display_bpp = 0; + + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-16") == 0) { + display_bpp = 16; + } else if (strcmp(argv[i], "-24") == 0) { + display_bpp = 24; + } + } + + /* Initialize SDL */ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { + fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + /* Create a window with a software back surface */ + display = SDL_SetVideoMode(320, 240, display_bpp, SDL_SWSURFACE); + if (display == NULL) { + fprintf(stderr, "Could not open display: %s\n", SDL_GetError()); + goto fail; + } + + GP_EventSetScreenSize(320, 240); + + /* Print basic information about the surface */ + printf("Display surface properties:\n"); + printf(" width: %4d, height: %4d, pitch: %4d\n", + display->w, display->h, display->pitch); + printf(" bits per pixel: %2d, bytes per pixel: %2d\n", + display->format->BitsPerPixel, display->format->BytesPerPixel); + + /* Set up a clipping rectangle to test proper clipping of pixels */ + SDL_Rect clip_rect = {10, 10, 300, 220}; + SDL_SetClipRect(display, &clip_rect); + + GP_SDL_ContextFromSurface(&context, display); + + /* Load pixel values compatible with the display. */ + red_pixel = GP_ColorToPixel(&context, GP_COL_RED); + green_pixel = GP_ColorToPixel(&context, GP_COL_GREEN); + blue_pixel = GP_ColorToPixel(&context, GP_COL_BLUE); + white_pixel = GP_ColorToPixel(&context, GP_COL_WHITE); + + /* Set up the refresh timer */ + timer = SDL_AddTimer(30, timer_callback, NULL); + if (timer == 0) { + fprintf(stderr, "Could not set up timer: %s\n", SDL_GetError()); + goto fail; + } + + /* Enter the event loop */ + event_loop(); + + /* We're done */ + SDL_Quit(); + return 0; + +fail: + SDL_Quit(); + return 1; +} -- 2.11.4.GIT