src/video/mir/SDL_mirevents.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 03 Feb 2014 11:52:54 -0500
changeset 8159 427e8fdf6f69
parent 8157 f5d262613ed2
child 8682 a31313cfa891
permissions -rw-r--r--
Hooked up dynamic loading for Mir.
     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 
    42 static void
    43 HandleKeyText(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 
    56 static void
    57 CheckKeyboardFocus(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 */
    70 static void
    71 HandleKeyEvent(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 
    88 static void
    89 HandleMouseButton(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 
   119 static void
   120 HandleTouchPress(int device_id, int source_id, SDL_bool down, float x, float y, float pressure)
   121 {
   122     SDL_SendTouch(device_id, source_id, down, x, y, pressure);
   123 }
   124 
   125 static void
   126 HandleTouchMotion(int device_id, int source_id, float x, float y, float pressure)
   127 {
   128     SDL_SendTouchMotion(device_id, source_id, x, y, pressure);
   129 }
   130 
   131 static void
   132 HandleMouseMotion(SDL_Window* sdl_window, int x, int y)
   133 {
   134     SDL_SendMouseMotion(sdl_window, 0, 0, x, y);
   135 }
   136 
   137 static void
   138 HandleMouseScroll(SDL_Window* sdl_window, int hscroll, int vscroll)
   139 {
   140     SDL_SendMouseWheel(sdl_window, 0, hscroll, vscroll);
   141 }
   142 
   143 static void
   144 AddTouchDevice(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 
   150 static void
   151 HandleTouchEvent(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 
   185 static void
   186 HandleMouseEvent(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 #if 0  /* !!! FIXME: needs a newer set of dev headers than Ubuntu 13.10 is shipping atm. */
   209         case mir_motion_action_scroll:
   210             HandleMouseScroll(sdl_window,
   211                               motion.pointer_coordinates[cord_index].hscroll,
   212                               motion.pointer_coordinates[cord_index].vscroll);
   213             break;
   214 #endif
   215         case mir_motion_action_cancel:
   216         case mir_motion_action_hover_enter:
   217         case mir_motion_action_hover_exit:
   218             break;
   219         default:
   220             break;
   221     }
   222 }
   223 
   224 static void
   225 HandleMotionEvent(MirMotionEvent const motion, SDL_Window* sdl_window)
   226 {
   227     int cord_index;
   228     for (cord_index = 0; cord_index < motion.pointer_count; cord_index++) {
   229 #if 0  /* !!! FIXME: needs a newer set of dev headers than Ubuntu 13.10 is shipping atm. */
   230         if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_mouse) {
   231             HandleMouseEvent(motion, cord_index, sdl_window);
   232         }
   233         else if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_finger) {
   234             HandleTouchEvent(motion, cord_index, sdl_window);
   235         }
   236 #else
   237         HandleMouseEvent(motion, cord_index, sdl_window);
   238 #endif
   239     }
   240 }
   241 
   242 void
   243 MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context)
   244 {
   245     SDL_Window* window = (SDL_Window*)context;
   246     switch (ev->type) {
   247         case (mir_event_type_key):
   248             HandleKeyEvent(ev->key, window);
   249             break;
   250         case (mir_event_type_motion):
   251             HandleMotionEvent(ev->motion, window);
   252             break;
   253         default:
   254             break;
   255     }
   256 }
   257 
   258 #endif /* SDL_VIDEO_DRIVER_MIR */
   259 
   260 /* vi: set ts=4 sw=4 expandtab: */