diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-04-30 21:24:13 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-04-30 21:24:13 +1000 |
commit | e67f3543332349e63b5099a241fdd85ce28ea54b (patch) | |
tree | 54bede11d48f561693d1288e0980660c644b4dc3 /sway/desktop/output.c | |
parent | Merge pull request #1873 from RyanDwyer/remove-arrange-windows (diff) | |
download | sway-e67f3543332349e63b5099a241fdd85ce28ea54b.tar.gz sway-e67f3543332349e63b5099a241fdd85ce28ea54b.tar.zst sway-e67f3543332349e63b5099a241fdd85ce28ea54b.zip |
Implement borders
Implements rendering of borders. Title text is still to do.
Implements the following configuration directives:
* client.focused
* client.focused_inactive
* client.unfocused
* client.urgent
* border
* default_border
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 205 |
1 files changed, 190 insertions, 15 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index d9ae890f..2511c610 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -116,8 +116,8 @@ static void surface_for_each_surface(struct wlr_surface *surface, | |||
116 | static void output_view_for_each_surface(struct sway_view *view, | 116 | static void output_view_for_each_surface(struct sway_view *view, |
117 | struct root_geometry *geo, wlr_surface_iterator_func_t iterator, | 117 | struct root_geometry *geo, wlr_surface_iterator_func_t iterator, |
118 | void *user_data) { | 118 | void *user_data) { |
119 | geo->x = view->swayc->x; | 119 | geo->x = view->x; |
120 | geo->y = view->swayc->y; | 120 | geo->y = view->y; |
121 | geo->width = view->surface->current->width; | 121 | geo->width = view->surface->current->width; |
122 | geo->height = view->surface->current->height; | 122 | geo->height = view->surface->current->height; |
123 | geo->rotation = 0; // TODO | 123 | geo->rotation = 0; // TODO |
@@ -217,23 +217,198 @@ static void render_unmanaged(struct sway_output *output, | |||
217 | render_surface_iterator, &data); | 217 | render_surface_iterator, &data); |
218 | } | 218 | } |
219 | 219 | ||
220 | static void render_container_iterator(struct sway_container *con, | 220 | static void render_view(struct sway_view *view, struct sway_output *output) { |
221 | void *_data) { | 221 | struct render_data data = { .output = output, .alpha = view->swayc->alpha }; |
222 | struct sway_output *output = _data; | 222 | output_view_for_each_surface( |
223 | if (!sway_assert(con->type == C_VIEW, "expected a view")) { | 223 | view, &data.root_geo, render_surface_iterator, &data); |
224 | return; | 224 | } |
225 | |||
226 | /** | ||
227 | * Render decorations for a view with "border normal". | ||
228 | */ | ||
229 | static void render_container_simple_border_normal(struct sway_output *output, | ||
230 | struct sway_container *con, struct border_colors *colors) { | ||
231 | struct wlr_renderer *renderer = | ||
232 | wlr_backend_get_renderer(output->wlr_output->backend); | ||
233 | struct wlr_box box; | ||
234 | float color[4]; | ||
235 | color[3] = con->alpha; | ||
236 | |||
237 | // Child border - left edge | ||
238 | memcpy(&color, colors->child_border, sizeof(float) * 3); | ||
239 | box.x = con->x; | ||
240 | box.y = con->y + 1; | ||
241 | box.width = con->sway_view->border_thickness; | ||
242 | box.height = con->height - 1; | ||
243 | wlr_render_rect(renderer, &box, color, | ||
244 | output->wlr_output->transform_matrix); | ||
245 | |||
246 | // Child border - right edge | ||
247 | box.x = con->x + con->width - con->sway_view->border_thickness; | ||
248 | box.y = con->y + 1; | ||
249 | box.width = con->sway_view->border_thickness; | ||
250 | box.height = con->height - 1; | ||
251 | wlr_render_rect(renderer, &box, color, | ||
252 | output->wlr_output->transform_matrix); | ||
253 | |||
254 | // Child border - bottom edge | ||
255 | box.x = con->x; | ||
256 | box.y = con->y + con->height - con->sway_view->border_thickness; | ||
257 | box.width = con->width; | ||
258 | box.height = con->sway_view->border_thickness; | ||
259 | wlr_render_rect(renderer, &box, color, | ||
260 | output->wlr_output->transform_matrix); | ||
261 | |||
262 | // Single pixel bar above title | ||
263 | memcpy(&color, colors->border, sizeof(float) * 3); | ||
264 | box.x = con->x; | ||
265 | box.y = con->y; | ||
266 | box.width = con->width; | ||
267 | box.height = 1; | ||
268 | wlr_render_rect(renderer, &box, color, | ||
269 | output->wlr_output->transform_matrix); | ||
270 | |||
271 | // Single pixel bar below title | ||
272 | box.x = con->x + con->sway_view->border_thickness; | ||
273 | box.y = con->sway_view->y - 1; | ||
274 | box.width = con->width - con->sway_view->border_thickness * 2; | ||
275 | box.height = 1; | ||
276 | wlr_render_rect(renderer, &box, color, | ||
277 | output->wlr_output->transform_matrix); | ||
278 | |||
279 | // Title background | ||
280 | memcpy(&color, colors->background, sizeof(float) * 3); | ||
281 | box.x = con->x + con->sway_view->border_thickness; | ||
282 | box.y = con->y + 1; | ||
283 | box.width = con->width - con->sway_view->border_thickness * 2; | ||
284 | box.height = con->sway_view->y - con->y - 2; | ||
285 | wlr_render_rect(renderer, &box, color, | ||
286 | output->wlr_output->transform_matrix); | ||
287 | |||
288 | // Title text | ||
289 | // TODO | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * Render decorations for a view with "border pixel". | ||
294 | */ | ||
295 | static void render_container_simple_border_pixel(struct sway_output *output, | ||
296 | struct sway_container *con, struct border_colors *colors) { | ||
297 | struct wlr_renderer *renderer = | ||
298 | wlr_backend_get_renderer(output->wlr_output->backend); | ||
299 | struct wlr_box box; | ||
300 | float color[4]; | ||
301 | color[3] = con->alpha; | ||
302 | |||
303 | // Child border - left edge | ||
304 | memcpy(&color, colors->child_border, sizeof(float) * 3); | ||
305 | box.x = con->x; | ||
306 | box.y = con->y; | ||
307 | box.width = con->sway_view->border_thickness; | ||
308 | box.height = con->height; | ||
309 | wlr_render_rect(renderer, &box, color, | ||
310 | output->wlr_output->transform_matrix); | ||
311 | |||
312 | // Child border - right edge | ||
313 | box.x = con->x + con->width - con->sway_view->border_thickness; | ||
314 | box.y = con->y; | ||
315 | box.width = con->sway_view->border_thickness; | ||
316 | box.height = con->height; | ||
317 | wlr_render_rect(renderer, &box, color, | ||
318 | output->wlr_output->transform_matrix); | ||
319 | |||
320 | // Child border - top edge | ||
321 | box.x = con->x; | ||
322 | box.y = con->y; | ||
323 | box.width = con->width; | ||
324 | box.height = con->sway_view->border_thickness; | ||
325 | wlr_render_rect(renderer, &box, color, | ||
326 | output->wlr_output->transform_matrix); | ||
327 | |||
328 | // Child border - bottom edge | ||
329 | box.x = con->x; | ||
330 | box.y = con->y + con->height - con->sway_view->border_thickness; | ||
331 | box.width = con->width; | ||
332 | box.height = con->sway_view->border_thickness; | ||
333 | wlr_render_rect(renderer, &box, color, | ||
334 | output->wlr_output->transform_matrix); | ||
335 | } | ||
336 | |||
337 | static void render_container(struct sway_output *output, | ||
338 | struct sway_container *con); | ||
339 | |||
340 | /** | ||
341 | * Render a container's children using a L_HORIZ or L_VERT layout. | ||
342 | * | ||
343 | * Wrap child views in borders and leave child containers borderless because | ||
344 | * they'll apply their own borders to their children. | ||
345 | */ | ||
346 | static void render_container_simple(struct sway_output *output, | ||
347 | struct sway_container *con) { | ||
348 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
349 | struct sway_container *focus = seat_get_focus(seat); | ||
350 | |||
351 | for (int i = 0; i < con->children->length; ++i) { | ||
352 | struct sway_container *child = con->children->items[i]; | ||
353 | |||
354 | if (child->type == C_VIEW) { | ||
355 | if (child->sway_view->border != B_NONE) { | ||
356 | struct border_colors *colors; | ||
357 | if (focus == child) { | ||
358 | colors = &config->border_colors.focused; | ||
359 | } else if (seat_get_focus_inactive(seat, con) == child) { | ||
360 | colors = &config->border_colors.focused_inactive; | ||
361 | } else { | ||
362 | colors = &config->border_colors.unfocused; | ||
363 | } | ||
364 | |||
365 | if (child->sway_view->border == B_NORMAL) { | ||
366 | render_container_simple_border_normal(output, child, | ||
367 | colors); | ||
368 | } else { | ||
369 | render_container_simple_border_pixel(output, child, colors); | ||
370 | } | ||
371 | } | ||
372 | render_view(child->sway_view, output); | ||
373 | } else { | ||
374 | render_container(output, child); | ||
375 | } | ||
225 | } | 376 | } |
226 | struct render_data data = { .output = output, .alpha = con->alpha }; | 377 | } |
227 | output_view_for_each_surface(con->sway_view, &data.root_geo, | 378 | |
228 | render_surface_iterator, &data); | 379 | /** |
380 | * Render a container's children using the L_TABBED layout. | ||
381 | */ | ||
382 | static void render_container_tabbed(struct sway_output *output, | ||
383 | struct sway_container *con) { | ||
384 | // TODO | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * Render a container's children using the L_STACKED layout. | ||
389 | */ | ||
390 | static void render_container_stacked(struct sway_output *output, | ||
391 | struct sway_container *con) { | ||
392 | // TODO | ||
229 | } | 393 | } |
230 | 394 | ||
231 | static void render_container(struct sway_output *output, | 395 | static void render_container(struct sway_output *output, |
232 | struct sway_container *con) { | 396 | struct sway_container *con) { |
233 | if (con->type == C_VIEW) { // Happens if a view is fullscreened | 397 | switch (con->layout) { |
234 | render_container_iterator(con, output); | 398 | case L_NONE: |
235 | } else { | 399 | case L_HORIZ: |
236 | container_descendants(con, C_VIEW, render_container_iterator, output); | 400 | case L_VERT: |
401 | render_container_simple(output, con); | ||
402 | break; | ||
403 | case L_STACKED: | ||
404 | render_container_stacked(output, con); | ||
405 | break; | ||
406 | case L_TABBED: | ||
407 | render_container_tabbed(output, con); | ||
408 | break; | ||
409 | case L_FLOATING: | ||
410 | // TODO | ||
411 | break; | ||
237 | } | 412 | } |
238 | } | 413 | } |
239 | 414 | ||
@@ -282,7 +457,7 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
282 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; | 457 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; |
283 | wlr_renderer_clear(renderer, clear_color); | 458 | wlr_renderer_clear(renderer, clear_color); |
284 | // TODO: handle views smaller than the output | 459 | // TODO: handle views smaller than the output |
285 | render_container(output, workspace->sway_workspace->fullscreen->swayc); | 460 | render_view(workspace->sway_workspace->fullscreen, output); |
286 | 461 | ||
287 | if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { | 462 | if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { |
288 | render_unmanaged(output, | 463 | render_unmanaged(output, |