Add glib main loop integration, use it in flower client.
authorKristian Høgsberg <krh@redhat.com>
Fri, 7 Nov 2008 19:27:23 +0000 (14:27 -0500)
committerKristian Høgsberg <krh@redhat.com>
Fri, 7 Nov 2008 19:27:23 +0000 (14:27 -0500)
Makefile
background.c
flower.c
pointer.c
wayland-client.c
wayland-client.h
wayland-glib.c [new file with mode: 0644]
wayland-glib.h [new file with mode: 0644]
window.c

index 383188d..eee5c5f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -42,7 +42,7 @@ glx-compositor.so : $(glx_compositor_objs)
 libwayland.so $(compositors) :
        gcc -o $@ $^ $(LDLIBS) -shared 
 
-flower_objs = flower.o
+flower_objs = flower.o wayland-glib.o
 pointer_objs = pointer.o
 background_objs = background.o
 window_objs = window.o gears.o
@@ -53,6 +53,9 @@ $(clients) : LDLIBS += $(shell pkg-config --libs cairo) -lrt
 background : CFLAGS += $(shell pkg-config --cflags gdk-pixbuf-2.0)
 background : LDLIBS += $(shell pkg-config --libs gdk-pixbuf-2.0)
 
+flower : CFLAGS += $(shell pkg-config --cflags glib-2.0)
+flower : LDLIBS += $(shell pkg-config --libs glib-2.0)
+
 window : CFLAGS += $(EAGLE_CFLAGS)
 window : LDLIBS += $(EAGLE_LDLIBS)
 
index 19748eb..429216d 100644 (file)
@@ -94,15 +94,14 @@ static uint32_t name_pixbuf(int fd, GdkPixbuf *pixbuf)
 }
 
 static int
-connection_update(struct wl_connection *connection,
-                 uint32_t mask, void *data)
+connection_update(uint32_t mask, void *data)
 {
        struct pollfd *p = data;
 
        p->events = 0;
-       if (mask & WL_CONNECTION_READABLE)
+       if (mask & WL_DISPLAY_READABLE)
                p->events |= POLLIN;
-       if (mask & WL_CONNECTION_WRITABLE)
+       if (mask & WL_DISPLAY_WRITABLE)
                p->events |= POLLOUT;
 
        return 0;
@@ -124,13 +123,13 @@ int main(int argc, char *argv[])
                return -1;
        }
 
-       display = wl_display_create(socket_name,
-                                   connection_update, &p[0]);
+       display = wl_display_create(socket_name);
        if (display == NULL) {
                fprintf(stderr, "failed to create display: %m\n");
                return -1;
        }
-       p[0].fd = wl_display_get_fd(display);
+       p[0].fd = wl_display_get_fd(display,
+                                   connection_update, &p[0]);
 
        surface = wl_display_create_surface(display);
 
@@ -153,9 +152,9 @@ int main(int argc, char *argv[])
                poll(p, 1, -1);
                mask = 0;
                if (p[0].revents & POLLIN)
-                       mask |= WL_CONNECTION_READABLE;
+                       mask |= WL_DISPLAY_READABLE;
                if (p[0].revents & POLLOUT)
-                       mask |= WL_CONNECTION_WRITABLE;
+                       mask |= WL_DISPLAY_WRITABLE;
                wl_display_iterate(display, mask);
        }
 
index e6c1c1f..f74be9d 100644 (file)
--- a/flower.c
+++ b/flower.c
 #include <math.h>
 #include <time.h>
 #include <cairo.h>
+#include <glib.h>
 
 #include "wayland-client.h"
+#include "wayland-glib.h"
 
 static const char gem_device[] = "/dev/dri/card0";
 static const char socket_name[] = "\0wayland";
@@ -131,33 +133,36 @@ draw_stuff(int width, int height)
        return surface;
 }
 
