Mir: Add cursor mode support

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.

Closes #839.
diff --git a/CMake/modules/FindMir.cmake b/CMake/modules/FindMir.cmake
index b1a495b..3f1fb0b 100644
--- a/CMake/modules/FindMir.cmake
+++ b/CMake/modules/FindMir.cmake
@@ -2,17 +2,36 @@
 #
 # This will define:
 #
-#   MIR_LIBRARIES   - Link these to use Wayland
-#   MIR_INCLUDE_DIR - Include directory for Wayland
-#
-# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
+#   MIR_FOUND       - System has Mir
+#   MIR_LIBRARIES   - Link these to use Mir
+#   MIR_INCLUDE_DIR - Include directory for Mir
+#   MIR_DEFINITIONS - Compiler switches required for using Mir
 
 if (NOT WIN32)
 
   find_package (PkgConfig)
   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_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 ()
diff --git a/src/mir_init.c b/src/mir_init.c
index dfe84f9..d58ff4f 100644
--- a/src/mir_init.c
+++ b/src/mir_init.c
@@ -198,12 +198,13 @@
     _glfwInitTimerPOSIX();
 
     // 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));
-    _glfwInitEventQueueMir(_glfw.mir.event_queue);
+    _glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
+    _glfwInitEventQueueMir(_glfw.mir.eventQueue);
 
-    error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL);
+    error = pthread_mutex_init(&_glfw.mir.eventMutex, NULL);
     if (error)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
@@ -221,9 +222,9 @@
     _glfwTerminateJoysticksLinux();
     _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);
 }
diff --git a/src/mir_monitor.c b/src/mir_monitor.c
index 94c1313..0cb4438 100644
--- a/src/mir_monitor.c
+++ b/src/mir_monitor.c
@@ -59,8 +59,8 @@
 
             monitors[i]->mir.x         = out->position_x;
             monitors[i]->mir.y         = out->position_y;
-            monitors[i]->mir.output_id = out->output_id;
-            monitors[i]->mir.cur_mode  = out->current_mode;
+            monitors[i]->mir.outputId  = out->output_id;
+            monitors[i]->mir.curMode   = out->current_mode;
 
             monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
                                                             &monitors[i]->modeCount);
@@ -75,7 +75,7 @@
 
 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)
@@ -129,7 +129,7 @@
     for (i = 0;  i < displayConfig->num_outputs;  i++)
     {
         const MirDisplayOutput* out = displayConfig->outputs + i;
-        if (out->output_id != monitor->mir.output_id)
+        if (out->output_id != monitor->mir.outputId)
             continue;
 
         modes = calloc(out->num_modes, sizeof(GLFWvidmode));
@@ -153,7 +153,7 @@
 
 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)
@@ -177,6 +177,6 @@
 {
     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
     _GLFW_REQUIRE_INIT_OR_RETURN(0);
-    return monitor->mir.output_id;
+    return monitor->mir.outputId;
 }
 
diff --git a/src/mir_platform.h b/src/mir_platform.h
index fc48392..250d4c3 100644
--- a/src/mir_platform.h
+++ b/src/mir_platform.h
@@ -84,6 +84,7 @@
     int                     width;
     int                     height;
     MirEGLNativeWindowType  window;
+    _GLFWcursor*            currentCursor;
 
 } _GLFWwindowMir;
 
@@ -91,8 +92,8 @@
 //
 typedef struct _GLFWmonitorMir
 {
-    int cur_mode;
-    int output_id;
+    int curMode;
+    int outputId;
     int x;
     int y;
 
@@ -104,14 +105,18 @@
 {
     MirConnection*          connection;
     MirEGLNativeDisplayType display;
-    MirCursorConfiguration* default_conf;
-    EventQueue* event_queue;
+    MirCursorConfiguration* defaultConf;
+    MirCursorConfiguration* disabledConf;
+    EventQueue* eventQueue;
 
     short int       publicKeys[256];
     short int       nativeKeys[GLFW_KEY_LAST + 1];
 
-    pthread_mutex_t event_mutex;
-    pthread_cond_t  event_cond;
+    pthread_mutex_t eventMutex;
+    pthread_cond_t  eventCond;
+
+    // The window whose disabled cursor mode is active
+    _GLFWwindow*    disabledCursorWindow;
 
 } _GLFWlibraryMir;
 
@@ -121,7 +126,7 @@
 typedef struct _GLFWcursorMir
 {
     MirCursorConfiguration* conf;
-    MirBufferStream*        custom_cursor;
+    MirBufferStream*        customCursor;
 } _GLFWcursorMir;
 
 
diff --git a/src/mir_window.c b/src/mir_window.c
index 3420abc..3f49cb0 100644
--- a/src/mir_window.c
+++ b/src/mir_window.c
@@ -54,37 +54,37 @@
 //      for single threaded event handling.
 static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
 {
-    EventNode* new_node = calloc(1, sizeof(EventNode));
-    new_node->event     = mir_event_ref(event);
-    new_node->window    = context;
+    EventNode* newNode = calloc(1, sizeof(EventNode));
+    newNode->event     = mir_event_ref(event);
+    newNode->window    = context;
 
-    return new_node;
+    return newNode;
 }
 
 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);
