src/video/mir/SDL_mirevents.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 03 Feb 2014 11:01:32 -0500
changeset 8157 f5d262613ed2
parent 8156 d88db77c637e
child 8159 427e8fdf6f69
permissions -rw-r--r--
Bumped copyright date on Mir code.
     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 static void
    41 HandleKeyText(int32_t key_code)
    42 {
    43     char text[8];
    44     int size = 0;
    45 
    46     size = xkb_keysym_to_utf8(key_code, text, sizeof text);
    47 
    48     if (size > 0) {
    49         text[size] = '\0';
    50         SDL_SendKeyboardText(text);
    51     }
    52 }
    53 
    54 static void
    55 CheckKeyboardFocus(SDL_Window* sdl_window)
    56 {
    57     SDL_Window* keyboard_window = SDL_GetKeyboardFocus();
    58 
    59     if (keyboard_window != sdl_window)
    60         SDL_SetKeyboardFocus(sdl_window);
    61 }
    62 
    63 
    64 /* FIXME
    65    Mir still needs to implement its IM API, for now we assume
    66    a single key press produces a character.
    67 */
    68 static void
    69 HandleKeyEvent(MirKeyEvent const ev, SDL_Window* window)
    70 {
    71     uint32_t scancode = SDL_SCANCODE_UNKNOWN;
    72     Uint8 key_state = ev.action == mir_key_action_up ? SDL_RELEASED : SDL_PRESSED;
    73 
    74     CheckKeyboardFocus(window);
    75 
    76     if (ev.scan_code < SDL_arraysize(xfree86_scancode_table2))
    77         scancode = xfree86_scancode_table2[ev.scan_code];
    78 
    79     if (scancode != SDL_SCANCODE_UNKNOWN)
    80         SDL_SendKeyboardKey(key_state, scancode);
    81 
    82     if (key_state == SDL_PRESSED)
    83         HandleKeyText(ev.key_code);
    84 }
    85 
    86 static void
    87 HandleMouseButton(SDL_Window* sdl_window, Uint8 state, MirMotionButton button_state)
    88 {
    89     static uint32_t last_sdl_button;
    90     uint32_t sdl_button;
    91 
    92     switch (button_state) {
    93         case mir_motion_button_primary:
    94             sdl_button = SDL_BUTTON_LEFT;
    95             break;
    96         case mir_motion_button_secondary:
    97             sdl_button = SDL_BUTTON_RIGHT;
    98             break;
    99         case mir_motion_button_tertiary:
   100             sdl_button = SDL_BUTTON_MIDDLE;
   101             break;
   102         case mir_motion_button_forward:
   103             sdl_button = SDL_BUTTON_X1;
   104             break;
   105         case mir_motion_button_back:
   106             sdl_button = SDL_BUTTON_X2;
   107             break;
   108         default:
   109             sdl_button = last_sdl_button;
   110             break;
   111     }
   112 
   113     last_sdl_button = sdl_button;
   114     SDL_SendMouseButton(sdl_window, 0, state, sdl_button);
   115 }
   116 
   117 static void
   118 HandleTouchPress(int device_id, int source_id, SDL_bool down, float x, float y, float pressure)
   119 {
   120     SDL_SendTouch(device_id, source_id, down, x, y, pressure);
   121 }
   122 
   123 static void
   124 HandleTouchMotion(int device_id, int source_id, float x, float y, float pressure)
   125 {
   126     SDL_SendTouchMotion(device_id, source_id, x, y, pressure);
   127 }
   128 
   129 static void
   130 HandleMouseMotion(SDL_Window* sdl_window, int x, int y)
   131 {
   132     SDL_SendMouseMotion(sdl_window, 0, 0, x, y);
   133 }
   134 
   135 static void
   136 HandleMouseScroll(SDL_Window* sdl_window, int hscroll, int vscroll)
   137 {
   138     SDL_SendMouseWheel(sdl_window, 0, hscroll, vscroll);
   139 }
   140 
   141 static void
   142 AddTouchDevice(int device_id)
   143 {
   144     if (SDL_AddTouch(device_id, "") < 0)
   145         SDL_SetError("Error: can't add touch %s, %d", __FILE__, __LINE__);
   146 }
   147 
   148 static void
   149 HandleTouchEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window)
   150 {
   151     int device_id = motion.device_id;
   152     int id = motion.pointer_coordinates[cord_index].id;
   153 
   154     int width  = sdl_window->w;
   155     int height = sdl_window->h;
   156     float x   = motion.pointer_coordinates[cord_index].x;
   157     float y   = motion.pointer_coordinates[cord_index].y;
   158 
   159     float n_x = x / width;
   160     float n_y = y / height;
   161     float pressure = motion.pointer_coordinates[cord_index].pressure;
   162 
   163     AddTouchDevice(motion.device_id);
   164 
   165     switch (motion.action) {
   166         case mir_motion_action_down:
   167         case mir_motion_action_pointer_down:
   168             HandleTouchPress(device_id, id, SDL_TRUE, n_x, n_y, pressure);
   169             break;
   170         case mir_motion_action_up:
   171         case mir_motion_action_pointer_up:
   172             HandleTouchPress(device_id, id, SDL_FALSE, n_x, n_y, pressure);
   173             break;
   174         case mir_motion_action_hover_move:
   175         case mir_motion_action_move:
   176             HandleTouchMotion(device_id, id, n_x, n_y, pressure);
   177             break;
   178         default:
   179             break;
   180     }
   181 }
   182 
   183 static void
   184 HandleMouseEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window)
   185 {
   186     SDL_SetMouseFocus(sdl_window);
   187 
   188     switch (motion.action) {
   189         case mir_motion_action_down:
   190         case mir_motion_action_pointer_down:
   191             HandleMouseButton(sdl_window, SDL_PRESSED, motion.button_state);
   192             break;
   193         case mir_motion_action_up:
   194         case mir_motion_action_pointer_up:
   195             HandleMouseButton(sdl_window, SDL_RELEASED, motion.button_state);
   196             break;
   197         case mir_motion_action_hover_move:
   198         case mir_motion_action_move:
   199             HandleMouseMotion(sdl_window,
   200                               motion.pointer_coordinates[cord_index].x,
   201                               motion.pointer_coordinates[cord_index].y);
   202             break;
   203         case mir_motion_action_outside:
   204             SDL_SetMouseFocus(NULL);
   205             break;
   206 #if 0  /* !!! FIXME: needs a newer set of dev headers than Ubuntu 13.10 is shipping atm. */
   207         case mir_motion_action_scroll:
   208             HandleMouseScroll(sdl_window,
   209                               motion.pointer_coordinates[cord_index].hscroll,
   210                               motion.pointer_coordinates[cord_index].vscroll);
   211             break;
   212 #endif
   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 
   222 static void
   223 HandleMotionEvent(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 0  /* !!! FIXME: needs a newer set of dev headers than Ubuntu 13.10 is shipping atm. */
   228         if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_mouse) {
   229             HandleMouseEvent(motion, cord_index, sdl_window);
   230         }
   231         else if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_finger) {
   232             HandleTouchEvent(motion, cord_index, sdl_window);
   233         }
   234 #else
   235         HandleMouseEvent(motion, cord_index, sdl_window);
   236 #endif
   237     }
   238 }
   239 
   240 void
   241 MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context)
   242 {
   243     SDL_Window* window = (SDL_Window*)context;
   244     switch (ev->type) {
   245         case (mir_event_type_key):
   246             HandleKeyEvent(ev->key, window);
   247             break;
   248         case (mir_event_type_motion):
   249             HandleMotionEvent(ev->motion, window);
   250             break;
   251         default:
   252             break;
   253     }
   254 }
   255 
   256 #endif /* SDL_VIDEO_DRIVER_MIR */
   257 
   258 /* vi: set ts=4 sw=4 expandtab: */