src/video/mir/SDL_mirevents.c
author Brandon Schaefer <brandon.schaefer@canonical.com>
Wed, 04 Jun 2014 12:55:18 -0700
changeset 8824 c2a79f186731
parent 8723 cfc134c9c369
child 9257 6f41196c2d6b
permissions -rw-r--r--
Assume all motion events are mouse events unless tool_type states otherwise.
     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 HandleMouseMotion(SDL_Window* sdl_window, int x, int y)
   121 {
   122     SDL_SendMouseMotion(sdl_window, 0, 0, x, y);
   123 }
   124 
   125 static void
   126 HandleTouchPress(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 
   131 static void
   132 HandleTouchMotion(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 
   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         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 
   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 (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 
   236 void
   237 MIR_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: */