diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-27 15:25:25 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-03-28 14:25:19 -0400 |
commit | 632bb948b7ffbb08a6e965dabf88347afd0a1fa8 (patch) | |
tree | cbd9d4e4e3a7c605d2b0a5e3e66ce35554a74c4b /client | |
parent | Add client protocols and swaybg skeleton (diff) | |
download | sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.tar.gz sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.tar.zst sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.zip |
Add solid-color rendering to swaybg
Diffstat (limited to 'client')
-rw-r--r-- | client/buffer-pool.c | 123 | ||||
-rw-r--r-- | client/meson.build | 21 |
2 files changed, 144 insertions, 0 deletions
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 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <assert.h> | ||
3 | #include <cairo/cairo.h> | ||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <string.h> | ||
7 | #include <sys/mman.h> | ||
8 | #include <pango/pangocairo.h> | ||
9 | #include <unistd.h> | ||
10 | #include <wayland-client.h> | ||
11 | #include "buffer_pool.h" | ||
12 | |||
13 | static int create_pool_file(size_t size, char **name) { | ||
14 | static const char template[] = "sway-client-XXXXXX"; | ||
15 | const char *path = getenv("XDG_RUNTIME_DIR"); | ||
16 | if (!path) { | ||
17 | return -1; | ||
18 | } | ||
19 | |||
20 | int ts = (path[strlen(path) - 1] == '/'); | ||
21 | |||
22 | *name = malloc( | ||
23 | strlen(template) + | ||
24 | strlen(path) + | ||
25 | (ts ? 0 : 1) + 1); | ||
26 | sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); | ||
27 | |||
28 | int fd = mkstemp(*name); | ||
29 | |||
30 | if (fd < 0) { | ||
31 | return -1; | ||
32 | } | ||
33 | |||
34 | if (ftruncate(fd, size) < 0) { | ||
35 | close(fd); | ||
36 | return -1; | ||
37 | } | ||
38 | |||
39 | return fd; | ||
40 | } | ||
41 | |||
42 | static void buffer_release(void *data, struct wl_buffer *wl_buffer) { | ||
43 | struct pool_buffer *buffer = data; | ||
44 | buffer->busy = false; | ||
45 | } | ||
46 | |||
47 | static const struct wl_buffer_listener buffer_listener = { | ||
48 | .release = buffer_release | ||
49 | }; | ||
50 | |||
51 | static struct pool_buffer *create_buffer(struct wl_shm *shm, | ||
52 | struct pool_buffer *buf, int32_t width, int32_t height, | ||
53 | uint32_t format) { | ||
54 | uint32_t stride = width * 4; | ||
55 | uint32_t size = stride * height; | ||
56 | |||
57 | char *name; | ||
58 | int fd = create_pool_file(size, &name); | ||
59 | assert(fd); | ||
60 | void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | ||
61 | struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); | ||
62 | buf->buffer = wl_shm_pool_create_buffer(pool, 0, | ||
63 | width, height, stride, format); | ||
64 | wl_shm_pool_destroy(pool); | ||
65 | close(fd); | ||
66 | unlink(name); | ||
67 | free(name); | ||
68 | fd = -1; | ||
69 | |||
70 | buf->width = width; | ||
71 | buf->height = height; | ||
72 | buf->surface = cairo_image_surface_create_for_data(data, | ||
73 | CAIRO_FORMAT_ARGB32, width, height, stride); | ||
74 | buf->cairo = cairo_create(buf->surface); | ||
75 | buf->pango = pango_cairo_create_context(buf->cairo); | ||
76 | |||
77 | wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); | ||
78 | return buf; | ||
79 | } | ||
80 | |||
81 | static void destroy_buffer(struct pool_buffer *buffer) { | ||
82 | if (buffer->buffer) { | ||
83 | wl_buffer_destroy(buffer->buffer); | ||
84 | } | ||
85 | if (buffer->cairo) { | ||
86 | cairo_destroy(buffer->cairo); | ||
87 | } | ||
88 | if (buffer->surface) { | ||
89 | cairo_surface_destroy(buffer->surface); | ||
90 | } | ||
91 | if (buffer->pango) { | ||
92 | g_object_unref(buffer->pango); | ||
93 | } | ||
94 | memset(buffer, 0, sizeof(struct pool_buffer)); | ||
95 | } | ||
96 | |||
97 | struct pool_buffer *get_next_buffer(struct wl_shm *shm, | ||
98 | struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { | ||
99 | struct pool_buffer *buffer = NULL; | ||
100 | |||
101 | for (size_t i = 0; i < 2; ++i) { | ||
102 | if (pool[i].busy) { | ||
103 | continue; | ||
104 | } | ||
105 | buffer = &pool[i]; | ||
106 | } | ||
107 | |||
108 | if (!buffer) { | ||
109 | return NULL; | ||
110 | } | ||
111 | |||
112 | if (buffer->width != width || buffer->height != height) { | ||
113 | destroy_buffer(buffer); | ||
114 | } | ||
115 | |||
116 | if (!buffer->buffer) { | ||
117 | if (!create_buffer(shm, buffer, width, height, | ||
118 | WL_SHM_FORMAT_ARGB8888)) { | ||
119 | return NULL; | ||
120 | } | ||
121 | } | ||
122 | return buffer; | ||
123 | } | ||
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 @@ | |||
1 | deps = [ | ||
2 | cairo, | ||
3 | pango, | ||
4 | pangocairo, | ||
5 | wlroots, | ||
6 | wayland_client, | ||
7 | ] | ||
8 | |||
9 | if gdk_pixbuf.found() | ||
10 | deps += [gdk_pixbuf] | ||
11 | endif | ||
12 | |||
13 | lib_sway_client = static_library( | ||
14 | 'sway-client', | ||
15 | files( | ||
16 | 'buffer-pool.c', | ||
17 | ), | ||
18 | dependencies: deps, | ||
19 | link_with: [lib_sway_common], | ||
20 | include_directories: sway_inc | ||
21 | ) | ||