mirror of
https://github.com/swaywm/sway.git
synced 2024-11-10 10:23:13 +00:00
Don't damage the whole output
This commit is contained in:
parent
e550e22c0b
commit
58914822aa
|
@ -1,8 +1,8 @@
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <time.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/types/wlr_box.h>
|
#include <wlr/types/wlr_box.h>
|
||||||
|
@ -12,6 +12,7 @@
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
#include <wlr/types/wlr_surface.h>
|
#include <wlr/types/wlr_surface.h>
|
||||||
#include <wlr/types/wlr_wl_shell.h>
|
#include <wlr/types/wlr_wl_shell.h>
|
||||||
|
#include <wlr/util/region.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "sway/input/input-manager.h"
|
#include "sway/input/input-manager.h"
|
||||||
#include "sway/input/seat.h"
|
#include "sway/input/seat.h"
|
||||||
|
@ -95,13 +96,13 @@ static bool get_surface_box(struct root_geometry *geo,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_surface_for_each_surface(struct wlr_surface *surface,
|
static void output_surface_for_each_surface(struct wlr_surface *surface,
|
||||||
double ox, double oy, float rotation, struct root_geometry *geo,
|
double ox, double oy, struct root_geometry *geo,
|
||||||
wlr_surface_iterator_func_t iterator, void *user_data) {
|
wlr_surface_iterator_func_t iterator, void *user_data) {
|
||||||
geo->x = ox;
|
geo->x = ox;
|
||||||
geo->y = oy;
|
geo->y = oy;
|
||||||
geo->width = surface->current->width;
|
geo->width = surface->current->width;
|
||||||
geo->height = surface->current->height;
|
geo->height = surface->current->height;
|
||||||
geo->rotation = rotation;
|
geo->rotation = 0;
|
||||||
|
|
||||||
wlr_surface_for_each_surface(surface, iterator, user_data);
|
wlr_surface_for_each_surface(surface, iterator, user_data);
|
||||||
}
|
}
|
||||||
|
@ -174,14 +175,14 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_surface(struct sway_output *output, struct timespec *when,
|
static void render_surface(struct sway_output *output, struct timespec *when,
|
||||||
struct wlr_surface *surface, double ox, double oy, float rotation) {
|
struct wlr_surface *surface, double ox, double oy) {
|
||||||
struct render_data data = {
|
struct render_data data = {
|
||||||
.output = output,
|
.output = output,
|
||||||
.when = when,
|
.when = when,
|
||||||
.alpha = 1.0f,
|
.alpha = 1.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
output_surface_for_each_surface(surface, ox, oy, rotation, &data.root_geo,
|
output_surface_for_each_surface(surface, ox, oy, &data.root_geo,
|
||||||
render_surface_iterator, &data);
|
render_surface_iterator, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +205,7 @@ static void render_layer(struct sway_output *output, struct timespec *when,
|
||||||
struct wlr_layer_surface *wlr_layer_surface =
|
struct wlr_layer_surface *wlr_layer_surface =
|
||||||
layer_surface->layer_surface;
|
layer_surface->layer_surface;
|
||||||
render_surface(output, when, wlr_layer_surface->surface,
|
render_surface(output, when, wlr_layer_surface->surface,
|
||||||
layer_surface->geo.x, layer_surface->geo.y, 0);
|
layer_surface->geo.x, layer_surface->geo.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +242,11 @@ static void render_output(struct sway_output *output, struct timespec *when,
|
||||||
goto renderer_end;
|
goto renderer_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: don't damage the whole output
|
||||||
|
int width, height;
|
||||||
|
wlr_output_transformed_resolution(wlr_output, &width, &height);
|
||||||
|
pixman_region32_union_rect(damage, damage, 0, 0, width, height);
|
||||||
|
|
||||||
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
|
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
|
||||||
wlr_renderer_clear(renderer, clear_color);
|
wlr_renderer_clear(renderer, clear_color);
|
||||||
|
|
||||||
|
@ -270,7 +276,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
|
||||||
unmanaged_surface->wlr_xwayland_surface;
|
unmanaged_surface->wlr_xwayland_surface;
|
||||||
double ox = unmanaged_surface->lx - output->swayc->x;
|
double ox = unmanaged_surface->lx - output->swayc->x;
|
||||||
double oy = unmanaged_surface->ly - output->swayc->y;
|
double oy = unmanaged_surface->ly - output->swayc->y;
|
||||||
render_surface(output, when, xsurface->surface, ox, oy, 0);
|
render_surface(output, when, xsurface->surface, ox, oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: consider revising this when fullscreen windows are supported
|
// TODO: consider revising this when fullscreen windows are supported
|
||||||
|
@ -318,22 +324,93 @@ void output_damage_whole(struct sway_output *output) {
|
||||||
wlr_output_damage_add_whole(output->damage);
|
wlr_output_damage_add_whole(output->damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct damage_data {
|
||||||
|
struct root_geometry root_geo;
|
||||||
|
struct sway_output *output;
|
||||||
|
bool whole;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy,
|
||||||
|
void *_data) {
|
||||||
|
struct damage_data *data = _data;
|
||||||
|
struct sway_output *output = data->output;
|
||||||
|
float rotation = data->root_geo.rotation;
|
||||||
|
bool whole = data->whole;
|
||||||
|
|
||||||
|
if (!wlr_surface_has_buffer(surface)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_box box;
|
||||||
|
bool intersects = get_surface_box(&data->root_geo, data->output, surface,
|
||||||
|
sx, sy, &box);
|
||||||
|
if (!intersects) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale_box(&box, output->wlr_output->scale);
|
||||||
|
|
||||||
|
if (whole) {
|
||||||
|
wlr_box_rotated_bounds(&box, rotation, &box);
|
||||||
|
wlr_output_damage_add_box(output->damage, &box);
|
||||||
|
} else {
|
||||||
|
int center_x = box.x + box.width/2;
|
||||||
|
int center_y = box.y + box.height/2;
|
||||||
|
|
||||||
|
pixman_region32_t damage;
|
||||||
|
pixman_region32_init(&damage);
|
||||||
|
pixman_region32_copy(&damage, &surface->current->surface_damage);
|
||||||
|
wlr_region_scale(&damage, &damage, output->wlr_output->scale);
|
||||||
|
if (ceil(output->wlr_output->scale) > surface->current->scale) {
|
||||||
|
// When scaling up a surface, it'll become blurry so we need to
|
||||||
|
// expand the damage region
|
||||||
|
wlr_region_expand(&damage, &damage,
|
||||||
|
ceil(output->wlr_output->scale) - surface->current->scale);
|
||||||
|
}
|
||||||
|
pixman_region32_translate(&damage, box.x, box.y);
|
||||||
|
wlr_region_rotated_bounds(&damage, &damage, rotation,
|
||||||
|
center_x, center_y);
|
||||||
|
wlr_output_damage_add(output->damage, &damage);
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void output_damage_surface(struct sway_output *output, double ox, double oy,
|
void output_damage_surface(struct sway_output *output, double ox, double oy,
|
||||||
struct wlr_surface *surface, bool whole) {
|
struct wlr_surface *surface, bool whole) {
|
||||||
// TODO
|
struct damage_data data = {
|
||||||
output_damage_whole(output);
|
.output = output,
|
||||||
|
.whole = whole,
|
||||||
|
};
|
||||||
|
|
||||||
|
output_surface_for_each_surface(surface, ox, oy, &data.root_geo,
|
||||||
|
damage_surface_iterator, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_damage_view(struct sway_output *output, struct sway_view *view,
|
void output_damage_view(struct sway_output *output, struct sway_view *view,
|
||||||
bool whole) {
|
bool whole) {
|
||||||
// TODO
|
if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) {
|
||||||
output_damage_whole(output);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct damage_data data = {
|
||||||
|
.output = output,
|
||||||
|
.whole = whole,
|
||||||
|
};
|
||||||
|
|
||||||
|
output_view_for_each_surface(view, &data.root_geo,
|
||||||
|
damage_surface_iterator, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_damage_whole_container(struct sway_output *output,
|
void output_damage_whole_container(struct sway_output *output,
|
||||||
struct sway_container *con) {
|
struct sway_container *con) {
|
||||||
// TODO
|
float scale = output->wlr_output->scale;
|
||||||
output_damage_whole(output);
|
struct wlr_box box = {
|
||||||
|
.x = con->x * scale,
|
||||||
|
.y = con->y * scale,
|
||||||
|
.width = con->width * scale,
|
||||||
|
.height = con->height * scale,
|
||||||
|
};
|
||||||
|
wlr_output_damage_add_box(output->damage, &box);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void damage_handle_destroy(struct wl_listener *listener, void *data) {
|
static void damage_handle_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
|
|
@ -143,9 +143,7 @@ static void destroy(struct sway_view *view) {
|
||||||
if (xdg_shell_v6_view == NULL) {
|
if (xdg_shell_v6_view == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wl_list_remove(&xdg_shell_v6_view->commit.link);
|
|
||||||
wl_list_remove(&xdg_shell_v6_view->destroy.link);
|
wl_list_remove(&xdg_shell_v6_view->destroy.link);
|
||||||
wl_list_remove(&xdg_shell_v6_view->new_popup.link);
|
|
||||||
wl_list_remove(&xdg_shell_v6_view->map.link);
|
wl_list_remove(&xdg_shell_v6_view->map.link);
|
||||||
wl_list_remove(&xdg_shell_v6_view->unmap.link);
|
wl_list_remove(&xdg_shell_v6_view->unmap.link);
|
||||||
free(xdg_shell_v6_view);
|
free(xdg_shell_v6_view);
|
||||||
|
@ -182,14 +180,28 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
|
||||||
static void handle_unmap(struct wl_listener *listener, void *data) {
|
static void handle_unmap(struct wl_listener *listener, void *data) {
|
||||||
struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
|
struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
|
||||||
wl_container_of(listener, xdg_shell_v6_view, unmap);
|
wl_container_of(listener, xdg_shell_v6_view, unmap);
|
||||||
|
|
||||||
view_unmap(&xdg_shell_v6_view->view);
|
view_unmap(&xdg_shell_v6_view->view);
|
||||||
|
|
||||||
|
wl_list_remove(&xdg_shell_v6_view->commit.link);
|
||||||
|
wl_list_remove(&xdg_shell_v6_view->new_popup.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_map(struct wl_listener *listener, void *data) {
|
static void handle_map(struct wl_listener *listener, void *data) {
|
||||||
struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
|
struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
|
||||||
wl_container_of(listener, xdg_shell_v6_view, map);
|
wl_container_of(listener, xdg_shell_v6_view, map);
|
||||||
struct sway_view *view = &xdg_shell_v6_view->view;
|
struct sway_view *view = &xdg_shell_v6_view->view;
|
||||||
|
struct wlr_xdg_surface_v6 *xdg_surface = view->wlr_xdg_surface_v6;
|
||||||
|
|
||||||
view_map(view, view->wlr_xdg_surface_v6->surface);
|
view_map(view, view->wlr_xdg_surface_v6->surface);
|
||||||
|
|
||||||
|
xdg_shell_v6_view->commit.notify = handle_commit;
|
||||||
|
wl_signal_add(&xdg_surface->surface->events.commit,
|
||||||
|
&xdg_shell_v6_view->commit);
|
||||||
|
|
||||||
|
xdg_shell_v6_view->new_popup.notify = handle_new_popup;
|
||||||
|
wl_signal_add(&xdg_surface->events.new_popup,
|
||||||
|
&xdg_shell_v6_view->new_popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_destroy(struct wl_listener *listener, void *data) {
|
static void handle_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
@ -226,14 +238,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
|
||||||
// - Look up pid and open on appropriate workspace
|
// - Look up pid and open on appropriate workspace
|
||||||
// - Criteria
|
// - Criteria
|
||||||
|
|
||||||
xdg_shell_v6_view->commit.notify = handle_commit;
|
|
||||||
wl_signal_add(&xdg_surface->surface->events.commit,
|
|
||||||
&xdg_shell_v6_view->commit);
|
|
||||||
|
|
||||||
xdg_shell_v6_view->new_popup.notify = handle_new_popup;
|
|
||||||
wl_signal_add(&xdg_surface->events.new_popup,
|
|
||||||
&xdg_shell_v6_view->new_popup);
|
|
||||||
|
|
||||||
xdg_shell_v6_view->map.notify = handle_map;
|
xdg_shell_v6_view->map.notify = handle_map;
|
||||||
wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map);
|
wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue