Mir: Add relative mouse support and the CursorModes

Implements a few other missing functions. Cleaning up naming convention
as well.

Fix FindMir.cmake was not finding the correct mirclient.so when
you wanted something other then the system library.
This commit is contained in:
Brandon Schaefer 2016-08-16 15:26:07 -07:00
parent f1c536fe13
commit c76c6dc91a
5 changed files with 167 additions and 77 deletions

View File

@ -2,17 +2,36 @@
# #
# This will define: # This will define:
# #
# MIR_LIBRARIES - Link these to use Wayland # MIR_FOUND - System has Mir
# MIR_INCLUDE_DIR - Include directory for Wayland # MIR_LIBRARIES - Link these to use Mir
# # MIR_INCLUDE_DIR - Include directory for Mir
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com> # MIR_DEFINITIONS - Compiler switches required for using Mir
if (NOT WIN32) if (NOT WIN32)
find_package (PkgConfig) find_package (PkgConfig)
pkg_check_modules (PKG_MIR QUIET mirclient) pkg_check_modules (PKG_MIR QUIET mirclient)
set(MIR_DEFINITIONS ${PKG_MIR_CFLAGS_OTHER})
find_path(MIR_INCLUDE_DIR
NAMES xkbcommon/xkbcommon.h
HINTS ${PC_XKBCOMMON_INCLUDE_DIR} ${PC_XKBCOMMON_INCLUDE_DIRS}
)
find_library(MIR_LIBRARY
NAMES mirclient
HINTS ${PKG_MIR_LIBRARIES} ${MIR_LIBRARY_DIRS}
)
set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS}) set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS})
set (MIR_LIBRARIES ${PKG_MIR_LIBRARIES}) set (MIR_LIBRARIES ${MIR_LIBRARY})
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (MIR DEFAULT_MSG
MIR_LIBRARIES
MIR_INCLUDE_DIR
)
mark_as_advanced (MIR_LIBRARIES MIR_INCLUDE_DIR)
endif () endif ()

View File

@ -189,12 +189,13 @@ int _glfwPlatformInit(void)
_glfwInitTimerPOSIX(); _glfwInitTimerPOSIX();
// Need the default conf for when we set a NULL cursor // Need the default conf for when we set a NULL cursor
_glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name); _glfw.mir.defaultConf = mir_cursor_configuration_from_name(mir_default_cursor_name);
_glfw.mir.disabledConf = mir_cursor_configuration_from_name(mir_disabled_cursor_name);
_glfw.mir.event_queue = calloc(1, sizeof(EventQueue)); _glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
_glfwInitEventQueueMir(_glfw.mir.event_queue); _glfwInitEventQueueMir(_glfw.mir.eventQueue);
error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL); error = pthread_mutex_init(&_glfw.mir.eventMutex, NULL);
if (error) if (error)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -212,9 +213,9 @@ void _glfwPlatformTerminate(void)
_glfwTerminateJoysticksLinux(); _glfwTerminateJoysticksLinux();
_glfwTerminateThreadLocalStoragePOSIX(); _glfwTerminateThreadLocalStoragePOSIX();
_glfwDeleteEventQueueMir(_glfw.mir.event_queue); _glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
pthread_mutex_destroy(&_glfw.mir.event_mutex); pthread_mutex_destroy(&_glfw.mir.eventMutex);
mir_connection_release(_glfw.mir.connection); mir_connection_release(_glfw.mir.connection);
} }

View File