-static int
-connection_update(struct wl_connection *connection,
-                 uint32_t mask, void *data)
+struct flower {
+       struct wl_surface *surface;
+       int i;
+       int x, y, width, height;
+};
+
+static gboolean
+move_flower(gpointer data)
 {
-       struct pollfd *p = data;
+       struct flower *flower = data;
 
-       p->events = 0;
-       if (mask & WL_CONNECTION_READABLE)
-               p->events |= POLLIN;
-       if (mask & WL_CONNECTION_WRITABLE)
-               p->events |= POLLOUT;
+       wl_surface_map(flower->surface, 
+                      flower->x + cos(flower->i / 31.0) * 400 - flower->width / 2,
+                      flower->y + sin(flower->i / 27.0) * 300 - flower->height / 2,
+                      flower->width, flower->height);
+       flower->i++;
 
-       return 0;
+       return TRUE;
 }
 
 int main(int argc, char *argv[])
 {
        struct wl_display *display;
-       struct wl_surface *surface;
-       const int x = 512, y = 384, width = 200, height = 200;
-       int fd, i, ret;
-       uint32_t name, mask;
+       int fd;
+       uint32_t name;
        cairo_surface_t *s;
-       struct pollfd p[2];
        struct timespec ts;
-       struct itimerspec its;
-       uint64_t expires;
+       GMainLoop *loop;
+       GSource *source;
+       struct flower flower;
 
        fd = open(gem_device, O_RDWR);
        if (fd < 0) {
@@ -165,60 +170,36 @@ int main(int argc, char *argv[])
                return -1;
        }
 
-       display = wl_display_create(socket_name,
-                                   connection_update, &p[0]);
+       loop = g_main_loop_new(NULL, FALSE);
+
+       display = wl_display_create(socket_name);
        if (display == NULL) {
                fprintf(stderr, "failed to create display: %m\n");
                return -1;
        }
-       p[0].fd = wl_display_get_fd(display);
 
-       surface = wl_display_create_surface(display);
+       source = wayland_source_new(display);
+       g_source_attach(source, NULL);
 
-       p[1].fd = timerfd_create(CLOCK_MONOTONIC, 0);
-       if (p[1].fd < 0) {
-               fprintf(stderr, "could not create timerfd\n: %m");
-               return -1;
-       }
+       flower.x = 512;
+       flower.y = 384;
+       flower.width = 200;
+       flower.height = 200;
+       flower.surface = wl_display_create_surface(display);
 
-       p[1].events = POLLIN;
        clock_gettime(CLOCK_MONOTONIC, &ts);
-       its.it_value = ts;
-       its.it_interval.tv_sec = 0;
-       its.it_interval.tv_nsec = 20 * 1000000;
-       if (timerfd_settime(p[1].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
-               fprintf(stderr, "could not set timerfd\n: %m");
-               return -1;
-       }
-
        srandom(ts.tv_nsec);
+       flower.i = ts.tv_nsec;
 
-       s = draw_stuff(width, height);
+       s = draw_stuff(flower.width, flower.height);
        name = name_cairo_surface(fd, s);
 
-       wl_surface_attach(surface, name, width, height,
+       wl_surface_attach(flower.surface, name, flower.width, flower.height,
                          cairo_image_surface_get_stride(s));
 
-       i = ts.tv_nsec;
-       while (ret = poll(p, 2, -1), ret >= 0) {
-               if (p[1].revents & POLLIN) {
-                       read(p[1].fd, &expires, sizeof expires);
-                       wl_surface_map(surface, 
-                                      x + cos(i / 31.0) * 400 - width / 2,
-                                      y + sin(i / 27.0) * 300 - height / 2,
-                                      width, height);
-                       i++;
-                       continue;
-               }
-
-               mask = 0;
-               if (p[0].revents & POLLIN)
-                       mask |= WL_CONNECTION_READABLE;
-               if (p[0].revents & POLLOUT)
-                       mask |= WL_CONNECTION_WRITABLE;
-               if (mask)
-                       wl_display_iterate(display, mask);
-       }
+       g_timeout_add(20, move_flower, &flower);
+
+       g_main_loop_run(loop);
 
        return 0;
 }
index cd2cb0b..1233f8c 100644 (file)
--- a/pointer.c
+++ b/pointer.c
@@ -98,15 +98,14 @@ draw_pointer(int width, int height)
 }
 
 static int
-connection_update(struct wl_connection *connection,
-                 uint32_t mask, void *data)
+connection_update(uint32_t mask, void *data)
 {
        struct pollfd *p = data;
 
        p->events = 0;
-       if (mask & WL_CONNECTION_READABLE)
+       if (mask & WL_DISPLAY_READABLE)
                p->events |= POLLIN;
-       if (mask & WL_CONNECTION_WRITABLE)
+       if (mask & WL_DISPLAY_WRITABLE)
                p->events |= POLLOUT;
 
        return 0;
@@ -142,13 +141,12 @@ int main(int argc, char *argv[])
                return -1;
        }
 
-       display = wl_display_create(socket_name,
-                                   connection_update, &p[0]);
+       display = wl_display_create(socket_name);
        if (display == NULL) {
                fprintf(stderr, "failed to create display: %m\n");
                return -1;
        }
-       p[0].fd = wl_display_get_fd(display);
+       p[0].fd = wl_display_get_fd(display, connection_update, &p[0]);
 
        pointer.width = 16;
        pointer.height = 16;
@@ -168,9 +166,9 @@ int main(int argc, char *argv[])
                poll(p, 1, -1);
                mask = 0;
                if (p[0].revents & POLLIN)
-                       mask |= WL_CONNECTION_READABLE;
+                       mask |= WL_DISPLAY_READABLE;
                if (p[0].revents & POLLOUT)
-                       mask |= WL_CONNECTION_WRITABLE;
+                       mask |= WL_DISPLAY_WRITABLE;
                wl_display_iterate(display, mask);
        }
 
