aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremersion <contact@emersion.fr>2018-01-27 10:43:17 +0100
committeremersion <contact@emersion.fr>2018-01-27 10:43:17 +0100
commit7111dd79efb6cccf39866051a92090cfc9ea5c67 (patch)
treed3e05791ad4341cddbb038840d99b2d4cd5bdae7
parenta011a1cb075bed2235162f1af7e88d0ee534acad (diff)
rootston: damage tracking for rotated views
-rw-r--r--include/rootston/view.h1
-rw-r--r--include/wlr/types/wlr_box.h6
-rw-r--r--rootston/cursor.c2
-rw-r--r--rootston/desktop.c18
-rw-r--r--rootston/output.c31
-rw-r--r--types/wlr_box.c29
6 files changed, 74 insertions, 13 deletions
diff --git a/include/rootston/view.h b/include/rootston/view.h
index 35660d64..c9d1deb2 100644
--- a/include/rootston/view.h
+++ b/include/rootston/view.h
@@ -164,6 +164,7 @@ void view_move_resize(struct roots_view *view, double x, double y,
void view_maximize(struct roots_view *view, bool maximized);
void view_set_fullscreen(struct roots_view *view, bool fullscreen,
struct wlr_output *output);
+void view_rotate(struct roots_view *view, float rotation);
void view_close(struct roots_view *view);
bool view_center(struct roots_view *view);
void view_setup(struct roots_view *view);
diff --git a/include/wlr/types/wlr_box.h b/include/wlr/types/wlr_box.h
index d6cc3509..fc86f0ac 100644
--- a/include/wlr/types/wlr_box.h
+++ b/include/wlr/types/wlr_box.h
@@ -26,4 +26,10 @@ void wlr_box_transform(const struct wlr_box *box,
enum wl_output_transform transform, int width, int height,
struct wlr_box *dest);
+/**
+ * Creates the smallest box that contains a rotated box.
+ */
+void wlr_box_rotated_bounds(const struct wlr_box *box, float rotation,
+ struct wlr_box *dest);
+
#endif
diff --git a/rootston/cursor.c b/rootston/cursor.c
index a09211b7..158c4708 100644
--- a/rootston/cursor.c
+++ b/rootston/cursor.c
@@ -203,7 +203,7 @@ static void roots_cursor_update_position(struct roots_cursor *cursor,
float angle = atan2(vx*uy - vy*ux, vx*ux + vy*uy);
int steps = 12;
angle = round(angle/M_PI*steps) / (steps/M_PI);
- view->rotation = cursor->view_rotation + angle;
+ view_rotate(view, cursor->view_rotation + angle);
}
break;
}
diff --git a/rootston/desktop.c b/rootston/desktop.c
index b2d586f4..25930d2a 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -200,7 +200,7 @@ void view_maximize(struct roots_view *view, bool maximized) {
view_move_resize(view, output_box->x, output_box->y, output_box->width,
output_box->height);
- view->rotation = 0;
+ view_rotate(view, 0);
}
if (view->maximized && !maximized) {
@@ -208,7 +208,7 @@ void view_maximize(struct roots_view *view, bool maximized) {
view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
view->saved.height);
- view->rotation = view->saved.rotation;
+ view_rotate(view, view->saved.rotation);
}
}
@@ -249,7 +249,7 @@ void view_set_fullscreen(struct roots_view *view, bool fullscreen,
wlr_output_layout_get_box(view->desktop->layout, output);
view_move_resize(view, output_box->x, output_box->y, output_box->width,
output_box->height);
- view->rotation = 0;
+ view_rotate(view, 0);
roots_output->fullscreen_view = view;
view->fullscreen_output = roots_output;
@@ -258,13 +258,23 @@ void view_set_fullscreen(struct roots_view *view, bool fullscreen,
if (was_fullscreen && !fullscreen) {
view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
view->saved.height);
- view->rotation = view->saved.rotation;
+ view_rotate(view, view->saved.rotation);
view->fullscreen_output->fullscreen_view = NULL;
view->fullscreen_output = NULL;
}
}
+void view_rotate(struct roots_view *view, float rotation) {
+ if (view->rotation == rotation) {
+ return;
+ }
+
+ view_damage_whole(view);
+ view->rotation = rotation;
+ view_damage_whole(view);
+}
+
void view_close(struct roots_view *view) {
if (view->close) {
view->close(view);
diff --git a/rootston/output.c b/rootston/output.c
index f928184b..d4cd1efd 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -155,7 +155,7 @@ struct render_data {
*/
static bool surface_intersect_output(struct wlr_surface *surface,
struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,
- double lx, double ly, struct wlr_box *box) {
+ double lx, double ly, float rotation, struct wlr_box *box) {
double ox = lx, oy = ly;
wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);
box->x = ox * wlr_output->scale;
@@ -167,6 +167,7 @@ static bool surface_intersect_output(struct wlr_surface *surface,
.x = lx, .y = ly,
.width = surface->current->width, .height = surface->current->height,
};
+ wlr_box_rotated_bounds(&layout_box, -rotation, &layout_box);
return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
}
@@ -215,15 +216,18 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,
struct wlr_box box;
bool intersects = surface_intersect_output(surface, output->desktop->layout,
- output->wlr_output, lx, ly, &box);
+ output->wlr_output, lx, ly, rotation, &box);
if (!intersects) {
return;
}
+ struct wlr_box rotated;
+ wlr_box_rotated_bounds(&box, -rotation, &rotated);
+
pixman_region32_t damage;
pixman_region32_init(&damage);
- pixman_region32_union_rect(&damage, &damage, box.x, box.y,
- box.width, box.height);
+ pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
+ rotated.width, rotated.height);
pixman_region32_intersect(&damage, &damage, data->damage);
bool damaged = pixman_region32_not_empty(&damage);
if (!damaged) {
@@ -415,6 +419,8 @@ static void render_output(struct roots_output *output) {
goto renderer_end;
}
+ wlr_renderer_clear(output->desktop->server->renderer, 1, 1, 1, 1);
+
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) {
@@ -526,12 +532,14 @@ static void damage_whole_surface(struct wlr_surface *surface,
}
struct wlr_box box;
- bool intersects = surface_intersect_output(surface,
- output->desktop->layout, output->wlr_output, lx, ly, &box);
+ bool intersects = surface_intersect_output(surface, output->desktop->layout,
+ output->wlr_output, lx, ly, rotation, &box);
if (!intersects) {
return;
}
+ wlr_box_rotated_bounds(&box, -rotation, &box);
+
pixman_region32_union_rect(&output->damage, &output->damage,
box.x, box.y, box.width, box.height);
@@ -547,6 +555,8 @@ static void damage_whole_decoration(struct roots_view *view,
struct wlr_box box;
get_decoration_box(view, output, &box);
+ wlr_box_rotated_bounds(&box, -view->rotation, &box);
+
pixman_region32_union_rect(&output->damage, &output->damage,
box.x, box.y, box.width, box.height);
}
@@ -576,8 +586,8 @@ static void damage_from_surface(struct wlr_surface *surface,
}
struct wlr_box box;
- bool intersects = surface_intersect_output(surface,
- output->desktop->layout, output->wlr_output, lx, ly, &box);
+ bool intersects = surface_intersect_output(surface, output->desktop->layout,
+ output->wlr_output, lx, ly, rotation, &box);
if (!intersects) {
return;
}
@@ -599,6 +609,11 @@ void output_damage_from_view(struct roots_output *output,
return;
}
+ if (view->rotation != 0) {
+ output_damage_whole_view(output, view);
+ return;
+ }
+
view_for_each_surface(view, damage_from_surface, output);
}
diff --git a/types/wlr_box.c b/types/wlr_box.c
index 3217a7d0..a7388209 100644
--- a/types/wlr_box.c
+++ b/types/wlr_box.c
@@ -114,3 +114,32 @@ void wlr_box_transform(const struct wlr_box *box,
break;
}
}
+
+void wlr_box_rotated_bounds(const struct wlr_box *box, float rotation,
+ struct wlr_box *dest) {
+ if (rotation == 0) {
+ *dest = *box;
+ return;
+ }
+
+ double ox = box->x + (double)box->width/2;
+ double oy = box->y + (double)box->height/2;
+
+ double c = fabs(cos(rotation));
+ double s = fabs(sin(rotation));
+
+ double x1 = ox + (box->x - ox) * c + (box->y - oy) * s;
+ double x2 = ox +
+ (box->x + box->width - ox) * c +
+ (box->y + box->height - oy) * s;
+
+ double y1 = oy + (box->x - ox) * s + (box->y - oy) * c;
+ double y2 = oy +
+ (box->x + box->width - ox) * s +
+ (box->y + box->height - oy) * c;
+
+ dest->x = fmin(x1, x2);
+ dest->width = fmax(x1, x2) - fmin(x1, x2);
+ dest->y = fmin(y1, y2);
+ dest->height = fmax(y1, y2) - fmin(y1, y2);
+}