window: Stop using glib mainloop in toy toolkit
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 14 Sep 2011 21:33:48 +0000 (17:33 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Mon, 19 Sep 2011 21:28:55 +0000 (17:28 -0400)
14 files changed:
clients/Makefile.am
clients/desktop-shell.c
clients/dnd.c
clients/flower.c
clients/gears.c
clients/image.c
clients/resizor.c
clients/screenshot.c
clients/smoke.c
clients/terminal.c
clients/wayland-glib.c [deleted file]
clients/wayland-glib.h [deleted file]
clients/window.c
clients/window.h

index ee56169..8c30882 100644 (file)
@@ -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
 
index 3f773e9..d7833e5 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/input.h>
 
 #include "wayland-client.h"
-#include "wayland-glib.h"
 #include "window.h"
 
 #include <desktop-shell-client-protocol.h>
index a521edc..707ef5d 100644 (file)
 #include <math.h>
 #include <sys/time.h>
 #include <cairo.h>
-#include <glib.h>
+#include <sys/epoll.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 #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 = {
index a87e20f..5ad58f1 100644 (file)
@@ -34,7 +34,6 @@
 #include <glib.h>
 
 #include "wayland-client.h"
-#include "wayland-glib.h"
 #include "window.h"
 
 static void
index e45368a..53b2036 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "wayland-util.h"
 #include "wayland-client.h"
-#include "wayland-glib.h"
 
 #include "window.h"
 
index 3eada1e..51ce1f0 100644 (file)
@@ -34,7 +34,6 @@
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 #include "wayland-client.h"
-#include "wayland-glib.h"
 
 #include "window.h"
 
index 3b52e68..e48095f 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "wayland-util.h"
 #include "wayland-client.h"
-#include "wayland-glib.h"
 
 #include "window.h"
 
index 1cccedf..124e576 100644 (file)
@@ -31,7 +31,6 @@
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 #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
index e084b27..061bd6d 100644 (file)
@@ -33,7 +33,6 @@
 #include <glib.h>
 
 #include "wayland-client.h"
-#include "wayland-glib.h"
 #include "window.h"
 
 struct smoke {
index cee832b..092e069 100644 (file)
 #include <ctype.h>
 #include <cairo.h>
 #include <glib.h>
+#include <sys/epoll.h>
 
 #include <X11/keysym.h>
 
 #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 (file)
index fa7a9f5..0000000
+++ /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 <stdint.h>
-#include <glib/giochannel.h>
-#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 (file)
index 13ff2ca..0000000
+++ /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 <glib/gmain.h>
-#include <wayland-client.h>
-
-GSource *wl_glib_source_new(struct wl_display *display);
-
-
-#endif
index 48b444a..e7a61ef 100644 (file)
@@ -32,9 +32,9 @@
 #include <time.h>
 #include <cairo.h>
 #include <glib.h>
-#include <glib-object.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <sys/mman.h>
+#include <sys/epoll.h>
 
 #include <wayland-egl.h>
 
@@ -51,7 +51,6 @@
 #include <linux/input.h>
 #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);
+               }
+       }
 }
index dc80123..df819bf 100644 (file)
 
 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 {