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