diff --git a/glfw/backend_utils.c b/glfw/backend_utils.c index 4c42c29a5..ec366421d 100644 --- a/glfw/backend_utils.c +++ b/glfw/backend_utils.c @@ -28,21 +28,22 @@ update_fds(EventLoopData *eld) { } } -void +int addWatch(EventLoopData *eld, int fd, int events, int enabled, watch_callback_func cb, void *cb_data) { - removeWatch(eld, fd); - if (eld->watches_count >= sizeof(eld->watches)/sizeof(eld->watches[0])) return; + removeWatch(eld, fd, events); + if (eld->watches_count >= sizeof(eld->watches)/sizeof(eld->watches[0])) return 0; Watch *w = eld->watches + eld->watches_count++; w->fd = fd; w->events = events; w->enabled = enabled; w->callback = cb; w->callback_data = cb_data; update_fds(eld); + return 1; } void -removeWatch(EventLoopData *eld, int fd) { +removeWatch(EventLoopData *eld, int fd, int events) { for (nfds_t i = 0; i < eld->watches_count; i++) { - if (eld->watches[i].fd == fd) { + if (eld->watches[i].fd == fd && eld->watches[i].events == events) { eld->watches_count--; if (i < eld->watches_count) { memmove(eld->watches + i, eld->watches + i + 1, sizeof(eld->watches[0]) * (eld->watches_count - i)); @@ -54,9 +55,9 @@ removeWatch(EventLoopData *eld, int fd) { } void -toggleWatch(EventLoopData *eld, int fd, int enabled) { +toggleWatch(EventLoopData *eld, int fd, int events, int enabled) { for (nfds_t i = 0; i < eld->watches_count; i++) { - if (eld->watches[i].fd == fd) { + if (eld->watches[i].fd == fd && eld->watches[i].events == events) { if (eld->watches[i].enabled != enabled) { eld->watches[i].enabled = enabled; update_fds(eld); diff --git a/glfw/backend_utils.h b/glfw/backend_utils.h index b2db23448..ae7a28854 100644 --- a/glfw/backend_utils.h +++ b/glfw/backend_utils.h @@ -44,9 +44,9 @@ typedef struct { } EventLoopData; -void addWatch(EventLoopData *eld, int fd, int events, int enabled, watch_callback_func cb, void *cb_data); -void removeWatch(EventLoopData *eld, int fd); -void toggleWatch(EventLoopData *eld, int fd, int enabled); +int addWatch(EventLoopData *eld, int fd, int events, int enabled, watch_callback_func cb, void *cb_data); +void removeWatch(EventLoopData *eld, int fd, int events); +void toggleWatch(EventLoopData *eld, int fd, int events, int enabled); void prepareForPoll(EventLoopData *eld); int pollWithTimeout(struct pollfd *fds, nfds_t nfds, double timeout); void dispatchEvents(EventLoopData *eld); diff --git a/glfw/dbus_glfw.c b/glfw/dbus_glfw.c index 955ac55f4..e36815b8b 100644 --- a/glfw/dbus_glfw.c +++ b/glfw/dbus_glfw.c @@ -40,11 +40,51 @@ report_error(DBusError *err, const char *fmt, ...) { dbus_error_free(err); } +static _GLFWDBUSData *dbus_data = NULL; + GLFWbool -glfw_dbus_init(_GLFWDBUSData *dbus) { +glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld) { + dbus->eld = eld; + dbus_data = dbus; return GLFW_TRUE; } +static void +on_dbus_watch_ready(int fd, int events, void *data) { + DBusWatch *watch = (DBusWatch*)data; + unsigned int flags = 0; + if (events & POLLERR) flags |= DBUS_WATCH_ERROR; + if (events & POLLHUP) flags |= DBUS_WATCH_HANGUP; + if (events & POLLIN) flags |= DBUS_WATCH_READABLE; + if (events & POLLOUT) flags |= DBUS_WATCH_WRITABLE; + dbus_watch_handle(watch, flags); +} + +static inline int +events_for_watch(DBusWatch *watch) { + int events = 0; + unsigned int flags = dbus_watch_get_flags(watch); + if (flags & DBUS_WATCH_READABLE) events |= POLLIN; + if (flags & DBUS_WATCH_WRITABLE) events |= POLLOUT; + return events; +} + +static dbus_bool_t +add_dbus_watch(DBusWatch *watch, void *data) { + if (addWatch(dbus_data->eld, dbus_watch_get_unix_fd(watch), events_for_watch(watch), dbus_watch_get_enabled(watch), on_dbus_watch_ready, watch)) return TRUE; + return FALSE; +} + +static void +remove_dbus_watch(DBusWatch *watch, void *data) { + removeWatch(dbus_data->eld, dbus_watch_get_unix_fd(watch), events_for_watch(watch)); +} + +static void +toggle_dbus_watch(DBusWatch *watch, void *data) { + toggleWatch(dbus_data->eld, dbus_watch_get_unix_fd(watch), events_for_watch(watch), dbus_watch_get_enabled(watch)); +} + DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg) { DBusError err; @@ -61,6 +101,12 @@ glfw_dbus_connect_to(const char *path, const char* err_msg) { return NULL; } dbus_connection_flush(ans); + if (!dbus_connection_set_watch_functions(ans, add_dbus_watch, remove_dbus_watch, toggle_dbus_watch, NULL, NULL)) { + _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to set DBUS watches on connection to: %s", path); + dbus_connection_close(ans); + dbus_connection_unref(ans); + return NULL; + } return ans; } diff --git a/glfw/dbus_glfw.h b/glfw/dbus_glfw.h index 926ab0ea5..f0b8da8a2 100644 --- a/glfw/dbus_glfw.h +++ b/glfw/dbus_glfw.h @@ -28,13 +28,15 @@ #pragma once #include +#include "backend_utils.h" typedef struct { DBusConnection *session_conn; + EventLoopData* eld; } _GLFWDBUSData; -GLFWbool glfw_dbus_init(_GLFWDBUSData *dbus); +GLFWbool glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld); void glfw_dbus_terminate(_GLFWDBUSData *dbus); DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg); void glfw_dbus_close_connection(DBusConnection *conn); diff --git a/glfw/wl_init.c b/glfw/wl_init.c index b1a0f5a7e..eeee4f388 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -665,6 +665,7 @@ int _glfwPlatformInit(void) return GLFW_FALSE; } initPollData(&_glfw.wl.eventLoopData, _glfw.wl.eventLoopData.wakeupFds[0], wl_display_get_fd(_glfw.wl.display)); + glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData); _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL); diff --git a/glfw/x11_init.c b/glfw/x11_init.c index c9939d4f4..f517ea2f9 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -641,6 +641,7 @@ int _glfwPlatformInit(void) } initPollData(&_glfw.x11.eventLoopData, _glfw.x11.eventLoopData.wakeupFds[0], ConnectionNumber(_glfw.x11.display)); + glfw_dbus_init(&_glfw.x11.dbus, &_glfw.x11.eventLoopData); _glfw.x11.screen = DefaultScreen(_glfw.x11.display); _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);