diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-10-22 10:37:30 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2017-11-11 09:08:50 -0500 |
commit | 7c448b408126aef0561be0761871f968921d7db0 (patch) | |
tree | 055716519b975eca17b2e27254217acd1b801c20 | |
parent | Find and link to wlroots (diff) | |
download | sway-7c448b408126aef0561be0761871f968921d7db0.tar.gz sway-7c448b408126aef0561be0761871f968921d7db0.tar.zst sway-7c448b408126aef0561be0761871f968921d7db0.zip |
Fire up the wlroots backend and run the event loop
-rw-r--r-- | include/sway/extensions.h | 56 | ||||
-rw-r--r-- | include/sway/server.h | 31 | ||||
-rw-r--r-- | sway/CMakeLists.txt | 3 | ||||
-rw-r--r-- | sway/commands.c | 2 | ||||
-rw-r--r-- | sway/extensions.c | 407 | ||||
-rw-r--r-- | sway/focus.c | 3 | ||||
-rw-r--r-- | sway/ipc-server.c | 389 | ||||
-rw-r--r-- | sway/layout.c | 5 | ||||
-rw-r--r-- | sway/main.c | 113 | ||||
-rw-r--r-- | sway/server.c | 54 | ||||
-rw-r--r-- | sway/workspace.c | 1 |
11 files changed, 160 insertions, 904 deletions
diff --git a/include/sway/extensions.h b/include/sway/extensions.h deleted file mode 100644 index 5212eb3a..00000000 --- a/include/sway/extensions.h +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | #ifndef _SWAY_EXTENSIONS_H | ||
2 | #define _SWAY_EXTENSIONS_H | ||
3 | |||
4 | #include <wayland-server.h> | ||
5 | #include <wlc/wlc-wayland.h> | ||
6 | #include "wayland-desktop-shell-server-protocol.h" | ||
7 | #include "list.h" | ||
8 | |||
9 | struct background_config { | ||
10 | wlc_handle output; | ||
11 | wlc_resource surface; | ||
12 | // we need the wl_resource of the surface in the destructor | ||
13 | struct wl_resource *wl_surface_res; | ||
14 | struct wl_client *client; | ||
15 | wlc_handle handle; | ||
16 | }; | ||
17 | |||
18 | struct panel_config { | ||
19 | // wayland resource used in callbacks, is used to track this panel | ||
20 | struct wl_resource *wl_resource; | ||
21 | wlc_handle output; | ||
22 | wlc_resource surface; | ||
23 | // we need the wl_resource of the surface in the destructor | ||
24 | struct wl_resource *wl_surface_res; | ||
25 | enum desktop_shell_panel_position panel_position; | ||
26 | // used to determine if client is a panel | ||
27 | struct wl_client *client; | ||
28 | // wlc handle for this panel's surface, not set until panel is created | ||
29 | wlc_handle handle; | ||
30 | }; | ||
31 | |||
32 | struct desktop_shell_state { | ||
33 | list_t *backgrounds; | ||
34 | list_t *panels; | ||
35 | list_t *lock_surfaces; | ||
36 | bool is_locked; | ||
37 | }; | ||
38 | |||
39 | struct swaylock_state { | ||
40 | bool active; | ||
41 | wlc_handle output; | ||
42 | wlc_resource surface; | ||
43 | }; | ||
44 | |||
45 | struct decoration_state { | ||
46 | list_t *csd_resources; | ||
47 | }; | ||
48 | |||
49 | extern struct desktop_shell_state desktop_shell; | ||
50 | extern struct decoration_state decoration_state; | ||
51 | |||
52 | void register_extensions(void); | ||
53 | |||
54 | void server_decoration_enable_csd(wlc_handle handle); | ||
55 | |||
56 | #endif | ||
diff --git a/include/sway/server.h b/include/sway/server.h new file mode 100644 index 00000000..471a0270 --- /dev/null +++ b/include/sway/server.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #ifndef _SWAY_SERVER_H | ||
2 | #define _SWAY_SERVER_H | ||
3 | #include <stdbool.h> | ||
4 | #include <wayland-server.h> | ||
5 | #include <wlr/backend.h> | ||
6 | #include <wlr/backend/session.h> | ||
7 | #include <wlr/types/wlr_data_device_manager.h> | ||
8 | #include <wlr/render.h> | ||
9 | // TODO WLR: make Xwayland optional | ||
10 | #include <wlr/xwayland.h> | ||
11 | |||
12 | struct sway_server { | ||
13 | // TODO WLR | ||
14 | //struct roots_desktop *desktop; | ||
15 | //struct roots_input *input; | ||
16 | |||
17 | struct wl_display *wl_display; | ||
18 | struct wl_event_loop *wl_event_loop; | ||
19 | |||
20 | struct wlr_backend *backend; | ||
21 | struct wlr_renderer *renderer; | ||
22 | |||
23 | struct wlr_data_device_manager *data_device_manager; | ||
24 | }; | ||
25 | |||
26 | bool server_init(struct sway_server *server); | ||
27 | void server_fini(struct sway_server *server); | ||
28 | |||
29 | struct sway_server server; | ||
30 | |||
31 | #endif | ||
diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 67af0f70..ac0530e5 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt | |||
@@ -25,9 +25,7 @@ add_executable(sway | |||
25 | container.c | 25 | container.c |
26 | criteria.c | 26 | criteria.c |
27 | debug_log.c | 27 | debug_log.c |
28 | extensions.c | ||
29 | focus.c | 28 | focus.c |
30 | handlers.c | ||
31 | input.c | 29 | input.c |
32 | input_state.c | 30 | input_state.c |
33 | ipc-json.c | 31 | ipc-json.c |
@@ -38,6 +36,7 @@ add_executable(sway | |||
38 | workspace.c | 36 | workspace.c |
39 | border.c | 37 | border.c |
40 | security.c | 38 | security.c |
39 | server.c | ||
41 | ) | 40 | ) |
42 | 41 | ||
43 | add_definitions( | 42 | add_definitions( |
diff --git a/sway/commands.c b/sway/commands.c index c7dbf731..e1181893 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -120,6 +120,7 @@ void input_cmd_apply(struct input_config *input) { | |||
120 | // Try to find the input device and apply configuration now. If | 120 | // Try to find the input device and apply configuration now. If |
121 | // this is during startup then there will be no container and config | 121 | // this is during startup then there will be no container and config |
122 | // will be applied during normal "new input" event from wlc. | 122 | // will be applied during normal "new input" event from wlc. |
123 | /* TODO WLR | ||
123 | struct libinput_device *device = NULL; | 124 | struct libinput_device *device = NULL; |
124 | for (int i = 0; i < input_devices->length; ++i) { | 125 | for (int i = 0; i < input_devices->length; ++i) { |
125 | device = input_devices->items[i]; | 126 | device = input_devices->items[i]; |
@@ -134,6 +135,7 @@ void input_cmd_apply(struct input_config *input) { | |||
134 | break; | 135 | break; |
135 | } | 136 | } |
136 | } | 137 | } |
138 | */ | ||
137 | } | 139 | } |
138 | } | 140 | } |
139 | 141 | ||
diff --git a/sway/extensions.c b/sway/extensions.c deleted file mode 100644 index 91746561..00000000 --- a/sway/extensions.c +++ /dev/null | |||
@@ -1,407 +0,0 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <wlc/wlc.h> | ||
3 | #include <wlc/wlc-wayland.h> | ||
4 | #include <wlc/wlc-render.h> | ||
5 | #include "wayland-desktop-shell-server-protocol.h" | ||
6 | #include "wayland-swaylock-server-protocol.h" | ||
7 | #include "wayland-gamma-control-server-protocol.h" | ||
8 | #include "wayland-server-decoration-server-protocol.h" | ||
9 | #include "sway/layout.h" | ||
10 | #include "sway/input_state.h" | ||
11 | #include "sway/extensions.h" | ||
12 | #include "sway/security.h" | ||
13 | #include "sway/ipc-server.h" | ||
14 | #include "log.h" | ||
15 | |||
16 | struct desktop_shell_state desktop_shell; | ||
17 | struct decoration_state decoration_state; | ||
18 | |||
19 | static struct panel_config *find_or_create_panel_config(struct wl_resource *resource) { | ||
20 | for (int i = 0; i < desktop_shell.panels->length; i++) { | ||
21 | struct panel_config *conf = desktop_shell.panels->items[i]; | ||
22 | if (conf->wl_resource == resource) { | ||
23 | sway_log(L_DEBUG, "Found existing panel config for resource %p", resource); | ||
24 | return conf; | ||
25 | } | ||
26 | } | ||
27 | sway_log(L_DEBUG, "Creating panel config for resource %p", resource); | ||
28 | struct panel_config *config = calloc(1, sizeof(struct panel_config)); | ||
29 | if (!config) { | ||
30 | sway_log(L_ERROR, "Unable to create panel config"); | ||
31 | return NULL; | ||
32 | } | ||
33 | list_add(desktop_shell.panels, config); | ||
34 | config->wl_resource = resource; | ||
35 | return config; | ||
36 | } | ||
37 | |||
38 | void background_surface_destructor(struct wl_resource *resource) { | ||
39 | sway_log(L_DEBUG, "Background surface killed"); | ||
40 | int i; | ||
41 | for (i = 0; i < desktop_shell.backgrounds->length; ++i) { | ||
42 | struct background_config *config = desktop_shell.backgrounds->items[i]; | ||
43 | if (config->wl_surface_res == resource) { | ||
44 | list_del(desktop_shell.backgrounds, i); | ||
45 | break; | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | |||
50 | void panel_surface_destructor(struct wl_resource *resource) { | ||
51 | sway_log(L_DEBUG, "Panel surface killed"); | ||
52 | int i; | ||
53 | for (i = 0; i < desktop_shell.panels->length; ++i) { | ||
54 | struct panel_config *config = desktop_shell.panels->items[i]; | ||
55 | if (config->wl_surface_res == resource) { | ||
56 | list_del(desktop_shell.panels, i); | ||
57 | arrange_windows(&root_container, -1, -1); | ||
58 | break; | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
63 | void lock_surface_destructor(struct wl_resource *resource) { | ||
64 | sway_log(L_DEBUG, "Lock surface killed"); | ||
65 | int i; | ||
66 | for (i = 0; i < desktop_shell.lock_surfaces->length; ++i) { | ||
67 | struct wl_resource *surface = desktop_shell.lock_surfaces->items[i]; | ||
68 | if (surface == resource) { | ||
69 | list_del(desktop_shell.lock_surfaces, i); | ||
70 | arrange_windows(&root_container, -1, -1); | ||
71 | break; | ||
72 | } | ||
73 | } | ||
74 | if (desktop_shell.lock_surfaces->length == 0) { | ||
75 | sway_log(L_DEBUG, "Desktop shell unlocked"); | ||
76 | desktop_shell.is_locked = false; | ||
77 | |||
78 | // We need to now give focus back to the focus which we internally | ||
79 | // track, since when we lock sway we don't actually change our internal | ||
80 | // focus tracking. | ||
81 | swayc_t *focus = get_focused_container(swayc_active_workspace()); | ||
82 | set_focused_container(focus); | ||
83 | wlc_view_focus(focus->handle); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | static void set_background(struct wl_client *client, struct wl_resource *resource, | ||
88 | struct wl_resource *_output, struct wl_resource *surface) { | ||
89 | pid_t pid; | ||
90 | wl_client_get_credentials(client, &pid, NULL, NULL); | ||
91 | if (!(get_feature_policy_mask(pid) & FEATURE_BACKGROUND)) { | ||
92 | sway_log(L_INFO, "Denying background feature to %d", pid); | ||
93 | return; | ||
94 | } | ||
95 | wlc_handle output = wlc_handle_from_wl_output_resource(_output); | ||
96 | if (!output) { | ||
97 | return; | ||
98 | } | ||
99 | sway_log(L_DEBUG, "Setting surface %p as background for output %d", surface, (int)output); | ||
100 | struct background_config *config = malloc(sizeof(struct background_config)); | ||
101 | if (!config) { | ||
102 | sway_log(L_ERROR, "Unable to allocate background config"); | ||
103 | return; | ||
104 | } | ||
105 | config->client = client; | ||
106 | config->output = output; | ||
107 | config->surface = wlc_resource_from_wl_surface_resource(surface); | ||
108 | config->wl_surface_res = surface; | ||
109 | list_add(desktop_shell.backgrounds, config); | ||
110 | wl_resource_set_destructor(surface, background_surface_destructor); | ||
111 | arrange_windows(swayc_by_handle(output), -1, -1); | ||
112 | wlc_output_schedule_render(config->output); | ||
113 | } | ||
114 | |||
115 | static void set_panel(struct wl_client *client, struct wl_resource *resource, | ||
116 | struct wl_resource *_output, struct wl_resource *surface) { | ||
117 | pid_t pid; | ||
118 | wl_client_get_credentials(client, &pid, NULL, NULL); | ||
119 | if (!(get_feature_policy_mask(pid) & FEATURE_PANEL)) { | ||
120 | sway_log(L_INFO, "Denying panel feature to %d", pid); | ||
121 | return; | ||
122 | } | ||
123 | wlc_handle output = wlc_handle_from_wl_output_resource(_output); | ||
124 | if (!output) { | ||
125 | return; | ||
126 | } | ||
127 | sway_log(L_DEBUG, "Setting surface %p as panel for output %d (wl_resource: %p)", surface, (int)output, resource); | ||
128 | struct panel_config *config = find_or_create_panel_config(resource); | ||
129 | config->output = output; | ||
130 | config->client = client; | ||
131 | config->surface = wlc_resource_from_wl_surface_resource(surface); | ||
132 | config->wl_surface_res = surface; | ||
133 | wl_resource_set_destructor(surface, panel_surface_destructor); | ||
134 | arrange_windows(&root_container, -1, -1); | ||
135 | wlc_output_schedule_render(config->output); | ||
136 | } | ||
137 | |||
138 | static void desktop_set_lock_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface) { | ||
139 | sway_log(L_ERROR, "desktop_set_lock_surface is not currently supported"); | ||
140 | } | ||
141 | |||
142 | static void desktop_unlock(struct wl_client *client, struct wl_resource *resource) { | ||
143 | sway_log(L_ERROR, "desktop_unlock is not currently supported"); | ||
144 | } | ||
145 | |||
146 | static void set_grab_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface) { | ||
147 | sway_log(L_ERROR, "desktop_set_grab_surface is not currently supported"); | ||
148 | } | ||
149 | |||
150 | static void desktop_ready(struct wl_client *client, struct wl_resource *resource) { | ||
151 | // nop | ||
152 | } | ||
153 | |||
154 | static void set_panel_position(struct wl_client *client, struct wl_resource *resource, uint32_t position) { | ||
155 | pid_t pid; | ||
156 | wl_client_get_credentials(client, &pid, NULL, NULL); | ||
157 | if (!(get_feature_policy_mask(pid) & FEATURE_PANEL)) { | ||
158 | sway_log(L_INFO, "Denying panel feature to %d", pid); | ||
159 | return; | ||
160 | } | ||
161 | struct panel_config *config = find_or_create_panel_config(resource); | ||
162 | sway_log(L_DEBUG, "Panel position for wl_resource %p changed %d => %d", resource, config->panel_position, position); | ||
163 | config->panel_position = position; | ||
164 | arrange_windows(&root_container, -1, -1); | ||
165 | } | ||
166 | |||
167 | static struct desktop_shell_interface desktop_shell_implementation = { | ||
168 | .set_background = set_background, | ||
169 | .set_panel = set_panel, | ||
170 | .set_lock_surface = desktop_set_lock_surface, | ||
171 | .unlock = desktop_unlock, | ||
172 | .set_grab_surface = set_grab_surface, | ||
173 | .desktop_ready = desktop_ready, | ||
174 | .set_panel_position = set_panel_position | ||
175 | }; | ||
176 | |||
177 | static void desktop_shell_bind(struct wl_client *client, void *data, | ||
178 | uint32_t version, uint32_t id) { | ||
179 | if (version > 3) { | ||
180 | // Unsupported version | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | struct wl_resource *resource = wl_resource_create(client, &desktop_shell_interface, version, id); | ||
185 | if (!resource) { | ||
186 | wl_client_post_no_memory(client); | ||
187 | } | ||
188 | |||
189 | wl_resource_set_implementation(resource, &desktop_shell_implementation, NULL, NULL); | ||
190 | } | ||
191 | |||
192 | static void set_lock_surface(struct wl_client *client, struct wl_resource *resource, | ||
193 | struct wl_resource *_output, struct wl_resource *surface) { | ||
194 | pid_t pid; | ||
195 | wl_client_get_credentials(client, &pid, NULL, NULL); | ||
196 | if (!(get_feature_policy_mask(pid) & FEATURE_LOCK)) { | ||
197 | sway_log(L_INFO, "Denying lock feature to %d", pid); | ||
198 | return; | ||
199 | } | ||
200 | swayc_t *output = swayc_by_handle(wlc_handle_from_wl_output_resource(_output)); | ||
201 | swayc_t *view = swayc_by_handle(wlc_handle_from_wl_surface_resource(surface)); | ||
202 | sway_log(L_DEBUG, "Setting lock surface to %p", view); | ||
203 | if (view && output) { | ||
204 | swayc_t *workspace = output->focused; | ||
205 | if (!swayc_is_child_of(view, workspace)) { | ||
206 | move_container_to(view, workspace); | ||
207 | } | ||
208 | // make the view floating so it doesn't rearrange other siblings. | ||
209 | if (!view->is_floating) { | ||
210 | destroy_container(remove_child(view)); | ||
211 | add_floating(workspace, view); | ||
212 | } | ||
213 | wlc_view_set_state(view->handle, WLC_BIT_FULLSCREEN, true); | ||
214 | wlc_view_bring_to_front(view->handle); | ||
215 | wlc_view_focus(view->handle); | ||
216 | desktop_shell.is_locked = true; | ||
217 | input_init(); | ||
218 | arrange_windows(workspace, -1, -1); | ||
219 | list_add(desktop_shell.lock_surfaces, surface); | ||
220 | wl_resource_set_destructor(surface, lock_surface_destructor); | ||
221 | } else { | ||
222 | sway_log(L_ERROR, "Attempted to set lock surface to non-view"); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static void unlock(struct wl_client *client, struct wl_resource *resource) { | ||
227 | sway_log(L_ERROR, "unlock is not currently supported"); | ||
228 | // This isn't really necessary, we just unlock when the client exits. | ||
229 | } | ||
230 | |||
231 | static struct lock_interface swaylock_implementation = { | ||
232 | .set_lock_surface = set_lock_surface, | ||
233 | .unlock = unlock | ||
234 | }; | ||
235 | |||
236 | static void swaylock_bind(struct wl_client *client, void *data, | ||
237 | uint32_t version, uint32_t id) { | ||
238 | if (version > 1) { | ||
239 | // Unsupported version | ||
240 | return; | ||
241 | } | ||
242 | |||
243 | struct wl_resource *resource = wl_resource_create(client, &lock_interface, version, id); | ||
244 | if (!resource) { | ||
245 | wl_client_post_no_memory(client); | ||
246 | } | ||
247 | |||
248 | wl_resource_set_implementation(resource, &swaylock_implementation, NULL, NULL); | ||
249 | } | ||
250 | |||
251 | static void gamma_control_destroy(struct wl_client *client, struct wl_resource *res) { | ||
252 | wl_resource_destroy(res); | ||
253 | } | ||
254 | |||
255 | static void gamma_control_set_gamma(struct wl_client *client, | ||
256 | struct wl_resource *res, struct wl_array *red, | ||
257 | struct wl_array *green, struct wl_array *blue) { | ||
258 | if (red->size != green->size || red->size != blue->size) { | ||
259 | wl_resource_post_error(res, GAMMA_CONTROL_ERROR_INVALID_GAMMA, | ||
260 | "The gamma ramps don't have the same size"); | ||
261 | return; | ||
262 | } | ||
263 | uint16_t *r = (uint16_t *)red->data; | ||
264 | uint16_t *g = (uint16_t *)green->data; | ||
265 | uint16_t *b = (uint16_t *)blue->data; | ||
266 | wlc_handle output = wlc_handle_from_wl_output_resource( | ||
267 | wl_resource_get_user_data(res)); | ||
268 | if (!output) { | ||
269 | return; | ||
270 | } | ||
271 | sway_log(L_DEBUG, "Setting gamma for output"); | ||
272 | wlc_output_set_gamma(output, red->size / sizeof(uint16_t), r, g, b); | ||
273 | } | ||
274 | |||
275 | static void gamma_control_reset_gamma(struct wl_client *client, | ||
276 | struct wl_resource *resource) { | ||
277 | // This space intentionally left blank | ||
278 | } | ||
279 | |||
280 | static struct gamma_control_interface gamma_control_implementation = { | ||
281 | .destroy = gamma_control_destroy, | ||
282 | .set_gamma = gamma_control_set_gamma, | ||
283 | .reset_gamma = gamma_control_reset_gamma | ||
284 | }; | ||
285 | |||
286 | static void gamma_control_manager_destroy(struct wl_client *client, | ||
287 | struct wl_resource *res) { | ||
288 | wl_resource_destroy(res); | ||
289 | } | ||
290 | |||
291 | static void gamma_control_manager_get(struct wl_client *client, | ||
292 | struct wl_resource *res, uint32_t id, struct wl_resource *_output) { | ||
293 | struct wl_resource *manager_res = wl_resource_create(client, | ||
294 | &gamma_control_interface, wl_resource_get_version(res), id); | ||
295 | wlc_handle output = wlc_handle_from_wl_output_resource(_output); | ||
296 | if (!output) { | ||
297 | return; | ||
298 | } | ||
299 | wl_resource_set_implementation(manager_res, &gamma_control_implementation, | ||
300 | _output, NULL); | ||
301 | gamma_control_send_gamma_size(manager_res, wlc_output_get_gamma_size(output)); | ||
302 | } | ||
303 | |||
304 | static struct gamma_control_manager_interface gamma_manager_implementation = { | ||
305 | .destroy = gamma_control_manager_destroy, | ||
306 | .get_gamma_control = gamma_control_manager_get | ||
307 | }; | ||
308 | |||
309 | static void gamma_control_manager_bind(struct wl_client *client, void *data, | ||
310 | uint32_t version, uint32_t id) { | ||
311 | if (version > 1) { | ||
312 | // Unsupported version | ||
313 | return; | ||
314 | } | ||
315 | struct wl_resource *resource = wl_resource_create(client, | ||
316 | &gamma_control_manager_interface, version, id); | ||
317 | if (!resource) { | ||
318 | wl_client_post_no_memory(client); | ||
319 | } | ||
320 | wl_resource_set_implementation(resource, &gamma_manager_implementation, NULL, NULL); | ||
321 | } | ||
322 | |||
323 | static void server_decoration_release(struct wl_client *client, | ||
324 | struct wl_resource *resource) { | ||
325 | wl_resource_destroy(resource); | ||
326 | } | ||
327 | |||
328 | void server_decoration_enable_csd(wlc_handle handle) { | ||
329 | swayc_t *view = swayc_by_handle(handle); | ||
330 | if (!view) { | ||
331 | sway_log(L_DEBUG, "view invalid"); | ||
332 | return; | ||
333 | } | ||
334 | sway_log(L_DEBUG, "%s requested client side decorations", view->name); | ||
335 | view->border_type = B_NONE; | ||
336 | update_geometry(view); | ||
337 | } | ||
338 | |||
339 | static void server_decoration_request_mode(struct wl_client *client, | ||
340 | struct wl_resource *resource, uint32_t mode) { | ||
341 | sway_log(L_DEBUG, "Client requested server decoration mode %d", mode); | ||
342 | if (mode == ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER) { | ||
343 | return; | ||
344 | } | ||
345 | struct wl_resource *surface = wl_resource_get_user_data(resource); | ||
346 | if (!surface) { | ||
347 | sway_log(L_DEBUG, "surface invalid"); | ||
348 | return; | ||
349 | } | ||
350 | wlc_handle handle = wlc_handle_from_wl_surface_resource(surface); | ||
351 | if (!handle) { | ||
352 | list_add(decoration_state.csd_resources, surface); | ||
353 | return; | ||
354 | } | ||
355 | server_decoration_enable_csd(handle); | ||
356 | } | ||
357 | |||
358 | static struct org_kde_kwin_server_decoration_interface server_decoration_implementation = { | ||
359 | .release = server_decoration_release, | ||
360 | .request_mode = server_decoration_request_mode, | ||
361 | }; | ||
362 | |||
363 | static void server_decoration_manager_create(struct wl_client *client, | ||
364 | struct wl_resource *resource, uint32_t id, struct wl_resource *surface) { | ||
365 | sway_log(L_DEBUG, "Client requested server decoration manager"); | ||
366 | struct wl_resource *manager = wl_resource_create(client, | ||
367 | &org_kde_kwin_server_decoration_interface, 1, id); | ||
368 | if (!manager) { | ||
369 | wl_client_post_no_memory(client); | ||
370 | } | ||
371 | wl_resource_set_implementation(manager, &server_decoration_implementation, surface, NULL); | ||
372 | } | ||
373 | |||
374 | // Jesus christ KDE, these names are whack as hell | ||
375 | static struct org_kde_kwin_server_decoration_manager_interface server_decoration_manager_implementation = { | ||
376 | .create = server_decoration_manager_create, | ||
377 | }; | ||
378 | |||
379 | static void server_decoration_manager_bind(struct wl_client *client, void *data, | ||
380 | uint32_t version, uint32_t id) { | ||
381 | if (version > 1) { | ||
382 | // Unsupported version | ||
383 | return; | ||
384 | } | ||
385 | struct wl_resource *resource = wl_resource_create(client, | ||
386 | &org_kde_kwin_server_decoration_manager_interface, version, id); | ||
387 | if (!resource) { | ||
388 | wl_client_post_no_memory(client); | ||
389 | } | ||
390 | wl_resource_set_implementation(resource, &server_decoration_manager_implementation, NULL, NULL); | ||
391 | org_kde_kwin_server_decoration_manager_send_default_mode(resource, | ||
392 | ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER); | ||
393 | } | ||
394 | |||
395 | void register_extensions(void) { | ||
396 | wl_global_create(wlc_get_wl_display(), &desktop_shell_interface, 3, NULL, desktop_shell_bind); | ||
397 | desktop_shell.backgrounds = create_list(); | ||
398 | desktop_shell.panels = create_list(); | ||
399 | desktop_shell.lock_surfaces = create_list(); | ||
400 | desktop_shell.is_locked = false; | ||
401 | decoration_state.csd_resources = create_list(); | ||
402 | wl_global_create(wlc_get_wl_display(), &lock_interface, 1, NULL, swaylock_bind); | ||
403 | wl_global_create(wlc_get_wl_display(), &gamma_control_manager_interface, 1, | ||
404 | NULL, gamma_control_manager_bind); | ||
405 | wl_global_create(wlc_get_wl_display(), &org_kde_kwin_server_decoration_manager_interface , | ||
406 | 1, NULL, server_decoration_manager_bind); | ||
407 | } | ||
diff --git a/sway/focus.c b/sway/focus.c index e9b032f8..66f7ee17 100644 --- a/sway/focus.c +++ b/sway/focus.c | |||
@@ -4,7 +4,6 @@ | |||
4 | #include "sway/workspace.h" | 4 | #include "sway/workspace.h" |
5 | #include "sway/layout.h" | 5 | #include "sway/layout.h" |
6 | #include "sway/config.h" | 6 | #include "sway/config.h" |
7 | #include "sway/extensions.h" | ||
8 | #include "sway/input_state.h" | 7 | #include "sway/input_state.h" |
9 | #include "sway/ipc-server.h" | 8 | #include "sway/ipc-server.h" |
10 | #include "sway/border.h" | 9 | #include "sway/border.h" |
@@ -163,12 +162,14 @@ bool set_focused_container(swayc_t *c) { | |||
163 | if (c->type == C_VIEW) { | 162 | if (c->type == C_VIEW) { |
164 | wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true); | 163 | wlc_view_set_state(c->handle, WLC_BIT_ACTIVATED, true); |
165 | } | 164 | } |
165 | /* TODO WLR | ||
166 | if (!desktop_shell.is_locked) { | 166 | if (!desktop_shell.is_locked) { |
167 | // If the system is locked, we do everything _but_ actually setting | 167 | // If the system is locked, we do everything _but_ actually setting |
168 | // focus. This includes making our internals think that this view is | 168 | // focus. This includes making our internals think that this view is |
169 | // focused. | 169 | // focused. |
170 | wlc_view_focus(c->handle); | 170 | wlc_view_focus(c->handle); |
171 | } | 171 | } |
172 | */ | ||
172 | if (c->parent->layout != L_TABBED && c->parent->layout != L_STACKED) { | 173 | if (c->parent->layout != L_TABBED && c->parent->layout != L_STACKED) { |
173 | update_container_border(c); | 174 | update_container_border(c); |
174 | } | 175 | } |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index b560b930..9ba736d8 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <sys/socket.h> | 10 | #include <sys/socket.h> |
11 | #include <sys/un.h> | 11 | #include <sys/un.h> |
12 | #include <stdbool.h> | 12 | #include <stdbool.h> |
13 | #include <wlc/wlc-render.h> | ||
14 | #include <unistd.h> | 13 | #include <unistd.h> |
15 | #include <stdlib.h> | 14 | #include <stdlib.h> |
16 | #include <sys/ioctl.h> | 15 | #include <sys/ioctl.h> |
@@ -31,21 +30,22 @@ struct ucred { | |||
31 | #include "sway/config.h" | 30 | #include "sway/config.h" |
32 | #include "sway/commands.h" | 31 | #include "sway/commands.h" |
33 | #include "sway/input.h" | 32 | #include "sway/input.h" |
33 | #include "sway/server.h" | ||
34 | #include "stringop.h" | 34 | #include "stringop.h" |
35 | #include "log.h" | 35 | #include "log.h" |
36 | #include "list.h" | 36 | #include "list.h" |
37 | #include "util.h" | 37 | #include "util.h" |
38 | 38 | ||
39 | static int ipc_socket = -1; | 39 | static int ipc_socket = -1; |
40 | static struct wlc_event_source *ipc_event_source = NULL; | 40 | static struct wl_event_source *ipc_event_source = NULL; |
41 | static struct sockaddr_un *ipc_sockaddr = NULL; | 41 | static struct sockaddr_un *ipc_sockaddr = NULL; |
42 | static list_t *ipc_client_list = NULL; | 42 | static list_t *ipc_client_list = NULL; |
43 | 43 | ||
44 | static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; | 44 | static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; |
45 | 45 | ||
46 | struct ipc_client { | 46 | struct ipc_client { |
47 | struct wlc_event_source *event_source; | 47 | struct wl_event_source *event_source; |
48 | struct wlc_event_source *writable_event_source; | 48 | struct wl_event_source *writable_event_source; |
49 | int fd; | 49 | int fd; |
50 | uint32_t payload_length; | 50 | uint32_t payload_length; |
51 | uint32_t security_policy; | 51 | uint32_t security_policy; |
@@ -58,25 +58,6 @@ struct ipc_client { | |||
58 | 58 | ||
59 | static list_t *ipc_get_pixel_requests = NULL; | 59 | static list_t *ipc_get_pixel_requests = NULL; |
60 | 60 | ||
61 | struct get_pixels_request { | ||
62 | struct ipc_client *client; | ||
63 | wlc_handle output; | ||
64 | struct wlc_geometry geo; | ||
65 | }; | ||
66 | |||
67 | struct get_clipboard_request { | ||
68 | struct ipc_client *client; | ||
69 | json_object *json; | ||
70 | int fd; | ||
71 | struct wlc_event_source *fd_event_source; | ||
72 | struct wlc_event_source *timer_event_source; | ||
73 | char *type; | ||
74 | unsigned int *pending; | ||
75 | char *buf; | ||
76 | size_t buf_size; | ||
77 | size_t buf_position; | ||
78 | }; | ||
79 | |||
80 | struct sockaddr_un *ipc_user_sockaddr(void); | 61 | struct sockaddr_un *ipc_user_sockaddr(void); |
81 | int ipc_handle_connection(int fd, uint32_t mask, void *data); | 62 | int ipc_handle_connection(int fd, uint32_t mask, void *data); |
82 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); | 63 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); |
@@ -118,12 +99,13 @@ void ipc_init(void) { | |||
118 | ipc_client_list = create_list(); | 99 | ipc_client_list = create_list(); |
119 | ipc_get_pixel_requests = create_list(); | 100 | ipc_get_pixel_requests = create_list(); |
120 | 101 | ||
121 | ipc_event_source = wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL); | 102 | ipc_event_source = wl_event_loop_add_fd(server.wl_event_loop, ipc_socket, |
103 | WL_EVENT_READABLE, ipc_handle_connection, NULL); | ||
122 | } | 104 | } |
123 | 105 | ||
124 | void ipc_terminate(void) { | 106 | void ipc_terminate(void) { |
125 | if (ipc_event_source) { | 107 | if (ipc_event_source) { |
126 | wlc_event_source_remove(ipc_event_source); | 108 | wl_event_source_remove(ipc_event_source); |
127 | } | 109 | } |
128 | close(ipc_socket); | 110 | close(ipc_socket); |
129 | unlink(ipc_sockaddr->sun_path); | 111 | unlink(ipc_sockaddr->sun_path); |
@@ -176,7 +158,7 @@ static pid_t get_client_pid(int client_fd) { | |||
176 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { | 158 | int ipc_handle_connection(int fd, uint32_t mask, void *data) { |
177 | (void) fd; (void) data; | 159 | (void) fd; (void) data; |
178 | sway_log(L_DEBUG, "Event on IPC listening socket"); | 160 | sway_log(L_DEBUG, "Event on IPC listening socket"); |
179 | assert(mask == WLC_EVENT_READABLE); | 161 | assert(mask == WL_EVENT_READABLE); |
180 | 162 | ||
181 | int client_fd = accept(ipc_socket, NULL, NULL); | 163 | int client_fd = accept(ipc_socket, NULL, NULL); |
182 | if (client_fd == -1) { | 164 | if (client_fd == -1) { |
@@ -207,7 +189,8 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { | |||
207 | client->payload_length = 0; | 189 | client->payload_length = 0; |
208 | client->fd = client_fd; | 190 | client->fd = client_fd; |
209 | client->subscribed_events = 0; | 191 | client->subscribed_events = 0; |
210 | client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); | 192 | client->event_source = wl_event_loop_add_fd(server.wl_event_loop, client_fd, |
193 | WL_EVENT_READABLE, ipc_client_handle_readable, client); | ||
211 | client->writable_event_source = NULL; | 194 | client->writable_event_source = NULL; |
212 | 195 | ||
213 | client->write_buffer_size = 128; | 196 | client->write_buffer_size = 128; |
@@ -234,13 +217,13 @@ static const int ipc_header_size = sizeof(ipc_magic)+8; | |||
234 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | 217 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { |
235 | struct ipc_client *client = data; | 218 | struct ipc_client *client = data; |
236 | 219 | ||
237 | if (mask & WLC_EVENT_ERROR) { | 220 | if (mask & WL_EVENT_ERROR) { |
238 | sway_log(L_ERROR, "IPC Client socket error, removing client"); | 221 | sway_log(L_ERROR, "IPC Client socket error, removing client"); |
239 | ipc_client_disconnect(client); | 222 | ipc_client_disconnect(client); |
240 | return 0; | 223 | return 0; |
241 | } | 224 | } |
242 | 225 | ||
243 | if (mask & WLC_EVENT_HANGUP) { | 226 | if (mask & WL_EVENT_HANGUP) { |
244 | sway_log(L_DEBUG, "Client %d hung up", client->fd); | 227 | sway_log(L_DEBUG, "Client %d hung up", client->fd); |
245 | ipc_client_disconnect(client); | 228 | ipc_client_disconnect(client); |
246 | return 0; | 229 | return 0; |
@@ -296,13 +279,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | |||
296 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | 279 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { |
297 | struct ipc_client *client = data; | 280 | struct ipc_client *client = data; |
298 | 281 | ||
299 | if (mask & WLC_EVENT_ERROR) { | 282 | if (mask & WL_EVENT_ERROR) { |
300 | sway_log(L_ERROR, "IPC Client socket error, removing client"); | 283 | sway_log(L_ERROR, "IPC Client socket error, removing client"); |
301 | ipc_client_disconnect(client); | 284 | ipc_client_disconnect(client); |
302 | return 0; | 285 | return 0; |
303 | } | 286 | } |
304 | 287 | ||
305 | if (mask & WLC_EVENT_HANGUP) { | 288 | if (mask & WL_EVENT_HANGUP) { |
306 | sway_log(L_DEBUG, "Client %d hung up", client->fd); | 289 | sway_log(L_DEBUG, "Client %d hung up", client->fd); |
307 | ipc_client_disconnect(client); | 290 | ipc_client_disconnect(client); |
308 | return 0; | 291 | return 0; |
@@ -328,7 +311,7 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { | |||
328 | client->write_buffer_len -= written; | 311 | client->write_buffer_len -= written; |
329 | 312 | ||
330 | if (client->write_buffer_len == 0 && client->writable_event_source) { | 313 | if (client->write_buffer_len == 0 && client->writable_event_source) { |
331 | wlc_event_source_remove(client->writable_event_source); | 314 | wl_event_source_remove(client->writable_event_source); |
332 | client->writable_event_source = NULL; | 315 | client->writable_event_source = NULL; |
333 | } | 316 | } |
334 | 317 | ||
@@ -345,9 +328,9 @@ void ipc_client_disconnect(struct ipc_client *client) { | |||
345 | } | 328 | } |
346 | 329 | ||
347 | sway_log(L_INFO, "IPC Client %d disconnected", client->fd); | 330 | sway_log(L_INFO, "IPC Client %d disconnected", client->fd); |
348 | wlc_event_source_remove(client->event_source); | 331 | wl_event_source_remove(client->event_source); |
349 | if (client->writable_event_source) { | 332 | if (client->writable_event_source) { |
350 | wlc_event_source_remove(client->writable_event_source); | 333 | wl_event_source_remove(client->writable_event_source); |
351 | } | 334 | } |
352 | int i = 0; | 335 | int i = 0; |
353 | while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; | 336 | while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; |
@@ -365,165 +348,6 @@ bool output_by_name_test(swayc_t *view, void *data) { | |||
365 | return !strcmp(name, view->name); | 348 | return !strcmp(name, view->name); |
366 | } | 349 | } |
367 | 350 | ||
368 | void ipc_get_pixels(wlc_handle output) { | ||
369 | if (ipc_get_pixel_requests->length == 0) { | ||
370 | return; | ||
371 | } | ||
372 | |||
373 | list_t *unhandled = create_list(); | ||
374 | |||
375 | struct get_pixels_request *req; | ||
376 | int i; | ||
377 | for (i = 0; i < ipc_get_pixel_requests->length; ++i) { | ||
378 | req = ipc_get_pixel_requests->items[i]; | ||
379 | if (req->output != output) { | ||
380 | list_add(unhandled, req); | ||
381 | continue; | ||
382 | } | ||
383 | |||
384 | const struct wlc_size *size = &req->geo.size; | ||
385 | struct wlc_geometry g_out; | ||
386 | char response_header[9]; | ||
387 | memset(response_header, 0, sizeof(response_header)); | ||
388 | char *data = malloc(sizeof(response_header) + size->w * size->h * 4); | ||
389 | if (!data) { | ||
390 | sway_log(L_ERROR, "Unable to allocate pixels for get_pixels"); | ||
391 | ipc_client_disconnect(req->client); | ||
392 | free(req); | ||
393 | continue; | ||
394 | } | ||
395 | wlc_pixels_read(WLC_RGBA8888, &req->geo, &g_out, data + sizeof(response_header)); | ||
396 | |||
397 | response_header[0] = 1; | ||
398 | uint32_t *_size = (uint32_t *)(response_header + 1); | ||
399 | _size[0] = g_out.size.w; | ||
400 | _size[1] = g_out.size.h; | ||
401 | size_t len = sizeof(response_header) + (g_out.size.w * g_out.size.h * 4); | ||
402 | memcpy(data, response_header, sizeof(response_header)); | ||
403 | ipc_send_reply(req->client, data, len); | ||
404 | free(data); | ||
405 | // free the request since it has been handled | ||
406 | free(req); | ||
407 | } | ||
408 | |||
409 | // free old list of pixel requests and set new list to all unhandled | ||
410 | // requests (request for another output). | ||
411 | list_free(ipc_get_pixel_requests); | ||
412 | ipc_get_pixel_requests = unhandled; | ||
413 | } | ||
414 | |||
415 | static bool is_text_target(const char *target) { | ||
416 | return (strncmp(target, "text/", 5) == 0 | ||
417 | || strcmp(target, "UTF8_STRING") == 0 | ||
418 | || strcmp(target, "STRING") == 0 | ||
419 | || strcmp(target, "TEXT") == 0 | ||
420 | || strcmp(target, "COMPOUND_TEXT") == 0); | ||
421 | } | ||
422 | |||
423 | static void release_clipboard_request(struct get_clipboard_request *req) { | ||
424 | if (--(*req->pending) == 0) { | ||
425 | const char *str = json_object_to_json_string(req->json); | ||
426 | ipc_send_reply(req->client, str, (uint32_t)strlen(str)); | ||
427 | json_object_put(req->json); | ||
428 | } | ||
429 | |||
430 | free(req->type); | ||
431 | free(req->buf); | ||
432 | wlc_event_source_remove(req->fd_event_source); | ||
433 | wlc_event_source_remove(req->timer_event_source); | ||
434 | close(req->fd); | ||
435 | free(req); | ||
436 | } | ||
437 | |||
438 | static int ipc_selection_data_cb(int fd, uint32_t mask, void *data) { | ||
439 | assert(data); | ||
440 | struct get_clipboard_request *req = (struct get_clipboard_request *)data; | ||
441 | |||
442 | if (mask & WLC_EVENT_ERROR) { | ||
443 | sway_log(L_ERROR, "Selection data fd error"); | ||
444 | goto error; | ||
445 | } | ||
446 | |||
447 | if (mask & WLC_EVENT_READABLE) { | ||
448 | static const unsigned int max_size = 8192 * 1024; | ||
449 | int amt = 0; | ||
450 | |||
451 | do { | ||
452 | int size = req->buf_size - req->buf_position; | ||
453 | int amt = read(fd, req->buf + req->buf_position, size - 1); | ||
454 | if (amt < 0) { | ||
455 | if (errno == EAGAIN) { | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | sway_log_errno(L_INFO, "Failed to read from clipboard data fd"); | ||
460 | goto release; | ||
461 | } | ||
462 | |||
463 | req->buf_position += amt; | ||
464 | if (req->buf_position >= req->buf_size - 1) { | ||
465 | if (req->buf_size >= max_size) { | ||
466 | sway_log(L_ERROR, "get_clipbard: selection data too large"); | ||
467 | goto error; | ||
468 | } | ||
469 | char *next = realloc(req->buf, req->buf_size *= 2); | ||
470 | if (!next) { | ||
471 | sway_log_errno(L_ERROR, "get_clipboard: realloc data buffer failed"); | ||
472 | goto error; | ||
473 | } | ||
474 | |||
475 | req->buf = next; | ||
476 | } | ||
477 | } while(amt != 0); | ||
478 | |||
479 | req->buf[req->buf_position] = '\0'; | ||
480 | |||
481 | json_object *obj = json_object_new_object(); | ||
482 | json_object_object_add(obj, "success", json_object_new_boolean(true)); | ||
483 | if (is_text_target(req->type)) { | ||
484 | json_object_object_add(obj, "content", json_object_new_string(req->buf)); | ||
485 | json_object_object_add(req->json, req->type, obj); | ||
486 | } else { | ||
487 | size_t outlen; | ||
488 | char *b64 = b64_encode(req->buf, req->buf_position, &outlen); | ||
489 | json_object_object_add(obj, "content", json_object_new_string(b64)); | ||
490 | free(b64); | ||
491 | |||
492 | char *type = malloc(strlen(req->type) + 8); | ||
493 | strcat(type, ";base64"); | ||
494 | json_object_object_add(req->json, type, obj); | ||
495 | free(type); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | goto release; | ||
500 | |||
501 | error:; | ||
502 | json_object *obj = json_object_new_object(); | ||
503 | json_object_object_add(obj, "success", json_object_new_boolean(false)); | ||
504 | json_object_object_add(obj, "error", | ||
505 | json_object_new_string("Failed to retrieve data")); | ||
506 | json_object_object_add(req->json, req->type, obj); | ||
507 | |||
508 | release: | ||
509 | release_clipboard_request(req); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int ipc_selection_timer_cb(void *data) { | ||
514 | assert(data); | ||
515 | struct get_clipboard_request *req = (struct get_clipboard_request *)data; | ||
516 | |||
517 | sway_log(L_INFO, "get_clipbard: timeout for type %s", req->type); | ||
518 | json_object *obj = json_object_new_object(); | ||
519 | json_object_object_add(obj, "success", json_object_new_boolean(false)); | ||
520 | json_object_object_add(obj, "error", json_object_new_string("Timeout")); | ||
521 | json_object_object_add(req->json, req->type, obj); | ||
522 | |||
523 | release_clipboard_request(req); | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | // greedy wildcard (only "*") matching | 351 | // greedy wildcard (only "*") matching |
528 | bool mime_type_matches(const char *mime_type, const char *pattern) { | 352 | bool mime_type_matches(const char *mime_type, const char *pattern) { |
529 | const char *wildcard = NULL; | 353 | const char *wildcard = NULL; |
@@ -553,125 +377,6 @@ bool mime_type_matches(const char *mime_type, const char *pattern) { | |||
553 | return (*mime_type == *pattern); | 377 | return (*mime_type == *pattern); |
554 | } | 378 | } |
555 | 379 | ||
556 | void ipc_get_clipboard(struct ipc_client *client, char *buf) { | ||
557 | size_t size; | ||
558 | const char **types = wlc_get_selection_types(&size); | ||
559 | if (client->payload_length == 0) { | ||
560 | json_object *obj = json_object_new_array(); | ||
561 | for (size_t i = 0; i < size; ++i) { | ||
562 | json_object_array_add(obj, json_object_new_string(types[i])); | ||
563 | } | ||
564 | |||
565 | const char *str = json_object_to_json_string(obj); | ||
566 | ipc_send_reply(client, str, strlen(str)); | ||
567 | json_object_put(obj); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | unescape_string(buf); | ||
572 | strip_quotes(buf); | ||
573 | list_t *requested = split_string(buf, " "); | ||
574 | json_object *json = json_object_new_object(); | ||
575 | unsigned int *pending = malloc(sizeof(unsigned int)); | ||
576 | *pending = 0; | ||
577 | |||
578 | for (size_t l = 0; l < (size_t) requested->length; ++l) { | ||
579 | const char *pattern = requested->items[l]; | ||
580 | bool found = false; | ||
581 | for (size_t i = 0; i < size; ++i) { | ||
582 | if (!mime_type_matches(types[i], pattern)) { | ||
583 | continue; | ||
584 | } | ||
585 | |||
586 | found = true; | ||
587 | |||
588 | struct get_clipboard_request *req = malloc(sizeof(*req)); | ||
589 | if (!req) { | ||
590 | sway_log(L_ERROR, "get_clipboard: request malloc failed"); | ||
591 | goto data_error; | ||
592 | } | ||
593 | |||
594 | int pipes[2]; | ||
595 | if (pipe(pipes) == -1) { | ||
596 | sway_log_errno(L_ERROR, "get_clipboard: pipe call failed"); | ||
597 | free(req); | ||
598 | goto data_error; | ||
599 | } | ||
600 | |||
601 | fcntl(pipes[0], F_SETFD, FD_CLOEXEC | O_NONBLOCK); | ||
602 | fcntl(pipes[1], F_SETFD, FD_CLOEXEC | O_NONBLOCK); | ||
603 | |||
604 | if (!wlc_get_selection_data(types[i], pipes[1])) { | ||
605 | close(pipes[0]); | ||
606 | close(pipes[1]); | ||
607 | free(req); | ||
608 | sway_log(L_ERROR, "get_clipboard: failed to retrieve " | ||
609 | "selection data"); | ||
610 | goto data_error; | ||
611 | } | ||
612 | |||
613 | if (!(req->buf = malloc(512))) { | ||
614 | close(pipes[0]); | ||
615 | close(pipes[1]); | ||
616 | free(req); | ||
617 | sway_log_errno(L_ERROR, "get_clipboard: buf malloc failed"); | ||
618 | goto data_error; | ||
619 | } | ||
620 | |||
621 | (*pending)++; | ||
622 | |||
623 | req->client = client; | ||
624 | req->type = strdup(types[i]); | ||
625 | req->json = json; | ||
626 | req->pending = pending; | ||
627 | req->buf_position = 0; | ||
628 | req->buf_size = 512; | ||
629 | req->fd = pipes[0]; | ||
630 | req->timer_event_source = wlc_event_loop_add_timer(ipc_selection_timer_cb, req); | ||
631 | req->fd_event_source = wlc_event_loop_add_fd(pipes[0], | ||
632 | WLC_EVENT_READABLE | WLC_EVENT_ERROR | WLC_EVENT_HANGUP, | ||
633 | &ipc_selection_data_cb, req); | ||
634 | |||
635 | wlc_event_source_timer_update(req->timer_event_source, 30000); | ||
636 | |||
637 | // NOTE: remove this goto to enable retrieving multiple | ||
638 | // targets at once. The whole implementation is already | ||
639 | // made for it. The only reason it was disabled | ||
640 | // at the time of writing is that neither wlc's xselection | ||
641 | // implementation nor (apparently) gtk on wayland supports | ||
642 | // multiple send requests at the same time which makes | ||
643 | // every request except the last one fail (and therefore | ||
644 | // return empty data) | ||
645 | goto cleanup; | ||
646 | } | ||
647 | |||
648 | if (!found) { | ||
649 | sway_log(L_INFO, "Invalid clipboard type %s requested", pattern); | ||
650 | } | ||
651 | } | ||
652 | |||
653 | if (*pending == 0) { | ||
654 | static const char *error_empty = "{ \"success\": false, \"error\": " | ||
655 | "\"No matching types found\" }"; | ||
656 | ipc_send_reply(client, error_empty, (uint32_t)strlen(error_empty)); | ||
657 | free(json); | ||
658 | free(pending); | ||
659 | } | ||
660 | |||
661 | goto cleanup; | ||
662 | |||
663 | data_error:; | ||
664 | static const char *error_json = "{ \"success\": false, \"error\": " | ||
665 | "\"Failed to create clipboard data request\" }"; | ||
666 | ipc_send_reply(client, error_json, (uint32_t)strlen(error_json)); | ||
667 | free(json); | ||
668 | free(pending); | ||
669 | |||
670 | cleanup: | ||
671 | list_free(requested); | ||
672 | free(types); | ||
673 | } | ||
674 | |||
675 | void ipc_client_handle_command(struct ipc_client *client) { | 380 | void ipc_client_handle_command(struct ipc_client *client) { |
676 | if (!sway_assert(client != NULL, "client != NULL")) { | 381 | if (!sway_assert(client != NULL, "client != NULL")) { |
677 | return; | 382 | return; |
@@ -830,52 +535,6 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
830 | goto exit_cleanup; | 535 | goto exit_cleanup; |
831 | } | 536 | } |
832 | 537 | ||
833 | case IPC_SWAY_GET_PIXELS: | ||
834 | { | ||
835 | char response_header[9]; | ||
836 | memset(response_header, 0, sizeof(response_header)); | ||
837 | |||
838 | json_object *obj = json_tokener_parse(buf); | ||
839 | json_object *o, *x, *y, *w, *h; | ||
840 | |||
841 | json_object_object_get_ex(obj, "output", &o); | ||
842 | json_object_object_get_ex(obj, "x", &x); | ||
843 | json_object_object_get_ex(obj, "y", &y); | ||
844 | json_object_object_get_ex(obj, "w", &w); | ||
845 | json_object_object_get_ex(obj, "h", &h); | ||
846 | |||
847 | struct wlc_geometry g = { | ||
848 | .origin = { | ||
849 | .x = json_object_get_int(x), | ||
850 | .y = json_object_get_int(y) | ||
851 | }, | ||
852 | .size = { | ||
853 | .w = json_object_get_int(w), | ||
854 | .h = json_object_get_int(h) | ||
855 | } | ||
856 | }; | ||
857 | |||
858 | swayc_t *output = swayc_by_test(&root_container, output_by_name_test, (void *)json_object_get_string(o)); | ||
859 | json_object_put(obj); | ||
860 | |||
861 | if (!output) { | ||
862 | sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name"); | ||
863 | ipc_send_reply(client, response_header, sizeof(response_header)); | ||
864 | goto exit_cleanup; | ||
865 | } | ||
866 | struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); | ||
867 | if (!req) { | ||
868 | sway_log(L_ERROR, "Unable to allocate get_pixels request"); | ||
869 | goto exit_cleanup; | ||
870 | } | ||
871 | req->client = client; | ||
872 | req->output = output->handle; | ||
873 | req->geo = g; | ||
874 | list_add(ipc_get_pixel_requests, req); | ||
875 | wlc_output_schedule_render(output->handle); | ||
876 | goto exit_cleanup; | ||
877 | } | ||
878 | |||
879 | case IPC_GET_BAR_CONFIG: | 538 | case IPC_GET_BAR_CONFIG: |
880 | { | 539 | { |
881 | if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { | 540 | if (!(client->security_policy & IPC_FEATURE_GET_BAR_CONFIG)) { |
@@ -917,14 +576,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
917 | } | 576 | } |
918 | 577 | ||
919 | case IPC_GET_CLIPBOARD: | 578 | case IPC_GET_CLIPBOARD: |
920 | { | 579 | // TODO WLR |
921 | if (!(client->security_policy & IPC_FEATURE_GET_CLIPBOARD)) { | 580 | break; |
922 | goto exit_denied; | ||
923 | } | ||
924 | |||
925 | ipc_get_clipboard(client, buf); | ||
926 | goto exit_cleanup; | ||
927 | } | ||
928 | 581 | ||
929 | default: | 582 | default: |
930 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); | 583 | sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); |
@@ -977,7 +630,9 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
977 | client->write_buffer_len += payload_length; | 630 | client->write_buffer_len += payload_length; |
978 | 631 | ||
979 | if (!client->writable_event_source) { | 632 | if (!client->writable_event_source) { |
980 | client->writable_event_source = wlc_event_loop_add_fd(client->fd, WLC_EVENT_WRITABLE, ipc_client_handle_writable, client); | 633 | client->writable_event_source = wl_event_loop_add_fd( |
634 | server.wl_event_loop, client->fd, WL_EVENT_WRITABLE, | ||
635 | ipc_client_handle_writable, client); | ||
981 | } | 636 | } |
982 | 637 | ||
983 | sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); | 638 | sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); |
diff --git a/sway/layout.c b/sway/layout.c index 69291daf..22f81688 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include <stdbool.h> | 3 | #include <stdbool.h> |
4 | #include <math.h> | 4 | #include <math.h> |
5 | #include <wlc/wlc.h> | 5 | #include <wlc/wlc.h> |
6 | #include "sway/extensions.h" | ||
7 | #include "sway/config.h" | 6 | #include "sway/config.h" |
8 | #include "sway/container.h" | 7 | #include "sway/container.h" |
9 | #include "sway/workspace.h" | 8 | #include "sway/workspace.h" |
@@ -1001,6 +1000,7 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
1001 | { | 1000 | { |
1002 | swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); | 1001 | swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); |
1003 | width = output->width, height = output->height; | 1002 | width = output->width, height = output->height; |
1003 | /* TODO WLR | ||
1004 | for (i = 0; i < desktop_shell.panels->length; ++i) { | 1004 | for (i = 0; i < desktop_shell.panels->length; ++i) { |
1005 | struct panel_config *config = desktop_shell.panels->items[i]; | 1005 | struct panel_config *config = desktop_shell.panels->items[i]; |
1006 | if (config->output == output->handle) { | 1006 | if (config->output == output->handle) { |
@@ -1022,6 +1022,7 @@ static void arrange_windows_r(swayc_t *container, double width, double height) { | |||
1022 | } | 1022 | } |
1023 | } | 1023 | } |
1024 | } | 1024 | } |
1025 | */ | ||
1025 | int gap = swayc_gap(container); | 1026 | int gap = swayc_gap(container); |
1026 | x = container->x = x + gap; | 1027 | x = container->x = x + gap; |
1027 | y = container->y = y + gap; | 1028 | y = container->y = y + gap; |
@@ -1380,11 +1381,13 @@ void arrange_windows(swayc_t *container, double width, double height) { | |||
1380 | } | 1381 | } |
1381 | 1382 | ||
1382 | void arrange_backgrounds(void) { | 1383 | void arrange_backgrounds(void) { |
1384 | /* TODO WLR | ||
1383 | struct background_config *bg; | 1385 | struct background_config *bg; |
1384 | for (int i = 0; i < desktop_shell.backgrounds->length; ++i) { | 1386 | for (int i = 0; i < desktop_shell.backgrounds->length; ++i) { |
1385 | bg = desktop_shell.backgrounds->items[i]; | 1387 | bg = desktop_shell.backgrounds->items[i]; |
1386 | wlc_view_send_to_back(bg->handle); | 1388 | wlc_view_send_to_back(bg->handle); |
1387 | } | 1389 | } |
1390 | */ | ||
1388 | } | 1391 | } |
1389 | 1392 | ||
1390 | /** | 1393 | /** |
diff --git a/sway/main.c b/sway/main.c index cc9147b8..efca96d5 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -3,7 +3,6 @@ | |||
3 | #include <stdio.h> | 3 | #include <stdio.h> |
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <stdbool.h> | 5 | #include <stdbool.h> |
6 | #include <wlc/wlc.h> | ||
7 | #include <sys/wait.h> | 6 | #include <sys/wait.h> |
8 | #include <sys/types.h> | 7 | #include <sys/types.h> |
9 | #include <sys/stat.h> | 8 | #include <sys/stat.h> |
@@ -15,13 +14,13 @@ | |||
15 | #include <sys/capability.h> | 14 | #include <sys/capability.h> |
16 | #include <sys/prctl.h> | 15 | #include <sys/prctl.h> |
17 | #endif | 16 | #endif |
18 | #include "sway/extensions.h" | ||
19 | #include "sway/layout.h" | 17 | #include "sway/layout.h" |
20 | #include "sway/config.h" | 18 | #include "sway/config.h" |
21 | #include "sway/security.h" | 19 | #include "sway/security.h" |
22 | #include "sway/handlers.h" | 20 | #include "sway/handlers.h" |
23 | #include "sway/input.h" | 21 | #include "sway/input.h" |
24 | #include "sway/ipc-server.h" | 22 | #include "sway/ipc-server.h" |
23 | #include "sway/server.h" | ||
25 | #include "ipc-client.h" | 24 | #include "ipc-client.h" |
26 | #include "readline.h" | 25 | #include "readline.h" |
27 | #include "stringop.h" | 26 | #include "stringop.h" |
@@ -31,11 +30,12 @@ | |||
31 | 30 | ||
32 | static bool terminate_request = false; | 31 | static bool terminate_request = false; |
33 | static int exit_value = 0; | 32 | static int exit_value = 0; |
33 | struct sway_server server; | ||
34 | 34 | ||
35 | void sway_terminate(int exit_code) { | 35 | void sway_terminate(int exit_code) { |
36 | terminate_request = true; | 36 | terminate_request = true; |
37 | exit_value = exit_code; | 37 | exit_value = exit_code; |
38 | wlc_terminate(); | 38 | wl_display_terminate(server.wl_display); |
39 | } | 39 | } |
40 | 40 | ||
41 | void sig_handler(int signal) { | 41 | void sig_handler(int signal) { |
@@ -43,16 +43,6 @@ void sig_handler(int signal) { | |||
43 | sway_terminate(EXIT_SUCCESS); | 43 | sway_terminate(EXIT_SUCCESS); |
44 | } | 44 | } |
45 | 45 | ||
46 | static void wlc_log_handler(enum wlc_log_type type, const char *str) { | ||
47 | if (type == WLC_LOG_ERROR) { | ||
48 | sway_log(L_ERROR, "[wlc] %s", str); | ||
49 | } else if (type == WLC_LOG_WARN) { | ||
50 | sway_log(L_INFO, "[wlc] %s", str); | ||
51 | } else { | ||
52 | sway_log(L_DEBUG, "[wlc] %s", str); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | void detect_raspi() { | 46 | void detect_raspi() { |
57 | bool raspi = false; | 47 | bool raspi = false; |
58 | FILE *f = fopen("/sys/firmware/devicetree/base/model", "r"); | 48 | FILE *f = fopen("/sys/firmware/devicetree/base/model", "r"); |
@@ -189,19 +179,7 @@ static void log_env() { | |||
189 | "LD_LIBRARY_PATH", | 179 | "LD_LIBRARY_PATH", |
190 | "SWAY_CURSOR_THEME", | 180 | "SWAY_CURSOR_THEME", |
191 | "SWAY_CURSOR_SIZE", | 181 | "SWAY_CURSOR_SIZE", |
192 | "SWAYSOCK", | 182 | "SWAYSOCK" |
193 | "WLC_DRM_DEVICE", | ||
194 | "WLC_SHM", | ||
195 | "WLC_OUTPUTS", | ||
196 | "WLC_XWAYLAND", | ||
197 | "WLC_LIBINPUT", | ||
198 | "WLC_REPEAT_DELAY", | ||
199 | "WLC_REPEAT_RATE", | ||
200 | "XKB_DEFAULT_RULES", | ||
201 | "XKB_DEFAULT_MODEL", | ||
202 | "XKB_DEFAULT_LAYOUT", | ||
203 | "XKB_DEFAULT_VARIANT", | ||
204 | "XKB_DEFAULT_OPTIONS", | ||
205 | }; | 183 | }; |
206 | for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { | 184 | for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) { |
207 | sway_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); | 185 | sway_log(L_INFO, "%s=%s", log_vars[i], getenv(log_vars[i])); |
@@ -295,6 +273,37 @@ static void executable_sanity_check() { | |||
295 | #endif | 273 | #endif |
296 | } | 274 | } |
297 | 275 | ||
276 | static void drop_permissions(bool keep_caps) { | ||
277 | if (getuid() != geteuid() || getgid() != getegid()) { | ||
278 | if (setgid(getgid()) != 0) { | ||
279 | sway_log(L_ERROR, "Unable to drop root"); | ||
280 | exit(EXIT_FAILURE); | ||
281 | } | ||
282 | if (setuid(getuid()) != 0) { | ||
283 | sway_log(L_ERROR, "Unable to drop root"); | ||
284 | exit(EXIT_FAILURE); | ||
285 | } | ||
286 | } | ||
287 | if (setuid(0) != -1) { | ||
288 | sway_log(L_ERROR, "Root privileges can be restored."); | ||
289 | exit(EXIT_FAILURE); | ||
290 | } | ||
291 | #ifdef __linux__ | ||
292 | if (keep_caps) { | ||
293 | // Drop every cap except CAP_SYS_PTRACE | ||
294 | cap_t caps = cap_init(); | ||
295 | cap_value_t keep = CAP_SYS_PTRACE; | ||
296 | sway_log(L_INFO, "Dropping extra capabilities"); | ||
297 | if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || | ||
298 | cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || | ||
299 | cap_set_proc(caps)) { | ||
300 | sway_log(L_ERROR, "Failed to drop extra capabilities"); | ||
301 | exit(EXIT_FAILURE); | ||
302 | } | ||
303 | } | ||
304 | #endif | ||
305 | } | ||
306 | |||
298 | int main(int argc, char **argv) { | 307 | int main(int argc, char **argv) { |
299 | static int verbose = 0, debug = 0, validate = 0; | 308 | static int verbose = 0, debug = 0, validate = 0; |
300 | 309 | ||
@@ -374,7 +383,7 @@ int main(int argc, char **argv) { | |||
374 | } | 383 | } |
375 | } | 384 | } |
376 | 385 | ||
377 | // we need to setup logging before wlc_init in case it fails. | 386 | // TODO: switch logging over to wlroots? |
378 | if (debug) { | 387 | if (debug) { |
379 | init_log(L_DEBUG); | 388 | init_log(L_DEBUG); |
380 | } else if (verbose || validate) { | 389 | } else if (verbose || validate) { |
@@ -388,20 +397,7 @@ int main(int argc, char **argv) { | |||
388 | sway_log(L_ERROR, "Don't use options with the IPC client"); | 397 | sway_log(L_ERROR, "Don't use options with the IPC client"); |
389 | exit(EXIT_FAILURE); | 398 | exit(EXIT_FAILURE); |
390 | } | 399 | } |
391 | if (getuid() != geteuid() || getgid() != getegid()) { | 400 | drop_permissions(false); |
392 | if (setgid(getgid()) != 0) { | ||
393 | sway_log(L_ERROR, "Unable to drop root"); | ||
394 | exit(EXIT_FAILURE); | ||
395 | } | ||
396 | if (setuid(getuid()) != 0) { | ||
397 | sway_log(L_ERROR, "Unable to drop root"); | ||
398 | exit(EXIT_FAILURE); | ||
399 | } | ||
400 | } | ||
401 | if (setuid(0) != -1) { | ||
402 | sway_log(L_ERROR, "Root privileges can be restored."); | ||
403 | exit(EXIT_FAILURE); | ||
404 | } | ||
405 | char *socket_path = getenv("SWAYSOCK"); | 401 | char *socket_path = getenv("SWAYSOCK"); |
406 | if (!socket_path) { | 402 | if (!socket_path) { |
407 | sway_log(L_ERROR, "Unable to retrieve socket path"); | 403 | sway_log(L_ERROR, "Unable to retrieve socket path"); |
@@ -413,8 +409,8 @@ int main(int argc, char **argv) { | |||
413 | } | 409 | } |
414 | 410 | ||
415 | executable_sanity_check(); | 411 | executable_sanity_check(); |
416 | #ifdef __linux__ | ||
417 | bool suid = false; | 412 | bool suid = false; |
413 | #ifdef __linux__ | ||
418 | if (getuid() != geteuid() || getgid() != getegid()) { | 414 | if (getuid() != geteuid() || getgid() != getegid()) { |
419 | // Retain capabilities after setuid() | 415 | // Retain capabilities after setuid() |
420 | if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { | 416 | if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { |
@@ -425,37 +421,14 @@ int main(int argc, char **argv) { | |||
425 | } | 421 | } |
426 | #endif | 422 | #endif |
427 | 423 | ||
428 | wlc_log_set_handler(wlc_log_handler); | ||
429 | log_kernel(); | 424 | log_kernel(); |
430 | log_distro(); | 425 | log_distro(); |
431 | log_env(); | 426 | log_env(); |
432 | detect_proprietary(); | 427 | detect_proprietary(); |
433 | detect_raspi(); | 428 | detect_raspi(); |
434 | 429 | ||
435 | input_devices = create_list(); | ||
436 | |||
437 | /* Changing code earlier than this point requires detailed review */ | ||
438 | /* (That code runs as root on systems without logind, and wlc_init drops to | ||
439 | * another user.) */ | ||
440 | register_wlc_handlers(); | ||
441 | if (!wlc_init()) { | ||
442 | return 1; | ||
443 | } | ||
444 | register_extensions(); | ||
445 | |||
446 | #ifdef __linux__ | 430 | #ifdef __linux__ |
447 | if (suid) { | 431 | drop_permissions(suid); |
448 | // Drop every cap except CAP_SYS_PTRACE | ||
449 | cap_t caps = cap_init(); | ||
450 | cap_value_t keep = CAP_SYS_PTRACE; | ||
451 | sway_log(L_INFO, "Dropping extra capabilities"); | ||
452 | if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) || | ||
453 | cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) || | ||
454 | cap_set_proc(caps)) { | ||
455 | sway_log(L_ERROR, "Failed to drop extra capabilities"); | ||
456 | exit(EXIT_FAILURE); | ||
457 | } | ||
458 | } | ||
459 | #endif | 432 | #endif |
460 | // handle SIGTERM signals | 433 | // handle SIGTERM signals |
461 | signal(SIGTERM, sig_handler); | 434 | signal(SIGTERM, sig_handler); |
@@ -465,8 +438,10 @@ int main(int argc, char **argv) { | |||
465 | 438 | ||
466 | sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); | 439 | sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); |
467 | 440 | ||
441 | if (!server_init(&server)) { | ||
442 | return 1; | ||
443 | } | ||
468 | init_layout(); | 444 | init_layout(); |
469 | |||
470 | ipc_init(); | 445 | ipc_init(); |
471 | 446 | ||
472 | if (validate) { | 447 | if (validate) { |
@@ -485,10 +460,10 @@ int main(int argc, char **argv) { | |||
485 | security_sanity_check(); | 460 | security_sanity_check(); |
486 | 461 | ||
487 | if (!terminate_request) { | 462 | if (!terminate_request) { |
488 | wlc_run(); | 463 | wl_display_run(server.wl_display); |
489 | } | 464 | } |
490 | 465 | ||
491 | list_free(input_devices); | 466 | server_fini(&server); |
492 | 467 | ||
493 | ipc_terminate(); | 468 | ipc_terminate(); |
494 | 469 | ||
diff --git a/sway/server.c b/sway/server.c new file mode 100644 index 00000000..39fa5d28 --- /dev/null +++ b/sway/server.c | |||
@@ -0,0 +1,54 @@ | |||
1 | #define _POSIX_C_SOURCE 200112L | ||
2 | #include <stdlib.h> | ||
3 | #include <stdbool.h> | ||
4 | #include <wayland-server.h> | ||
5 | #include <wlr/backend.h> | ||
6 | #include <wlr/backend/session.h> | ||
7 | #include <wlr/types/wlr_data_device_manager.h> | ||
8 | #include <wlr/render.h> | ||
9 | #include <wlr/render/gles2.h> | ||
10 | // TODO WLR: make Xwayland optional | ||
11 | #include <wlr/xwayland.h> | ||
12 | #include "sway/server.h" | ||
13 | #include "log.h" | ||
14 | |||
15 | bool server_init(struct sway_server *server) { | ||
16 | sway_log(L_DEBUG, "Initializing Wayland server"); | ||
17 | |||
18 | server->wl_display = wl_display_create(); | ||
19 | server->wl_event_loop = wl_display_get_event_loop(server->wl_display); | ||
20 | server->backend = wlr_backend_autocreate(server->wl_display); | ||
21 | |||
22 | server->renderer = wlr_gles2_renderer_create(server->backend); | ||
23 | wl_display_init_shm(server->wl_display); | ||
24 | |||
25 | // TODO WLR | ||
26 | //server->desktop = desktop_create(server, server.config); | ||
27 | //server->input = input_create(&server, server.config); | ||
28 | server->data_device_manager = | ||
29 | wlr_data_device_manager_create(server->wl_display); | ||
30 | |||
31 | const char *socket = wl_display_add_socket_auto(server->wl_display); | ||
32 | if (!socket) { | ||
33 | sway_log_errno(L_ERROR, "Unable to open wayland socket"); | ||
34 | wlr_backend_destroy(server->backend); | ||
35 | return false; | ||
36 | } | ||
37 | |||
38 | sway_log(L_INFO, "Running compositor on wayland display '%s'", socket); | ||
39 | setenv("_WAYLAND_DISPLAY", socket, true); | ||
40 | |||
41 | if (!wlr_backend_start(server->backend)) { | ||
42 | sway_log(L_ERROR, "Failed to start backend"); | ||
43 | wlr_backend_destroy(server->backend); | ||
44 | return false; | ||
45 | } | ||
46 | |||
47 | setenv("WAYLAND_DISPLAY", socket, true); | ||
48 | return true; | ||
49 | } | ||
50 | |||
51 | void server_fini(struct sway_server *server) { | ||
52 | // TODO WLR: tear down more stuff | ||
53 | wlr_backend_destroy(server->backend); | ||
54 | } | ||
diff --git a/sway/workspace.c b/sway/workspace.c index e0367190..14cde146 100644 --- a/sway/workspace.c +++ b/sway/workspace.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <strings.h> | 8 | #include <strings.h> |
9 | #include <sys/types.h> | 9 | #include <sys/types.h> |
10 | #include "sway/ipc-server.h" | 10 | #include "sway/ipc-server.h" |
11 | #include "sway/extensions.h" | ||
12 | #include "sway/workspace.h" | 11 | #include "sway/workspace.h" |
13 | #include "sway/layout.h" | 12 | #include "sway/layout.h" |
14 | #include "sway/container.h" | 13 | #include "sway/container.h" |