cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_mirevents.c (7464B)


      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
     42static void
     43HandleKeyText(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
     56static void
     57CheckKeyboardFocus(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*/
     70static void
     71HandleKeyEvent(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
     88static void
     89HandleMouseButton(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
    119static void
    120HandleMouseMotion(SDL_Window* sdl_window, int x, int y)
    121{
    122    SDL_SendMouseMotion(sdl_window, 0, 0, x, y);
    123}
    124
    125static void
    126HandleTouchPress(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
    131static void
    132HandleTouchMotion(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
    137static void
    138HandleMouseScroll(SDL_Window* sdl_window, int hscroll, int vscroll)
    139{
    140    SDL_SendMouseWheel(sdl_window, 0, hscroll, vscroll);
    141}
    142
    143static void
    144AddTouchDevice(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
    150static void
    151HandleTouchEvent(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
    185static void
    186HandleMouseEvent(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
    222static void
    223HandleMotionEvent(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
    236void
    237MIR_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: */