diff --git a/LICENSE b/LICENSE index 41a8d9f..b047cf6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,5 @@ -Copyright (c) 2018-2019 Jente Hidskes +Copyright (c) 2018-2020 Jente Hidskes +Copyright (c) 2019 The Sway authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/meson.build b/meson.build index cbb8f2b..6121eee 100644 --- a/meson.build +++ b/meson.build @@ -83,7 +83,9 @@ cage_sources = [ 'cage.c', 'idle_inhibit_v1.c', 'output.c', + 'render.c', 'seat.c', + 'util.c', 'view.c', 'xdg_shell.c', ] @@ -94,8 +96,10 @@ cage_headers = [ configuration: conf_data), 'idle_inhibit_v1.h', 'output.h', + 'render.h', 'seat.h', 'server.h', + 'util.h', 'view.h', 'xdg_shell.h', ] diff --git a/output.c b/output.c index 4517c80..862911e 100644 --- a/output.c +++ b/output.c @@ -1,7 +1,8 @@ /* * Cage: A Wayland kiosk. * - * Copyright (C) 2018-2019 Jente Hidskes + * Copyright (C) 2018-2020 Jente Hidskes + * Copyright (C) 2019 The Sway authors * * See the LICENSE file accompanying this file. */ @@ -31,65 +32,133 @@ #include #include "output.h" +#include "render.h" #include "server.h" +#include "util.h" #include "view.h" -static void -scissor_output(struct wlr_output *output, pixman_box32_t *rect) -{ - struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); +static void output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data); - struct wlr_box box = { - .x = rect->x1, - .y = rect->y1, - .width = rect->x2 - rect->x1, - .height = rect->y2 - rect->y1, - }; +struct surface_iterator_data { + cg_surface_iterator_func_t user_iterator; + void *user_data; - int output_width, output_height; - wlr_output_transformed_resolution(output, &output_width, &output_height); - enum wl_output_transform transform = wlr_output_transform_invert(output->transform); - wlr_box_transform(&box, &box, transform, output_width, output_height); - - wlr_renderer_scissor(renderer, &box); -} - -static void -send_frame_done(struct wlr_surface *surface, int _unused, int _not_used, void *data) -{ - struct timespec *now = data; - wlr_surface_send_frame_done(surface, now); -} - -/* Used to move all of the data necessary to damage a surface. */ -struct damage_data { struct cg_output *output; /* Output-local coordinates. */ double ox, oy; - bool whole; }; -static void -damage_surface(struct wlr_surface *surface, int sx, int sy, void *data) +// TODO: this doesn't just get the surface box; it also indicates if said box overlaps +// with the current output box. +static bool // TODO: remove surface_iterator_data argument? +get_surface_box(struct surface_iterator_data *data, + struct wlr_surface *surface, int sx, int sy, + struct wlr_box *surface_box) { - struct damage_data *ddata = data; - struct cg_output *output = ddata->output; - struct wlr_output *wlr_output = output->wlr_output; + struct cg_output *output = data->output; if (!wlr_surface_has_buffer(surface)) { - return; + return false; } struct wlr_box box = { - .x = (ddata->ox + sx) * wlr_output->scale, - .y = (ddata->oy + sy) * wlr_output->scale, - .width = surface->current.width * wlr_output->scale, - .height = surface->current.height * wlr_output->scale, + .x = sx + surface->sx, + .y = sy + surface->sy, + .width = surface->current.width, + .height = surface->current.height, }; - if (ddata->whole) { - wlr_output_damage_add_box(output->damage, &box); + struct cg_server *server = output->server; + struct wlr_box *output_box = wlr_output_layout_get_box(server->output_layout, output->wlr_output); + + struct wlr_box intersection; + bool intersects = wlr_box_intersection(&intersection, output_box, &box); + + // TODO: why can't we do this before the intersection check? + box.x += data->ox; + box.y += data->oy; + + if (surface_box) { + memcpy(surface_box, &box, sizeof(struct wlr_box)); + } + + return intersects; +} + +static void +output_for_each_surface_iterator(struct wlr_surface *surface, int sx, int sy, void *user_data) +{ + struct surface_iterator_data *data = user_data; + + struct wlr_box box; + bool intersects = get_surface_box(data, surface, sx, sy, &box); + if (!intersects) { + return; + } + + data->user_iterator(data->output, surface, &box, data->user_data); +} + +static void +output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *surface, + double ox, double oy, cg_surface_iterator_func_t iterator, + void *user_data) +{ + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .ox = ox, + .oy = oy, + }; + + wlr_surface_for_each_surface(surface, output_for_each_surface_iterator, &data); +} + +void +output_view_for_each_surface(struct cg_output *output, struct cg_view *view, + cg_surface_iterator_func_t iterator, void *user_data) +{ + struct surface_iterator_data data = { + .user_iterator = iterator, + .user_data = user_data, + .output = output, + .ox = view->lx, + .oy = view->ly, + }; + + wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy); + view_for_each_surface(view, output_for_each_surface_iterator, &data); +} + +struct send_frame_done_data { + struct timespec when; +}; + +static void +send_frame_done_iterator(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data) +{ + struct send_frame_done_data *data = user_data; + wlr_surface_send_frame_done(surface, &data->when); +} + +static void +send_frame_done(struct cg_output *output, struct send_frame_done_data *data) +{ + output_for_each_surface(output, send_frame_done_iterator, data); +} + +static void +damage_surface_iterator(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data) +{ + struct wlr_output *wlr_output = output->wlr_output; + bool whole = *(bool *) user_data; + + scale_box(box, output->wlr_output->scale); + + if (whole) { + wlr_output_damage_add_box(output->damage, box); } else if (pixman_region32_not_empty(&surface->buffer_damage)) { pixman_region32_t damage; pixman_region32_init(&damage); @@ -103,188 +172,74 @@ damage_surface(struct wlr_surface *surface, int sx, int sy, void *data) wlr_region_expand(&damage, &damage, ceil(wlr_output->scale) - surface->current.scale); } - pixman_region32_translate(&damage, box.x, box.y); + pixman_region32_translate(&damage, box->x, box->y); wlr_output_damage_add(output->damage, &damage); pixman_region32_fini(&damage); } } -/* Used to move all of the data necessary to render a surface from the - * top-level frame handler to the per-surface render function. */ -struct render_data { - struct wlr_output_layout *output_layout; - struct wlr_output *output; - struct timespec *when; - pixman_region32_t *damage; - - /* Output-local coordinates. */ - double ox, oy; -}; - -static void -render_surface(struct wlr_surface *surface, int sx, int sy, void *data) +void +output_damage_surface(struct cg_output *output, struct wlr_surface *surface, + double lx, double ly, bool whole) { - struct render_data *rdata = data; - struct wlr_output *output = rdata->output; + double ox = lx, oy = ly; + wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy); + output_surface_for_each_surface(output, surface, ox, oy, damage_surface_iterator, &whole); +} - if (!wlr_surface_has_buffer(surface)) { - return; +void +output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons, + cg_surface_iterator_func_t iterator, void *user_data) +{ + struct cg_drag_icon *drag_icon; + wl_list_for_each(drag_icon, drag_icons, link) { + if (drag_icon->wlr_drag_icon->mapped) { + double ox = drag_icon->lx; + double oy = drag_icon->ly; + wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy); + output_surface_for_each_surface(output, drag_icon->wlr_drag_icon->surface, + ox, oy, iterator, user_data); + } } - - struct wlr_texture *texture = wlr_surface_get_texture(surface); - if (!texture) { - wlr_log(WLR_DEBUG, "Cannot obtain surface texture"); - return; - } - - struct wlr_box box = { - .x = (rdata->ox + sx) * output->scale, - .y = (rdata->oy + sy) * output->scale, - .width = surface->current.width * output->scale, - .height = surface->current.height * output->scale, - }; - - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, box.x, box.y, box.width, box.height); - pixman_region32_intersect(&damage, &damage, rdata->damage); - if (!pixman_region32_not_empty(&damage)) { - goto buffer_damage_finish; - } - - float matrix[9]; - enum wl_output_transform transform = wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, &box, transform, 0, output->transform_matrix); - - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); - for (int i = 0; i < nrects; i++) { - scissor_output(output, &rects[i]); - wlr_render_texture_with_matrix(surface->renderer, texture, matrix, 1); - } - - buffer_damage_finish: - pixman_region32_fini(&damage); } static void -drag_icons_for_each_surface(struct cg_server *server, wlr_surface_iterator_func_t iterator, - void *data) +output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data) { - struct render_data *rdata = data; - struct wlr_output *wlr_output = rdata->output; - - struct cg_drag_icon *drag_icon; - wl_list_for_each(drag_icon, &server->seat->drag_icons, link) { - if (!drag_icon->wlr_drag_icon->mapped) { - continue; - } - rdata->ox = drag_icon->lx; - rdata->oy = drag_icon->ly; - wlr_output_layout_output_coords(server->output_layout, wlr_output, &rdata->ox, &rdata->oy); - wlr_surface_for_each_surface(drag_icon->wlr_drag_icon->surface, - iterator, - data); + struct cg_view *view; + wl_list_for_each_reverse(view, &output->server->views, link) { + output_view_for_each_surface(output, view, iterator, user_data); } + + output_drag_icons_for_each_surface(output, &output->server->seat->drag_icons, iterator, user_data); } static void handle_output_damage_frame(struct wl_listener *listener, void *data) { struct cg_output *output = wl_container_of(listener, output, damage_frame); - struct wlr_renderer *renderer = wlr_backend_get_renderer(output->server->backend); - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); bool needs_frame; - pixman_region32_t buffer_damage; - pixman_region32_init(&buffer_damage); - if (!wlr_output_damage_attach_render(output->damage, &needs_frame, &buffer_damage)) { + pixman_region32_t damage; + pixman_region32_init(&damage); + if (!wlr_output_damage_attach_render(output->damage, &needs_frame, &damage)) { wlr_log(WLR_ERROR, "Cannot make damage output current"); - goto buffer_damage_finish; + goto damage_finish; } if (!needs_frame) { wlr_output_rollback(output->wlr_output); - goto buffer_damage_finish; + goto damage_finish; } - wlr_renderer_begin(renderer, output->wlr_output->width, output->wlr_output->height); + output_render(output, &damage); - if (!pixman_region32_not_empty(&buffer_damage)) { - wlr_log(WLR_DEBUG, "Output isn't damaged but needs a buffer frame"); - goto renderer_end; - } + damage_finish: + pixman_region32_fini(&damage); -#ifdef DEBUG - if (output->server->debug_damage_tracking) { - wlr_renderer_clear(renderer, (float[]){1, 0, 0, 1}); - } -#endif - - float color[4] = {0, 0, 0, 1.0}; - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&buffer_damage, &nrects); - for (int i = 0; i < nrects; i++) { - scissor_output(output->wlr_output, &rects[i]); - wlr_renderer_clear(renderer, color); - } - - struct render_data rdata = { - .output_layout = output->server->output_layout, - .output = output->wlr_output, - .when = &now, - .damage = &buffer_damage, - }; - - struct cg_view *view; - wl_list_for_each_reverse(view, &output->server->views, link) { - rdata.ox = view->lx; - rdata.oy = view->ly; - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &rdata.ox, &rdata.oy); - view_for_each_surface(view, render_surface, &rdata); - } - - drag_icons_for_each_surface(output->server, render_surface, &rdata); - - renderer_end: - /* Draw software cursor in case hardware cursors aren't - available. This is a no-op when they are. */ - wlr_output_render_software_cursors(output->wlr_output, &buffer_damage); - wlr_renderer_scissor(renderer, NULL); - wlr_renderer_end(renderer); - - int output_width, output_height; - wlr_output_transformed_resolution(output->wlr_output, &output_width, &output_height); - - pixman_region32_t frame_damage; - pixman_region32_init(&frame_damage); - - enum wl_output_transform transform = wlr_output_transform_invert(output->wlr_output->transform); - wlr_region_transform(&frame_damage, &output->damage->current, transform, output_width, output_height); - -#ifdef DEBUG - if (output->server->debug_damage_tracking) { - pixman_region32_union_rect(&frame_damage, &frame_damage, 0, 0, output_width, output_height); - } -#endif - - wlr_output_set_damage(output->wlr_output, &frame_damage); - pixman_region32_fini(&frame_damage); - - if (!wlr_output_commit(output->wlr_output)) { - wlr_log(WLR_ERROR, "Could not commit output"); - goto buffer_damage_finish; - } - - buffer_damage_finish: - pixman_region32_fini(&buffer_damage); - - wl_list_for_each_reverse(view, &output->server->views, link) { - view_for_each_surface(view, send_frame_done, &now); - } - drag_icons_for_each_surface(output->server, send_frame_done, &now); + struct send_frame_done_data frame_data = {0}; + clock_gettime(CLOCK_MONOTONIC, &frame_data.when); + send_frame_done(output, &frame_data); } static void @@ -407,47 +362,6 @@ handle_new_output(struct wl_listener *listener, void *data) wlr_output_commit(wlr_output); } -void -output_damage_view_surface(struct cg_output *output, struct cg_view *view) -{ - struct damage_data data = { - .output = output, - .ox = view->lx, - .oy = view->ly, - .whole = false, - }; - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy); - view_for_each_surface(view, damage_surface, &data); -} - -void -output_damage_view_whole(struct cg_output *output, struct cg_view *view) -{ - struct damage_data data = { - .output = output, - .ox = view->lx, - .oy = view->ly, - .whole = true, - }; - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy); - view_for_each_surface(view, damage_surface, &data); -} - -void -output_damage_drag_icon(struct cg_output *output, struct cg_drag_icon *drag_icon) -{ - struct damage_data data = { - .output = output, - .ox = drag_icon->lx, - .oy = drag_icon->ly, - .whole = true, - }; - wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy); - wlr_surface_for_each_surface(drag_icon->wlr_drag_icon->surface, - damage_surface, - &data); -} - void output_set_window_title(struct cg_output *output, const char *title) { diff --git a/output.h b/output.h index 1563799..608f762 100644 --- a/output.h +++ b/output.h @@ -23,10 +23,12 @@ struct cg_output { struct wl_list link; // cg_server::outputs }; +typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data); + void handle_new_output(struct wl_listener *listener, void *data); -void output_damage_view_surface(struct cg_output *output, struct cg_view *view); -void output_damage_view_whole(struct cg_output *cg_output, struct cg_view *view); -void output_damage_drag_icon(struct cg_output *output, struct cg_drag_icon *icon); +void output_view_for_each_surface(struct cg_output *output, struct cg_view *view, cg_surface_iterator_func_t iterator, void *user_data); +void output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons, cg_surface_iterator_func_t iterator, void *user_data); +void output_damage_surface(struct cg_output *output, struct wlr_surface *surface, double lx, double ly, bool whole); void output_set_window_title(struct cg_output *output, const char *title); #endif diff --git a/render.c b/render.c new file mode 100644 index 0000000..b75ad7d --- /dev/null +++ b/render.c @@ -0,0 +1,188 @@ +/* + * Cage: A Wayland kiosk. + * + * Copyright (C) 2018-2020 Jente Hidskes + * Copyright (C) 2019 The Sway authors + * + * See the LICENSE file accompanying this file. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "output.h" +#include "seat.h" +#include "server.h" +#include "util.h" +#include "view.h" + +static void +scissor_output(struct wlr_output *output, pixman_box32_t *rect) +{ + struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); + + struct wlr_box box = { + .x = rect->x1, + .y = rect->y1, + .width = rect->x2 - rect->x1, + .height = rect->y2 - rect->y1, + }; + + int output_width, output_height; + wlr_output_transformed_resolution(output, &output_width, &output_height); + enum wl_output_transform transform = wlr_output_transform_invert(output->transform); + wlr_box_transform(&box, &box, transform, output_width, output_height); + + wlr_renderer_scissor(renderer, &box); +} + +struct render_data { + pixman_region32_t *damage; +}; + +static void +render_texture(struct wlr_output *wlr_output, pixman_region32_t *output_damage, + struct wlr_texture *texture, const struct wlr_box *box, + const float matrix[static 9]) +{ + struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); + + pixman_region32_t damage; + pixman_region32_init(&damage); + pixman_region32_union_rect(&damage, &damage, box->x, box->y, box->width, box->height); + pixman_region32_intersect(&damage, &damage, output_damage); + if (!pixman_region32_not_empty(&damage)) { + goto damage_finish; + } + + int nrects; + pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); + for (int i = 0; i < nrects; i++) { + scissor_output(wlr_output, &rects[i]); + wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0f); + } + + damage_finish: + pixman_region32_fini(&damage); +} + +static void +render_surface_iterator(struct cg_output *output, struct wlr_surface *surface, + struct wlr_box *box, void *user_data) +{ + struct render_data *data = user_data; + struct wlr_output *wlr_output = output->wlr_output; + pixman_region32_t *output_damage = data->damage; + + struct wlr_texture *texture = wlr_surface_get_texture(surface); + if (!texture) { + wlr_log(WLR_DEBUG, "Cannot obtain surface texture"); + return; + } + + scale_box(box, wlr_output->scale); + + float matrix[9]; + enum wl_output_transform transform = wlr_output_transform_invert(surface->current.transform); + wlr_matrix_project_box(matrix, box, transform, 0.0f, wlr_output->transform_matrix); + + render_texture(wlr_output, output_damage, texture, box, matrix); +} + +static void +render_drag_icons(struct cg_output *output, pixman_region32_t *damage, struct wl_list *drag_icons) +{ + struct render_data data = { + .damage = damage, + }; + output_drag_icons_for_each_surface(output, drag_icons, render_surface_iterator, &data); +} + +/** + * Render all toplevels without descending into popups. + */ +static void +render_view_toplevels(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage) +{ + struct render_data data = { + .damage = damage, + }; + + output_view_for_each_surface(output, view, render_surface_iterator, &data); +} + +void +output_render(struct cg_output *output, pixman_region32_t *damage) +{ + struct cg_server *server = output->server; + struct wlr_output *wlr_output = output->wlr_output; + + struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); + wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); + + if (!pixman_region32_not_empty(damage)) { + wlr_log(WLR_DEBUG, "Output isn't damaged but needs a buffer swap"); + goto renderer_end; + } + +#ifdef DEBUG + if (server->debug_damage_tracking) { + wlr_renderer_clear(renderer, (float[]){1.0f, 0.0f, 0.0f, 1.0f}); + } +#endif + + float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + int nrects; + pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); + for (int i = 0; i < nrects; i++) { + scissor_output(wlr_output, &rects[i]); + wlr_renderer_clear(renderer, color); + } + + // TODO: render only top view, possibly use focused view for this, see #35. + struct cg_view *view; + wl_list_for_each_reverse(view, &server->views, link) { + render_view_toplevels(view, output, damage); + // TODO: popups on top view, possibly use focused view for this + // TODO: render only top view, possibly use focused view for this + } + + render_drag_icons(output, damage, &server->seat->drag_icons); + + renderer_end: + /* Draw software cursor in case hardware cursors aren't + available. This is a no-op when they are. */ + wlr_output_render_software_cursors(wlr_output, damage); + wlr_renderer_scissor(renderer, NULL); + wlr_renderer_end(renderer); + + int output_width, output_height; + wlr_output_transformed_resolution(wlr_output, &output_width, &output_height); + + pixman_region32_t frame_damage; + pixman_region32_init(&frame_damage); + + enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform); + wlr_region_transform(&frame_damage, &output->damage->current, transform, output_width, output_height); + +#ifdef DEBUG + if (server->debug_damage_tracking) { + pixman_region32_union_rect(&frame_damage, &frame_damage, 0, 0, output_width, output_height); + } +#endif + + wlr_output_set_damage(wlr_output, &frame_damage); + pixman_region32_fini(&frame_damage); + + if (!wlr_output_commit(wlr_output)) { + wlr_log(WLR_ERROR, "Could not commit output"); + } +} diff --git a/render.h b/render.h new file mode 100644 index 0000000..085b00b --- /dev/null +++ b/render.h @@ -0,0 +1,8 @@ +#ifndef CG_RENDER_H +#define CG_RENDER_H + +#include "output.h" + +void output_render(struct cg_output *output, pixman_region32_t *damage); + +#endif diff --git a/seat.c b/seat.c index a723eac..3f400db 100644 --- a/seat.c +++ b/seat.c @@ -1,7 +1,7 @@ /* * Cage: A Wayland kiosk. * - * Copyright (C) 2018-2019 Jente Hidskes + * Copyright (C) 2018-2020 Jente Hidskes * * See the LICENSE file accompanying this file. */ @@ -586,7 +586,8 @@ drag_icon_damage(struct cg_drag_icon *drag_icon) { struct cg_output *output; wl_list_for_each(output, &drag_icon->seat->server->outputs, link) { - output_damage_drag_icon(output, drag_icon); + output_damage_surface(output, drag_icon->wlr_drag_icon->surface, + drag_icon->lx, drag_icon->ly, true); } } diff --git a/util.c b/util.c new file mode 100644 index 0000000..95de499 --- /dev/null +++ b/util.c @@ -0,0 +1,36 @@ +/* + * Cage: A Wayland kiosk. + * + * Copyright (C) 2019 The Sway authors + * + * See the LICENSE file accompanying this file. + */ + +#include + +#include "util.h" + +int +scale_length(int length, int offset, float scale) +{ + /** + * One does not simply multiply the width by the scale. We allow fractional + * scaling, which means the resulting scaled width might be a decimal. + * So we round it. + * + * But even this can produce undesirable results depending on the X or Y + * offset of the box. For example, with a scale of 1.5, a box with + * width=1 should not scale to 2px if its X coordinate is 1, because the + * X coordinate would have scaled to 2px. + */ + return round((offset + length) * scale) - round(offset * scale); +} + +void +scale_box(struct wlr_box *box, float scale) +{ + box->width = scale_length(box->width, box->x, scale); + box->height = scale_length(box->height, box->y, scale); + box->x = round(box->x * scale); + box->y = round(box->y * scale); +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..db6bc7d --- /dev/null +++ b/util.h @@ -0,0 +1,11 @@ +#ifndef CG_UTIL_H +#define CG_UTIL_H + +#include + +/** Apply scale to a width or height. */ +int scale_length(int length, int offset, float scale); + +void scale_box(struct wlr_box *box, float scale); + +#endif diff --git a/view.c b/view.c index ee3ba73..e22ab04 100644 --- a/view.c +++ b/view.c @@ -1,7 +1,7 @@ /* * Cage: A Wayland kiosk. * - * Copyright (C) 2018-2019 Jente Hidskes + * Copyright (C) 2018-2020 Jente Hidskes * * See the LICENSE file accompanying this file. */ @@ -140,7 +140,7 @@ view_damage_part(struct cg_view *view) { struct cg_output *output; wl_list_for_each(output, &view->server->outputs, link) { - output_damage_view_surface(output, view); + output_damage_surface(output, view->wlr_surface, view->lx, view->ly, false); } } @@ -149,7 +149,7 @@ view_damage_whole(struct cg_view *view) { struct cg_output *output; wl_list_for_each(output, &view->server->outputs, link) { - output_damage_view_whole(output, view); + output_damage_surface(output, view->wlr_surface, view->lx, view->ly, true); } }