From e5fec3326e94342c5f10eadd8bb0a01f366ecb40 Mon Sep 17 00:00:00 2001 From: fwsmit Date: Tue, 24 Nov 2020 13:28:50 +0100 Subject: [PATCH] Wayland: optimize by making input code asyncronous --- src/draw.c | 4 +- src/dunst.c | 4 +- src/wayland/libgwater-wayland.c | 192 ++++++++++++++++++++++++++++++++ src/wayland/libgwater-wayland.h | 42 +++++++ src/wayland/wl.c | 10 +- 5 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 src/wayland/libgwater-wayland.c create mode 100644 src/wayland/libgwater-wayland.h diff --git a/src/draw.c b/src/draw.c index d83ab7e..d31c3b8 100644 --- a/src/draw.c +++ b/src/draw.c @@ -752,8 +752,8 @@ static void calc_window_pos(int width, int height, int *ret_x, int *ret_y) *ret_y = scr->y + settings.geometry.y; } } - LOG_I("Screen size: %ix%i", scr->w, scr->h); - LOG_I("Return value: %ix%i", *ret_x, *ret_y); + LOG_D("Screen size: %ix%i", scr->w, scr->h); + LOG_D("Return value: %ix%i", *ret_x, *ret_y); } void draw(void) diff --git a/src/dunst.c b/src/dunst.c index b6ff627..7d98a19 100644 --- a/src/dunst.c +++ b/src/dunst.c @@ -57,6 +57,7 @@ static gboolean run(void *data); void wake_up(void) { + LOG_D("Waking up"); run(NULL); } @@ -78,13 +79,14 @@ static gboolean run(void *data) draw(); output->win_show(win); } else { + LOG_I("Calling win_hide"); output->win_hide(win); } if (active) { gint64 now = time_monotonic_now(); gint64 sleep = queues_get_next_datachange(now); - sleep = 100000; // Make sure wayland input is handled in time FIXME + /* sleep = 100000; // Make sure wayland input is handled in time FIXME (fixed)*/ gint64 timeout_at = now + sleep; LOG_D("Sleeping for %li ms", sleep/1000); diff --git a/src/wayland/libgwater-wayland.c b/src/wayland/libgwater-wayland.c new file mode 100644 index 0000000..f9681e9 --- /dev/null +++ b/src/wayland/libgwater-wayland.c @@ -0,0 +1,192 @@ +/* + * libgwater-wayland - Wayland GSource + * + * Copyright © 2014-2017 Quentin "Sardem FF7" Glidic + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef G_LOG_DOMAIN +#undef G_LOG_DOMAIN +#endif /* G_LOG_DOMAIN */ +#define G_LOG_DOMAIN "GWaterWayland" + +#include + +#include + +#include + +#include "libgwater-wayland.h" + +struct _GWaterWaylandSource { + GSource source; + gboolean display_owned; + struct wl_display *display; + gpointer fd; + int error; +}; + +static gboolean +_g_water_wayland_source_prepare(GSource *source, gint *timeout) +{ + GWaterWaylandSource *self = (GWaterWaylandSource *)source; + + *timeout = 0; + if ( wl_display_prepare_read(self->display) != 0 ) + return TRUE; + else if ( wl_display_flush(self->display) < 0 ) + { + self->error = errno; + return TRUE; + } + + *timeout = -1; + return FALSE; +} + +static gboolean +_g_water_wayland_source_check(GSource *source) +{ + GWaterWaylandSource *self = (GWaterWaylandSource *)source; + + if ( self->error > 0 ) + return TRUE; + + GIOCondition revents; + revents = g_source_query_unix_fd(source, self->fd); + + if ( revents & G_IO_IN ) + { + if ( wl_display_read_events(self->display) < 0 ) + self->error = errno; + } + else + wl_display_cancel_read(self->display); + + return ( revents > 0 ); +} + +static gboolean +_g_water_wayland_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + GWaterWaylandSource *self = (GWaterWaylandSource *)source; + GIOCondition revents; + + revents = g_source_query_unix_fd(source, self->fd); + if ( ( self->error > 0 ) || ( revents & (G_IO_ERR | G_IO_HUP) ) ) + { + errno = self->error; + self->error = 0; + if ( callback != NULL ) + return callback(user_data); + return G_SOURCE_REMOVE; + } + + if ( wl_display_dispatch_pending(self->display) < 0 ) + { + if ( callback != NULL ) + return callback(user_data); + return G_SOURCE_REMOVE; + } + + return G_SOURCE_CONTINUE; +} + +static void +_g_water_wayland_source_finalize(GSource *source) +{ + GWaterWaylandSource *self = (GWaterWaylandSource *)source; + + if ( self->display_owned ) + wl_display_disconnect(self->display); +} + +static GSourceFuncs _g_water_wayland_source_funcs = { + .prepare = _g_water_wayland_source_prepare, + .check = _g_water_wayland_source_check, + .dispatch = _g_water_wayland_source_dispatch, + .finalize = _g_water_wayland_source_finalize, +}; + +GWaterWaylandSource * +g_water_wayland_source_new(GMainContext *context, const gchar *name) +{ + struct wl_display *display; + GWaterWaylandSource *self; + + display = wl_display_connect(name); + if ( display == NULL ) + return NULL; + + self = g_water_wayland_source_new_for_display(context, display); + self->display_owned = TRUE; + return self; +} + +GWaterWaylandSource * +g_water_wayland_source_new_for_display(GMainContext *context, struct wl_display *display) +{ + g_return_val_if_fail(display != NULL, NULL); + + GSource *source; + GWaterWaylandSource *self; + + source = g_source_new(&_g_water_wayland_source_funcs, sizeof(GWaterWaylandSource)); + self = (GWaterWaylandSource *)source; + self->display = display; + + self->fd = g_source_add_unix_fd(source, wl_display_get_fd(self->display), G_IO_IN | G_IO_ERR | G_IO_HUP); + + g_source_attach(source, context); + + return self; +} + +void +g_water_wayland_source_free(GWaterWaylandSource *self) +{ + GSource * source = (GSource *)self; + g_return_if_fail(self != NULL); + + g_source_destroy(source); + + g_source_unref(source); +} + +void +g_water_wayland_source_set_error_callback(GWaterWaylandSource *self, GSourceFunc callback, gpointer user_data, GDestroyNotify destroy_notify) +{ + g_return_if_fail(self != NULL); + + g_source_set_callback((GSource *)self, callback, user_data, destroy_notify); +} + +struct wl_display * +g_water_wayland_source_get_display(GWaterWaylandSource *self) +{ + g_return_val_if_fail(self != NULL, NULL); + + return self->display; +} diff --git a/src/wayland/libgwater-wayland.h b/src/wayland/libgwater-wayland.h new file mode 100644 index 0000000..700b6d4 --- /dev/null +++ b/src/wayland/libgwater-wayland.h @@ -0,0 +1,42 @@ +/* + * libgwater-wayland - Wayland GSource + * + * Copyright © 2014-2017 Quentin "Sardem FF7" Glidic + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef __G_WATER_WAYLAND_H__ +#define __G_WATER_WAYLAND_H__ + +G_BEGIN_DECLS + +typedef struct _GWaterWaylandSource GWaterWaylandSource; + +GWaterWaylandSource *g_water_wayland_source_new(GMainContext *context, const gchar *name); +GWaterWaylandSource *g_water_wayland_source_new_for_display(GMainContext *context, struct wl_display *display); +void g_water_wayland_source_free(GWaterWaylandSource *self); + +void g_water_wayland_source_set_error_callback(GWaterWaylandSource *self, GSourceFunc callback, gpointer user_data, GDestroyNotify destroy_notify); +struct wl_display *g_water_wayland_source_get_display(GWaterWaylandSource *source); + +G_END_DECLS + +#endif /* __G_WATER_WAYLAND_H__ */ diff --git a/src/wayland/wl.c b/src/wayland/wl.c index 7e557dd..d830487 100644 --- a/src/wayland/wl.c +++ b/src/wayland/wl.c @@ -25,6 +25,7 @@ #include "../log.h" #include "../settings.h" #include "../queues.h" +#include "libgwater-wayland.h" struct window_wl { struct wl_surface *surface; @@ -36,6 +37,8 @@ struct window_wl { cairo_t * c_ctx; struct dimensions dim; + GWaterWaylandSource *esrc; + char *data; size_t size; }; @@ -235,7 +238,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, } } } - + wake_up(); } static const struct wl_pointer_listener pointer_listener = { @@ -527,6 +530,8 @@ static void send_frame() { if (ctx.height != height) { struct dimensions dim = ctx.cur_dim; // Set window size + LOG_D("Wl: Window dimensions %ix%i", dim.w, dim.h); + LOG_D("Wl: Window position %ix%i", dim.x, dim.y); zwlr_layer_surface_v1_set_size(ctx.layer_surface, dim.w, dim.h); @@ -637,11 +642,14 @@ void wl_deinit(void) { window wl_win_create(void) { struct window_wl *win = g_malloc0(sizeof(struct window_wl)); + win->esrc = g_water_wayland_source_new_for_display(NULL, ctx.display); return win; } void wl_win_destroy(window winptr) { struct window_wl *win = (struct window_wl*)winptr; + + g_water_wayland_source_free(win->esrc); // FIXME: Dealloc everything g_free(win); }