Create an event queue to store all MirEvents.
This ensures all events come out of the same thread, as well as ensuring the threads sync up correctly when touching the event queue.
This commit is contained in:
parent
0a5d57eade
commit
f306ea2f5d
@ -26,6 +26,7 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
@ -33,6 +34,8 @@
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
_glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__);
|
||||
|
||||
if (!mir_connection_is_valid(_glfw.mir.connection))
|
||||
@ -51,6 +54,17 @@ int _glfwPlatformInit(void)
|
||||
_glfwInitTimer();
|
||||
_glfwInitJoysticks();
|
||||
|
||||
_glfw.mir.event_queue = calloc(1, sizeof(EventQueue));
|
||||
_glfwInitEventQueue(_glfw.mir.event_queue);
|
||||
|
||||
error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL);
|
||||
if (error)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Failed to create Event Mutex Error: %i\n", error);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
@ -59,6 +73,10 @@ void _glfwPlatformTerminate(void)
|
||||
_glfwTerminateContextAPI();
|
||||
_glfwTerminateJoysticks();
|
||||
|
||||
_glfwDeleteEventQueue(_glfw.mir.event_queue);
|
||||
|
||||
pthread_mutex_destroy(&_glfw.mir.event_mutex);
|
||||
|
||||
mir_connection_release(_glfw.mir.connection);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,10 @@
|
||||
#include "posix_time.h"
|
||||
#include "linux_joystick.h"
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(_GLFW_EGL)
|
||||
#include "egl_context.h"
|
||||
#else
|
||||
@ -47,6 +51,12 @@
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
|
||||
|
||||
// Mir-specific Event Queue
|
||||
//
|
||||
typedef struct EventQueue
|
||||
{
|
||||
TAILQ_HEAD(, EventNode) head;
|
||||
} EventQueue;
|
||||
|
||||
// Mir-specific per-window data
|
||||
//
|
||||
@ -78,6 +88,10 @@ typedef struct _GLFWlibraryMir
|
||||
{
|
||||
MirConnection* connection;
|
||||
MirEGLNativeDisplayType display;
|
||||
EventQueue* event_queue;
|
||||
|
||||
pthread_mutex_t event_mutex;
|
||||
pthread_cond_t event_cond;
|
||||
|
||||
} _GLFWlibraryMir;
|
||||
|
||||
@ -89,4 +103,8 @@ typedef struct _GLFWcursorMir
|
||||
{
|
||||
} _GLFWcursorMir;
|
||||
|
||||
|
||||
extern void _glfwInitEventQueue(EventQueue* queue);
|
||||
extern void _glfwDeleteEventQueue(EventQueue* queue);
|
||||
|
||||
#endif // _mir_platform_h_
|
||||
|
114
src/mir_window.c
114
src/mir_window.c
@ -28,8 +28,66 @@
|
||||
#include "xkb_unicode.h"
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
typedef struct EventNode
|
||||
{
|
||||
TAILQ_ENTRY(EventNode) entries;
|
||||
MirEvent* event;
|
||||
_GLFWwindow* window;
|
||||
} EventNode;
|
||||
|
||||
static void deleteNode(EventQueue* queue, EventNode* node)
|
||||
{
|
||||
free(node->event);
|
||||
free(node);
|
||||
}
|
||||
|
||||
static int emptyEventQueue(EventQueue* queue)
|
||||
{
|
||||
return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
static EventNode* newEventNode(MirEvent const* event, _GLFWwindow* context)
|
||||
{
|
||||
EventNode* new_node = calloc(1, sizeof(EventNode));
|
||||
new_node->event = calloc(1, sizeof(MirEvent));
|
||||
new_node->window = context;
|
||||
|
||||
memcpy(new_node->event, event, sizeof(MirEvent));
|
||||
return new_node;
|
||||
}
|
||||
|
||||
static void enqueueEvent(MirEvent const* event, _GLFWwindow* context)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||
|
||||
EventNode* new_node = newEventNode(event, context);
|
||||
TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries);
|
||||
|
||||
pthread_cond_signal(&_glfw.mir.event_cond);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.event_mutex);
|
||||
}
|
||||
|
||||
static EventNode* dequeueEvent(EventQueue* queue)
|
||||
{
|
||||
EventNode* node = NULL;
|
||||
|
||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||
|
||||
node = queue->head.tqh_first;
|
||||
|
||||
if (node)
|
||||
TAILQ_REMOVE(&queue->head, node, entries);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.event_mutex);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static MirPixelFormat findValidPixelFormat(void)
|
||||
{
|
||||
unsigned int i, validFormats, size = 32;
|
||||
@ -298,21 +356,26 @@ static void handleMotionEvent(const MirMotionEvent motion, _GLFWwindow* window)
|
||||
handleMouseEvent(motion, i, window);
|
||||
}
|
||||
|
||||
static void handleInput(MirSurface* surface, const MirEvent* event, void* context)
|
||||
static void handleInput(MirEvent const* event, _GLFWwindow* window)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case mir_event_type_key:
|
||||
handleKeyEvent(event->key, (_GLFWwindow*) context);
|
||||
handleKeyEvent(event->key, window);
|
||||
break;
|
||||
case mir_event_type_motion:
|
||||
handleMotionEvent(event->motion, (_GLFWwindow*) context);
|
||||
handleMotionEvent(event->motion, window);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void addNewEvent(MirSurface* surface, MirEvent const* event, void* context)
|
||||
{
|
||||
enqueueEvent(event, context);
|
||||
}
|
||||
|
||||
static int createSurface(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceParameters params =
|
||||
@ -327,7 +390,7 @@ static int createSurface(_GLFWwindow* window)
|
||||
|
||||
MirEventDelegate delegate =
|
||||
{
|
||||
handleInput,
|
||||
addNewEvent,
|
||||
window
|
||||
};
|
||||
|
||||
@ -353,6 +416,30 @@ static int createSurface(_GLFWwindow* window)
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInitEventQueue(EventQueue* queue)
|
||||
{
|
||||
TAILQ_INIT(&queue->head);
|
||||
}
|
||||
|
||||
void _glfwDeleteEventQueue(EventQueue* queue)
|
||||
{
|
||||
EventNode* node, *node_next;
|
||||
node = queue->head.tqh_first;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
node_next = node->entries.tqe_next;
|
||||
|
||||
TAILQ_REMOVE(&queue->head, node, entries);
|
||||
deleteNode(queue, node);
|
||||
|
||||
node = node_next;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
@ -475,14 +562,25 @@ void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
// Mir does event handling in a different thread, so windows get events
|
||||
// directly as they happen
|
||||
EventNode* node = NULL;
|
||||
|
||||
while ((node = dequeueEvent(_glfw.mir.event_queue)))
|
||||
{
|
||||
handleInput(node->event, node->window);
|
||||
deleteNode(_glfw.mir.event_queue, node);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
// Mir does event handling in a different thread, so windows get events
|
||||
// directly as they happen
|
||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||
|
||||
if (emptyEventQueue(_glfw.mir.event_queue))
|
||||
pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.event_mutex);
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
}
|
||||
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
|
Loading…
Reference in New Issue
Block a user