diff --git a/clients/Makefile b/clients/Makefile index 35419eb3..81e87924 100644 --- a/clients/Makefile +++ b/clients/Makefile @@ -1,5 +1,8 @@ include ../config.mk +CFLAGS += -I.. $(CLIENT_CFLAGS) +LDLIBS += -L.. -lwayland $(CLIENT_LIBS) -lrt -lm + egl_clients = gears cairo_clients = flower screenshot terminal image view @@ -16,12 +19,5 @@ image : image.o window.o wayland-glib.o view : view.o window.o wayland-glib.o terminal : LDLIBS += -lutil -image : CFLAGS += $(GDK_PIXBUF_CFLAGS) -image : LDLIBS += $(GDK_PIXBUF_LIBS) view : CFLAGS += $(POPPLER_CFLAGS) view : LDLIBS += $(POPPLER_LIBS) - -$(egl_clients) : CFLAGS += $(EGL_CLIENT_CFLAGS) -$(egl_clients) : LDLIBS += -L.. -lwayland $(EGL_CLIENT_LIBS) -lrt -lm -$(cairo_clients) : CFLAGS += $(CAIRO_CLIENT_CFLAGS) $(EGL_CLIENT_CFLAGS) -$(cairo_clients) : LDLIBS += -L.. -lwayland $(CAIRO_CLIENT_LIBS) $(EGL_CLIENT_LIBS) -lrt -lm diff --git a/clients/flower.c b/clients/flower.c index 8b5e1bbc..5b188461 100644 --- a/clients/flower.c +++ b/clients/flower.c @@ -112,9 +112,6 @@ handle_frame(struct window *window, int main(int argc, char *argv[]) { - struct wl_display *display; - struct wl_visual *visual; - int fd; cairo_surface_t *s; struct timespec ts; struct flower flower; diff --git a/clients/gears.c b/clients/gears.c index 789537bd..1697170c 100644 --- a/clients/gears.c +++ b/clients/gears.c @@ -51,7 +51,6 @@ struct gears { struct window *window; struct display *d; - struct wl_compositor *compositor; struct rectangle rectangle; EGLDisplay display; @@ -319,9 +318,9 @@ keyboard_focus_handler(struct window *window, } static void -handle_acknowledge(void *data, - struct wl_compositor *compositor, - uint32_t key, uint32_t frame) +acknowledge_handler(struct window *window, + uint32_t key, uint32_t frame, + void *data) { struct gears *gears = data; @@ -334,9 +333,8 @@ handle_acknowledge(void *data, } static void -handle_frame(void *data, - struct wl_compositor *compositor, - uint32_t frame, uint32_t timestamp) +frame_handler(struct window *window, + uint32_t frame, uint32_t timestamp, void *data) { struct gears *gears = data; @@ -347,11 +345,6 @@ handle_frame(void *data, gears->angle = (GLfloat) (timestamp % 8192) * 360 / 8192.0; } -static const struct wl_compositor_listener compositor_listener = { - handle_acknowledge, - handle_frame, -}; - static struct gears * gears_create(struct display *display) { @@ -434,17 +427,14 @@ gears_create(struct display *display) if (glCheckFramebufferStatus (GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE) fprintf(stderr, "framebuffer incomplete\n"); - gears->compositor = display_get_compositor(display); - resize_window(gears); draw_gears(gears); - handle_frame(gears, gears->compositor, 0, 0); + frame_handler(gears->window, 0, 0, gears); window_set_resize_handler(gears->window, resize_handler, gears); window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler, gears); - - wl_compositor_add_listener(gears->compositor, - &compositor_listener, gears); + window_set_acknowledge_handler(gears->window, acknowledge_handler, gears); + window_set_frame_handler(gears->window, frame_handler, gears); return gears; } diff --git a/clients/image.c b/clients/image.c index 1403f559..4e4074e0 100644 --- a/clients/image.c +++ b/clients/image.c @@ -45,7 +45,6 @@ static const char socket_name[] = "\0wayland"; struct image { struct window *window; struct display *display; - struct wl_compositor *compositor; uint32_t key; gboolean redraw_scheduled; @@ -226,9 +225,8 @@ keyboard_focus_handler(struct window *window, } static void -handle_acknowledge(void *data, - struct wl_compositor *compositor, - uint32_t key, uint32_t frame) +acknowledge_handler(struct window *window, + uint32_t key, uint32_t frame, void *data) { struct image *image = data; @@ -243,18 +241,6 @@ handle_acknowledge(void *data, } } -static void -handle_frame(void *data, - struct wl_compositor *compositor, - uint32_t frame, uint32_t timestamp) -{ -} - -static const struct wl_compositor_listener compositor_listener = { - handle_acknowledge, - handle_frame, -}; - static struct image * image_create(struct display *display, uint32_t key, const char *filename) { @@ -281,11 +267,9 @@ image_create(struct display *display, uint32_t key, const char *filename) image->key = key + 100; image->redraw_scheduled = 1; - image->compositor = display_get_compositor(display); window_set_resize_handler(image->window, resize_handler, image); window_set_keyboard_focus_handler(image->window, keyboard_focus_handler, image); - - wl_compositor_add_listener(image->compositor, &compositor_listener, image); + window_set_acknowledge_handler(image->window, acknowledge_handler, image); image_draw(image); diff --git a/clients/terminal.c b/clients/terminal.c index 48e137b4..a16fdcbb 100644 --- a/clients/terminal.c +++ b/clients/terminal.c @@ -50,7 +50,6 @@ static int option_fullscreen; struct terminal { struct window *window; struct display *display; - struct wl_compositor *compositor; int redraw_scheduled, redraw_pending; char *data; int width, height, start, row, column; @@ -418,9 +417,8 @@ resize_handler(struct window *window, void *data) } static void -handle_acknowledge(void *data, - struct wl_compositor *compositor, - uint32_t key, uint32_t frame) +acknowledge_handler(struct window *window, + uint32_t key, uint32_t frame, void *data) { struct terminal *terminal = data; @@ -431,18 +429,6 @@ handle_acknowledge(void *data, } } -static void -handle_frame(void *data, - struct wl_compositor *compositor, - uint32_t frame, uint32_t timestamp) -{ -} - -static const struct wl_compositor_listener compositor_listener = { - handle_acknowledge, - handle_frame, -}; - static void key_handler(struct window *window, uint32_t key, uint32_t unicode, uint32_t state, uint32_t modifiers, void *data) @@ -493,12 +479,9 @@ terminal_create(struct display *display, int fullscreen) terminal->redraw_scheduled = 1; terminal->margin = 5; - terminal->compositor = display_get_compositor(display); window_set_fullscreen(terminal->window, terminal->fullscreen); window_set_resize_handler(terminal->window, resize_handler, terminal); - - wl_compositor_add_listener(terminal->compositor, - &compositor_listener, terminal); + window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal); window_set_key_handler(terminal->window, key_handler, terminal); window_set_keyboard_focus_handler(terminal->window, diff --git a/clients/view.c b/clients/view.c index 8567b846..b9d348b1 100644 --- a/clients/view.c +++ b/clients/view.c @@ -49,7 +49,6 @@ static const char socket_name[] = "\0wayland"; struct view { struct window *window; struct display *display; - struct wl_compositor *compositor; uint32_t key; gboolean redraw_scheduled; @@ -109,7 +108,7 @@ view_draw(struct view *view) &rectangle, view->surface); - wl_compositor_commit(view->compositor, view->key); + window_commit(view->window, 0); } static gboolean @@ -175,9 +174,8 @@ resize_handler(struct window *window, void *data) } static void -handle_acknowledge(void *data, - struct wl_compositor *compositor, - uint32_t key, uint32_t frame) +acknowledge_handler(struct window *window, + uint32_t key, uint32_t frame, void *data) { struct view *view = data; @@ -202,18 +200,6 @@ keyboard_focus_handler(struct window *window, view_schedule_redraw(view); } -static void -handle_frame(void *data, - struct wl_compositor *compositor, - uint32_t frame, uint32_t timestamp) -{ -} - -static const struct wl_compositor_listener compositor_listener = { - handle_acknowledge, - handle_frame, -}; - static struct view * view_create(struct display *display, uint32_t key, const char *filename) { @@ -242,14 +228,11 @@ view_create(struct display *display, uint32_t key, const char *filename) view->key = key + 100; view->redraw_scheduled = 1; - view->compositor = display_get_compositor(display); window_set_resize_handler(view->window, resize_handler, view); window_set_key_handler(view->window, key_handler, view); window_set_keyboard_focus_handler(view->window, keyboard_focus_handler, view); - - wl_compositor_add_listener(view->compositor, - &compositor_listener, view); + window_set_acknowledge_handler(view->window, acknowledge_handler, view); view->document = poppler_document_new_from_file(view->filename, NULL, &error); diff --git a/clients/window.c b/clients/window.c index 6d423abd..a867a888 100644 --- a/clients/window.c +++ b/clients/window.c @@ -30,6 +30,7 @@ #include #include #include +#include #define EGL_EGLEXT_PROTOTYPES 1 #define GL_GLEXT_PROTOTYPES 1 @@ -58,6 +59,8 @@ struct display { int fd; GMainLoop *loop; GSource *source; + struct wl_list window_list; + char *device_name; }; struct window { @@ -83,9 +86,11 @@ struct window { window_resize_handler_t resize_handler; window_key_handler_t key_handler; window_keyboard_focus_handler_t keyboard_focus_handler; + window_acknowledge_handler_t acknowledge_handler; window_frame_handler_t frame_handler; void *user_data; + struct wl_list link; }; static void @@ -320,42 +325,6 @@ window_get_surface(struct window *window) return window->cairo_surface; } -static void -window_handle_acknowledge(void *data, - struct wl_compositor *compositor, - uint32_t key, uint32_t frame) -{ - struct window *window = data; - cairo_surface_t *pending; - - /* The acknowledge event means that the server - * processed our last commit request and we can now - * safely free the old window buffer if we resized and - * render the next frame into our back buffer.. */ - - pending = window->pending_surface; - window->pending_surface = NULL; - if (pending != window->cairo_surface) - window_attach_surface(window); - cairo_surface_destroy(pending); -} - -static void -window_handle_frame(void *data, - struct wl_compositor *compositor, - uint32_t frame, uint32_t timestamp) -{ - struct window *window = data; - - if (window->frame_handler) - (*window->frame_handler)(window, frame, timestamp, window->user_data); -} - -static const struct wl_compositor_listener compositor_listener = { - window_handle_acknowledge, - window_handle_frame, -}; - enum window_state { WINDOW_STABLE, WINDOW_MOVING, @@ -708,6 +677,14 @@ window_set_key_handler(struct window *window, window->user_data = data; } +void +window_set_acknowledge_handler(struct window *window, + window_acknowledge_handler_t handler, void *data) +{ + window->acknowledge_handler = handler; + window->user_data = data; +} + void window_set_frame_handler(struct window *window, window_frame_handler_t handler, void *data) @@ -760,8 +737,7 @@ window_create(struct display *display, const char *title, window->state = WINDOW_STABLE; window->decoration = 1; - wl_compositor_add_listener(display->compositor, - &compositor_listener, window); + wl_list_insert(display->window_list.prev, &window->link); wl_input_device_add_listener(display->input_device, &input_device_listener, window); @@ -769,6 +745,61 @@ window_create(struct display *display, const char *title, return window; } +static void +display_handle_device(void *data, + struct wl_compositor *compositor, + const char *device) +{ + struct display *d = data; + + d->device_name = strdup(device); +} + +static void +display_handle_acknowledge(void *data, + struct wl_compositor *compositor, + uint32_t key, uint32_t frame) +{ + struct display *d = data; + struct window *window; + cairo_surface_t *pending; + + /* The acknowledge event means that the server processed our + * last commit request and we can now safely free the old + * window buffer if we resized and render the next frame into + * our back buffer.. */ + wl_list_for_each(window, &d->window_list, link) { + pending = window->pending_surface; + window->pending_surface = NULL; + if (pending != window->cairo_surface) + window_attach_surface(window); + cairo_surface_destroy(pending); + if (window->acknowledge_handler) + (*window->acknowledge_handler)(window, key, frame, window->user_data); + } +} + +static void +display_handle_frame(void *data, + struct wl_compositor *compositor, + uint32_t frame, uint32_t timestamp) +{ + struct display *d = data; + struct window *window; + + wl_list_for_each(window, &d->window_list, link) { + if (window->frame_handler) + (*window->frame_handler)(window, frame, + timestamp, window->user_data); + } +} + +static const struct wl_compositor_listener compositor_listener = { + display_handle_device, + display_handle_acknowledge, + display_handle_frame, +}; + static void display_handle_geometry(void *data, struct wl_output *output, @@ -794,6 +825,7 @@ display_handle_global(struct wl_display *display, if (wl_object_implements(object, "compositor", 1)) { d->compositor = (struct wl_compositor *) object; + wl_compositor_add_listener(d->compositor, &compositor_listener, d); } else if (wl_object_implements(object, "output", 1)) { d->output = (struct wl_output *) object; wl_output_add_listener(d->output, &output_listener, d); @@ -802,7 +834,6 @@ display_handle_global(struct wl_display *display, } } -static const char gem_device[] = "/dev/dri/card0"; static const char socket_name[] = "\0wayland"; struct display * @@ -812,7 +843,6 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) struct display *d; EGLint major, minor, count; EGLConfig config; - struct wl_display *display; int fd; GOptionContext *context; GError *error; @@ -824,6 +854,8 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) EGL_NONE }; + g_type_init(); + context = g_option_context_new(NULL); if (option_entries) { g_option_context_add_main_entries(context, option_entries, "Wayland View"); @@ -837,15 +869,22 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) if (d == NULL) return NULL; - fd = open(gem_device, O_RDWR); - if (fd < 0) { - fprintf(stderr, "drm open failed: %m\n"); + d->display = wl_display_create(socket_name, sizeof socket_name); + if (d->display == NULL) { + fprintf(stderr, "failed to create display: %m\n"); return NULL; } - display = wl_display_create(socket_name, sizeof socket_name); - if (display == NULL) { - fprintf(stderr, "failed to create display: %m\n"); + /* Set up listener so we'll catch all events. */ + wl_display_add_global_listener(d->display, + display_handle_global, d); + + /* Process connection events. */ + wl_display_iterate(d->display, WL_DISPLAY_READABLE); + + fd = open(d->device_name, O_RDWR); + if (fd < 0) { + fprintf(stderr, "drm open failed: %m\n"); return NULL; } @@ -882,24 +921,18 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) return NULL; } - d->display = display; d->device = cairo_egl_device_create(d->dpy, d->ctx); if (d->device == NULL) { fprintf(stderr, "failed to get cairo drm device\n"); return NULL; } - /* Set up listener so we'll catch all events. */ - wl_display_add_global_listener(display, - display_handle_global, d); - - /* Process connection events. */ - wl_display_iterate(display, WL_DISPLAY_READABLE); - d->loop = g_main_loop_new(NULL, FALSE); - d->source = wl_glib_source_new(display); + d->source = wl_glib_source_new(d->display); g_source_attach(d->source, NULL); + wl_list_init(&d->window_list); + return d; } diff --git a/clients/window.h b/clients/window.h index e913ca3b..18318263 100644 --- a/clients/window.h +++ b/clients/window.h @@ -56,7 +56,7 @@ enum { typedef void (*window_resize_handler_t)(struct window *window, void *data); typedef void (*window_frame_handler_t)(struct window *window, uint32_t frame, uint32_t timestamp, void *data); -typedef void (*window_acknowledge_handler_t)(struct window *window, uint32_t key, void *data); +typedef void (*window_acknowledge_handler_t)(struct window *window, uint32_t key, uint32_t frame, void *data); typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t unicode, uint32_t state, uint32_t modifiers, void *data); typedef void (*window_keyboard_focus_handler_t)(struct window *window, @@ -120,6 +120,10 @@ window_set_keyboard_focus_handler(struct window *window, window_keyboard_focus_handler_t handler, void *data); +void +window_set_acknowledge_handler(struct window *window, + window_acknowledge_handler_t handler, void *data); + void window_set_frame_handler(struct window *window, window_frame_handler_t handler, void *data); diff --git a/compositor.c b/compositor.c index 21e5ea01..805d54ff 100644 --- a/compositor.c +++ b/compositor.c @@ -1144,7 +1144,8 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device) return -1; } - ec->drm_fd = open(udev_device_get_devnode(device), O_RDWR); + ec->base.device = strdup(udev_device_get_devnode(device)); + ec->drm_fd = open(ec->base.device, O_RDWR); if (ec->drm_fd < 0) { /* Probably permissions error */ fprintf(stderr, "couldn't open %s, skipping\n", diff --git a/config.mk.in b/config.mk.in index 59135c74..fa47cf2f 100644 --- a/config.mk.in +++ b/config.mk.in @@ -12,14 +12,8 @@ COMPOSITOR_LIBS = @COMPOSITOR_LIBS@ FFI_CFLAGS = @FFI_CFLAGS@ FFI_LIBS = @FFI_LIBS@ -EGL_CLIENT_CFLAGS = @EGL_CLIENT_CFLAGS@ -EGL_CLIENT_LIBS = @EGL_CLIENT_LIBS@ - -CAIRO_CLIENT_CFLAGS = @CAIRO_CLIENT_CFLAGS@ -CAIRO_CLIENT_LIBS = @CAIRO_CLIENT_LIBS@ - -GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ -GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +CLIENT_CFLAGS = @CLIENT_CFLAGS@ +CLIENT_LIBS = @CLIENT_LIBS@ POPPLER_CFLAGS = @POPPLER_CFLAGS@ POPPLER_LIBS = @POPPLER_LIBS@ diff --git a/configure.ac b/configure.ac index d5f6065a..40401216 100644 --- a/configure.ac +++ b/configure.ac @@ -6,9 +6,7 @@ PKG_CHECK_MODULES(FFI, [libffi]) PKG_CHECK_MODULES(COMPOSITOR, [egl gl libpng cairo gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.17]) -PKG_CHECK_MODULES(EGL_CLIENT, [egl gl cairo glib-2.0 libudev]) -PKG_CHECK_MODULES(CAIRO_CLIENT, [cairo-gl glib-2.0]) -PKG_CHECK_MODULES(GDK_PIXBUF, [gdk-pixbuf-2.0]) +PKG_CHECK_MODULES(CLIENT, [egl gl cairo-gl gdk-pixbuf-2.0 glib-2.0 gobject-2.0]) PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0]) if test $CC = gcc; then diff --git a/wayland-client.h b/wayland-client.h index 186fcc62..faeb7689 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -65,6 +65,9 @@ struct wl_visual * wl_display_get_rgb_visual(struct wl_display *display); struct wl_compositor_listener { + void (*device)(void *data, + struct wl_compositor *compositor, + const char *device); void (*acknowledge)(void *data, struct wl_compositor *compositor, uint32_t key, uint32_t frame); diff --git a/wayland-protocol.c b/wayland-protocol.c index 7d3b83ae..19e5db74 100644 --- a/wayland-protocol.c +++ b/wayland-protocol.c @@ -46,6 +46,7 @@ static const struct wl_message compositor_methods[] = { }; static const struct wl_message compositor_events[] = { + { "device", "s" }, { "acknowledge", "uu" }, { "frame", "uu" } }; diff --git a/wayland-protocol.h b/wayland-protocol.h index 2b87a141..fa29fe72 100644 --- a/wayland-protocol.h +++ b/wayland-protocol.h @@ -37,8 +37,9 @@ extern const struct wl_interface wl_display_interface; #define WL_COMPOSITOR_CREATE_SURFACE 0 #define WL_COMPOSITOR_COMMIT 1 -#define WL_COMPOSITOR_ACKNOWLEDGE 0 -#define WL_COMPOSITOR_FRAME 1 +#define WL_COMPOSITOR_DEVICE 0 +#define WL_COMPOSITOR_ACKNOWLEDGE 1 +#define WL_COMPOSITOR_FRAME 2 extern const struct wl_interface wl_compositor_interface; @@ -46,8 +47,7 @@ extern const struct wl_interface wl_compositor_interface; #define WL_SURFACE_DESTROY 0 #define WL_SURFACE_ATTACH 1 #define WL_SURFACE_MAP 2 -#define WL_SURFACE_COPY 3 -#define WL_SURFACE_DAMAGE 4 +#define WL_SURFACE_DAMAGE 3 extern const struct wl_interface wl_surface_interface; diff --git a/wayland.c b/wayland.c index db427416..dcadf266 100644 --- a/wayland.c +++ b/wayland.c @@ -275,6 +275,16 @@ wl_client_send_acknowledge(struct wl_client *client, WL_COMPOSITOR_ACKNOWLEDGE, key, frame); } +static void +post_compositor_device(struct wl_client *client, struct wl_object *global) +{ + struct wl_compositor *compositor = + container_of(global, struct wl_compositor, base); + + wl_client_post_event(client, global, + WL_COMPOSITOR_DEVICE, compositor->device); +} + WL_EXPORT int wl_display_set_compositor(struct wl_display *display, struct wl_compositor *compositor, @@ -284,7 +294,7 @@ wl_display_set_compositor(struct wl_display *display, compositor->base.implementation = (void (**)(void)) implementation; wl_display_add_object(display, &compositor->base); - if (wl_display_add_global(display, &compositor->base, NULL)) + if (wl_display_add_global(display, &compositor->base, post_compositor_device)) return -1; return 0; diff --git a/wayland.h b/wayland.h index 434a46bd..bffd415e 100644 --- a/wayland.h +++ b/wayland.h @@ -86,6 +86,7 @@ int wl_display_add_global(struct wl_display *display, struct wl_object *object, struct wl_compositor { struct wl_object base; + const char *device; }; struct wl_surface {