diff options
author | Drew DeVault <sir@cmpwn.com> | 2015-11-19 07:58:57 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2015-11-19 07:58:57 -0500 |
commit | b4e5e1381f909b173a171fb3941610aec989df48 (patch) | |
tree | f7dcf63dc6f4ac05c8fbb86da37d52766f210130 /wayland | |
parent | Fix background extensions (diff) | |
download | sway-b4e5e1381f909b173a171fb3941610aec989df48.tar.gz sway-b4e5e1381f909b173a171fb3941610aec989df48.tar.zst sway-b4e5e1381f909b173a171fb3941610aec989df48.zip |
Refactor the crap out of wayland clients
And create a background surface on every output when invoking swaybg.
Diffstat (limited to 'wayland')
-rw-r--r-- | wayland/buffers.c | 20 | ||||
-rw-r--r-- | wayland/client.c | 218 | ||||
-rw-r--r-- | wayland/registry.c | 116 | ||||
-rw-r--r-- | wayland/window.c | 123 |
4 files changed, 249 insertions, 228 deletions
diff --git a/wayland/buffers.c b/wayland/buffers.c index dfedfcf7..1e5e5693 100644 --- a/wayland/buffers.c +++ b/wayland/buffers.c | |||
@@ -49,7 +49,7 @@ static const struct wl_buffer_listener buffer_listener = { | |||
49 | .release = buffer_release | 49 | .release = buffer_release |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static struct buffer *create_buffer(struct client_state *state, struct buffer *buf, | 52 | static struct buffer *create_buffer(struct window *window, struct buffer *buf, |
53 | int32_t width, int32_t height, uint32_t format) { | 53 | int32_t width, int32_t height, uint32_t format) { |
54 | 54 | ||
55 | uint32_t stride = width * 4; | 55 | uint32_t stride = width * 4; |
@@ -62,7 +62,7 @@ static struct buffer *create_buffer(struct client_state *state, struct buffer *b | |||
62 | return NULL; // never reached | 62 | return NULL; // never reached |
63 | } | 63 | } |
64 | void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | 64 | void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
65 | struct wl_shm_pool *pool = wl_shm_create_pool(state->shm, fd, size); | 65 | struct wl_shm_pool *pool = wl_shm_create_pool(window->registry->shm, fd, size); |
66 | buf->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, format); | 66 | buf->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, format); |
67 | wl_shm_pool_destroy(pool); | 67 | wl_shm_pool_destroy(pool); |
68 | close(fd); | 68 | close(fd); |
@@ -76,7 +76,7 @@ static struct buffer *create_buffer(struct client_state *state, struct buffer *b | |||
76 | buf->cairo = cairo_create(buf->surface); | 76 | buf->cairo = cairo_create(buf->surface); |
77 | buf->pango = pango_cairo_create_context(buf->cairo); | 77 | buf->pango = pango_cairo_create_context(buf->cairo); |
78 | 78 | ||
79 | wl_buffer_add_listener(buf->buffer, &buffer_listener, state); | 79 | wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); |
80 | return buf; | 80 | return buf; |
81 | } | 81 | } |
82 | 82 | ||
@@ -93,32 +93,32 @@ static void destroy_buffer(struct buffer *buffer) { | |||
93 | memset(buffer, 0, sizeof(struct buffer)); | 93 | memset(buffer, 0, sizeof(struct buffer)); |
94 | } | 94 | } |
95 | 95 | ||
96 | struct buffer *get_next_buffer(struct client_state *state) { | 96 | struct buffer *get_next_buffer(struct window *window) { |
97 | struct buffer *buffer = NULL; | 97 | struct buffer *buffer = NULL; |
98 | 98 | ||
99 | int i; | 99 | int i; |
100 | for (i = 0; i < 2; ++i) { | 100 | for (i = 0; i < 2; ++i) { |
101 | if (state->buffers[i].busy) { | 101 | if (window->buffers[i].busy) { |
102 | continue; | 102 | continue; |
103 | } | 103 | } |
104 | buffer = &state->buffers[i]; | 104 | buffer = &window->buffers[i]; |
105 | } | 105 | } |
106 | 106 | ||
107 | if (!buffer) { | 107 | if (!buffer) { |
108 | return NULL; | 108 | return NULL; |
109 | } | 109 | } |
110 | 110 | ||
111 | if (buffer->width != state->width || buffer->height != state->height) { | 111 | if (buffer->width != window->width || buffer->height != window->height) { |
112 | destroy_buffer(buffer); | 112 | destroy_buffer(buffer); |
113 | } | 113 | } |
114 | 114 | ||
115 | if (!buffer->buffer) { | 115 | if (!buffer->buffer) { |
116 | if (!create_buffer(state, buffer, state->width, state->height, WL_SHM_FORMAT_ARGB8888)) { | 116 | if (!create_buffer(window, buffer, window->width, window->height, WL_SHM_FORMAT_ARGB8888)) { |
117 | return NULL; | 117 | return NULL; |
118 | } | 118 | } |
119 | } | 119 | } |
120 | 120 | ||
121 | state->cairo = buffer->cairo; | 121 | window->cairo = buffer->cairo; |
122 | state->buffer = buffer; | 122 | window->buffer = buffer; |
123 | return buffer; | 123 | return buffer; |
124 | } | 124 | } |
diff --git a/wayland/client.c b/wayland/client.c deleted file mode 100644 index ab8adc47..00000000 --- a/wayland/client.c +++ /dev/null | |||
@@ -1,218 +0,0 @@ | |||
1 | #include <wayland-client.h> | ||
2 | #include <wayland-cursor.h> | ||
3 | #include "wayland-xdg-shell-client-protocol.h" | ||
4 | #include "wayland-desktop-shell-client-protocol.h" | ||
5 | #include <cairo/cairo.h> | ||
6 | #include <pango/pangocairo.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <string.h> | ||
9 | #include <stdio.h> | ||
10 | #include <unistd.h> | ||
11 | #include <errno.h> | ||
12 | #include <sys/mman.h> | ||
13 | #include "client/client.h" | ||
14 | #include "client/buffer.h" | ||
15 | #include "list.h" | ||
16 | #include "log.h" | ||
17 | |||
18 | static void display_handle_mode(void *data, struct wl_output *wl_output, | ||
19 | uint32_t flags, int32_t width, int32_t height, int32_t refresh) { | ||
20 | struct output_state *state = data; | ||
21 | if (flags & WL_OUTPUT_MODE_CURRENT) { | ||
22 | state->flags = flags; | ||
23 | state->width = width; | ||
24 | state->height = height; | ||
25 | } | ||
26 | } | ||
27 | |||
28 | static void display_handle_geometry(void *data, struct wl_output *wl_output, | ||
29 | int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, | ||
30 | int32_t subpixel, const char *make, const char *model, int32_t transform) { | ||
31 | // this space intentionally left blank | ||
32 | } | ||
33 | |||
34 | static void display_handle_done(void *data, struct wl_output *wl_output) { | ||
35 | // this space intentionally left blank | ||
36 | } | ||
37 | |||
38 | static void display_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) { | ||
39 | // this space intentionally left blank | ||
40 | } | ||
41 | |||
42 | static const struct wl_output_listener output_listener = { | ||
43 | .mode = display_handle_mode, | ||
44 | .geometry = display_handle_geometry, | ||
45 | .done = display_handle_done, | ||
46 | .scale = display_handle_scale | ||
47 | }; | ||
48 | |||
49 | static void pointer_handle_enter(void *data, struct wl_pointer *pointer, | ||
50 | uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) { | ||
51 | struct client_state *state = data; | ||
52 | struct wl_cursor_image *image = state->cursor.cursor->images[0]; | ||
53 | wl_pointer_set_cursor(pointer, serial, state->cursor.surface, image->hotspot_x, image->hotspot_y); | ||
54 | } | ||
55 | |||
56 | static void pointer_handle_leave(void *data, struct wl_pointer *pointer, | ||
57 | uint32_t serial, struct wl_surface *surface) { | ||
58 | } | ||
59 | |||
60 | static void pointer_handle_motion(void *data, struct wl_pointer *pointer, | ||
61 | uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { | ||
62 | } | ||
63 | |||
64 | static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, | ||
65 | uint32_t time, uint32_t button, uint32_t state_w) { | ||
66 | } | ||
67 | |||
68 | static void pointer_handle_axis(void *data, struct wl_pointer *pointer, | ||
69 | uint32_t time, uint32_t axis, wl_fixed_t value) { | ||
70 | } | ||
71 | |||
72 | static const struct wl_pointer_listener pointer_listener = { | ||
73 | .enter = pointer_handle_enter, | ||
74 | .leave = pointer_handle_leave, | ||
75 | .motion = pointer_handle_motion, | ||
76 | .button = pointer_handle_button, | ||
77 | .axis = pointer_handle_axis | ||
78 | }; | ||
79 | |||
80 | static void registry_global(void *data, struct wl_registry *registry, | ||
81 | uint32_t name, const char *interface, uint32_t version) { | ||
82 | struct client_state *state = data; | ||
83 | |||
84 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | ||
85 | state->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, version); | ||
86 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | ||
87 | state->shm = wl_registry_bind(registry, name, &wl_shm_interface, version); | ||
88 | } else if (strcmp(interface, wl_shell_interface.name) == 0) { | ||
89 | state->shell = wl_registry_bind(registry, name, &wl_shell_interface, version); | ||
90 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { | ||
91 | state->seat = wl_registry_bind(registry, name, &wl_seat_interface, version); | ||
92 | state->pointer = wl_seat_get_pointer(state->seat); | ||
93 | wl_pointer_add_listener(state->pointer, &pointer_listener, state); | ||
94 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | ||
95 | struct wl_output *output = wl_registry_bind(registry, name, &wl_output_interface, version); | ||
96 | struct output_state *ostate = malloc(sizeof(struct output_state)); | ||
97 | ostate->output = output; | ||
98 | wl_output_add_listener(output, &output_listener, ostate); | ||
99 | list_add(state->outputs, ostate); | ||
100 | } else if (strcmp(interface, desktop_shell_interface.name) == 0) { | ||
101 | state->desktop_shell = wl_registry_bind(registry, name, &desktop_shell_interface, version); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) { | ||
106 | // this space intentionally left blank | ||
107 | } | ||
108 | |||
109 | static const struct wl_registry_listener registry_listener = { | ||
110 | .global = registry_global, | ||
111 | .global_remove = registry_global_remove | ||
112 | }; | ||
113 | |||
114 | void shell_surface_configure(void *data, struct wl_shell_surface *wl_shell_surface, | ||
115 | uint32_t edges, int32_t width, int32_t height) { | ||
116 | struct client_state *state = data; | ||
117 | state->width = width; | ||
118 | state->height = height; | ||
119 | } | ||
120 | |||
121 | static const struct wl_shell_surface_listener surface_listener = { | ||
122 | .configure = shell_surface_configure | ||
123 | }; | ||
124 | |||
125 | struct client_state *client_setup(uint32_t width, uint32_t height, bool shell_surface) { | ||
126 | struct client_state *state = malloc(sizeof(struct client_state)); | ||
127 | memset(state, 0, sizeof(struct client_state)); | ||
128 | state->outputs = create_list(); | ||
129 | state->width = width; | ||
130 | state->height = height; | ||
131 | |||
132 | state->display = wl_display_connect(NULL); | ||
133 | if (!state->display) { | ||
134 | sway_log(L_ERROR, "Error opening display"); | ||
135 | client_teardown(state); | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | struct wl_registry *registry = wl_display_get_registry(state->display); | ||
140 | wl_registry_add_listener(registry, ®istry_listener, state); | ||
141 | wl_display_dispatch(state->display); | ||
142 | wl_display_roundtrip(state->display); | ||
143 | wl_registry_destroy(registry); | ||
144 | |||
145 | state->surface = wl_compositor_create_surface(state->compositor); | ||
146 | if (shell_surface) { | ||
147 | state->shell_surface = wl_shell_get_shell_surface(state->shell, state->surface); | ||
148 | wl_shell_surface_add_listener(state->shell_surface, &surface_listener, state); | ||
149 | wl_shell_surface_set_toplevel(state->shell_surface); | ||
150 | } | ||
151 | |||
152 | state->cursor.cursor_theme = wl_cursor_theme_load("default", 32, state->shm); // TODO: let you customize this | ||
153 | state->cursor.cursor = wl_cursor_theme_get_cursor(state->cursor.cursor_theme, "left_ptr"); | ||
154 | state->cursor.surface = wl_compositor_create_surface(state->compositor); | ||
155 | |||
156 | struct wl_cursor_image *image = state->cursor.cursor->images[0]; | ||
157 | struct wl_buffer *cursor_buf = wl_cursor_image_get_buffer(image); | ||
158 | wl_surface_attach(state->cursor.surface, cursor_buf, 0, 0); | ||
159 | wl_surface_damage(state->cursor.surface, 0, 0, image->width, image->height); | ||
160 | wl_surface_commit(state->cursor.surface); | ||
161 | |||
162 | return state; | ||
163 | } | ||
164 | |||
165 | static void frame_callback(void *data, struct wl_callback *callback, uint32_t time) { | ||
166 | struct client_state *state = data; | ||
167 | wl_callback_destroy(callback); | ||
168 | state->frame_cb = NULL; | ||
169 | } | ||
170 | |||
171 | static const struct wl_callback_listener listener = { | ||
172 | frame_callback | ||
173 | }; | ||
174 | |||
175 | int client_prerender(struct client_state *state) { | ||
176 | if (state->frame_cb) { | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | get_next_buffer(state); | ||
181 | return 1; | ||
182 | } | ||
183 | |||
184 | int client_render(struct client_state *state) { | ||
185 | state->frame_cb = wl_surface_frame(state->surface); | ||
186 | wl_callback_add_listener(state->frame_cb, &listener, state); | ||
187 | |||
188 | wl_surface_damage(state->surface, 0, 0, state->buffer->width, state->buffer->height); | ||
189 | wl_surface_attach(state->surface, state->buffer->buffer, 0, 0); | ||
190 | wl_surface_commit(state->surface); | ||
191 | |||
192 | return 1; | ||
193 | } | ||
194 | |||
195 | void client_teardown(struct client_state *state) { | ||
196 | if (state->pointer) { | ||
197 | wl_pointer_destroy(state->pointer); | ||
198 | } | ||
199 | if (state->seat) { | ||
200 | wl_seat_destroy(state->seat); | ||
201 | } | ||
202 | if (state->shell) { | ||
203 | wl_shell_destroy(state->shell); | ||
204 | } | ||
205 | if (state->shm) { | ||
206 | wl_shm_destroy(state->shm); | ||
207 | } | ||
208 | if (state->compositor) { | ||
209 | wl_compositor_destroy(state->compositor); | ||
210 | } | ||
211 | if (state->display) { | ||
212 | wl_display_disconnect(state->display); | ||
213 | } | ||
214 | if (state->outputs) { | ||
215 | // TODO: Free the outputs themselves | ||
216 | list_free(state->outputs); | ||
217 | } | ||
218 | } | ||
diff --git a/wayland/registry.c b/wayland/registry.c new file mode 100644 index 00000000..a7eb89d1 --- /dev/null +++ b/wayland/registry.c | |||
@@ -0,0 +1,116 @@ | |||
1 | #include <wayland-client.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include "wayland-desktop-shell-client-protocol.h" | ||
5 | #include "client/registry.h" | ||
6 | #include "log.h" | ||
7 | |||
8 | static void display_handle_mode(void *data, struct wl_output *wl_output, | ||
9 | uint32_t flags, int32_t width, int32_t height, int32_t refresh) { | ||
10 | struct output_state *state = data; | ||
11 | if (flags & WL_OUTPUT_MODE_CURRENT) { | ||
12 | state->flags = flags; | ||
13 | state->width = width; | ||
14 | state->height = height; | ||
15 | } | ||
16 | } | ||
17 | |||
18 | static void display_handle_geometry(void *data, struct wl_output *wl_output, | ||
19 | int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, | ||
20 | int32_t subpixel, const char *make, const char *model, int32_t transform) { | ||
21 | // this space intentionally left blank | ||
22 | } | ||
23 | |||
24 | static void display_handle_done(void *data, struct wl_output *wl_output) { | ||
25 | // this space intentionally left blank | ||
26 | } | ||
27 | |||
28 | static void display_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) { | ||
29 | // this space intentionally left blank | ||
30 | } | ||
31 | |||
32 | static const struct wl_output_listener output_listener = { | ||
33 | .mode = display_handle_mode, | ||
34 | .geometry = display_handle_geometry, | ||
35 | .done = display_handle_done, | ||
36 | .scale = display_handle_scale | ||
37 | }; | ||
38 | |||
39 | static void registry_global(void *data, struct wl_registry *registry, | ||
40 | uint32_t name, const char *interface, uint32_t version) { | ||
41 | struct registry *reg = data; | ||
42 | |||
43 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | ||
44 | reg->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, version); | ||
45 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | ||
46 | reg->shm = wl_registry_bind(registry, name, &wl_shm_interface, version); | ||
47 | } else if (strcmp(interface, wl_shell_interface.name) == 0) { | ||
48 | reg->shell = wl_registry_bind(registry, name, &wl_shell_interface, version); | ||
49 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { | ||
50 | reg->seat = wl_registry_bind(registry, name, &wl_seat_interface, version); | ||
51 | reg->pointer = wl_seat_get_pointer(reg->seat); | ||
52 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | ||
53 | struct wl_output *output = wl_registry_bind(registry, name, &wl_output_interface, version); | ||
54 | struct output_state *ostate = malloc(sizeof(struct output_state)); | ||
55 | ostate->output = output; | ||
56 | wl_output_add_listener(output, &output_listener, ostate); | ||
57 | list_add(reg->outputs, ostate); | ||
58 | } else if (strcmp(interface, desktop_shell_interface.name) == 0) { | ||
59 | reg->desktop_shell = wl_registry_bind(registry, name, &desktop_shell_interface, version); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) { | ||
64 | // this space intentionally left blank | ||
65 | } | ||
66 | |||
67 | static const struct wl_registry_listener registry_listener = { | ||
68 | .global = registry_global, | ||
69 | .global_remove = registry_global_remove | ||
70 | }; | ||
71 | |||
72 | struct registry *registry_poll(void) { | ||
73 | struct registry *registry = malloc(sizeof(struct registry)); | ||
74 | memset(registry, 0, sizeof(struct registry)); | ||
75 | registry->outputs = create_list(); | ||
76 | |||
77 | registry->display = wl_display_connect(NULL); | ||
78 | if (!registry->display) { | ||
79 | sway_log(L_ERROR, "Error opening display"); | ||
80 | registry_teardown(registry); | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | struct wl_registry *reg = wl_display_get_registry(registry->display); | ||
85 | wl_registry_add_listener(reg, ®istry_listener, registry); | ||
86 | wl_display_dispatch(registry->display); | ||
87 | wl_display_roundtrip(registry->display); | ||
88 | wl_registry_destroy(reg); | ||
89 | |||
90 | return registry; | ||
91 | } | ||
92 | |||
93 | void registry_teardown(struct registry *registry) { | ||
94 | if (registry->pointer) { | ||
95 | wl_pointer_destroy(registry->pointer); | ||
96 | } | ||
97 | if (registry->seat) { | ||
98 | wl_seat_destroy(registry->seat); | ||
99 | } | ||
100 | if (registry->shell) { | ||
101 | wl_shell_destroy(registry->shell); | ||
102 | } | ||
103 | if (registry->shm) { | ||
104 | wl_shm_destroy(registry->shm); | ||
105 | } | ||
106 | if (registry->compositor) { | ||
107 | wl_compositor_destroy(registry->compositor); | ||
108 | } | ||
109 | if (registry->display) { | ||
110 | wl_display_disconnect(registry->display); | ||
111 | } | ||
112 | if (registry->outputs) { | ||
113 | // TODO: Free the outputs themselves | ||
114 | list_free(registry->outputs); | ||
115 | } | ||
116 | } | ||
diff --git a/wayland/window.c b/wayland/window.c new file mode 100644 index 00000000..af50c04c --- /dev/null +++ b/wayland/window.c | |||
@@ -0,0 +1,123 @@ | |||
1 | #include <wayland-client.h> | ||
2 | #include <wayland-cursor.h> | ||
3 | #include "wayland-xdg-shell-client-protocol.h" | ||
4 | #include "wayland-desktop-shell-client-protocol.h" | ||
5 | #include <cairo/cairo.h> | ||
6 | #include <pango/pangocairo.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <string.h> | ||
9 | #include <stdio.h> | ||
10 | #include <unistd.h> | ||
11 | #include <errno.h> | ||
12 | #include <sys/mman.h> | ||
13 | #include "client/window.h" | ||
14 | #include "client/buffer.h" | ||
15 | #include "list.h" | ||
16 | #include "log.h" | ||
17 | |||
18 | static void pointer_handle_enter(void *data, struct wl_pointer *pointer, | ||
19 | uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) { | ||
20 | sway_log(L_INFO, "Set cursor"); | ||
21 | struct window *window = data; | ||
22 | struct wl_cursor_image *image = window->cursor.cursor->images[0]; | ||
23 | wl_pointer_set_cursor(pointer, serial, window->cursor.surface, image->hotspot_x, image->hotspot_y); | ||
24 | } | ||
25 | |||
26 | static void pointer_handle_leave(void *data, struct wl_pointer *pointer, | ||
27 | uint32_t serial, struct wl_surface *surface) { | ||
28 | } | ||
29 | |||
30 | static void pointer_handle_motion(void *data, struct wl_pointer *pointer, | ||
31 | uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) { | ||
32 | } | ||
33 | |||
34 | static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, | ||
35 | uint32_t time, uint32_t button, uint32_t state_w) { | ||
36 | } | ||
37 | |||
38 | static void pointer_handle_axis(void *data, struct wl_pointer *pointer, | ||
39 | uint32_t time, uint32_t axis, wl_fixed_t value) { | ||
40 | } | ||
41 | |||
42 | static const struct wl_pointer_listener pointer_listener = { | ||
43 | .enter = pointer_handle_enter, | ||
44 | .leave = pointer_handle_leave, | ||
45 | .motion = pointer_handle_motion, | ||
46 | .button = pointer_handle_button, | ||
47 | .axis = pointer_handle_axis | ||
48 | }; | ||
49 | |||
50 | void shell_surface_configure(void *data, struct wl_shell_surface *wl_shell_surface, | ||
51 | uint32_t edges, int32_t width, int32_t height) { | ||
52 | struct window *window = data; | ||
53 | window->width = width; | ||
54 | window->height = height; | ||
55 | } | ||
56 | |||
57 | static const struct wl_shell_surface_listener surface_listener = { | ||
58 | .configure = shell_surface_configure | ||
59 | }; | ||
60 | |||
61 | struct window *window_setup(struct registry *registry, uint32_t width, uint32_t height, bool shell_surface) { | ||
62 | struct window *window = malloc(sizeof(struct window)); | ||
63 | memset(window, 0, sizeof(struct window)); | ||
64 | window->width = width; | ||
65 | window->height = height; | ||
66 | window->registry = registry; | ||
67 | |||
68 | window->surface = wl_compositor_create_surface(registry->compositor); | ||
69 | if (shell_surface) { | ||
70 | window->shell_surface = wl_shell_get_shell_surface(registry->shell, window->surface); | ||
71 | wl_shell_surface_add_listener(window->shell_surface, &surface_listener, window); | ||
72 | wl_shell_surface_set_toplevel(window->shell_surface); | ||
73 | } | ||
74 | if (registry->pointer) { | ||
75 | sway_log(L_INFO, "Register pointer"); | ||
76 | wl_pointer_add_listener(registry->pointer, &pointer_listener, window); | ||
77 | } | ||
78 | |||
79 | window->cursor.cursor_theme = wl_cursor_theme_load("default", 32, registry->shm); // TODO: let you customize this | ||
80 | window->cursor.cursor = wl_cursor_theme_get_cursor(window->cursor.cursor_theme, "left_ptr"); | ||
81 | window->cursor.surface = wl_compositor_create_surface(registry->compositor); | ||
82 | |||
83 | struct wl_cursor_image *image = window->cursor.cursor->images[0]; | ||
84 | struct wl_buffer *cursor_buf = wl_cursor_image_get_buffer(image); | ||
85 | wl_surface_attach(window->cursor.surface, cursor_buf, 0, 0); | ||
86 | wl_surface_damage(window->cursor.surface, 0, 0, image->width, image->height); | ||
87 | wl_surface_commit(window->cursor.surface); | ||
88 | |||
89 | return window; | ||
90 | } | ||
91 | |||
92 | static void frame_callback(void *data, struct wl_callback *callback, uint32_t time) { | ||
93 | struct window *window = data; | ||
94 | wl_callback_destroy(callback); | ||
95 | window->frame_cb = NULL; | ||
96 | } | ||
97 | |||
98 | static const struct wl_callback_listener listener = { | ||
99 | frame_callback | ||
100 | }; | ||
101 | |||
102 | int window_prerender(struct window *window) { | ||
103 | if (window->frame_cb) { | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | get_next_buffer(window); | ||
108 | return 1; | ||
109 | } | ||
110 | |||
111 | int window_render(struct window *window) { | ||
112 | window->frame_cb = wl_surface_frame(window->surface); | ||
113 | wl_callback_add_listener(window->frame_cb, &listener, window); | ||
114 | |||
115 | wl_surface_damage(window->surface, 0, 0, window->buffer->width, window->buffer->height); | ||
116 | wl_surface_attach(window->surface, window->buffer->buffer, 0, 0); | ||
117 | wl_surface_commit(window->surface); | ||
118 | |||
119 | return 1; | ||
120 | } | ||
121 | |||
122 | void window_teardown(struct window *window) { | ||
123 | } | ||