From 632bb948b7ffbb08a6e965dabf88347afd0a1fa8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 15:25:25 -0400 Subject: Add solid-color rendering to swaybg --- client/buffer-pool.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++ client/meson.build | 21 +++++++++ 2 files changed, 144 insertions(+) create mode 100644 client/buffer-pool.c create mode 100644 client/meson.build (limited to 'client') diff --git a/client/buffer-pool.c b/client/buffer-pool.c new file mode 100644 index 00000000..26d0f7e5 --- /dev/null +++ b/client/buffer-pool.c @@ -0,0 +1,123 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "buffer_pool.h" + +static int create_pool_file(size_t size, char **name) { + static const char template[] = "sway-client-XXXXXX"; + const char *path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + return -1; + } + + int ts = (path[strlen(path) - 1] == '/'); + + *name = malloc( + strlen(template) + + strlen(path) + + (ts ? 0 : 1) + 1); + sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); + + int fd = mkstemp(*name); + + if (fd < 0) { + return -1; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static void buffer_release(void *data, struct wl_buffer *wl_buffer) { + struct pool_buffer *buffer = data; + buffer->busy = false; +} + +static const struct wl_buffer_listener buffer_listener = { + .release = buffer_release +}; + +static struct pool_buffer *create_buffer(struct wl_shm *shm, + struct pool_buffer *buf, int32_t width, int32_t height, + uint32_t format) { + uint32_t stride = width * 4; + uint32_t size = stride * height; + + char *name; + int fd = create_pool_file(size, &name); + assert(fd); + void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); + buf->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, stride, format); + wl_shm_pool_destroy(pool); + close(fd); + unlink(name); + free(name); + fd = -1; + + buf->width = width; + buf->height = height; + buf->surface = cairo_image_surface_create_for_data(data, + CAIRO_FORMAT_ARGB32, width, height, stride); + buf->cairo = cairo_create(buf->surface); + buf->pango = pango_cairo_create_context(buf->cairo); + + wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); + return buf; +} + +static void destroy_buffer(struct pool_buffer *buffer) { + if (buffer->buffer) { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->cairo) { + cairo_destroy(buffer->cairo); + } + if (buffer->surface) { + cairo_surface_destroy(buffer->surface); + } + if (buffer->pango) { + g_object_unref(buffer->pango); + } + memset(buffer, 0, sizeof(struct pool_buffer)); +} + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { + struct pool_buffer *buffer = NULL; + + for (size_t i = 0; i < 2; ++i) { + if (pool[i].busy) { + continue; + } + buffer = &pool[i]; + } + + if (!buffer) { + return NULL; + } + + if (buffer->width != width || buffer->height != height) { + destroy_buffer(buffer); + } + + if (!buffer->buffer) { + if (!create_buffer(shm, buffer, width, height, + WL_SHM_FORMAT_ARGB8888)) { + return NULL; + } + } + return buffer; +} diff --git a/client/meson.build b/client/meson.build new file mode 100644 index 00000000..597899ce --- /dev/null +++ b/client/meson.build @@ -0,0 +1,21 @@ +deps = [ + cairo, + pango, + pangocairo, + wlroots, + wayland_client, +] + +if gdk_pixbuf.found() + deps += [gdk_pixbuf] +endif + +lib_sway_client = static_library( + 'sway-client', + files( + 'buffer-pool.c', + ), + dependencies: deps, + link_with: [lib_sway_common], + include_directories: sway_inc +) -- cgit v1.2.3 From 53e3763b58575cda89562d0fa1a4f9270a9c74f6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 16:01:29 -0400 Subject: Fix style --- client/buffer-pool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'client') diff --git a/client/buffer-pool.c b/client/buffer-pool.c index 26d0f7e5..7f673ae9 100644 --- a/client/buffer-pool.c +++ b/client/buffer-pool.c @@ -13,7 +13,7 @@ static int create_pool_file(size_t size, char **name) { static const char template[] = "sway-client-XXXXXX"; const char *path = getenv("XDG_RUNTIME_DIR"); - if (!path) { + if (!path) { return -1; } -- cgit v1.2.3 From d39bda76c4007c42452a81883fefc671b816a74b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 12:21:50 -0400 Subject: Address review comments --- client/buffer-pool.c | 123 ------------------------------------------------- client/meson.build | 23 ++++------ client/pool-buffer.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/cairo.c | 6 +-- include/buffer_pool.h | 21 --------- include/cairo.h | 3 +- include/meson.build | 1 + include/pool-buffer.h | 21 +++++++++ meson.build | 5 +- swaybg/main.c | 44 ++++++------------ swaybg/meson.build | 36 +++++++-------- 11 files changed, 193 insertions(+), 214 deletions(-) delete mode 100644 client/buffer-pool.c create mode 100644 client/pool-buffer.c delete mode 100644 include/buffer_pool.h create mode 100644 include/meson.build create mode 100644 include/pool-buffer.h (limited to 'client') diff --git a/client/buffer-pool.c b/client/buffer-pool.c deleted file mode 100644 index 7f673ae9..00000000 --- a/client/buffer-pool.c +++ /dev/null @@ -1,123 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "buffer_pool.h" - -static int create_pool_file(size_t size, char **name) { - static const char template[] = "sway-client-XXXXXX"; - const char *path = getenv("XDG_RUNTIME_DIR"); - if (!path) { - return -1; - } - - int ts = (path[strlen(path) - 1] == '/'); - - *name = malloc( - strlen(template) + - strlen(path) + - (ts ? 0 : 1) + 1); - sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); - - int fd = mkstemp(*name); - - if (fd < 0) { - return -1; - } - - if (ftruncate(fd, size) < 0) { - close(fd); - return -1; - } - - return fd; -} - -static void buffer_release(void *data, struct wl_buffer *wl_buffer) { - struct pool_buffer *buffer = data; - buffer->busy = false; -} - -static const struct wl_buffer_listener buffer_listener = { - .release = buffer_release -}; - -static struct pool_buffer *create_buffer(struct wl_shm *shm, - struct pool_buffer *buf, int32_t width, int32_t height, - uint32_t format) { - uint32_t stride = width * 4; - uint32_t size = stride * height; - - char *name; - int fd = create_pool_file(size, &name); - assert(fd); - void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); - buf->buffer = wl_shm_pool_create_buffer(pool, 0, - width, height, stride, format); - wl_shm_pool_destroy(pool); - close(fd); - unlink(name); - free(name); - fd = -1; - - buf->width = width; - buf->height = height; - buf->surface = cairo_image_surface_create_for_data(data, - CAIRO_FORMAT_ARGB32, width, height, stride); - buf->cairo = cairo_create(buf->surface); - buf->pango = pango_cairo_create_context(buf->cairo); - - wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); - return buf; -} - -static void destroy_buffer(struct pool_buffer *buffer) { - if (buffer->buffer) { - wl_buffer_destroy(buffer->buffer); - } - if (buffer->cairo) { - cairo_destroy(buffer->cairo); - } - if (buffer->surface) { - cairo_surface_destroy(buffer->surface); - } - if (buffer->pango) { - g_object_unref(buffer->pango); - } - memset(buffer, 0, sizeof(struct pool_buffer)); -} - -struct pool_buffer *get_next_buffer(struct wl_shm *shm, - struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { - struct pool_buffer *buffer = NULL; - - for (size_t i = 0; i < 2; ++i) { - if (pool[i].busy) { - continue; - } - buffer = &pool[i]; - } - - if (!buffer) { - return NULL; - } - - if (buffer->width != width || buffer->height != height) { - destroy_buffer(buffer); - } - - if (!buffer->buffer) { - if (!create_buffer(shm, buffer, width, height, - WL_SHM_FORMAT_ARGB8888)) { - return NULL; - } - } - return buffer; -} diff --git a/client/meson.build b/client/meson.build index 597899ce..2bdda457 100644 --- a/client/meson.build +++ b/client/meson.build @@ -1,21 +1,16 @@ -deps = [ - cairo, - pango, - pangocairo, - wlroots, - wayland_client, -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - lib_sway_client = static_library( 'sway-client', files( - 'buffer-pool.c', + 'pool-buffer.c', ), - dependencies: deps, + dependencies: [ + cairo, + gdk_pixbuf, + pango, + pangocairo, + wlroots, + wayland_client, + ], link_with: [lib_sway_common], include_directories: sway_inc ) diff --git a/client/pool-buffer.c b/client/pool-buffer.c new file mode 100644 index 00000000..93cfcfc5 --- /dev/null +++ b/client/pool-buffer.c @@ -0,0 +1,124 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "pool-buffer.h" + +static int create_pool_file(size_t size, char **name) { + static const char template[] = "sway-client-XXXXXX"; + const char *path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + return -1; + } + + int ts = (path[strlen(path) - 1] == '/'); + + *name = malloc( + strlen(template) + + strlen(path) + + (ts ? 0 : 1) + 1); + sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); + + int fd = mkstemp(*name); + + if (fd < 0) { + return -1; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static void buffer_release(void *data, struct wl_buffer *wl_buffer) { + struct pool_buffer *buffer = data; + buffer->busy = false; +} + +static const struct wl_buffer_listener buffer_listener = { + .release = buffer_release +}; + +static struct pool_buffer *create_buffer(struct wl_shm *shm, + struct pool_buffer *buf, int32_t width, int32_t height, + uint32_t format) { + uint32_t stride = width * 4; + uint32_t size = stride * height; + + char *name; + int fd = create_pool_file(size, &name); + assert(fd); + void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); + buf->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, stride, format); + wl_shm_pool_destroy(pool); + close(fd); + unlink(name); + free(name); + fd = -1; + + buf->width = width; + buf->height = height; + buf->surface = cairo_image_surface_create_for_data(data, + CAIRO_FORMAT_ARGB32, width, height, stride); + buf->cairo = cairo_create(buf->surface); + buf->pango = pango_cairo_create_context(buf->cairo); + + wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); + return buf; +} + +static void destroy_buffer(struct pool_buffer *buffer) { + if (buffer->buffer) { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->cairo) { + cairo_destroy(buffer->cairo); + } + if (buffer->surface) { + cairo_surface_destroy(buffer->surface); + } + if (buffer->pango) { + g_object_unref(buffer->pango); + } + memset(buffer, 0, sizeof(struct pool_buffer)); +} + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { + struct pool_buffer *buffer = NULL; + + for (size_t i = 0; i < 2; ++i) { + if (pool[i].busy) { + continue; + } + buffer = &pool[i]; + } + + if (!buffer) { + return NULL; + } + + if (buffer->width != width || buffer->height != height) { + destroy_buffer(buffer); + } + + if (!buffer->buffer) { + if (!create_buffer(shm, buffer, width, height, + WL_SHM_FORMAT_ARGB8888)) { + return NULL; + } + } + return buffer; +} diff --git a/common/cairo.c b/common/cairo.c index c6bd0da9..c267c77c 100644 --- a/common/cairo.c +++ b/common/cairo.c @@ -1,7 +1,7 @@ #include #include #include "cairo.h" -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF #include #endif @@ -30,7 +30,7 @@ cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, return new; } -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { int chan = gdk_pixbuf_get_n_channels(gdkbuf); if (chan < 3) { @@ -124,4 +124,4 @@ cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdk cairo_surface_mark_dirty(cs); return cs; } -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF diff --git a/include/buffer_pool.h b/include/buffer_pool.h deleted file mode 100644 index cdebd64d..00000000 --- a/include/buffer_pool.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _SWAY_BUFFERS_H -#define _SWAY_BUFFERS_H -#include -#include -#include -#include -#include - -struct pool_buffer { - struct wl_buffer *buffer; - cairo_surface_t *surface; - cairo_t *cairo; - PangoContext *pango; - uint32_t width, height; - bool busy; -}; - -struct pool_buffer *get_next_buffer(struct wl_shm *shm, - struct pool_buffer pool[static 2], uint32_t width, uint32_t height); - -#endif diff --git a/include/cairo.h b/include/cairo.h index f5f474d7..31672705 100644 --- a/include/cairo.h +++ b/include/cairo.h @@ -8,7 +8,8 @@ void cairo_set_source_u32(cairo_t *cairo, uint32_t color); cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, int width, int height); -#ifdef WITH_GDK_PIXBUF +#include "config.h" +#ifdef HAVE_GDK_PIXBUF #include cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 00000000..65ed027a --- /dev/null +++ b/include/meson.build @@ -0,0 +1 @@ +configure_file(output: 'config.h', configuration: conf_data) diff --git a/include/pool-buffer.h b/include/pool-buffer.h new file mode 100644 index 00000000..cdebd64d --- /dev/null +++ b/include/pool-buffer.h @@ -0,0 +1,21 @@ +#ifndef _SWAY_BUFFERS_H +#define _SWAY_BUFFERS_H +#include +#include +#include +#include +#include + +struct pool_buffer { + struct wl_buffer *buffer; + cairo_surface_t *surface; + cairo_t *cairo; + PangoContext *pango; + uint32_t width, height; + bool busy; +}; + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height); + +#endif diff --git a/meson.build b/meson.build index 0c35b0e5..b681f43a 100644 --- a/meson.build +++ b/meson.build @@ -38,8 +38,10 @@ math = cc.find_library('m') git = find_program('git', required: false) a2x = find_program('a2x', required: false) +conf_data = configuration_data() + if gdk_pixbuf.found() - add_project_arguments('-DWITH_GDK_PIXBUF', language : 'c') + conf_data.set('HAVE_GDK_PIXBUF', true) endif if a2x.found() @@ -92,6 +94,7 @@ add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') sway_inc = include_directories('include') +subdir('include') subdir('protocols') subdir('common') subdir('sway') diff --git a/swaybg/main.c b/swaybg/main.c index 62ddec6c..f431526c 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,7 +7,7 @@ #include #include #include -#include "buffer_pool.h" +#include "pool-buffer.h" #include "cairo.h" #include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -127,7 +128,7 @@ static void render_image(struct swaybg_state *state) { break; } case BACKGROUND_MODE_SOLID_COLOR: - // Should never happen + assert(0); break; } cairo_paint(cairo); @@ -158,7 +159,7 @@ static bool prepare_context(struct swaybg_state *state) { state->context.color = parse_color(state->args->path); return is_valid_color(state->args->path); } -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF GError *err = NULL; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(state->args->path, &err); if (!pixbuf) { @@ -170,17 +171,17 @@ static bool prepare_context(struct swaybg_state *state) { #else state->context.image = cairo_image_surface_create_from_png( state->args->path); -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF if (!state->context.image) { wlr_log(L_ERROR, "Failed to read background image."); return false; } if (cairo_surface_status(state->context.image) != CAIRO_STATUS_SUCCESS) { wlr_log(L_ERROR, "Failed to read background image: %s." -#ifndef WITH_GDK_PIXBUF +#ifndef HAVE_GDK_PIXBUF "\nSway was compiled without gdk_pixbuf support, so only" "\nPNG images can be loaded. This is the likely cause." -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF , cairo_status_to_string( cairo_surface_status(state->context.image))); return false; @@ -256,7 +257,6 @@ int main(int argc, const char **argv) { } args.output_idx = atoi(argv[1]); args.path = argv[2]; - args.mode = atoi(argv[3]); args.mode = BACKGROUND_MODE_STRETCH; if (strcmp(argv[3], "stretch") == 0) { @@ -280,38 +280,20 @@ int main(int argc, const char **argv) { return 1; } - state.display = wl_display_connect(NULL); - if (!state.display) { - wlr_log(L_ERROR, "Failed to create display\n"); - return 1; - } + assert(state.display = wl_display_connect(NULL)); struct wl_registry *registry = wl_display_get_registry(state.display); wl_registry_add_listener(registry, ®istry_listener, &state); wl_display_roundtrip(state.display); + assert(state.compositor && state.layer_shell && state.output && state.shm); - if (!state.compositor) { - wlr_log(L_DEBUG, "wl-compositor not available"); - return 1; - } - if (!state.layer_shell) { - wlr_log(L_ERROR, "layer-shell not available"); - return 1; - } - - state.surface = wl_compositor_create_surface(state.compositor); - if (!state.surface) { - wlr_log(L_ERROR, "failed to create wl_surface"); - return 1; - } + assert(state.surface = wl_compositor_create_surface(state.compositor)); state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( state.layer_shell, state.surface, state.output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); - if (!state.layer_surface) { - wlr_log(L_ERROR, "failed to create zwlr_layer_surface"); - return 1; - } + assert(state.layer_surface); + zwlr_layer_surface_v1_set_size(state.layer_surface, 0, 0); zwlr_layer_surface_v1_set_anchor(state.layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | @@ -320,10 +302,10 @@ int main(int argc, const char **argv) { ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); zwlr_layer_surface_v1_add_listener(state.layer_surface, &layer_surface_listener, &state); + state.run_display = true; wl_surface_commit(state.surface); wl_display_roundtrip(state.display); - state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank } diff --git a/swaybg/meson.build b/swaybg/meson.build index 7f5d6bd1..5e10f3c7 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build @@ -1,22 +1,18 @@ -deps = [ - cairo, - jsonc, - math, - pango, - pangocairo, - sway_protos, - wayland_client, -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - executable( - 'swaybg', - 'main.c', - include_directories: [sway_inc], - dependencies: deps, - link_with: [lib_sway_common, lib_sway_client], - install: true + 'swaybg', + 'main.c', + include_directories: [sway_inc], + dependencies: [ + cairo, + gdk_pixbuf, + jsonc, + math, + pango, + pangocairo, + sway_protos, + wayland_client, + wlroots, + ], + link_with: [lib_sway_common, lib_sway_client], + install: true ) -- cgit v1.2.3