index 8503a30..005954b 100644 (file)
@@ -25,6 +25,10 @@ struct wl_display {
        struct wl_connection *connection;
        int fd;
        uint32_t id;
+       uint32_t mask;
+
+       wl_display_update_func_t update;
+       void *update_data;
 
        wl_display_event_func_t event_handler;
        void *event_handler_data;
@@ -34,9 +38,22 @@ struct wl_surface {
        struct wl_proxy proxy;
 };
 
+static int
+connection_update(struct wl_connection *connection,
+                 uint32_t mask, void *data)
+{
+       struct wl_display *display = data;
+
+       display->mask = mask;
+       if (display->update)
+               return display->update(display->mask,
+                                      display->update_data);
+
+       return 0;
+}
+
 struct wl_display *
-wl_display_create(const char *address,
-                 wl_connection_update_func_t update, void *data)
+wl_display_create(const char *address)
 {
        struct wl_display *display;
        struct sockaddr_un name;
@@ -79,7 +96,8 @@ wl_display_create(const char *address,
        display->proxy.id = id;
 
        display->connection = wl_connection_create(display->fd,
-                                                  update, data);
+                                                  connection_update,
+                                                  display);
 
        return display;
 }
@@ -93,8 +111,14 @@ wl_display_destroy(struct wl_display *display)
 }
 
 int
-wl_display_get_fd(struct wl_display *display)
+wl_display_get_fd(struct wl_display *display,
+                 wl_display_update_func_t update, void *data)
 {
+       display->update = update;
+       display->update_data = data;
+
+       display->update(display->mask, display->update_data);
+
        return display->fd;
 }
 
index 82b9b7c..d96e59c 100644 (file)
@@ -1,15 +1,19 @@
 #ifndef _WAYLAND_CLIENT_H
 #define _WAYLAND_CLIENT_H
 
-#include "connection.h"
-
 struct wl_display;
 struct wl_surface;
 
-struct wl_display *wl_display_create(const char *address,
-                                    wl_connection_update_func_t update, void *data);
+#define WL_DISPLAY_READABLE 0x01
+#define WL_DISPLAY_WRITABLE 0x02
+
+typedef int (*wl_display_update_func_t)(uint32_t mask, void *data);
+
+struct wl_display *wl_display_create(const char *address);
 void wl_display_destroy(struct wl_display *display);