-    TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries);
+    EventNode* newNode = newEventNode(event, context);
+    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)
 {
     EventNode* node = NULL;
 
-    pthread_mutex_lock(&_glfw.mir.event_mutex);
+    pthread_mutex_lock(&_glfw.mir.eventMutex);
 
     node = queue->head.tqh_first;
 
     if (node)
         TAILQ_REMOVE(&queue->head, node, entries);
 
-    pthread_mutex_unlock(&_glfw.mir.event_mutex);
+    pthread_mutex_unlock(&_glfw.mir.eventMutex);
 
     return node;
 }
@@ -201,16 +201,31 @@
 static void handlePointerMotion(_GLFWwindow* window,
                                 const MirPointerEvent* pointer_event)
 {
-    int current_x = window->virtualCursorPosX;
-    int current_y = window->virtualCursorPosY;
-    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);
+    const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
+    const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
 
-    _glfwInputCursorPos(window, x, y);
-    if (dx != 0 || dy != 0)
-      _glfwInputScroll(window, dx, dy);
+    if (window->cursorMode == GLFW_CURSOR_DISABLED)
+    {
+        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);
+    }
+
+    if (hscroll != 0 || vscroll != 0)
+      _glfwInputScroll(window, hscroll, vscroll);
 }
 
 static void handlePointerEvent(const MirPointerEvent* pointer_event,
@@ -234,7 +249,6 @@
               break;
           default:
               break;
-
     }
 }
 
@@ -286,7 +300,7 @@
                         "Mir: Unable to find a correct pixel format");
         return GLFW_FALSE;
     }
- 
+
     spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
                                                          window->mir.width,
                                                          window->mir.height,
@@ -312,6 +326,17 @@
     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                      //////
 //////////////////////////////////////////////////////////////////////////
@@ -370,6 +395,7 @@
 
     window->mir.width  = wndconfig->width;
     window->mir.height = wndconfig->height;
+    window->mir.currentCursor = NULL;
 
     if (!createSurface(window))
         return GLFW_FALSE;
@@ -390,6 +416,9 @@
 
 void _glfwPlatformDestroyWindow(_GLFWwindow* window)
 {
+    if (_glfw.mir.disabledCursorWindow == window)
+        _glfw.mir.disabledCursorWindow = NULL;
+
     if (mir_surface_is_valid(window->mir.surface))
     {
         mir_surface_release_sync(window->mir.surface);
@@ -475,18 +504,35 @@
 
 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)
 {
-    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)
 {
-    _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_maximized);
+
+    mir_surface_apply_spec(window->mir.surface, spec);
+    mir_surface_spec_release(spec);
 }
 
 void _glfwPlatformHideWindow(_GLFWwindow* window)
@@ -529,9 +575,7 @@
 
 int _glfwPlatformWindowFocused(_GLFWwindow* window)
 {
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
-    return GLFW_FALSE;
+    return mir_surface_get_focus(window->mir.surface) == mir_surface_focused;
 }
 
 int _glfwPlatformWindowIconified(_GLFWwindow* window)
@@ -548,48 +592,46 @@
 
 int _glfwPlatformWindowMaximized(_GLFWwindow* window)
 {
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
-    return GLFW_FALSE;
+    return mir_surface_get_state(window->mir.surface) == mir_surface_state_maximized;
 }
 
 void _glfwPlatformPollEvents(void)
 {
     EventNode* node = NULL;
 
-    while ((node = dequeueEvent(_glfw.mir.event_queue)))
+    while ((node = dequeueEvent(_glfw.mir.eventQueue)))
     {
         handleEvent(node->event, node->window);
-        deleteNode(_glfw.mir.event_queue, node);
+        deleteNode(_glfw.mir.eventQueue, node);
     }
 }
 
 void _glfwPlatformWaitEvents(void)
 {
-    pthread_mutex_lock(&_glfw.mir.event_mutex);
+    pthread_mutex_lock(&_glfw.mir.eventMutex);
 
-    if (emptyEventQueue(_glfw.mir.event_queue))
-        pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex);
+    if (emptyEventQueue(_glfw.mir.eventQueue))
+        pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
 
-    pthread_mutex_unlock(&_glfw.mir.event_mutex);
+    pthread_mutex_unlock(&_glfw.mir.eventMutex);
 
     _glfwPlatformPollEvents();
 }
 
 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;
         clock_gettime(CLOCK_REALTIME, &time);
         time.tv_sec += (long) timeout;
         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();
 }
@@ -606,7 +648,6 @@
         *height = window->mir.height;
 }
 
-// FIXME implement
 int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
                               const GLFWimage* image,
                               int xhot, int yhot)
@@ -654,7 +695,7 @@
         pixels += r_stride;
     }
 
-    cursor->mir.custom_cursor = stream;
+    cursor->mir.customCursor = stream;
 
     return GLFW_TRUE;
 }
@@ -686,8 +727,8 @@
 
     if (cursor_name)
     {
-        cursor->mir.conf          = mir_cursor_configuration_from_name(cursor_name);
-        cursor->mir.custom_cursor = NULL;
+        cursor->mir.conf         = mir_cursor_configuration_from_name(cursor_name);
+        cursor->mir.customCursor = NULL;
 
         return GLFW_TRUE;
     }
@@ -699,23 +740,25 @@
 {
     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);
+    if (cursor->mir.customCursor)
+        mir_buffer_stream_release_sync(cursor->mir.customCursor);
 }
 
 void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
 {
     if (cursor && cursor->mir.conf)
     {
+        window->mir.currentCursor = cursor;
+
         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
     {
-        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 _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
 {
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+    if (mode == GLFW_CURSOR_DISABLED)
+    {
+        _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)