diff --git a/Makefile b/Makefile index 383188d..eee5c5f 100644 --- 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) diff --git a/background.c b/background.c index 19748eb..429216d 100644 --- a/background.c +++ b/background.c @@ -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); } diff --git a/flower.c b/flower.c index e6c1c1f..f74be9d 100644 --- a/flower.c +++ b/flower.c @@ -12,8 +12,10 @@ #include #include #include +#include #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; - } + g_timeout_add(20, move_flower, &flower); - 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_main_loop_run(loop); return 0; } diff --git a/pointer.c b/pointer.c index cd2cb0b..1233f8c 100644 --- 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); } diff --git a/wayland-client.c b/wayland-client.c index 8503a30..005954b 100644 --- a/wayland-client.c +++ b/wayland-client.c @@ -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; } diff --git a/wayland-client.h b/wayland-client.h index 82b9b7c..d96e59c 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -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 index 0000000..10bcfea --- /dev/null +++ b/wayland-glib.c @@ -0,0 +1,83 @@ +#include +#include +#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 index 0000000..751467e --- /dev/null +++ b/wayland-glib.h @@ -0,0 +1,10 @@ +#ifndef _WAYLAND_GLIB_H_ +#define _WAYLAND_GLIB_H_ + +#include + +typedef struct _WaylandSource WaylandSource; + +GSource *wayland_source_new(struct wl_display *display); + +#endif diff --git a/window.c b/window.c index 94cd2bf..b936c58 100644 --- 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) {