diff --git a/src/mir_init.c b/src/mir_init.c index 153e4005..c4b8d1d3 100644 --- a/src/mir_init.c +++ b/src/mir_init.c @@ -1,7 +1,7 @@ //======================================================================== // GLFW 3.1 Mir - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2014 Brandon Schaefer +// Copyright (c) 2014-2015 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 @@ -55,6 +55,9 @@ int _glfwPlatformInit(void) if (!_glfwInitContextAPI()) return GL_FALSE; + // Need the default conf for when we set a NULL cursor + _glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name); + _glfwInitTimer(); _glfwInitJoysticks(); diff --git a/src/mir_monitor.c b/src/mir_monitor.c index 93073d33..9ee6d24d 100644 --- a/src/mir_monitor.c +++ b/src/mir_monitor.c @@ -1,7 +1,7 @@ //======================================================================== // GLFW 3.1 Mir - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2014 Brandon Schaefer +// Copyright (c) 2014-2015 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 @@ -86,6 +86,39 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = monitor->mir.y; } +void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, MirPixelFormat const pf) +{ + switch (pf) + { + case mir_pixel_format_rgb_565: + mode->redBits = 5; + mode->greenBits = 6; + mode->blueBits = 5; + break; + case mir_pixel_format_rgba_5551: + mode->redBits = 5; + mode->greenBits = 5; + mode->blueBits = 5; + break; + case mir_pixel_format_rgba_4444: + mode->redBits = 4; + mode->greenBits = 4; + mode->blueBits = 4; + break; + case mir_pixel_format_abgr_8888: + case mir_pixel_format_xbgr_8888: + case mir_pixel_format_argb_8888: + case mir_pixel_format_xrgb_8888: + case mir_pixel_format_bgr_888: + case mir_pixel_format_rgb_888: + default: + mode->redBits = 8; + mode->greenBits = 8; + mode->blueBits = 8; + break; + } +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { int i; @@ -106,9 +139,8 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) modes[*found].width = out->modes[*found].horizontal_resolution; modes[*found].height = out->modes[*found].vertical_resolution; modes[*found].refreshRate = out->modes[*found].refresh_rate; - modes[*found].redBits = 8; - modes[*found].greenBits = 8; - modes[*found].blueBits = 8; + + FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]); } break; diff --git a/src/mir_platform.h b/src/mir_platform.h index 34ef3ef2..fbd8d812 100644 --- a/src/mir_platform.h +++ b/src/mir_platform.h @@ -1,7 +1,7 @@ //======================================================================== // GLFW 3.1 Mir - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2014 Brandon Schaefer +// Copyright (c) 2014-2015 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 @@ -89,6 +89,7 @@ typedef struct _GLFWlibraryMir { MirConnection* connection; MirEGLNativeDisplayType display; + MirCursorConfiguration* default_conf; EventQueue* event_queue; pthread_mutex_t event_mutex; @@ -102,6 +103,8 @@ typedef struct _GLFWlibraryMir // typedef struct _GLFWcursorMir { + MirCursorConfiguration* conf; + MirBufferStream* custom_cursor; } _GLFWcursorMir; diff --git a/src/mir_window.c b/src/mir_window.c index cbc8e059..8d64f919 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -1,7 +1,7 @@ //======================================================================== // GLFW 3.1 Mir - www.glfw.org //------------------------------------------------------------------------ -// Copyright (c) 2014 Brandon Schaefer +// Copyright (c) 2014-2015 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 @@ -34,13 +34,13 @@ typedef struct EventNode { TAILQ_ENTRY(EventNode) entries; - MirEvent* event; + const MirEvent* event; _GLFWwindow* window; } EventNode; static void deleteNode(EventQueue* queue, EventNode* node) { - free(node->event); + mir_event_unref(node->event); free(node); } @@ -49,17 +49,19 @@ static int emptyEventQueue(EventQueue* queue) return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE; } -static EventNode* newEventNode(MirEvent const* event, _GLFWwindow* context) +// TODO The mir_event_ref is not supposed to be used but ... its needed +// in this case. Need to wait until we can read from an FD set up by mir +// for single threaded event handling. +static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context) { EventNode* new_node = calloc(1, sizeof(EventNode)); - new_node->event = calloc(1, sizeof(MirEvent)); + new_node->event = mir_event_ref(event); new_node->window = context; - memcpy(new_node->event, event, sizeof(MirEvent)); return new_node; } -static void enqueueEvent(MirEvent const* event, _GLFWwindow* context) +static void enqueueEvent(const MirEvent* event, _GLFWwindow* context) { pthread_mutex_lock(&_glfw.mir.event_mutex); @@ -87,6 +89,9 @@ static EventNode* dequeueEvent(EventQueue* queue) return node; } +/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out + the best pixel format! +*/ static MirPixelFormat findValidPixelFormat(void) { unsigned int i, validFormats, mirPixelFormats = 32; @@ -113,13 +118,13 @@ static int mirModToGLFWMod(uint32_t mods) { int publicMods = 0x0; - if (mods & mir_key_modifier_alt) + if (mods & mir_input_event_modifier_alt) publicMods |= GLFW_MOD_ALT; - else if (mods & mir_key_modifier_shift) + else if (mods & mir_input_event_modifier_shift) publicMods |= GLFW_MOD_SHIFT; - else if (mods & mir_key_modifier_ctrl) + else if (mods & mir_input_event_modifier_ctrl) publicMods |= GLFW_MOD_CONTROL; - else if (mods & mir_key_modifier_meta) + else if (mods & mir_input_event_modifier_meta) publicMods |= GLFW_MOD_SUPER; return publicMods; @@ -250,97 +255,93 @@ static int toGLFWKeyCode(uint32_t key) } } -static void handleKeyEvent(const MirKeyEvent key, _GLFWwindow* window) +static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window) { - const int pressed = key.action == mir_key_action_up ? GLFW_RELEASE : GLFW_PRESS; - const int mods = mirModToGLFWMod(key.modifiers); - const long text = _glfwKeySym2Unicode(key.key_code); - const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + const int action = mir_keyboard_event_action (key_event); + const int scan_code = mir_keyboard_event_scan_code(key_event); + const int key_code = mir_keyboard_event_key_code (key_event); + const int modifiers = mir_keyboard_event_modifiers(key_event); - _glfwInputKey(window, toGLFWKeyCode(key.scan_code), key.scan_code, pressed, mods); + const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS; + const int mods = mirModToGLFWMod(modifiers); + const long text = _glfwKeySym2Unicode(key_code); + const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + + _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods); if (text != -1) _glfwInputChar(window, text, mods, plain); } -static void handleMouseButton(_GLFWwindow* window, - int pressed, int mods, MirMotionButton button) +static void handlePointerButton(_GLFWwindow* window, + int pressed, + const MirPointerEvent* pointer_event) { - static int lastButton; + MirPointerButton button = mir_pointer_event_buttons (pointer_event); + int mods = mir_pointer_event_modifiers(pointer_event); + const int publicMods = mirModToGLFWMod(mods); int publicButton; - const int publicMods = mirModToGLFWMod(mods); switch (button) { - case mir_motion_button_primary: + case mir_pointer_button_primary: publicButton = GLFW_MOUSE_BUTTON_LEFT; break; - case mir_motion_button_secondary: + case mir_pointer_button_secondary: publicButton = GLFW_MOUSE_BUTTON_RIGHT; break; - case mir_motion_button_tertiary: + case mir_pointer_button_tertiary: publicButton = GLFW_MOUSE_BUTTON_MIDDLE; break; - case mir_motion_button_forward: + case mir_pointer_button_forward: // FIXME What is the forward button? publicButton = GLFW_MOUSE_BUTTON_4; break; - case mir_motion_button_back: + case mir_pointer_button_back: // FIXME What is the back button? publicButton = GLFW_MOUSE_BUTTON_5; break; default: - publicButton = lastButton; break; } - lastButton = publicButton; - _glfwInputMouseClick(window, publicButton, pressed, publicMods); } -static void handleMouseMotion(_GLFWwindow* window, int x, int y) +static void handlePointerMotion(_GLFWwindow* window, + const MirPointerEvent* pointer_event) { - _glfwInputCursorMotion(window, x, y); + int current_x = window->cursorPosX; + int current_y = window->cursorPosY; + int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x); + int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y); + int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll); + int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll); + + if (current_x != x || current_y != y) + _glfwInputCursorMotion(window, x, y); + if (dx != 0 || dy != 0) + _glfwInputScroll(window, dx, dy); } -static void handleMouseScroll(_GLFWwindow* window, int dx, int dy) -{ - _glfwInputScroll(window, dx, dy); -} - -static void handleMouseEvent(const MirMotionEvent motion, - int cord_index, +static void handlePointerEvent(const MirPointerEvent* pointer_event, _GLFWwindow* window) { - switch (motion.action) + int action = mir_pointer_event_action(pointer_event); + + switch (action) { - case mir_motion_action_down: - case mir_motion_action_pointer_down: - handleMouseButton(window, GLFW_PRESS, - motion.modifiers, motion.button_state); + case mir_pointer_action_button_down: + handlePointerButton(window, GLFW_PRESS, pointer_event); break; - case mir_motion_action_up: - case mir_motion_action_pointer_up: - handleMouseButton(window, GLFW_RELEASE, - motion.modifiers, motion.button_state); + case mir_pointer_action_button_up: + handlePointerButton(window, GLFW_RELEASE, pointer_event); 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); + case mir_pointer_action_motion: + handlePointerMotion(window, pointer_event); 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: + case mir_pointer_action_enter: + case mir_pointer_action_leave: break; default: break; @@ -348,61 +349,66 @@ static void handleMouseEvent(const MirMotionEvent motion, } } -static void handleMotionEvent(const MirMotionEvent motion, _GLFWwindow* window) +static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window) { - int i; - for (i = 0; i < motion.pointer_count; i++) - handleMouseEvent(motion, i, window); -} + int type = mir_input_event_get_type(input_event); -static void handleInput(MirEvent const* event, _GLFWwindow* window) -{ - switch (event->type) + switch (type) { - case mir_event_type_key: - handleKeyEvent(event->key, window); + case mir_input_event_type_key: + handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window); break; - case mir_event_type_motion: - handleMotionEvent(event->motion, window); + case mir_input_event_type_pointer: + handlePointerEvent(mir_input_event_get_pointer_event(input_event), window); break; default: break; } } -static void addNewEvent(MirSurface* surface, MirEvent const* event, void* context) +static void handleEvent(const MirEvent* event, _GLFWwindow* window) +{ + int type = mir_event_get_type(event); + + switch (type) + { + case mir_event_type_input: + handleInput(mir_event_get_input_event(event), window); + break; + default: + break; + } +} + +static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context) { enqueueEvent(event, context); } 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 - }; + MirSurfaceSpec* spec; + MirBufferUsage buffer_usage = mir_buffer_usage_hardware; + MirPixelFormat pixel_format = findValidPixelFormat(); - MirEventDelegate delegate = - { - addNewEvent, - window - }; - - params.pixel_format = findValidPixelFormat(); - if (params.pixel_format == mir_pixel_format_invalid) + if (pixel_format == mir_pixel_format_invalid) { _glfwInputError(GLFW_PLATFORM_ERROR, "Mir: Unable to find a correct pixel format"); return GL_FALSE; } + + spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection, + window->mir.width, + window->mir.height, + pixel_format); + + mir_surface_spec_set_buffer_usage(spec, buffer_usage); + mir_surface_spec_set_name(spec, "MirSurface"); + + window->mir.surface = mir_surface_create_sync(spec); + mir_surface_spec_release(spec); - window->mir.surface = - mir_connection_create_surface_sync(_glfw.mir.connection, ¶ms); if (!mir_surface_is_valid(window->mir.surface)) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -412,7 +418,7 @@ static int createSurface(_GLFWwindow* window) return GL_FALSE; } - mir_surface_set_event_handler(window->mir.surface, &delegate); + mir_surface_set_event_handler(window->mir.surface, addNewEvent, window); return GL_TRUE; } @@ -470,7 +476,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, { _glfwInputError(GLFW_PLATFORM_ERROR, "Mir: Requested surface size too large: %ix%i", - wndconfig->width, wndconfig->height); + wndconfig->width, wndconfig->height); return GL_FALSE; } @@ -482,7 +488,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!createSurface(window)) return GL_FALSE; - window->mir.window = mir_surface_get_egl_native_window(window->mir.surface); + window->mir.window = mir_buffer_stream_get_egl_native_window( + mir_surface_get_buffer_stream(window->mir.surface)); return GL_TRUE; } @@ -500,8 +507,26 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + MirSurfaceSpec* spec; + const char* e_title = title ? title : ""; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_name(spec, e_title); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); +} + +void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +{ + MirSurfaceSpec* spec; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_width (spec, width); + mir_surface_spec_set_height(spec, height); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); } void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) @@ -524,12 +549,6 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } -void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) -{ - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); -} - void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) { if (width) @@ -550,14 +569,24 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + MirSurfaceSpec* spec; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_state(spec, mir_surface_state_hidden); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); } void _glfwPlatformShowWindow(_GLFWwindow* window) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + MirSurfaceSpec* spec; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_state(spec, mir_surface_state_restored); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); } void _glfwPlatformUnhideWindow(_GLFWwindow* window) @@ -582,9 +611,7 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window) int _glfwPlatformWindowVisible(_GLFWwindow* window) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); - return GL_FALSE; + return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed; } void _glfwPlatformPollEvents(void) @@ -593,7 +620,7 @@ void _glfwPlatformPollEvents(void) while ((node = dequeueEvent(_glfw.mir.event_queue))) { - handleInput(node->event, node->window); + handleEvent(node->event, node->window); deleteNode(_glfw.mir.event_queue, node); } } @@ -622,34 +649,122 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh *height = window->mir.height; } +// FIXME implement int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + MirBufferStream* stream; + MirPixelFormat pixel_format = findValidPixelFormat(); - return GL_FALSE; + int i_w = image->width; + int i_h = image->height; + + if (pixel_format == mir_pixel_format_invalid) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unable to find a correct pixel format"); + return GL_FALSE; + } + + stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection, + i_w, i_h, + pixel_format, + mir_buffer_usage_software); + + cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot); + + char* dest; + unsigned char *pixels; + int i, r_stride, bytes_per_pixel, bytes_per_row; + + MirGraphicsRegion region; + mir_buffer_stream_get_graphics_region(stream, ®ion); + + // FIXME Figure this out based on the current_pf + bytes_per_pixel = 4; + bytes_per_row = bytes_per_pixel * i_w; + + dest = region.vaddr; + pixels = image->pixels; + + r_stride = region.stride; + + for (i = 0; i < i_h; i++) + { + memcpy(dest, pixels, bytes_per_row); + dest += r_stride; + pixels += r_stride; + } + + cursor->mir.custom_cursor = stream; + + return GL_TRUE; +} + +char const* getSystemCursorName(int shape) +{ + switch (shape) + { + case GLFW_ARROW_CURSOR: + return mir_arrow_cursor_name; + case GLFW_IBEAM_CURSOR: + return mir_caret_cursor_name; + case GLFW_CROSSHAIR_CURSOR: + return mir_crosshair_cursor_name; + case GLFW_HAND_CURSOR: + return mir_open_hand_cursor_name; + case GLFW_HRESIZE_CURSOR: + return mir_horizontal_resize_cursor_name; + case GLFW_VRESIZE_CURSOR: + return mir_vertical_resize_cursor_name; + } + + return NULL; } int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + char const* cursor_name = getSystemCursorName(shape); + + if (cursor_name) + { + cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name); + cursor->mir.custom_cursor = NULL; + + return GL_TRUE; + } return GL_FALSE; } void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + if (cursor->mir.conf) + mir_cursor_configuration_destroy(cursor->mir.conf); + if (cursor->mir.custom_cursor) + mir_buffer_stream_release_sync(cursor->mir.custom_cursor); } void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + if (cursor && cursor->mir.conf) + { + mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf)); + if (cursor->mir.custom_cursor) + { + /* FIXME Bug https://bugs.launchpad.net/mir/+bug/1477285 + Requires a triple buffer swap to get the cursor buffer on top! (since mir is tripled buffered) + */ + mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor); + mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor); + mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor); + } + } + else + { + mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf)); + } } void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)