diff --git a/CMake/modules/FindMir.cmake b/CMake/modules/FindMir.cmake new file mode 100644 index 000000000..b1a495ba1 --- /dev/null +++ b/CMake/modules/FindMir.cmake @@ -0,0 +1,18 @@ +# Try to find Mir on a Unix system +# +# This will define: +# +# MIR_LIBRARIES - Link these to use Wayland +# MIR_INCLUDE_DIR - Include directory for Wayland +# +# Copyright (c) 2014 Brandon Schaefer + +if (NOT WIN32) + + find_package (PkgConfig) + pkg_check_modules (PKG_MIR QUIET mirclient) + + set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS}) + set (MIR_LIBRARIES ${PKG_MIR_LIBRARIES}) + +endif () diff --git a/CMakeLists.txt b/CMakeLists.txt index aa57cc67b..be1c6b66e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ endif() if (UNIX AND NOT APPLE) option(GLFW_USE_WAYLAND "Use Wayland for context creation (implies EGL as well)" OFF) + option(GLFW_USE_MIR "Use Mir for context creation (implies EGL as well)" OFF) endif() if (MSVC) @@ -45,6 +46,8 @@ endif() if (GLFW_USE_WAYLAND) set(GLFW_USE_EGL ON) +elseif (GLFW_USE_MIR) + set(GLFW_USE_EGL ON) endif() if (GLFW_USE_EGL) @@ -174,6 +177,9 @@ elseif (UNIX) if (GLFW_USE_WAYLAND) set(_GLFW_WAYLAND 1) message(STATUS "Using Wayland for window creation") + elseif (GLFW_USE_MIR) + set(_GLFW_MIR 1) + message(STATUS "Using Mir for window creation") else() set(_GLFW_X11 1) message(STATUS "Using X11 for window creation") @@ -343,6 +349,29 @@ if (_GLFW_WAYLAND) endif() endif() +#-------------------------------------------------------------------- +# Use Mir for window creation +#-------------------------------------------------------------------- +if (_GLFW_MIR) + find_package(Mir REQUIRED) + set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} mirclient") + + list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIR}") + list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}") + + find_package(XKBCommon REQUIRED) + set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} xkbcommon") + list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}") + list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}") + + find_library(MATH_LIBRARY m) + mark_as_advanced(MATH_LIBRARY) + if (MATH_LIBRARY) + list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}") + set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} -lm") + endif() +endif() + #-------------------------------------------------------------------- # Use GLX for context creation #-------------------------------------------------------------------- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e006a8f1e..9ba9fc563 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,11 @@ elseif (_GLFW_WAYLAND) posix_time.h posix_tls.h xkb_unicode.h) set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c) +elseif (_GLFW_MIR) + set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h + posix_time.h posix_tls.h xkb_unicode.h) + set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c + linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c) endif() if (_GLFW_EGL) diff --git a/src/glfw_config.h.in b/src/glfw_config.h.in index 11c2aa768..485cac58f 100644 --- a/src/glfw_config.h.in +++ b/src/glfw_config.h.in @@ -42,6 +42,8 @@ #cmakedefine _GLFW_COCOA // Define this to 1 if building GLFW for Wayland #cmakedefine _GLFW_WAYLAND +// Define this to 1 if building GLFW for Mir +#cmakedefine _GLFW_MIR // Define this to 1 if building GLFW for EGL #cmakedefine _GLFW_EGL diff --git a/src/internal.h b/src/internal.h index 62504e4fe..0565256ca 100644 --- a/src/internal.h +++ b/src/internal.h @@ -74,6 +74,8 @@ typedef struct _GLFWcursor _GLFWcursor; #include "x11_platform.h" #elif defined(_GLFW_WAYLAND) #include "wl_platform.h" +#elif defined(_GLFW_MIR) + #include "mir_platform.h" #else #error "No supported window creation API selected" #endif diff --git a/src/mir_init.c b/src/mir_init.c new file mode 100644 index 000000000..d50796f09 --- /dev/null +++ b/src/mir_init.c @@ -0,0 +1,75 @@ +//======================================================================== +// GLFW 3.1 Mir - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2014 Brandon Schaefer +// +// 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. +// +//======================================================================== + +#include "internal.h" + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +int _glfwPlatformInit(void) +{ + _glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__); + + if (!mir_connection_is_valid(_glfw.mir.connection)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unable to connect to Server\n"); + return GL_FALSE; + } + + _glfw.mir.native_display = mir_connection_get_egl_native_display(_glfw.mir.connection); + + if (!_glfwInitContextAPI()) + return GL_FALSE; + + _glfwInitTimer(); + _glfwInitJoysticks(); + + return GL_TRUE; +} + +void _glfwPlatformTerminate(void) +{ + _glfwTerminateContextAPI(); + _glfwTerminateJoysticks(); + mir_connection_release(_glfw.mir.connection); +} + +const char* _glfwPlatformGetVersionString(void) +{ + const char* version = _GLFW_VERSION_NUMBER " Mir EGL " +#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) + " clock_gettime" +#endif +#if defined(_GLFW_BUILD_DLL) + " shared" +#endif + ; + + return version; +} + diff --git a/src/mir_monitor.c b/src/mir_monitor.c new file mode 100644 index 000000000..9d16dd0fe --- /dev/null +++ b/src/mir_monitor.c @@ -0,0 +1,142 @@ +//======================================================================== +// GLFW 3.1 Mir - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2014 Brandon Schaefer +// +// 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. +// +//======================================================================== + +#include "internal.h" + +#include + +GLFWvidmode* createMonitorModes(MirDisplayOutput const* out) +{ + GLFWvidmode* modes = calloc(out->num_modes, sizeof(GLFWvidmode)); + + int n_mode; + for (n_mode = 0; n_mode < out->num_modes; n_mode++) + { + modes[n_mode].width = out->modes[n_mode].horizontal_resolution; + modes[n_mode].height = out->modes[n_mode].vertical_resolution; + modes[n_mode].refreshRate = out->modes[n_mode].refresh_rate; + modes[n_mode].redBits = 8; + modes[n_mode].greenBits = 8; + modes[n_mode].blueBits = 8; + } + + return modes; +} + +_GLFWmonitor* createNewMonitor(MirDisplayOutput const* out) +{ + _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor)); + + monitor->mir.x = out->position_x; + monitor->mir.y = out->position_y; + monitor->mir.output_id = out->output_id; + monitor->mir.cur_mode = out->current_mode; + monitor->modeCount = out->num_modes; + monitor->widthMM = out->physical_width_mm; + monitor->heightMM = out->physical_height_mm; + monitor->modes = createMonitorModes(out); + + _glfwPlatformGetVideoMode(monitor, &monitor->currentMode); + + return monitor; +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +_GLFWmonitor** _glfwPlatformGetMonitors(int* count) +{ + int d, found = 0; + MirDisplayConfiguration* display_config = mir_connection_create_display_config(_glfw.mir.connection); + + _GLFWmonitor** monitors = NULL; + _GLFWmonitor* monitor = NULL; + + for (d = 0; d < display_config->num_outputs; d++) + { + MirDisplayOutput const* out = display_config->outputs + d; + + if (out->used && + out->connected && + out->num_modes && + out->current_mode < out->num_modes) + { + found++; + monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found); + monitor = createNewMonitor(out); + monitors[d] = monitor; + } + } + + *count = found; + mir_display_config_destroy(display_config); + + return monitors; +} + +GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) +{ + return first->mir.output_id == second->mir.output_id; +} + +void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) +{ + if (xpos) + *xpos = monitor->mir.x; + if (ypos) + *ypos = monitor->mir.y; +} + +GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) +{ + GLFWvidmode* modes = NULL; + int i, count = monitor->modeCount; + + modes = calloc(count, sizeof(GLFWvidmode)); + for (i = 0; i < count; i++) + modes[i] = monitor->modes[i]; + + *found = count; + return modes; +} + +void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) +{ + *mode = monitor->modes[monitor->mir.cur_mode]; +} + +void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} diff --git a/src/mir_platform.h b/src/mir_platform.h new file mode 100644 index 000000000..a89a93b6f --- /dev/null +++ b/src/mir_platform.h @@ -0,0 +1,82 @@ +//======================================================================== +// GLFW 3.1 Mir - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2014 Brandon Schaefer +// +// 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. +// +//======================================================================== + +#ifndef _mir_platform_h_ +#define _mir_platform_h_ + +#include + +#include "posix_tls.h" +#include "posix_time.h" +#include "linux_joystick.h" + +#if defined(_GLFW_EGL) + #include "egl_context.h" +#else + #error "The Mir backend depends on EGL platform support" +#endif + +#define _GLFW_EGL_NATIVE_WINDOW window->mir.native_window +#define _GLFW_EGL_NATIVE_DISPLAY _glfw.mir.native_display + +#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir; +#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorMir mir; +#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir; +#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir; + +typedef struct _GLFWwindowMir +{ + MirSurface* surface; + int width; + int height; + + EGLSurface egl_surface; + MirEGLNativeWindowType native_window; + +} _GLFWwindowMir; + +typedef struct _GLFWmonitorMir +{ + int cur_mode; + int output_id; + int x; + int y; + +} _GLFWmonitorMir; + +typedef struct _GLFWlibraryMir +{ + MirConnection* connection; + MirEGLNativeDisplayType native_display; + +} _GLFWlibraryMir; + +// TODO Only system cursors are implemented in mir atm. Need to wait for support. +typedef struct _GLFWcursorMir +{ +} _GLFWcursorMir; + +#endif // _mir_platform_h_ diff --git a/src/mir_window.c b/src/mir_window.c new file mode 100644 index 000000000..392151746 --- /dev/null +++ b/src/mir_window.c @@ -0,0 +1,542 @@ +//======================================================================== +// GLFW 3.1 Mir - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2014 Brandon Schaefer +// +// 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. +// +//======================================================================== + +#include "internal.h" +#include "xkb_unicode.h" + +#include + +static MirPixelFormat findValidPixelFormat() +{ + unsigned int pf_size = 32; + unsigned int valid_formats; + unsigned int f; + + MirPixelFormat formats[pf_size]; + mir_connection_get_available_surface_formats(_glfw.mir.connection, formats, + pf_size, &valid_formats); + + for (f = 0; f < valid_formats; f++) + { + MirPixelFormat cur_pf = formats[f]; + + if (cur_pf == mir_pixel_format_abgr_8888 || + cur_pf == mir_pixel_format_xbgr_8888 || + cur_pf == mir_pixel_format_argb_8888 || + cur_pf == mir_pixel_format_xrgb_8888) + { + return cur_pf; + } + } + + return mir_pixel_format_invalid; +} + +static int mirModToGLFWMod(uint32_t mod) +{ + int glfw_mod = 0x0; + + if (mod & mir_key_modifier_alt) + { + glfw_mod |= GLFW_MOD_ALT; + } + else if (mod & mir_key_modifier_shift) + { + glfw_mod |= GLFW_MOD_SHIFT; + } + else if (mod & mir_key_modifier_ctrl) + { + glfw_mod |= GLFW_MOD_CONTROL; + } + else if (mod & mir_key_modifier_meta) + { + glfw_mod |= GLFW_MOD_SUPER; + } + + return glfw_mod; +} + +// Taken from wl_init.c +static int toGLFWKeyCode(uint32_t key) +{ + switch (key) + { + case KEY_GRAVE: return GLFW_KEY_GRAVE_ACCENT; + case KEY_1: return GLFW_KEY_1; + case KEY_2: return GLFW_KEY_2; + case KEY_3: return GLFW_KEY_3; + case KEY_4: return GLFW_KEY_4; + case KEY_5: return GLFW_KEY_5; + case KEY_6: return GLFW_KEY_6; + case KEY_7: return GLFW_KEY_7; + case KEY_8: return GLFW_KEY_8; + case KEY_9: return GLFW_KEY_9; + case KEY_0: return GLFW_KEY_0; + case KEY_MINUS: return GLFW_KEY_MINUS; + case KEY_EQUAL: return GLFW_KEY_EQUAL; + case KEY_Q: return GLFW_KEY_Q; + case KEY_W: return GLFW_KEY_W; + case KEY_E: return GLFW_KEY_E; + case KEY_R: return GLFW_KEY_R; + case KEY_T: return GLFW_KEY_T; + case KEY_Y: return GLFW_KEY_Y; + case KEY_U: return GLFW_KEY_U; + case KEY_I: return GLFW_KEY_I; + case KEY_O: return GLFW_KEY_O; + case KEY_P: return GLFW_KEY_P; + case KEY_LEFTBRACE: return GLFW_KEY_LEFT_BRACKET; + case KEY_RIGHTBRACE: return GLFW_KEY_RIGHT_BRACKET; + case KEY_A: return GLFW_KEY_A; + case KEY_S: return GLFW_KEY_S; + case KEY_D: return GLFW_KEY_D; + case KEY_F: return GLFW_KEY_F; + case KEY_G: return GLFW_KEY_G; + case KEY_H: return GLFW_KEY_H; + case KEY_J: return GLFW_KEY_J; + case KEY_K: return GLFW_KEY_K; + case KEY_L: return GLFW_KEY_L; + case KEY_SEMICOLON: return GLFW_KEY_SEMICOLON; + case KEY_APOSTROPHE: return GLFW_KEY_APOSTROPHE; + case KEY_Z: return GLFW_KEY_Z; + case KEY_X: return GLFW_KEY_X; + case KEY_C: return GLFW_KEY_C; + case KEY_V: return GLFW_KEY_V; + case KEY_B: return GLFW_KEY_B; + case KEY_N: return GLFW_KEY_N; + case KEY_M: return GLFW_KEY_M; + case KEY_COMMA: return GLFW_KEY_COMMA; + case KEY_DOT: return GLFW_KEY_PERIOD; + case KEY_SLASH: return GLFW_KEY_SLASH; + case KEY_BACKSLASH: return GLFW_KEY_BACKSLASH; + case KEY_ESC: return GLFW_KEY_ESCAPE; + case KEY_TAB: return GLFW_KEY_TAB; + case KEY_LEFTSHIFT: return GLFW_KEY_LEFT_SHIFT; + case KEY_RIGHTSHIFT: return GLFW_KEY_RIGHT_SHIFT; + case KEY_LEFTCTRL: return GLFW_KEY_LEFT_CONTROL; + case KEY_RIGHTCTRL: return GLFW_KEY_RIGHT_CONTROL; + case KEY_LEFTALT: return GLFW_KEY_LEFT_ALT; + case KEY_RIGHTALT: return GLFW_KEY_RIGHT_ALT; + case KEY_LEFTMETA: return GLFW_KEY_LEFT_SUPER; + case KEY_RIGHTMETA: return GLFW_KEY_RIGHT_SUPER; + case KEY_MENU: return GLFW_KEY_MENU; + case KEY_NUMLOCK: return GLFW_KEY_NUM_LOCK; + case KEY_CAPSLOCK: return GLFW_KEY_CAPS_LOCK; + case KEY_PRINT: return GLFW_KEY_PRINT_SCREEN; + case KEY_SCROLLLOCK: return GLFW_KEY_SCROLL_LOCK; + case KEY_PAUSE: return GLFW_KEY_PAUSE; + case KEY_DELETE: return GLFW_KEY_DELETE; + case KEY_BACKSPACE: return GLFW_KEY_BACKSPACE; + case KEY_ENTER: return GLFW_KEY_ENTER; + case KEY_HOME: return GLFW_KEY_HOME; + case KEY_END: return GLFW_KEY_END; + case KEY_PAGEUP: return GLFW_KEY_PAGE_UP; + case KEY_PAGEDOWN: return GLFW_KEY_PAGE_DOWN; + case KEY_INSERT: return GLFW_KEY_INSERT; + case KEY_LEFT: return GLFW_KEY_LEFT; + case KEY_RIGHT: return GLFW_KEY_RIGHT; + case KEY_DOWN: return GLFW_KEY_DOWN; + case KEY_UP: return GLFW_KEY_UP; + case KEY_F1: return GLFW_KEY_F1; + case KEY_F2: return GLFW_KEY_F2; + case KEY_F3: return GLFW_KEY_F3; + case KEY_F4: return GLFW_KEY_F4; + case KEY_F5: return GLFW_KEY_F5; + case KEY_F6: return GLFW_KEY_F6; + case KEY_F7: return GLFW_KEY_F7; + case KEY_F8: return GLFW_KEY_F8; + case KEY_F9: return GLFW_KEY_F9; + case KEY_F10: return GLFW_KEY_F10; + case KEY_F11: return GLFW_KEY_F11; + case KEY_F12: return GLFW_KEY_F12; + case KEY_F13: return GLFW_KEY_F13; + case KEY_F14: return GLFW_KEY_F14; + case KEY_F15: return GLFW_KEY_F15; + case KEY_F16: return GLFW_KEY_F16; + case KEY_F17: return GLFW_KEY_F17; + case KEY_F18: return GLFW_KEY_F18; + case KEY_F19: return GLFW_KEY_F19; + case KEY_F20: return GLFW_KEY_F20; + case KEY_F21: return GLFW_KEY_F21; + case KEY_F22: return GLFW_KEY_F22; + case KEY_F23: return GLFW_KEY_F23; + case KEY_F24: return GLFW_KEY_F24; + case KEY_KPSLASH: return GLFW_KEY_KP_DIVIDE; + case KEY_KPDOT: return GLFW_KEY_KP_MULTIPLY; + case KEY_KPMINUS: return GLFW_KEY_KP_SUBTRACT; + case KEY_KPPLUS: return GLFW_KEY_KP_ADD; + case KEY_KP0: return GLFW_KEY_KP_0; + case KEY_KP1: return GLFW_KEY_KP_1; + case KEY_KP2: return GLFW_KEY_KP_2; + case KEY_KP3: return GLFW_KEY_KP_3; + case KEY_KP4: return GLFW_KEY_KP_4; + case KEY_KP5: return GLFW_KEY_KP_5; + case KEY_KP6: return GLFW_KEY_KP_6; + case KEY_KP7: return GLFW_KEY_KP_7; + case KEY_KP8: return GLFW_KEY_KP_8; + case KEY_KP9: return GLFW_KEY_KP_9; + case KEY_KPCOMMA: return GLFW_KEY_KP_DECIMAL; + case KEY_KPEQUAL: return GLFW_KEY_KP_EQUAL; + case KEY_KPENTER: return GLFW_KEY_KP_ENTER; + default: return GLFW_KEY_UNKNOWN; + } +} + +static void handleKeyEvent(MirKeyEvent const key, _GLFWwindow* window) +{ + int pressed = key.action == mir_key_action_up ? GLFW_RELEASE : GLFW_PRESS; + int mods = mirModToGLFWMod(key.modifiers); + + long text = _glfwKeySym2Unicode(key.key_code); + int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + + _glfwInputKey(window, toGLFWKeyCode(key.scan_code), key.scan_code, pressed, mods); + + if (text != -1) + _glfwInputChar(window, text, mods, plain); +} + +static void handleMouseButton(_GLFWwindow* window, int pressed, int mir_mods, MirMotionButton button) +{ + static int last_button; + int glfw_button; + int mods = mirModToGLFWMod(mir_mods); + + switch (button) + { + case mir_motion_button_primary: + glfw_button = GLFW_MOUSE_BUTTON_LEFT; + break; + case mir_motion_button_secondary: + glfw_button = GLFW_MOUSE_BUTTON_RIGHT; + break; + case mir_motion_button_tertiary: + glfw_button = GLFW_MOUSE_BUTTON_MIDDLE; + break; + case mir_motion_button_forward: + // FIXME What is the forward button? + glfw_button = GLFW_MOUSE_BUTTON_4; + break; + case mir_motion_button_back: + // FIXME What is the back button? + glfw_button = GLFW_MOUSE_BUTTON_5; + break; + default: + glfw_button = last_button; + break; + } + + last_button = glfw_button; + + _glfwInputMouseClick(window, glfw_button, pressed, mods); +} + +static void handleMouseMotion(_GLFWwindow* window, int x, int y) +{ + _glfwInputCursorMotion(window, x, y); +} + +static void handleMouseScroll(_GLFWwindow* window, int dx, int dy) +{ + _glfwInputScroll(window, dx, dy); +} + +static void handleMouseEvent(MirMotionEvent const motion, int cord_index, _GLFWwindow* window) +{ + switch (motion.action) + { + case mir_motion_action_down: + case mir_motion_action_pointer_down: + handleMouseButton(window, GLFW_PRESS, motion.modifiers, motion.button_state); + break; + case mir_motion_action_up: + case mir_motion_action_pointer_up: + handleMouseButton(window, GLFW_RELEASE, motion.modifiers, motion.button_state); + break; + case mir_motion_action_hover_move: + case mir_motion_action_move: + handleMouseMotion(window, + motion.pointer_coordinates[cord_index].x, + motion.pointer_coordinates[cord_index].y); + break; + case mir_motion_action_outside: + break; + case mir_motion_action_scroll: + handleMouseScroll(window, + motion.pointer_coordinates[cord_index].hscroll, + motion.pointer_coordinates[cord_index].vscroll); + break; + case mir_motion_action_cancel: + case mir_motion_action_hover_enter: + case mir_motion_action_hover_exit: + break; + default: + break; + + } +} + +static void handleMotionEvent(MirMotionEvent const motion, _GLFWwindow* window) +{ + int cord_index; + for (cord_index = 0; cord_index < motion.pointer_count; cord_index++) + handleMouseEvent(motion, cord_index, window); +} + +static void handleInput(MirSurface* surface, MirEvent const* event, void* context) +{ + switch (event->type) + { + case(mir_event_type_key): + handleKeyEvent(event->key, (_GLFWwindow*)context); + break; + case(mir_event_type_motion): + handleMotionEvent(event->motion, (_GLFWwindow*)context); + break; + default: + break; + } +} + +static int createSurface(_GLFWwindow* window) +{ + MirSurfaceParameters params = + { + .name = "MirSurface", + .width = window->mir.width, + .height = window->mir.height, + .pixel_format = mir_pixel_format_invalid, + .buffer_usage = mir_buffer_usage_hardware, + .output_id = mir_display_output_id_invalid + }; + + MirEventDelegate delegate = + { + handleInput, + window + }; + + params.pixel_format = findValidPixelFormat(); + if (params.pixel_format == mir_pixel_format_invalid) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unable to find a correct pixel format!\n"); + return GL_FALSE; + } + + window->mir.surface = mir_connection_create_surface_sync(_glfw.mir.connection, ¶ms); + if (!mir_surface_is_valid(window->mir.surface)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unable to create surface!\n"); + return GL_FALSE; + } + + mir_surface_set_event_handler(window->mir.surface, &delegate); + + return GL_TRUE; +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +int _glfwPlatformCreateWindow(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) +{ + if (!_glfwCreateContext(window, ctxconfig, fbconfig)) + return GL_FALSE; + + if (wndconfig->monitor) + { + mir_surface_set_type(window->mir.surface, mir_surface_state_fullscreen); + + if (wndconfig->width > wndconfig->monitor->currentMode.width || + wndconfig->height > wndconfig->monitor->currentMode.height) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Requested surface size is to large (%i %i)\n", + wndconfig->width, wndconfig->height); + + return GL_FALSE; + } + } + + window->mir.width = wndconfig->width; + window->mir.height = wndconfig->height; + + if (!createSurface(window)) + return GL_FALSE; + + window->mir.native_window = mir_surface_get_egl_native_window(window->mir.surface); + + return GL_TRUE; +} + +void _glfwPlatformDestroyWindow(_GLFWwindow* window) +{ + if (mir_surface_is_valid(window->mir.surface)) + { + mir_surface_release_sync(window->mir.surface); + window->mir.surface = NULL; + } + + _glfwDestroyContext(window); +} + +void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) +{ + if (width) + *width = window->mir.width; + if (height) + *height = window->mir.height; +} + +void _glfwPlatformIconifyWindow(_GLFWwindow* window) +{ + mir_surface_set_type(window->mir.surface, mir_surface_state_minimized); +} + +void _glfwPlatformRestoreWindow(_GLFWwindow* window) +{ + mir_surface_set_type(window->mir.surface, mir_surface_state_restored); +} + +void _glfwPlatformHideWindow(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformShowWindow(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformUnhideWindow(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +// Mir does event handling in a different thread, so windows get events directly as they happen +void _glfwPlatformPollEvents(void) +{ +} + +void _glfwPlatformWaitEvents(void) +{ +} + +void _glfwPlatformPostEmptyEvent(void) +{ +} + +void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) +{ + if (width) + *width = window->mir.width; + if (height) + *height = window->mir.height; +} + +int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); + + return 0; +} + +void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformApplyCursorMode(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); +} + +const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!\n", __PRETTY_FUNCTION__); + + return NULL; +} diff --git a/src/wl_init.c b/src/wl_init.c index 9105df7ae..0269ee34d 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -600,6 +600,7 @@ int _glfwPlatformInit(void) void _glfwPlatformTerminate(void) { _glfwTerminateContextAPI(); + _glfwTerminateJoysticks(); if (_glfw.wl.cursorTheme) wl_cursor_theme_destroy(_glfw.wl.cursorTheme);