@ -59,8 +59,8 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
monitors[i]->mir.x = out->position_x; monitors[i]->mir.x = out->position_x;
monitors[i]->mir.y = out->position_y; monitors[i]->mir.y = out->position_y;
monitors[i]->mir.output_id = out->output_id; monitors[i]->mir.outputId = out->output_id;
monitors[i]->mir.cur_mode = out->current_mode; monitors[i]->mir.curMode = out->current_mode;
monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i], monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
&monitors[i]->modeCount); &monitors[i]->modeCount);
@ -75,7 +75,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{ {
return first->mir.output_id == second->mir.output_id; return first->mir.outputId == second->mir.outputId;
} }
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
@ -129,7 +129,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
for (i = 0; i < displayConfig->num_outputs; i++) for (i = 0; i < displayConfig->num_outputs; i++)
{ {
const MirDisplayOutput* out = displayConfig->outputs + i; const MirDisplayOutput* out = displayConfig->outputs + i;
if (out->output_id != monitor->mir.output_id) if (out->output_id != monitor->mir.outputId)
continue; continue;
modes = calloc(out->num_modes, sizeof(GLFWvidmode)); modes = calloc(out->num_modes, sizeof(GLFWvidmode));
@ -153,7 +153,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{ {
*mode = monitor->modes[monitor->mir.cur_mode]; *mode = monitor->modes[monitor->mir.curMode];
} }
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
@ -177,6 +177,6 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(0); _GLFW_REQUIRE_INIT_OR_RETURN(0);
return monitor->mir.output_id; return monitor->mir.outputId;
} }

View File

