src/video/mir/SDL_mirevents.c
author bschaefer
Sun, 21 Feb 2016 15:19:35 -0800
changeset 10089 25fda20d0173
parent 9998 f67cf37e9cd4
child 10180 7356b2938fba
permissions -rw-r--r--
Fix API/ABI breakage in Mir 0.13/0.14.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 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 (sdl_window && 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(MirKeyboardEvent const* key_event, SDL_Window* window)
    72 {
    73     xkb_keysym_t key_code;
    74     Uint8 key_state;
    75     int event_scancode;
    76     uint32_t sdl_scancode = SDL_SCANCODE_UNKNOWN;
    77 
    78     MirKeyboardAction action = MIR_mir_keyboard_event_action(key_event);
    79 
    80     key_state      = SDL_PRESSED;
    81     key_code       = MIR_mir_keyboard_event_key_code(key_event);
    82     event_scancode = MIR_mir_keyboard_event_scan_code(key_event);
    83 
    84     if (action == mir_keyboard_action_up)
    85         key_state = SDL_RELEASED;
    86 
    87     CheckKeyboardFocus(window);
    88 
    89     if (event_scancode < SDL_arraysize(xfree86_scancode_table2))
    90         sdl_scancode = xfree86_scancode_table2[event_scancode];
    91 
    92     if (sdl_scancode != SDL_SCANCODE_UNKNOWN)
    93         SDL_SendKeyboardKey(key_state, sdl_scancode);
    94 
    95     if (key_state == SDL_PRESSED)
    96         HandleKeyText(key_code);
    97 }
    98 
    99 static void
   100 HandleMouseButton(SDL_Window* sdl_window, Uint8 state, MirPointerEvent const* pointer)
   101 {
   102     uint32_t sdl_button           = SDL_BUTTON_LEFT;
   103     MirPointerButton button_state = mir_pointer_button_primary;
   104 
   105     static uint32_t old_button_states = 0;
   106     uint32_t new_button_states = MIR_mir_pointer_event_buttons(pointer);
   107 
   108     // XOR on our old button states vs our new states to get the newley pressed/released button
   109     button_state = new_button_states ^ old_button_states;
   110 
   111     switch (button_state) {
   112         case mir_pointer_button_primary:
   113             sdl_button = SDL_BUTTON_LEFT;
   114             break;
   115         case mir_pointer_button_secondary:
   116             sdl_button = SDL_BUTTON_RIGHT;
   117             break;
   118         case mir_pointer_button_tertiary:
   119             sdl_button = SDL_BUTTON_MIDDLE;
   120             break;
   121         case mir_pointer_button_forward:
   122             sdl_button = SDL_BUTTON_X1;
   123             break;
   124         case mir_pointer_button_back:
   125             sdl_button = SDL_BUTTON_X2;
   126             break;
   127         default:
   128             break;
   129     }
   130 
   131     old_button_states = new_button_states;
   132 
   133     SDL_SendMouseButton(sdl_window, 0, state, sdl_button);
   134 }
   135 
   136 static void
   137 HandleMouseMotion(SDL_Window* sdl_window, int x, int y)
   138 {
   139     SDL_SendMouseMotion(sdl_window, 0, 0, x, y);
   140 }
   141 
   142 static void
   143 HandleTouchPress(int device_id, int source_id, SDL_bool down, float x, float y, float pressure)
   144 {
   145     SDL_SendTouch(device_id, source_id, down, x, y, pressure);
   146 }
   147 
   148 static void
   149 HandleTouchMotion(int device_id, int source_id, float x, float y, float pressure)
   150 {
   151     SDL_SendTouchMotion(device_id, source_id, x, y, pressure);
   152 }
   153 
   154 static void
   155 HandleMouseScroll(SDL_Window* sdl_window, int hscroll, int vscroll)
   156 {
   157     SDL_SendMouseWheel(sdl_window, 0, hscroll, vscroll, SDL_MOUSEWHEEL_NORMAL);
   158 }
   159 
   160 static void
   161 AddTouchDevice(int device_id)
   162 {
   163     if (SDL_AddTouch(device_id, "") < 0)
   164         SDL_SetError("Error: can't add touch %s, %d", __FILE__, __LINE__);
   165 }
   166 
   167 static void
   168 HandleTouchEvent(MirTouchEvent const* touch, int device_id, SDL_Window* sdl_window)
   169 {
   170     int i, point_count;
   171     point_count = MIR_mir_touch_event_point_count(touch);
   172 
   173     AddTouchDevice(device_id);
   174 
   175     for (i = 0; i < point_count; i++) {
   176         int id = MIR_mir_touch_event_id(touch, i);
   177 
   178         int width  = sdl_window->w;
   179         int height = sdl_window->h;
   180 
   181         float x = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_x);
   182         float y = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_y);
   183 
   184         float n_x = x / width;
   185         float n_y = y / height;
   186 
   187         float pressure = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_pressure);
   188 
   189         switch (MIR_mir_touch_event_action(touch, i)) {
   190             case mir_touch_action_up:
   191                 HandleTouchPress(device_id, id, SDL_FALSE, n_x, n_y, pressure);
   192                 break;
   193             case mir_touch_action_down:
   194                 HandleTouchPress(device_id, id, SDL_TRUE, n_x, n_y, pressure);
   195                 break;
   196             case mir_touch_action_change:
   197                 HandleTouchMotion(device_id, id, n_x, n_y, pressure);
   198                 break;
   199         }
   200     }
   201 }
   202 
   203 static void
   204 HandleMouseEvent(MirPointerEvent const* pointer, SDL_Window* sdl_window)
   205 {
   206     SDL_SetMouseFocus(sdl_window);
   207 
   208     switch (MIR_mir_pointer_event_action(pointer)) {
   209         case mir_pointer_action_button_down:
   210             HandleMouseButton(sdl_window, SDL_PRESSED, pointer);
   211             break;
   212         case mir_pointer_action_button_up:
   213             HandleMouseButton(sdl_window, SDL_RELEASED, pointer);
   214             break;
   215         case mir_pointer_action_motion: {
   216             int x, y;
   217             int hscroll, vscroll;
   218             SDL_Mouse* mouse = SDL_GetMouse();
   219             x = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_x);
   220             y = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_y);
   221             hscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_hscroll);
   222             vscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_vscroll);
   223 
   224             if (mouse && (mouse->x != x || mouse->y != y))
   225                 HandleMouseMotion(sdl_window, x, y);
   226             if (vscroll != 0 || hscroll != 0)
   227                 HandleMouseScroll(sdl_window, hscroll, vscroll);
   228         }
   229             break;
   230         case mir_pointer_action_leave:
   231             SDL_SetMouseFocus(NULL);
   232             break;
   233         case mir_pointer_action_enter:
   234         default:
   235             break;
   236     }
   237 }
   238 
   239 static void
   240 MIR_HandleInput(MirInputEvent const* input_event, SDL_Window* window)
   241 {
   242     switch (MIR_mir_input_event_get_type(input_event)) {
   243         case (mir_input_event_type_key):
   244             HandleKeyEvent(MIR_mir_input_event_get_keyboard_event(input_event), window);
   245             break;
   246         case (mir_input_event_type_pointer):
   247             HandleMouseEvent(MIR_mir_input_event_get_pointer_event(input_event), window);
   248             break;
   249         case (mir_input_event_type_touch):
   250             HandleTouchEvent(MIR_mir_input_event_get_touch_event(input_event),
   251                              MIR_mir_input_event_get_device_id(input_event),
   252                              window);
   253             break;
   254         default:
   255             break;
   256     }
   257 }
   258 
   259 static void
   260 MIR_HandleResize(MirResizeEvent const* resize_event, SDL_Window* window)
   261 {
   262     int new_w = MIR_mir_resize_event_get_width (resize_event);
   263     int new_h = MIR_mir_resize_event_get_height(resize_event);
   264 
   265     int old_w = window->w;
   266     int old_h = window->h;
   267 
   268     if (new_w != old_w || new_h != old_h)
   269         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, new_w, new_h);
   270 }
   271 
   272 void
   273 MIR_HandleEvent(MirSurface* surface, MirEvent const* ev, void* context)
   274 {
   275     MirEventType event_type = MIR_mir_event_get_type(ev);
   276     SDL_Window* window      = (SDL_Window*)context;
   277 
   278     if (window) {
   279         switch (event_type) {
   280             case (mir_event_type_input):
   281                 MIR_HandleInput(MIR_mir_event_get_input_event(ev), window);
   282                 break;
   283             case (mir_event_type_resize):
   284                 MIR_HandleResize(MIR_mir_event_get_resize_event(ev), window);
   285                 break;
   286             default:
   287                 break;
   288         }
   289     }
   290 }
   291 
   292 #endif /* SDL_VIDEO_DRIVER_MIR */
   293 
   294 /* vi: set ts=4 sw=4 expandtab: */