[RFC weston 1/2] libweston: Add event loop abstraction API
Quentin Glidic
sardemff7+wayland at sardemff7.net
Mon Feb 19 19:19:04 UTC 2018
From: Quentin Glidic <sardemff7+git at sardemff7.net>
This will allow compositors to pick any event loop implementation they
want, and integrating the libweston components with it.
Specifically, idle and timeout sources can now have proper priorities to
avoid being ghosted by client event processing.
Signed-off-by: Quentin Glidic <sardemff7+git at sardemff7.net>
---
compositor/main.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++--
libweston/compositor.c | 86 +++++++++++++++++++++++
libweston/compositor.h | 67 ++++++++++++++++++
3 files changed, 329 insertions(+), 6 deletions(-)
diff --git a/compositor/main.c b/compositor/main.c
index 18810f288..c0a5ba506 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -76,6 +76,180 @@ struct wet_compositor {
bool drm_use_current_mode;
};
+static struct wet_compositor *
+to_wet_compositor(struct weston_compositor *compositor)
+{
+ return weston_compositor_get_user_data(compositor);
+}
+
+struct wet_event_source {
+ struct wl_event_loop *loop;
+ struct wl_event_source *source;
+ weston_event_source_callback cb;
+ weston_event_source_fd_callback fd_cb;
+ void *user_data;
+};
+
+static void
+wet_event_source_idle_cb(void *data)
+{
+ struct wet_event_source *wsource = data;
+ enum weston_event_source_status ret;
+
+ ret = wsource->cb(wsource->user_data);
+ if (ret == WESTON_EVENT_SOURCE_REMOVE)
+ return;
+
+ wsource->source = wl_event_loop_add_idle(wsource->loop, wet_event_source_idle_cb, wsource);
+ if (wsource->source == NULL)
+ free(wsource);
+}
+
+static void *
+wet_event_source_add_idle(struct weston_compositor *compositor,
+ enum weston_event_source_priority priority,
+ weston_event_source_callback cb, void *user_data)
+{
+ struct wet_event_source *wsource = malloc(sizeof(struct wet_event_source));
+ if (wsource == NULL)
+ return NULL;
+
+ wsource->loop = wl_display_get_event_loop(compositor->wl_display);
+ wsource->cb = cb;
+ wsource->user_data = user_data;
+
+ wsource->source = wl_event_loop_add_idle(wsource->loop, wet_event_source_idle_cb, wsource);
+ if (wsource->source == NULL) {
+ free(wsource);
+ return NULL;
+ }
+
+ return wsource;
+}
+
+static int
+wet_event_source_timeout_cb(void *data)
+{
+ struct wet_event_source *wsource = data;
+ enum weston_event_source_status ret;
+
+ ret = wsource->cb(wsource->user_data);
+ if (ret == WESTON_EVENT_SOURCE_CONTINUE)
+ return 0;
+
+ wl_event_source_remove(wsource->source);
+ free(wsource);
+ return 0;
+}
+
+static void *
+wet_event_source_add_timeout(struct weston_compositor *compositor,
+ enum weston_event_source_priority priority,
+ uint32_t milliseconds,
+ weston_event_source_callback cb, void *user_data)
+{
+ struct wet_event_source *wsource = malloc(sizeof(struct wet_event_source));
+ if (wsource == NULL)
+ return NULL;
+
+ wsource->loop = wl_display_get_event_loop(compositor->wl_display);
+ wsource->cb = cb;
+ wsource->user_data = user_data;
+
+ wsource->source = wl_event_loop_add_timer(wsource->loop, wet_event_source_timeout_cb, wsource);
+ if (wsource->source == NULL) {
+ free(wsource);
+ return NULL;
+ }
+
+ if (milliseconds > 0)
+ wl_event_source_timer_update(wsource->source, milliseconds);
+
+ return wsource;
+}
+
+static void
+wet_event_source_update_timeout(struct weston_compositor *compositor,
+ void *source, uint32_t milliseconds)
+{
+ struct wet_event_source *wsource = source;
+
+ wl_event_source_timer_update(wsource->source, milliseconds);
+}
+
+static int
+wet_event_source_fd_cb(int fd, uint32_t mask, void *data)
+{
+ struct wet_event_source *wsource = data;
+ enum weston_event_source_status ret;
+
+ ret = wsource->fd_cb(fd, mask, wsource->user_data);
+ if (ret == WESTON_EVENT_SOURCE_CONTINUE)
+ return 0;
+
+ wl_event_source_remove(wsource->source);
+ free(wsource);
+ return 0;
+}
+
+static void *
+wet_event_source_add_fd(struct weston_compositor *compositor,
+ enum weston_event_source_priority priority,
+ int fd, enum weston_event_source_fd_events events,
+ weston_event_source_fd_callback cb, void *user_data)
+{
+ struct wet_event_source *wsource = malloc(sizeof(struct wet_event_source));
+ if (wsource == NULL)
+ return NULL;
+
+ wsource->loop = wl_display_get_event_loop(compositor->wl_display);
+ wsource->fd_cb = cb;
+ wsource->user_data = user_data;
+
+ wsource->source = wl_event_loop_add_fd(wsource->loop, fd, events, wet_event_source_fd_cb, wsource);
+ if (wsource->source == NULL) {
+ free(wsource);
+ return NULL;
+ }
+
+ return wsource;
+}
+
+static void
+wet_event_source_update_fd(struct weston_compositor *compositor, void *source,
+ enum weston_event_source_fd_events events)
+{
+ struct wet_event_source *wsource = source;
+
+ wl_event_source_fd_update(wsource->source, events);
+}
+
+static bool
+wet_event_source_is_valid(struct weston_compositor *compositor, void *source)
+{
+ return (source != NULL);
+}
+
+static void
+wet_event_source_remove(struct weston_compositor *compositor, void *source)
+{
+ struct wet_event_source *wsource = source;
+
+ wl_event_source_remove(wsource->source);
+ free(wsource);
+}
+
+
+static const struct weston_event_loop wet_event_loop = {
+ .add_idle = wet_event_source_add_idle,
+ .add_timeout = wet_event_source_add_timeout,
+ .update_timeout = wet_event_source_update_timeout,
+ .add_fd = wet_event_source_add_fd,
+ .update_fd = wet_event_source_update_fd,
+ .is_valid = wet_event_source_is_valid,
+ .remove = wet_event_source_remove,
+};
+
static FILE *weston_logfile = NULL;
static int cached_tm_mday = -1;
@@ -346,12 +520,6 @@ log_uname(void)
usys.version, usys.machine);
}
-static struct wet_compositor *
-to_wet_compositor(struct weston_compositor *compositor)
-{
- return weston_compositor_get_user_data(compositor);
-}
-
static void
wet_set_pending_output_handler(struct weston_compositor *ec,
wl_notify_func_t handler)
@@ -1773,6 +1941,8 @@ int main(int argc, char *argv[])
}
segv_compositor = ec;
+ ec->event_loop = &wet_event_loop;
+
if (weston_compositor_init_config(ec, config) < 0)
goto out;
diff --git a/libweston/compositor.c b/libweston/compositor.c
index aec937bb8..2f129da38 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -5732,3 +5732,89 @@ weston_compositor_load_xwayland(struct weston_compositor *compositor)
return -1;
return 0;
}
+
+
+WL_EXPORT void
+*weston_compositor_event_source_add_idle(struct weston_compositor *compositor, enum weston_event_source_priority priority, weston_event_source_callback cb, void *user_data)
+{
+ assert(compositor->event_loop != NULL);
+ assert(compositor->event_loop->add_idle != NULL);
+
+ return compositor->event_loop->add_idle(compositor, priority, cb, user_data);
+}
+
+WL_EXPORT void
+*weston_compositor_event_source_add_timeout(struct weston_compositor *compositor, enum weston_event_source_priority priority, uint32_t milliseconds, weston_event_source_callback cb, void *user_data)
+{
+ assert(compositor->event_loop != NULL);
+ assert(compositor->event_loop->add_timeout != NULL);
+
+ return compositor->event_loop->add_timeout(compositor, priority, milliseconds, cb, user_data);
+}
+
+WL_EXPORT void
+weston_compositor_event_source_update_timeout(struct weston_compositor *compositor, void *source, uint32_t milliseconds)
+{
+ assert(compositor->event_loop != NULL);
+ assert(compositor->event_loop->update_timeout != NULL);
+
+ compositor->event_loop->update_timeout(compositor, source, milliseconds);
+}
+
+WL_EXPORT void
+*weston_compositor_event_source_add_timeout_seconds(struct weston_compositor *compositor, enum weston_event_source_priority priority, uint32_t seconds, weston_event_source_callback cb, void *user_data)
+{
+ assert(compositor->event_loop != NULL);
+
+ if (compositor->event_loop->add_timeout_seconds == NULL)
+ return compositor->event_loop->add_timeout(compositor, priority, seconds * 1000, cb, user_data);
+ else
+ return compositor->event_loop->add_timeout_seconds(compositor, priority, seconds, cb, user_data);
+}
+
+WL_EXPORT void
+weston_compositor_event_source_update_timeout_seconds(struct weston_compositor *compositor, void *source, uint32_t seconds)
+{
+ assert(compositor->event_loop != NULL);
+
+ if (compositor->event_loop->update_timeout_seconds == NULL)
+ return compositor->event_loop->update_timeout(compositor, source, seconds * 1000);
+ else
+ return compositor->event_loop->update_timeout_seconds(compositor, source, seconds);
+}
+
+WL_EXPORT void
+*weston_compositor_event_source_add_fd(struct weston_compositor *compositor, enum weston_event_source_priority priority, int fd, enum weston_event_source_fd_events events, weston_event_source_fd_callback cb, void *user_data)
+{
+ assert(compositor->event_loop != NULL);
+ assert(compositor->event_loop->add_fd != NULL);
+
+ return compositor->event_loop->add_fd(compositor, priority, fd, events, cb, user_data);
+}
+
+WL_EXPORT void
+weston_compositor_event_source_update_fd(struct weston_compositor *compositor, void *source, enum weston_event_source_fd_events events)
+{
+ assert(compositor->event_loop != NULL);
+ assert(compositor->event_loop->update_fd != NULL);
+
+ return compositor->event_loop->update_fd(compositor, source, events);
+}
+
+WL_EXPORT bool
+weston_compositor_event_source_is_valid(struct weston_compositor *compositor, void *source)
+{
+ assert(compositor->event_loop != NULL);
+ assert(compositor->event_loop->is_valid != NULL);
+
+ return compositor->event_loop->is_valid(compositor, source);
+}
+
+WL_EXPORT void
+weston_compositor_event_source_remove(struct weston_compositor *compositor, void *source)
+{
+ assert(compositor->event_loop != NULL);
+ assert(compositor->event_loop->remove != NULL);
+
+ return compositor->event_loop->remove(compositor, source);
+}
diff --git a/libweston/compositor.h b/libweston/compositor.h
index ca1acc605..9d662b9d5 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -857,11 +857,13 @@ struct weston_backend {
struct weston_desktop_xwayland;
struct weston_desktop_xwayland_interface;
+struct weston_event_loop;
struct weston_compositor {
struct wl_signal destroy_signal;
struct wl_display *wl_display;
+ const struct weston_event_loop *event_loop;
struct weston_desktop_xwayland *xwayland;
const struct weston_desktop_xwayland_interface *xwayland_interface;
@@ -1959,6 +1961,71 @@ weston_pending_output_coldplug(struct weston_compositor *compositor);
struct weston_output *
weston_output_from_resource(struct wl_resource *resource);
+enum weston_event_source_priority {
+ WESTON_EVENT_SOURCE_PRIORITY_HIGH = -100,
+ WESTON_EVENT_SOURCE_PRIORITY_DEFAULT = 0,
+ WESTON_EVENT_SOURCE_PRIORITY_TIMEOUT = 0,
+ WESTON_EVENT_SOURCE_PRIORITY_FD = 0,
+ WESTON_EVENT_SOURCE_PRIORITY_IDLE = 200,
+ WESTON_EVENT_SOURCE_PRIORITY_LOW = 300,
+};
+enum weston_event_source_status {
+ WESTON_EVENT_SOURCE_REMOVE,
+ WESTON_EVENT_SOURCE_CONTINUE,
+};
+enum weston_event_source_fd_events {
+ WESTON_EVENT_SOURCE_FD_IN = (1 << 0),
+ WESTON_EVENT_SOURCE_FD_OUT = (1 << 1),
+ WESTON_EVENT_SOURCE_FD_HUP = (1 << 2),
+ WESTON_EVENT_SOURCE_FD_ERR = (1 << 3),
+};
+typedef enum weston_event_source_status (*weston_event_source_callback)(void *user_data);
+typedef enum weston_event_source_status (*weston_event_source_fd_callback)(int fd, enum weston_event_source_fd_events events, void *user_data);
+struct weston_event_loop {
+ void *(*add_idle)
+ (struct weston_compositor *compositor,
+ enum weston_event_source_priority priority,
+ weston_event_source_callback cb, void *user_data);
+ void *(*add_timeout)
+ (struct weston_compositor *compositor,
+ enum weston_event_source_priority priority,
+ uint32_t milliseconds,
+ weston_event_source_callback cb, void *user_data);
+ void (*update_timeout)
+ (struct weston_compositor *compositor, void *source,
+ uint32_t milliseconds);
+ void *(*add_timeout_seconds)
+ (struct weston_compositor *compositor,
+ enum weston_event_source_priority priority,
+ uint32_t seconds,
+ weston_event_source_callback cb, void *user_data);
+ void (*update_timeout_seconds)
+ (struct weston_compositor *compositor, void *source,
+ uint32_t seconds);
+ void *(*add_fd)
+ (struct weston_compositor *compositor,
+ enum weston_event_source_priority priority,
+ int fd, enum weston_event_source_fd_events events,
+ weston_event_source_fd_callback cb, void *user_data);
+ void (*update_fd)
+ (struct weston_compositor *compositor, void *source,
+ enum weston_event_source_fd_events events);
+ bool (*is_valid)
+ (struct weston_compositor *compositor, void *source);
+ void (*remove)
+ (struct weston_compositor *compositor, void *source);
+};
+
+void *weston_compositor_event_source_add_idle(struct weston_compositor *compositor, enum weston_event_source_priority priority, weston_event_source_callback cb, void *user_data);
+void *weston_compositor_event_source_add_timeout(struct weston_compositor *compositor, enum weston_event_source_priority priority, uint32_t milliseconds, weston_event_source_callback cb, void *user_data);
+void weston_compositor_event_source_update_timeout(struct weston_compositor *compositor, void *source, uint32_t milliseconds);
+void *weston_compositor_event_source_add_timeout_seconds(struct weston_compositor *compositor, enum weston_event_source_priority priority, uint32_t seconds, weston_event_source_callback cb, void *user_data);
+void weston_compositor_event_source_update_timeout_seconds(struct weston_compositor *compositor, void *source, uint32_t seconds);
+void *weston_compositor_event_source_add_fd(struct weston_compositor *compositor, enum weston_event_source_priority priority, int fd, enum weston_event_source_fd_events events, weston_event_source_fd_callback cb, void *user_data);
+void weston_compositor_event_source_update_fd(struct weston_compositor *compositor, void *source, enum weston_event_source_fd_events events);
+bool weston_compositor_event_source_is_valid(struct weston_compositor *compositor, void *source);
+void weston_compositor_event_source_remove(struct weston_compositor *compositor, void *source);
+
#ifdef __cplusplus
}
#endif
--
2.15.1
More information about the wayland-devel
mailing list