diff options
author | chai <chaifix@163.com> | 2019-05-11 22:54:56 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-05-11 22:54:56 +0800 |
commit | 9645be0af1b1d5cb0ad5892d5464e1b23c51b550 (patch) | |
tree | 129c716bed8e93312421c3adb2f8e7c4f811602d /source/3rd-party/SDL2/src/video/mir/SDL_mirevents.c |
Diffstat (limited to 'source/3rd-party/SDL2/src/video/mir/SDL_mirevents.c')
-rw-r--r-- | source/3rd-party/SDL2/src/video/mir/SDL_mirevents.c | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/mir/SDL_mirevents.c b/source/3rd-party/SDL2/src/video/mir/SDL_mirevents.c new file mode 100644 index 0000000..df92799 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/mir/SDL_mirevents.c @@ -0,0 +1,321 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com> +*/ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_MIR + +#include "../../events/SDL_events_c.h" +#include "../../events/SDL_keyboard_c.h" +#include "../../events/SDL_touch_c.h" +#include "../../events/scancodes_xfree86.h" + +#include "SDL_mirevents.h" +#include "SDL_mirwindow.h" + +#include <xkbcommon/xkbcommon.h> + +#include "SDL_mirdyn.h" + +static void +HandleKeyText(int32_t key_code) +{ + char text[8]; + int size = 0; + + size = MIR_xkb_keysym_to_utf8(key_code, text, sizeof text); + + if (size > 0) { + text[size] = '\0'; + SDL_SendKeyboardText(text); + } +} + +/* FIXME + Mir still needs to implement its IM API, for now we assume + a single key press produces a character. +*/ +static void +HandleKeyEvent(MirKeyboardEvent const* key_event, SDL_Window* window) +{ + xkb_keysym_t key_code; + Uint8 key_state; + int event_scancode; + uint32_t sdl_scancode = SDL_SCANCODE_UNKNOWN; + + MirKeyboardAction action = MIR_mir_keyboard_event_action(key_event); + + key_state = SDL_PRESSED; + key_code = MIR_mir_keyboard_event_key_code(key_event); + event_scancode = MIR_mir_keyboard_event_scan_code(key_event); + + if (action == mir_keyboard_action_up) + key_state = SDL_RELEASED; + + if (event_scancode < SDL_arraysize(xfree86_scancode_table2)) + sdl_scancode = xfree86_scancode_table2[event_scancode]; + + if (sdl_scancode != SDL_SCANCODE_UNKNOWN) + SDL_SendKeyboardKey(key_state, sdl_scancode); + + if (key_state == SDL_PRESSED) + HandleKeyText(key_code); +} + +static void +HandleMouseButton(SDL_Window* sdl_window, Uint8 state, MirPointerEvent const* pointer) +{ + uint32_t sdl_button = SDL_BUTTON_LEFT; + MirPointerButton button_state = mir_pointer_button_primary; + + static uint32_t old_button_states = 0; + uint32_t new_button_states = MIR_mir_pointer_event_buttons(pointer); + + // XOR on our old button states vs our new states to get the newley pressed/released button + button_state = new_button_states ^ old_button_states; + + switch (button_state) { + case mir_pointer_button_primary: + sdl_button = SDL_BUTTON_LEFT; + break; + case mir_pointer_button_secondary: + sdl_button = SDL_BUTTON_RIGHT; + break; + case mir_pointer_button_tertiary: + sdl_button = SDL_BUTTON_MIDDLE; + break; + case mir_pointer_button_forward: + sdl_button = SDL_BUTTON_X1; + break; + case mir_pointer_button_back: + sdl_button = SDL_BUTTON_X2; + break; + default: + break; + } + + old_button_states = new_button_states; + + SDL_SendMouseButton(sdl_window, 0, state, sdl_button); +} + +static void +HandleMouseMotion(SDL_Window* sdl_window, int x, int y) +{ + SDL_Mouse* mouse = SDL_GetMouse(); + SDL_SendMouseMotion(sdl_window, 0, mouse->relative_mode, x, y); +} + +static void +HandleTouchPress(int device_id, int source_id, SDL_bool down, float x, float y, float pressure) +{ + SDL_SendTouch(device_id, source_id, down, x, y, pressure); +} + +static void +HandleTouchMotion(int device_id, int source_id, float x, float y, float pressure) +{ + SDL_SendTouchMotion(device_id, source_id, x, y, pressure); +} + +static void +HandleMouseScroll(SDL_Window* sdl_window, float hscroll, float vscroll) +{ + SDL_SendMouseWheel(sdl_window, 0, hscroll, vscroll, SDL_MOUSEWHEEL_NORMAL); +} + +static void +AddTouchDevice(int device_id) +{ + if (SDL_AddTouch(device_id, "") < 0) + SDL_SetError("Error: can't add touch %s, %d", __FILE__, __LINE__); +} + +static void +HandleTouchEvent(MirTouchEvent const* touch, int device_id, SDL_Window* sdl_window) +{ + int i, point_count; + point_count = MIR_mir_touch_event_point_count(touch); + + AddTouchDevice(device_id); + + for (i = 0; i < point_count; i++) { + int id = MIR_mir_touch_event_id(touch, i); + + int width = sdl_window->w; + int height = sdl_window->h; + + float x = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_x); + float y = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_y); + + float n_x = x / width; + float n_y = y / height; + + float pressure = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_pressure); + + switch (MIR_mir_touch_event_action(touch, i)) { + case mir_touch_action_up: + HandleTouchPress(device_id, id, SDL_FALSE, n_x, n_y, pressure); + break; + case mir_touch_action_down: + HandleTouchPress(device_id, id, SDL_TRUE, n_x, n_y, pressure); + break; + case mir_touch_action_change: + HandleTouchMotion(device_id, id, n_x, n_y, pressure); + break; + case mir_touch_actions: + break; + } + } +} + +static void +HandleMouseEvent(MirPointerEvent const* pointer, SDL_Window* sdl_window) +{ + SDL_SetMouseFocus(sdl_window); + + switch (MIR_mir_pointer_event_action(pointer)) { + case mir_pointer_action_button_down: + HandleMouseButton(sdl_window, SDL_PRESSED, pointer); + break; + case mir_pointer_action_button_up: + HandleMouseButton(sdl_window, SDL_RELEASED, pointer); + break; + case mir_pointer_action_motion: { + int x, y; + float hscroll, vscroll; + SDL_Mouse* mouse = SDL_GetMouse(); + x = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_x); + y = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_y); + + if (mouse) { + if (mouse->relative_mode) { + int relative_x = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_x); + int relative_y = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_y); + HandleMouseMotion(sdl_window, relative_x, relative_y); + } + else if (mouse->x != x || mouse->y != y) { + HandleMouseMotion(sdl_window, x, y); + } + } + + hscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_hscroll); + vscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_vscroll); + if (vscroll != 0 || hscroll != 0) + HandleMouseScroll(sdl_window, hscroll, vscroll); + } + break; + case mir_pointer_action_leave: + SDL_SetMouseFocus(NULL); + break; + case mir_pointer_action_enter: + default: + break; + } +} + +static void +HandleInput(MirInputEvent const* input_event, SDL_Window* window) +{ + switch (MIR_mir_input_event_get_type(input_event)) { + case (mir_input_event_type_key): + HandleKeyEvent(MIR_mir_input_event_get_keyboard_event(input_event), window); + break; + case (mir_input_event_type_pointer): + HandleMouseEvent(MIR_mir_input_event_get_pointer_event(input_event), window); + break; + case (mir_input_event_type_touch): + HandleTouchEvent(MIR_mir_input_event_get_touch_event(input_event), + MIR_mir_input_event_get_device_id(input_event), + window); + break; + default: + break; + } +} + +static void +HandleResize(MirResizeEvent const* resize_event, SDL_Window* window) +{ + int new_w = MIR_mir_resize_event_get_width (resize_event); + int new_h = MIR_mir_resize_event_get_height(resize_event); + + int old_w = window->w; + int old_h = window->h; + + if (new_w != old_w || new_h != old_h) + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, new_w, new_h); +} + +static void +HandleWindow(MirWindowEvent const* event, SDL_Window* window) +{ + MirWindowAttrib attrib = MIR_mir_window_event_get_attribute(event); + int value = MIR_mir_window_event_get_attribute_value(event); + + if (attrib == mir_window_attrib_focus) { + if (value == mir_window_focus_state_focused) { + SDL_SetKeyboardFocus(window); + } + else if (value == mir_window_focus_state_unfocused) { + SDL_SetKeyboardFocus(NULL); + } + } +} + +static void +MIR_HandleClose(SDL_Window* window) { + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0, 0); +} + +void +MIR_HandleEvent(MirWindow* mirwindow, MirEvent const* ev, void* context) +{ + MirEventType event_type = MIR_mir_event_get_type(ev); + SDL_Window* window = (SDL_Window*)context; + + if (window) { + switch (event_type) { + case (mir_event_type_input): + HandleInput(MIR_mir_event_get_input_event(ev), window); + break; + case (mir_event_type_resize): + HandleResize(MIR_mir_event_get_resize_event(ev), window); + break; + case (mir_event_type_window): + HandleWindow(MIR_mir_event_get_window_event(ev), window); + break; + case (mir_event_type_close_window): + MIR_HandleClose(window); + break; + default: + break; + } + } +} + +#endif /* SDL_VIDEO_DRIVER_MIR */ + +/* vi: set ts=4 sw=4 expandtab: */ |