-int wl_display_get_fd(struct wl_display *display);
+int wl_display_get_fd(struct wl_display *display,
+                     wl_display_update_func_t update, void *data);
+
 void wl_display_iterate(struct wl_display *display, uint32_t mask);
 
 typedef void (*wl_display_event_func_t)(struct wl_display *display,
diff --git a/wayland-glib.c b/wayland-glib.c
new file mode 100644 (file)
index 0000000..10bcfea
--- /dev/null
@@ -0,0 +1,83 @@
+#include <stdint.h>
+#include <glib/giochannel.h>
+#include "wayland-client.h"
+#include "wayland-glib.h"
+
+struct _WaylandSource {
+       GSource source;
+       GPollFD pfd;
+       uint32_t mask;
+       struct wl_display *display;
+};
+
+static gboolean
+wayland_source_prepare(GSource *base, gint *timeout)
+{
+       WaylandSource *source = (WaylandSource *) 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
+wayland_source_check(GSource *base)
+{
+       WaylandSource *source = (WaylandSource *) base;
+
+       return source->pfd.revents;
+}
+
+static gboolean
+wayland_source_dispatch(GSource *base,
+                       GSourceFunc callback,
+                       gpointer data)
+{
+       WaylandSource *source = (WaylandSource *) base;
+
+       wl_display_iterate(source->display,
+                          WL_DISPLAY_READABLE | WL_DISPLAY_WRITABLE);
+
+       return TRUE;
+}
+
+static GSourceFuncs wayland_source_funcs = {
+       wayland_source_prepare,
+       wayland_source_check,
+       wayland_source_dispatch,
+       NULL
+};
+
+static int
+wayland_source_update(uint32_t mask, void *data)
+{
+       WaylandSource *source = data;
+
+       source->mask = mask;
+
+       return 0;
+}
+
+GSource *
+wayland_source_new(struct wl_display *display)
+{
+       WaylandSource *source;
+
+       source = (WaylandSource *) g_source_new(&wayland_source_funcs,
+                                               sizeof (WaylandSource));
+       source->display = display;
+       source->pfd.fd = wl_display_get_fd(display,
+                                          wayland_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/wayland-glib.h b/wayland-glib.h
new file mode 100644 (file)
index 0000000..751467e
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _WAYLAND_GLIB_H_
+#define _WAYLAND_GLIB_H_
+
+#include <glib/gmain.h>
+
+typedef struct _WaylandSource WaylandSource;
+
+GSource *wayland_source_new(struct wl_display *display);
+
+#endif
index 94cd2bf..b936c58 100644 (file)
--- a/window.c
+++ b/window.c
@@ -168,15 +168,14 @@ draw_window(struct window *window)
 }
 
 static int
-connection_update(struct wl_connection *connection,
-                 uint32_t mask, void *data)
+connection_update(uint32_t mask, void *data)
 {
        struct pollfd *p = data;
 
        p->events = 0;
-       if (mask & WL_CONNECTION_READABLE)
+       if (mask & WL_DISPLAY_READABLE)
                p->events |= POLLIN;
-       if (mask & WL_CONNECTION_WRITABLE)
+       if (mask & WL_DISPLAY_WRITABLE)
                p->events |= POLLOUT;
 
        return 0;
@@ -302,13 +301,13 @@ int main(int argc, char *argv[])
                return -1;
        }
 
-       display = wl_display_create(socket_name,
-                                   connection_update, &p[0]);
+       display = wl_display_create(socket_name);
        if (display == NULL) {
                fprintf(stderr, "failed to create display: %m\n");
                return -1;
        }
-       p[0].fd = wl_display_get_fd(display);
+       p[0].fd = wl_display_get_fd(display,
+                                   connection_update, &p[0]);
 
        window.surface = wl_display_create_surface(display);
        window.x = 200;
@@ -333,9 +332,9 @@ int main(int argc, char *argv[])
                                  window.width, window.height);
                angle += 1;
                if (p[0].revents & POLLIN)
-                       mask |= WL_CONNECTION_READABLE;
+                       mask |= WL_DISPLAY_READABLE;
                if (p[0].revents & POLLOUT)
-                       mask |= WL_CONNECTION_WRITABLE;
+                       mask |= WL_DISPLAY_WRITABLE;
                if (mask)
                        wl_display_iterate(display, mask);
                if (window.need_redraw) {