From 3a69627f438dae394c972fb4b84975b35756d2d7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 14 Sep 2011 17:33:48 -0400 Subject: [PATCH] window: Stop using glib mainloop in toy toolkit --- clients/Makefile.am | 2 - clients/desktop-shell.c | 1 - clients/dnd.c | 32 +++++++-------- clients/flower.c | 1 - clients/gears.c | 1 - clients/image.c | 1 - clients/resizor.c | 1 - clients/screenshot.c | 1 - clients/smoke.c | 1 - clients/terminal.c | 37 ++++++++--------- clients/wayland-glib.c | 105 ------------------------------------------------ clients/wayland-glib.h | 32 --------------- clients/window.c | 100 ++++++++++++++++++++++++++++++++++++--------- clients/window.h | 12 ++++++ 14 files changed, 125 insertions(+), 202 deletions(-) delete mode 100644 clients/wayland-glib.c delete mode 100644 clients/wayland-glib.h diff --git a/clients/Makefile.am b/clients/Makefile.am index ee56169..8c30882 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -34,8 +34,6 @@ AM_CPPFLAGS = \ libtoytoolkit_a_SOURCES = \ window.c \ window.h \ - wayland-glib.c \ - wayland-glib.h \ cairo-util.c \ cairo-util.h diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index 3f773e9..d7833e5 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -32,7 +32,6 @@ #include #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" #include diff --git a/clients/dnd.c b/clients/dnd.c index a521edc..707ef5d 100644 --- a/clients/dnd.c +++ b/clients/dnd.c @@ -29,11 +29,10 @@ #include #include #include -#include +#include #include #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" @@ -60,9 +59,11 @@ struct dnd_offer { int refcount; struct dnd *dnd; struct wl_array types; + struct task io_task; const char *drag_type; uint32_t tag; int x, y; + int fd; }; struct item { @@ -421,24 +422,21 @@ drag_offer_motion(void *data, } } -static gboolean -drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data) +static void +drop_io_func(struct task *task, uint32_t events) { - struct dnd_offer *dnd_offer = data; + struct dnd_offer *dnd_offer = + container_of(task, struct dnd_offer, io_task); struct dnd *dnd = dnd_offer->dnd; struct dnd_flower_message dnd_flower_message; - int fd; unsigned int len; struct item *item; - fd = g_io_channel_unix_get_fd(source); - len = read(fd, &dnd_flower_message, sizeof dnd_flower_message); + len = read(dnd_offer->fd, + &dnd_flower_message, sizeof dnd_flower_message); fprintf(stderr, "read %d bytes\n", len); - close(fd); - g_source_remove(dnd_offer->tag); - - g_io_channel_unref(source); + close(dnd_offer->fd); item = item_create(dnd->display, dnd_offer->x - dnd_flower_message.x_offset - 26, @@ -449,15 +447,12 @@ drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data) window_schedule_redraw(dnd->window); dnd_offer_destroy(dnd_offer); - - return TRUE; } static void drag_offer_drop(void *data, struct wl_drag_offer *offer) { struct dnd_offer *dnd_offer = data; - GIOChannel *channel; int p[2]; if (!dnd_offer->drag_type) { @@ -473,9 +468,10 @@ drag_offer_drop(void *data, struct wl_drag_offer *offer) wl_drag_offer_receive(offer, p[1]); close(p[1]); - channel = g_io_channel_unix_new(p[0]); - dnd_offer->tag = g_io_add_watch(channel, G_IO_IN, - drop_io_func, dnd_offer); + dnd_offer->io_task.run = drop_io_func; + dnd_offer->fd = p[0]; + display_watch_fd(dnd_offer->dnd->display, + p[0], EPOLLIN, &dnd_offer->io_task); } static const struct wl_drag_offer_listener drag_offer_listener = { diff --git a/clients/flower.c b/clients/flower.c index a87e20f..5ad58f1 100644 --- a/clients/flower.c +++ b/clients/flower.c @@ -34,7 +34,6 @@ #include #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" static void diff --git a/clients/gears.c b/clients/gears.c index e45368a..53b2036 100644 --- a/clients/gears.c +++ b/clients/gears.c @@ -38,7 +38,6 @@ #include "wayland-util.h" #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" diff --git a/clients/image.c b/clients/image.c index 3eada1e..51ce1f0 100644 --- a/clients/image.c +++ b/clients/image.c @@ -34,7 +34,6 @@ #include #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" diff --git a/clients/resizor.c b/clients/resizor.c index 3b52e68..e48095f 100644 --- a/clients/resizor.c +++ b/clients/resizor.c @@ -29,7 +29,6 @@ #include "wayland-util.h" #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" diff --git a/clients/screenshot.c b/clients/screenshot.c index 1cccedf..124e576 100644 --- a/clients/screenshot.c +++ b/clients/screenshot.c @@ -31,7 +31,6 @@ #include #include "wayland-client.h" -#include "wayland-glib.h" #include "screenshooter-client-protocol.h" /* The screenshooter is a good example of a custom object exposed by diff --git a/clients/smoke.c b/clients/smoke.c index e084b27..061bd6d 100644 --- a/clients/smoke.c +++ b/clients/smoke.c @@ -33,7 +33,6 @@ #include #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" struct smoke { diff --git a/clients/terminal.c b/clients/terminal.c index cee832b..092e069 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -32,12 +32,12 @@ #include #include #include +#include #include #include "wayland-util.h" #include "wayland-client.h" -#include "wayland-glib.h" #include "window.h" @@ -359,6 +359,7 @@ struct terminal { struct window *window; struct display *display; union utf8_char *data; + struct task io_task; char *tab_ruler; struct attr *data_attr; struct attr curr_attr; @@ -375,7 +376,6 @@ struct terminal { int width, height, start, row, column; int saved_row, saved_column; int fd, master; - GIOChannel *channel; uint32_t modifiers; char escape[MAX_ESCAPE+1]; int escape_length; @@ -2326,25 +2326,22 @@ terminal_create(struct display *display, int fullscreen) return terminal; } -static gboolean -io_handler(GIOChannel *source, - GIOCondition condition, - gpointer data) +static void +io_handler(struct task *task, uint32_t events) { - struct terminal *terminal = data; - gchar buffer[256]; - gsize bytes_read; - GError *error = NULL; - - if(condition == G_IO_HUP) - exit(0); + struct terminal *terminal = + container_of(task, struct terminal, io_task); + char buffer[256]; + int len; - g_io_channel_read_chars(source, buffer, sizeof buffer, - &bytes_read, &error); + if (events & EPOLLHUP) + exit(0); - terminal_data(terminal, buffer, bytes_read); + len = read(terminal->master, buffer, sizeof buffer); + if (len < 0) + exit(0); - return TRUE; + terminal_data(terminal, buffer, len); } static int @@ -2367,10 +2364,10 @@ terminal_run(struct terminal *terminal, const char *path) } terminal->master = master; - terminal->channel = g_io_channel_unix_new(master); fcntl(master, F_SETFL, O_NONBLOCK); - g_io_add_watch(terminal->channel, G_IO_IN, io_handler, terminal); - g_io_add_watch(terminal->channel, G_IO_HUP, io_handler, terminal); + terminal->io_task.run = io_handler; + display_watch_fd(terminal->display, terminal->master, + EPOLLIN | EPOLLHUP, &terminal->io_task); window_set_fullscreen(terminal->window, terminal->fullscreen); if (!terminal->fullscreen) diff --git a/clients/wayland-glib.c b/clients/wayland-glib.c deleted file mode 100644 index fa7a9f5..0000000 --- a/clients/wayland-glib.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include -#include -#include "wayland-client.h" -#include "wayland-glib.h" - -typedef struct _WlSource { - GSource source; - GPollFD pfd; - uint32_t mask; - struct wl_display *display; -} WlSource; - -static gboolean -wl_glib_source_prepare(GSource *base, gint *timeout) -{ - WlSource *source = (WlSource *) base; - - *timeout = -1; - - /* We have to add/remove the GPollFD if we want to update our - * poll event mask dynamically. Instead, let's just flush all - * write on idle instead, which is what this amounts to. */ - - while (source->mask & WL_DISPLAY_WRITABLE) - wl_display_iterate(source->display, - WL_DISPLAY_WRITABLE); - - return FALSE; -} - -static gboolean -wl_glib_source_check(GSource *base) -{ - WlSource *source = (WlSource *) base; - - return source->pfd.revents; -} - -static gboolean -wl_glib_source_dispatch(GSource *base, - GSourceFunc callback, - gpointer data) -{ - WlSource *source = (WlSource *) base; - - wl_display_iterate(source->display, - WL_DISPLAY_READABLE); - - return TRUE; -} - -static GSourceFuncs wl_glib_source_funcs = { - wl_glib_source_prepare, - wl_glib_source_check, - wl_glib_source_dispatch, - NULL -}; - -static int -wl_glib_source_update(uint32_t mask, void *data) -{ - WlSource *source = data; - - source->mask = mask; - - return 0; -} - -GSource * -wl_glib_source_new(struct wl_display *display) -{ - WlSource *source; - - source = (WlSource *) g_source_new(&wl_glib_source_funcs, - sizeof (WlSource)); - source->display = display; - source->pfd.fd = wl_display_get_fd(display, - wl_glib_source_update, source); - source->pfd.events = G_IO_IN | G_IO_ERR; - g_source_add_poll(&source->source, &source->pfd); - - return &source->source; -} diff --git a/clients/wayland-glib.h b/clients/wayland-glib.h deleted file mode 100644 index 13ff2ca..0000000 --- a/clients/wayland-glib.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _WAYLAND_GLIB_H_ -#define _WAYLAND_GLIB_H_ - -#include -#include - -GSource *wl_glib_source_new(struct wl_display *display); - - -#endif diff --git a/clients/window.c b/clients/window.c index 48b444a..e7a61ef 100644 --- a/clients/window.c +++ b/clients/window.c @@ -32,9 +32,9 @@ #include #include #include -#include #include #include +#include #include @@ -51,7 +51,6 @@ #include #include "wayland-util.h" #include "wayland-client.h" -#include "wayland-glib.h" #include "cairo-util.h" #include "window.h" @@ -68,9 +67,14 @@ struct display { EGLConfig premultiplied_argb_config; EGLContext ctx; cairo_device_t *device; - int fd; - GMainLoop *loop; - GSource *source; + + int display_fd; + uint32_t mask; + struct task display_task; + + int epoll_fd; + struct wl_list deferred_list; + struct wl_list window_list; struct wl_list input_list; char *device_name; @@ -99,6 +103,7 @@ struct window { int x, y; int resize_edges; int redraw_scheduled; + struct task redraw_task; int minimum_width, minimum_height; int margin; int type; @@ -1374,23 +1379,22 @@ window_set_child_size(struct window *window, int32_t width, int32_t height) } } -static gboolean -idle_redraw(void *data) +static void +idle_redraw(struct task *task, uint32_t events) { - struct window *window = data; + struct window *window = + container_of(task, struct window, redraw_task); window->redraw_handler(window, window->user_data); - window->redraw_scheduled = 0; - - return FALSE; } void window_schedule_redraw(struct window *window) { if (!window->redraw_scheduled) { - g_idle_add(idle_redraw, window); + window->redraw_task.run = idle_redraw; + display_defer(window->display, &window->redraw_task); window->redraw_scheduled = 1; } } @@ -1927,6 +1931,25 @@ init_egl(struct display *d) return 0; } +static int +event_mask_update(uint32_t mask, void *data) +{ + struct display *d = data; + + d->mask = mask; + + return 0; +} + +static void +handle_display_data(struct task *task, uint32_t events) +{ + struct display *display = + container_of(task, struct display, display_task); + + wl_display_iterate(display->display, display->mask); +} + struct display * display_create(int *argc, char **argv[], const GOptionEntry *option_entries) { @@ -1967,6 +1990,12 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) return NULL; } + d->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + d->display_fd = wl_display_get_fd(d->display, event_mask_update, d); + d->display_task.run = handle_display_data; + display_watch_fd(d, d->display_fd, EPOLLIN, &d->display_task); + + wl_list_init(&d->deferred_list); wl_list_init(&d->input_list); /* Set up listener so we'll catch all events. */ @@ -1987,10 +2016,6 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) display_render_frame(d); - d->loop = g_main_loop_new(NULL, FALSE); - d->source = wl_glib_source_new(d->display); - g_source_attach(d->source, NULL); - wl_list_init(&d->window_list); init_xkb(d); @@ -2060,7 +2085,46 @@ display_release(struct display *display) } void -display_run(struct display *d) +display_defer(struct display *display, struct task *task) +{ + wl_list_insert(&display->deferred_list, &task->link); +} + +void +display_watch_fd(struct display *display, + int fd, uint32_t events, struct task *task) { - g_main_loop_run(d->loop); + struct epoll_event ep; + + ep.events = events; + ep.data.ptr = task; + epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep); +} + +void +display_run(struct display *display) +{ + struct task *task; + struct epoll_event ep[16]; + int i, count; + + while (1) { + while (display->mask & WL_DISPLAY_WRITABLE) + wl_display_iterate(display->display, + WL_DISPLAY_WRITABLE); + + count = epoll_wait(display->epoll_fd, + ep, ARRAY_LENGTH(ep), -1); + for (i = 0; i < count; i++) { + task = ep[i].data.ptr; + task->run(task, ep[i].events); + } + + while (!wl_list_empty(&display->deferred_list)) { + task = container_of(display->deferred_list.next, + struct task, link); + wl_list_remove(&task->link); + task->run(task, 0); + } + } } diff --git a/clients/window.h b/clients/window.h index dc80123..df819bf 100644 --- a/clients/window.h +++ b/clients/window.h @@ -30,6 +30,11 @@ struct window; +struct task { + void (*run)(struct task *task, uint32_t events); + struct wl_list link; +}; + struct rectangle { int32_t x; int32_t y; @@ -99,6 +104,13 @@ void display_flush_cairo_device(struct display *display); void +display_defer(struct display *display, struct task *task); + +void +display_watch_fd(struct display *display, + int fd, uint32_t events, struct task *task); + +void display_run(struct display *d); enum pointer_type { -- 2.7.4