@ -84,6 +84,7 @@ typedef struct _GLFWwindowMir
int width; int width;
int height; int height;
MirEGLNativeWindowType window; MirEGLNativeWindowType window;
_GLFWcursor* currentCursor;
} _GLFWwindowMir; } _GLFWwindowMir;
@ -91,8 +92,8 @@ typedef struct _GLFWwindowMir
// //
typedef struct _GLFWmonitorMir typedef struct _GLFWmonitorMir
{ {
int cur_mode; int curMode;
int output_id; int outputId;
int x; int x;
int y; int y;
@ -104,13 +105,17 @@ typedef struct _GLFWlibraryMir
{ {
MirConnection* connection; MirConnection* connection;
MirEGLNativeDisplayType display; MirEGLNativeDisplayType display;
MirCursorConfiguration* default_conf; MirCursorConfiguration* defaultConf;
EventQueue* event_queue; MirCursorConfiguration* disabledConf;
EventQueue* eventQueue;
short int publicKeys[256]; short int publicKeys[256];
pthread_mutex_t event_mutex; pthread_mutex_t eventMutex;
pthread_cond_t event_cond; pthread_cond_t eventCond;
// The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow;
} _GLFWlibraryMir; } _GLFWlibraryMir;
@ -120,7 +125,7 @@ typedef struct _GLFWlibraryMir
typedef struct _GLFWcursorMir typedef struct _GLFWcursorMir
{ {
MirCursorConfiguration* conf; MirCursorConfiguration* conf;
MirBufferStream* custom_cursor; MirBufferStream* customCursor;
} _GLFWcursorMir; } _GLFWcursorMir;

View File

@ -54,37 +54,37 @@ static GLFWbool emptyEventQueue(EventQueue* queue)
// for single threaded event handling. // for single threaded event handling.
static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context) static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
{ {
EventNode* new_node = calloc(1, sizeof(EventNode)); EventNode* newNode = calloc(1, sizeof(EventNode));
new_node->event = mir_event_ref(event); newNode->event = mir_event_ref(event);
new_node->window = context; newNode->window = context;
return new_node; return newNode;
} }
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context) static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
{ {
pthread_mutex_lock(&_glfw.mir.event_mutex); pthread_mutex_lock(&_glfw.mir.eventMutex);
EventNode* new_node = newEventNode(event, context); EventNode* newNode = newEventNode(event, context);
TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries); TAILQ_INSERT_TAIL(&_glfw.mir.eventQueue->head, newNode, entries);
pthread_cond_signal(&_glfw.mir.event_cond); pthread_cond_signal(&_glfw.mir.eventCond);
pthread_mutex_unlock(&_glfw.mir.event_mutex); pthread_mutex_unlock(&_glfw.mir.eventMutex);
} }
static EventNode* dequeueEvent(EventQueue* queue) static EventNode* dequeueEvent(EventQueue* queue)
{ {
EventNode* node = NULL; EventNode* node = NULL;
pthread_mutex_lock(&_glfw.mir.event_mutex); pthread_mutex_lock(&_glfw.mir.eventMutex);
node = queue->head.tqh_first; node = queue->head.tqh_first;
if (node) if (node)
TAILQ_REMOVE(&queue->head, node, entries); TAILQ_REMOVE(&queue->head, node, entries);
pthread_mutex_unlock(&_glfw.mir.event_mutex); pthread_mutex_unlock(&_glfw.mir.eventMutex);
return node; return node;
} }
@ -201,16 +201,31 @@ static void handlePointerButton(_GLFWwindow* window,
static void handlePointerMotion(_GLFWwindow* window, static void handlePointerMotion(_GLFWwindow* window,
const MirPointerEvent* pointer_event) const MirPointerEvent* pointer_event)
{ {
int current_x = window->virtualCursorPosX; const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
int current_y = window->virtualCursorPosY; const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
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); if (window->cursorMode == GLFW_CURSOR_DISABLED)
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 (_glfw.mir.disabledCursorWindow != window)
return;
const int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x);
const int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y);
const int current_x = window->virtualCursorPosX;
const int current_y = window->virtualCursorPosY;
_glfwInputCursorPos(window, dx + current_x, dy + current_y);
}
else
{
const int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
const int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
_glfwInputCursorPos(window, x, y); _glfwInputCursorPos(window, x, y);
if (dx != 0 || dy != 0) }
_glfwInputScroll(window, dx, dy);
if (hscroll != 0 || vscroll != 0)
_glfwInputScroll(window, hscroll, vscroll);
} }
static void handlePointerEvent(const MirPointerEvent* pointer_event, static void handlePointerEvent(const MirPointerEvent* pointer_event,
@ -234,7 +249,6 @@ static void handlePointerEvent(const MirPointerEvent* pointer_event,
break; break;
default: default:
break; break;
} }
} }
@ -312,6 +326,17 @@ static GLFWbool createSurface(_GLFWwindow* window)
return GLFW_TRUE; return GLFW_TRUE;
} }
static void setSurfaceConfinement(_GLFWwindow* window, MirPointerConfinementState state)
{
MirSurfaceSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_pointer_confinement(spec, state);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -370,6 +395,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
window->mir.width = wndconfig->width; window->mir.width = wndconfig->width;
window->mir.height = wndconfig->height; window->mir.height = wndconfig->height;
window->mir.currentCursor = NULL;
if (!createSurface(window)) if (!createSurface(window))
return GLFW_FALSE; return GLFW_FALSE;
@ -390,6 +416,9 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
void _glfwPlatformDestroyWindow(_GLFWwindow* window) void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{ {
if (_glfw.mir.disabledCursorWindow == window)
_glfw.mir.disabledCursorWindow = NULL;
if (mir_surface_is_valid(window->mir.surface)) if (mir_surface_is_valid(window->mir.surface))
{ {
mir_surface_release_sync(window->mir.surface); mir_surface_release_sync(window->mir.surface);
@ -475,18 +504,35 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformIconifyWindow(_GLFWwindow* window) void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{ {
mir_surface_set_state(window->mir.surface, mir_surface_state_minimized); MirSurfaceSpec* spec;
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_state(spec, mir_surface_state_minimized);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
} }
void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{ {
mir_surface_set_state(window->mir.surface, mir_surface_state_restored); 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 _glfwPlatformMaximizeWindow(_GLFWwindow* window) void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, MirSurfaceSpec* spec;
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
mir_surface_spec_set_state(spec, mir_surface_state_maximized);
mir_surface_apply_spec(window->mir.surface, spec);
mir_surface_spec_release(spec);
} }
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
@ -529,9 +575,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
int _glfwPlatformWindowFocused(_GLFWwindow* window) int _glfwPlatformWindowFocused(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, return mir_surface_get_focus(window->mir.surface) == mir_surface_focused;
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
} }
int _glfwPlatformWindowIconified(_GLFWwindow* window) int _glfwPlatformWindowIconified(_GLFWwindow* window)
@ -548,48 +592,46 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
int _glfwPlatformWindowMaximized(_GLFWwindow* window) int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, return mir_surface_get_state(window->mir.surface) == mir_surface_state_maximized;
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
} }
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
EventNode* node = NULL; EventNode* node = NULL;
while ((node = dequeueEvent(_glfw.mir.event_queue))) while ((node = dequeueEvent(_glfw.mir.eventQueue)))
{ {
handleEvent(node->event, node->window); handleEvent(node->event, node->window);
deleteNode(_glfw.mir.event_queue, node); deleteNode(_glfw.mir.eventQueue, node);
} }
} }
void _glfwPlatformWaitEvents(void) void _glfwPlatformWaitEvents(void)
{ {
pthread_mutex_lock(&_glfw.mir.event_mutex); pthread_mutex_lock(&_glfw.mir.eventMutex);
if (emptyEventQueue(_glfw.mir.event_queue)) if (emptyEventQueue(_glfw.mir.eventQueue))
pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex); pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
pthread_mutex_unlock(&_glfw.mir.event_mutex); pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents(); _glfwPlatformPollEvents();
} }
void _glfwPlatformWaitEventsTimeout(double timeout) void _glfwPlatformWaitEventsTimeout(double timeout)
{ {
pthread_mutex_lock(&_glfw.mir.event_mutex); pthread_mutex_lock(&_glfw.mir.eventMutex);
if (emptyEventQueue(_glfw.mir.event_queue)) if (emptyEventQueue(_glfw.mir.eventQueue))
{ {
struct timespec time; struct timespec time;
clock_gettime(CLOCK_REALTIME, &time); clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += (long) timeout; time.tv_sec += (long) timeout;
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9); time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time); pthread_cond_timedwait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex, &time);
} }
pthread_mutex_unlock(&_glfw.mir.event_mutex); pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents(); _glfwPlatformPollEvents();
} }
@ -606,7 +648,6 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
*height = window->mir.height; *height = window->mir.height;
} }
// FIXME implement
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot) int xhot, int yhot)
@ -654,7 +695,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
pixels += r_stride; pixels += r_stride;
} }
cursor->mir.custom_cursor = stream; cursor->mir.customCursor = stream;
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -687,7 +728,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
if (cursor_name) if (cursor_name)
{ {
cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name); cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
cursor->mir.custom_cursor = NULL; cursor->mir.customCursor = NULL;
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -699,23 +740,25 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{ {
if (cursor->mir.conf) if (cursor->mir.conf)
mir_cursor_configuration_destroy(cursor->mir.conf); mir_cursor_configuration_destroy(cursor->mir.conf);
if (cursor->mir.custom_cursor) if (cursor->mir.customCursor)
mir_buffer_stream_release_sync(cursor->mir.custom_cursor); mir_buffer_stream_release_sync(cursor->mir.customCursor);
} }
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{ {
if (cursor && cursor->mir.conf) if (cursor && cursor->mir.conf)
{ {
window->mir.currentCursor = cursor;
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf)); mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
if (cursor->mir.custom_cursor) if (cursor->mir.customCursor)
{ {
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor); mir_buffer_stream_swap_buffers_sync(cursor->mir.customCursor);
} }
} }
else else
{ {
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf)); mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.defaultConf));
} }
} }
@ -733,8 +776,30 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, if (mode == GLFW_CURSOR_DISABLED)
"Mir: Unsupported function %s", __PRETTY_FUNCTION__); {
_glfw.mir.disabledCursorWindow = window;
setSurfaceConfinement(window, mir_pointer_confined_to_surface);
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.disabledConf));
}
else
{
// If we were disabled before lets undo that!
if (_glfw.mir.disabledCursorWindow == window)
{
_glfw.mir.disabledCursorWindow = NULL;
setSurfaceConfinement(window, mir_pointer_unconfined);
}
if (window->cursorMode == GLFW_CURSOR_NORMAL)
{
_glfwPlatformSetCursor(window, window->mir.currentCursor);
}
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
{
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.disabledConf));
}
}
} }
const char* _glfwPlatformGetKeyName(int key, int scancode) const char* _glfwPlatformGetKeyName(int key, int scancode)