Commit 99f45f2e5b97490b5ee36f25aac4c56066e59f59 Parent: da7a19f94fd2bb82e51b67e3f32254f9d776f015 Author: mcol <mcol@posteo.net> Date: 2021-02-07 23:01:29 +0000 Committer: mcol <mcol@posteo.net> Committed: 2021-02-07 23:01:29 +0000 add rudimentary damage tracking
src/types.h Modified
@@ -123,11 +123,13 @@ struct wlr_xdg_surface *surface; struct wl_listener map_listener; struct wl_listener unmap_listener; + struct wl_listener commit_listener; struct wl_listener destroy_listener; struct wl_listener request_move_listener; struct wl_listener request_resize_listener; struct wl_listener request_fullscreen_listener; double x, y; + int width, height; bool is_scratchpad; }; @@ -135,6 +137,7 @@ struct wl_list link; struct wl_list layer_views[4]; struct wlr_output *wlr_output; + struct wlr_output_damage *wlr_output_damage; struct wl_listener frame_listener; struct wl_listener destroy_listener; };
src/shell.c Modified
@@ -1,7 +1,9 @@ +#include <wlr/types/wlr_output_damage.h> #include <wlr/types/wlr_xdg_shell.h> #include <wlr/util/edges.h> #include "action.h" +#include "output.h" #include "scratchpad.h" #include "types.h" @@ -19,6 +21,7 @@ void focus_view(struct view *view, struct wlr_surface *surface) { if (view == NULL) { wlr_seat_keyboard_notify_clear_focus(wimp.seat); + damage_all_outputs(); return; } struct wlr_seat *seat = wimp.seat; @@ -47,6 +50,7 @@ seat, view->surface->surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers ); + damage_all_outputs(); } @@ -75,13 +79,15 @@ motion.dy = (y + height) * zoom - extents->height; } pan_desk(&motion); + + damage_all_outputs(); } void fullscreen_xdg_surface( - struct view *view, struct wlr_xdg_surface *xdg_surface, struct wlr_output *output + struct view *view, struct wlr_xdg_surface *xdg_surface, struct wlr_output *wlr_output ) { - /* output can be NULL, in which case it is calculated using the surface's position */ + /* wlr_output can be NULL, in which case it is calculated using the surface's position */ struct wlr_box *saved_geo = &wimp.current_desk->fullscreened_saved_geo; struct wlr_xdg_surface *prev_surface = wimp.current_desk->fullscreened; @@ -100,12 +106,12 @@ if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) return; - if (!output) { + if (!wlr_output) { double x = view->x + xdg_surface->geometry.width / 2; double y = view->y + xdg_surface->geometry.height / 2; double lx, ly; wlr_output_layout_closest_point(wimp.output_layout, NULL, x, y, &lx, &ly); - output = wlr_output_layout_output_at(wimp.output_layout, lx, ly); + wlr_output = wlr_output_layout_output_at(wimp.output_layout, lx, ly); } wimp.current_desk->fullscreened = xdg_surface; @@ -116,7 +122,9 @@ saved_geo->height = xdg_surface->geometry.height; wlr_xdg_toplevel_set_fullscreen(xdg_surface, true); double zoom = wimp.current_desk->zoom; - wlr_xdg_toplevel_set_size(xdg_surface, output->width / zoom, output->height / zoom); + wlr_xdg_toplevel_set_size(xdg_surface, wlr_output->width / zoom, wlr_output->height / zoom); + struct output *output = wlr_output->data; + wlr_output_damage_add_whole(output->wlr_output_damage); } @@ -127,9 +135,39 @@ } +static void on_commit(struct wl_listener *listener, void *data) { + struct view *view = wl_container_of(listener, view, commit_listener); + + struct wlr_box new; + wlr_xdg_surface_get_geometry(view->surface, &new); + + if (new.width != view->width || new.height != view->height) { + struct wlr_box old = { + .x = view->x, + .y = view->x, + .width = view->width, + .height = view->height, + }; + if (new.width > old.width || new.height > old.height) { + damage_box(&new, true); + } else if (new.width <= old.width || new.height <= old.height) { + damage_box(&old, true); + } + view->width = new.width; + view->height = new.height; + + } else { + damage_by_view(view, false); + } +} + + static void on_map(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, map_listener); + view->commit_listener.notify = on_commit; + wl_signal_add(&view->surface->surface->events.commit, &view->commit_listener); + if (view->is_scratchpad) { struct scratchpad *scratchpad = scratchpad_from_view(view); scratchpad_apply_geo(scratchpad); @@ -139,6 +177,7 @@ focus_view(view, view->surface->surface); } + static void on_unmap(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, unmap_listener); struct scratchpad *scratchpad; @@ -151,6 +190,8 @@ wl_list_insert(wimp.current_desk->views.prev, &view->link); } + wl_list_remove(&view->commit_listener.link); + if (view->surface->surface != wimp.seat->keyboard_state.focused_surface) { return; }
src/output.h Modified
@@ -4,5 +4,8 @@ #include "types.h" void set_up_outputs(); +void damage_box(struct wlr_box *geo, bool add_borders); +void damage_by_view(struct view *view, bool with_borders); +void damage_all_outputs(); #endif
src/output.c Modified
@@ -1,7 +1,9 @@ #include <time.h> +#include <pixman.h> #include <wlr/types/wlr_gamma_control_v1.h> #include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_matrix.h> +#include <wlr/types/wlr_output_damage.h> #include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_management_v1.h> #include <wlr/types/wlr_xdg_output_v1.h> @@ -72,16 +74,25 @@ static void on_frame(struct wl_listener *listener, void *data) { struct output *output = wl_container_of(listener, output, frame_listener); + + bool needs_frame; + pixman_region32_t damage; + pixman_region32_init(&damage); + + if (!wlr_output_damage_attach_render(output->wlr_output_damage, &needs_frame, &damage)) { + goto finish; + } + + if (!needs_frame) { + wlr_output_rollback(output->wlr_output); + goto finish; + } + struct wlr_renderer *renderer = wimp.renderer; struct desk *desk = wimp.current_desk; - struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - if (!wlr_output_attach_render(output->wlr_output, NULL)) { - return; - } - int width, height; double zoom = desk->zoom; wlr_output_effective_resolution(output->wlr_output, &width, &height); @@ -204,6 +215,51 @@ wlr_output_render_software_cursors(output->wlr_output, NULL); // no-op with HW cursors wlr_renderer_end(renderer); wlr_output_commit(output->wlr_output); + +finish: + pixman_region32_fini(&damage); +} + + +void damage_box(struct wlr_box *geo, bool add_borders) { + + struct wlr_box damaged; + memcpy(&damaged, geo, sizeof(struct wlr_box)); + + if (add_borders) { + int border_width = wimp.current_desk->border_width; + damaged.x -= border_width; + damaged.y -= border_width; + damaged.width += border_width * 2; + damaged.height += border_width * 2; + } + + struct output *output; + wl_list_for_each(output, &wimp.outputs, link) { + wlr_output_damage_add_box(output->wlr_output_damage, &damaged); + } +} + + +void damage_by_view(struct view *view, bool with_borders) { + double zoom = wimp.current_desk->zoom; + + struct wlr_box geo = { + .x = view->x, + .y = view->y, + .width = view->width * zoom, + .height = view->height * zoom, + }; + + damage_box(&geo, with_borders); +} + + +void damage_all_outputs() { + struct output *output; + wl_list_for_each(output, &wimp.outputs, link) { + wlr_output_damage_add_whole(output->wlr_output_damage); + } } @@ -243,10 +299,11 @@ struct output *output = calloc(1, sizeof(struct output)); output->wlr_output = wlr_output; wlr_output->data = output; + output->wlr_output_damage = wlr_output_damage_create(wlr_output); output->frame_listener.notify = on_frame; output->destroy_listener.notify = on_destroy; - wl_signal_add(&wlr_output->events.frame, &output->frame_listener); + wl_signal_add(&output->wlr_output_damage->events.frame, &output->frame_listener); wl_signal_add(&wlr_output->events.destroy, &output->destroy_listener); wl_list_insert(&wimp.outputs, &output->link);
src/layer_shell.c Modified
@@ -1,4 +1,5 @@ #include <wlr/types/wlr_layer_shell_v1.h> +#include <wlr/types/wlr_output_damage.h> #include "layer_shell.h" @@ -76,6 +77,8 @@ } } } + + wlr_output_damage_add_whole(output->wlr_output_damage); }
src/desk.c Modified
@@ -1,5 +1,6 @@ #include "config.h" #include "desk.h" +#include "output.h" #include "scratchpad.h" #include "shell.h" #include "types.h" @@ -75,6 +76,8 @@ struct view *view = wl_container_of(desk->views.next, view, link); focus_view(view, view->surface->surface); } + + damage_all_outputs(); }
src/action.c Modified
@@ -7,6 +7,7 @@ #include "config.h" #include "cursor.h" #include "desk.h" +#include "output.h" #include "shell.h" #include "types.h" @@ -149,6 +150,7 @@ } desk->panned_x -= dx; desk->panned_y -= dy; + damage_all_outputs(); } @@ -170,6 +172,7 @@ desk->panned_x -= fx; desk->panned_y -= fy; desk->zoom = 1; + damage_all_outputs(); } @@ -195,6 +198,7 @@ } desk->panned_x -= fx; desk->panned_y -= fy; + damage_all_outputs(); } @@ -230,6 +234,7 @@ mark->key = 0; wimp.mark_waiting = true; wl_list_insert(&wimp.marks, &mark->link); + damage_all_outputs(); } @@ -363,6 +368,7 @@ height -= border_width * 2; wlr_xdg_toplevel_set_size(view->surface, width / zoom, height / zoom); wlr_xdg_toplevel_set_tiled(view->surface, true); + damage_all_outputs(); } @@ -386,6 +392,7 @@ double height = (output->height - border_width * 2) / zoom; wlr_xdg_toplevel_set_size(view->surface, width, height); wlr_xdg_toplevel_set_tiled(view->surface, true); + damage_all_outputs(); }
Makefile Modified
@@ -5,7 +5,8 @@ LDFLAGS += $(shell pkg-config --cflags --libs wlroots) \ $(shell pkg-config --cflags --libs wayland-server) \ $(shell pkg-config --cflags --libs xkbcommon) \ - $(shell pkg-config --cflags --libs cairo) + $(shell pkg-config --cflags --libs cairo) \ + $(shell pkg-config --cflags --libs pixman-1) PREFIX ?= /usr/local BINPREFIX ?= $(PREFIX)/bin