SDL_mirevents.c (7464B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21 22/* 23 Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com> 24*/ 25 26#include "../../SDL_internal.h" 27 28#if SDL_VIDEO_DRIVER_MIR 29 30#include "../../events/SDL_events_c.h" 31#include "../../events/SDL_keyboard_c.h" 32#include "../../events/SDL_touch_c.h" 33#include "../../events/scancodes_xfree86.h" 34 35#include "SDL_mirevents.h" 36#include "SDL_mirwindow.h" 37 38#include <xkbcommon/xkbcommon.h> 39 40#include "SDL_mirdyn.h" 41 42static void 43HandleKeyText(int32_t key_code) 44{ 45 char text[8]; 46 int size = 0; 47 48 size = MIR_xkb_keysym_to_utf8(key_code, text, sizeof text); 49 50 if (size > 0) { 51 text[size] = '\0'; 52 SDL_SendKeyboardText(text); 53 } 54} 55 56static void 57CheckKeyboardFocus(SDL_Window* sdl_window) 58{ 59 SDL_Window* keyboard_window = SDL_GetKeyboardFocus(); 60 61 if (keyboard_window != sdl_window) 62 SDL_SetKeyboardFocus(sdl_window); 63} 64 65 66/* FIXME 67 Mir still needs to implement its IM API, for now we assume 68 a single key press produces a character. 69*/ 70static void 71HandleKeyEvent(MirKeyEvent const ev, SDL_Window* window) 72{ 73 uint32_t scancode = SDL_SCANCODE_UNKNOWN; 74 Uint8 key_state = ev.action == mir_key_action_up ? SDL_RELEASED : SDL_PRESSED; 75 76 CheckKeyboardFocus(window); 77 78 if (ev.scan_code < SDL_arraysize(xfree86_scancode_table2)) 79 scancode = xfree86_scancode_table2[ev.scan_code]; 80 81 if (scancode != SDL_SCANCODE_UNKNOWN) 82 SDL_SendKeyboardKey(key_state, scancode); 83 84 if (key_state == SDL_PRESSED) 85 HandleKeyText(ev.key_code); 86} 87 88static void 89HandleMouseButton(SDL_Window* sdl_window, Uint8 state, MirMotionButton button_state) 90{ 91 static uint32_t last_sdl_button; 92 uint32_t sdl_button; 93 94 switch (button_state) { 95 case mir_motion_button_primary: 96 sdl_button = SDL_BUTTON_LEFT; 97 break; 98 case mir_motion_button_secondary: 99 sdl_button = SDL_BUTTON_RIGHT; 100 break; 101 case mir_motion_button_tertiary: 102 sdl_button = SDL_BUTTON_MIDDLE; 103 break; 104 case mir_motion_button_forward: 105 sdl_button = SDL_BUTTON_X1; 106 break; 107 case mir_motion_button_back: 108 sdl_button = SDL_BUTTON_X2; 109 break; 110 default: 111 sdl_button = last_sdl_button; 112 break; 113 } 114 115 last_sdl_button = sdl_button; 116 SDL_SendMouseButton(sdl_window, 0, state, sdl_button); 117} 118 119static void 120HandleMouseMotion(SDL_Window* sdl_window, int x, int y) 121{ 122 SDL_SendMouseMotion(sdl_window, 0, 0, x, y); 123} 124 125static void 126HandleTouchPress(int device_id, int source_id, SDL_bool down, float x, float y, float pressure) 127{ 128 SDL_SendTouch(device_id, source_id, down, x, y, pressure); 129} 130 131static void 132HandleTouchMotion(int device_id, int source_id, float x, float y, float pressure) 133{ 134 SDL_SendTouchMotion(device_id, source_id, x, y, pressure); 135} 136 137static void 138HandleMouseScroll(SDL_Window* sdl_window, int hscroll, int vscroll) 139{ 140 SDL_SendMouseWheel(sdl_window, 0, hscroll, vscroll); 141} 142 143static void 144AddTouchDevice(int device_id) 145{ 146 if (SDL_AddTouch(device_id, "") < 0) 147 SDL_SetError("Error: can't add touch %s, %d", __FILE__, __LINE__); 148} 149 150static void 151HandleTouchEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window) 152{ 153 int device_id = motion.device_id; 154 int id = motion.pointer_coordinates[cord_index].id; 155 156 int width = sdl_window->w; 157 int height = sdl_window->h; 158 float x = motion.pointer_coordinates[cord_index].x; 159 float y = motion.pointer_coordinates[cord_index].y; 160 161 float n_x = x / width; 162 float n_y = y / height; 163 float pressure = motion.pointer_coordinates[cord_index].pressure; 164 165 AddTouchDevice(motion.device_id); 166 167 switch (motion.action) { 168 case mir_motion_action_down: 169 case mir_motion_action_pointer_down: 170 HandleTouchPress(device_id, id, SDL_TRUE, n_x, n_y, pressure); 171 break; 172 case mir_motion_action_up: 173 case mir_motion_action_pointer_up: 174 HandleTouchPress(device_id, id, SDL_FALSE, n_x, n_y, pressure); 175 break; 176 case mir_motion_action_hover_move: 177 case mir_motion_action_move: 178 HandleTouchMotion(device_id, id, n_x, n_y, pressure); 179 break; 180 default: 181 break; 182 } 183} 184 185static void 186HandleMouseEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window) 187{ 188 SDL_SetMouseFocus(sdl_window); 189 190 switch (motion.action) { 191 case mir_motion_action_down: 192 case mir_motion_action_pointer_down: 193 HandleMouseButton(sdl_window, SDL_PRESSED, motion.button_state); 194 break; 195 case mir_motion_action_up: 196 case mir_motion_action_pointer_up: 197 HandleMouseButton(sdl_window, SDL_RELEASED, motion.button_state); 198 break; 199 case mir_motion_action_hover_move: 200 case mir_motion_action_move: 201 HandleMouseMotion(sdl_window, 202 motion.pointer_coordinates[cord_index].x, 203 motion.pointer_coordinates[cord_index].y); 204 break; 205 case mir_motion_action_outside: 206 SDL_SetMouseFocus(NULL); 207 break; 208 case mir_motion_action_scroll: 209 HandleMouseScroll(sdl_window, 210 motion.pointer_coordinates[cord_index].hscroll, 211 motion.pointer_coordinates[cord_index].vscroll); 212 break; 213 case mir_motion_action_cancel: 214 case mir_motion_action_hover_enter: 215 case mir_motion_action_hover_exit: 216 break; 217 default: 218 break; 219 } 220} 221 222static void 223HandleMotionEvent(MirMotionEvent const motion, SDL_Window* sdl_window) 224{ 225 int cord_index; 226 for (cord_index = 0; cord_index < motion.pointer_count; cord_index++) { 227 if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_finger) { 228 HandleTouchEvent(motion, cord_index, sdl_window); 229 } 230 else { 231 HandleMouseEvent(motion, cord_index, sdl_window); 232 } 233 } 234} 235 236void 237MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context) 238{ 239 SDL_Window* window = (SDL_Window*)context; 240 switch (ev->type) { 241 case (mir_event_type_key): 242 HandleKeyEvent(ev->key, window); 243 break; 244 case (mir_event_type_motion): 245 HandleMotionEvent(ev->motion, window); 246 break; 247 default: 248 break; 249 } 250} 251 252#endif /* SDL_VIDEO_DRIVER_MIR */ 253 254/* vi: set ts=4 sw=4 expandtab: */