aboutsummaryrefslogtreecommitdiff
path: root/sway/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop')
-rw-r--r--sway/desktop/output.c55
-rw-r--r--sway/desktop/render.c6
-rw-r--r--sway/desktop/surface.c17
3 files changed, 61 insertions, 17 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 0f715c19..6498198b 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -23,6 +23,7 @@
#include "sway/layers.h"
#include "sway/output.h"
#include "sway/server.h"
+#include "sway/surface.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/root.h"
@@ -80,6 +81,7 @@ struct surface_iterator_data {
void *user_data;
struct sway_output *output;
+ struct sway_view *view;
double ox, oy;
int width, height;
float rotation;
@@ -134,7 +136,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface,
return;
}
- data->user_iterator(data->output, surface, &box, data->rotation,
+ data->user_iterator(data->output, data->view, surface, &box, data->rotation,
data->user_data);
}
@@ -145,6 +147,7 @@ void output_surface_for_each_surface(struct sway_output *output,
.user_iterator = iterator,
.user_data = user_data,
.output = output,
+ .view = NULL,
.ox = ox,
.oy = oy,
.width = surface->current.width,
@@ -163,6 +166,7 @@ void output_view_for_each_surface(struct sway_output *output,
.user_iterator = iterator,
.user_data = user_data,
.output = output,
+ .view = view,
.ox = view->container->surface_x - output->lx
- view->geometry.x,
.oy = view->container->surface_y - output->ly
@@ -182,6 +186,7 @@ void output_view_for_each_popup(struct sway_output *output,
.user_iterator = iterator,
.user_data = user_data,
.output = output,
+ .view = view,
.ox = view->container->surface_x - output->lx
- view->geometry.x,
.oy = view->container->surface_y - output->ly
@@ -224,6 +229,7 @@ void output_layer_for_each_surface(struct sway_output *output,
.user_iterator = iterator,
.user_data = user_data,
.output = output,
+ .view = NULL,
.ox = popup_sx,
.oy = popup_sy,
.width = surface->current.width,
@@ -291,6 +297,7 @@ static void output_for_each_surface(struct sway_output *output,
.user_iterator = iterator,
.user_data = user_data,
.output = output,
+ .view = NULL,
};
struct sway_workspace *workspace = output_get_active_workspace(output);
@@ -401,18 +408,37 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {
return false;
}
-static void send_frame_done_iterator(struct sway_output *output,
+struct send_frame_done_data {
+ struct timespec when;
+ int msec_until_refresh;
+};
+
+static void send_frame_done_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
- void *data) {
- struct timespec *when = data;
- wlr_surface_send_frame_done(surface, when);
+ void *user_data) {
+ int view_max_render_time = 0;
+ if (view != NULL) {
+ view_max_render_time = view->max_render_time;
+ }
+
+ struct send_frame_done_data *data = user_data;
+
+ int delay = data->msec_until_refresh - output->max_render_time
+ - view_max_render_time;
+
+ if (output->max_render_time == 0 || view_max_render_time == 0 || delay < 1) {
+ wlr_surface_send_frame_done(surface, &data->when);
+ } else {
+ struct sway_surface *sway_surface = surface->data;
+ wl_event_source_timer_update(sway_surface->frame_done_timer, delay);
+ }
}
-static void send_frame_done(struct sway_output *output, struct timespec *when) {
- output_for_each_surface(output, send_frame_done_iterator, when);
+static void send_frame_done(struct sway_output *output, struct send_frame_done_data *data) {
+ output_for_each_surface(output, send_frame_done_iterator, data);
}
-static void count_surface_iterator(struct sway_output *output,
+static void count_surface_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *_box, float rotation,
void *data) {
size_t *n = data;
@@ -533,7 +559,7 @@ int output_repaint_timer_handler(void *data) {
return 0;
}
-static void damage_handle_frame(struct wl_listener *listener, void *data) {
+static void damage_handle_frame(struct wl_listener *listener, void *user_data) {
struct sway_output *output =
wl_container_of(listener, output, damage_frame);
if (!output->enabled || !output->wlr_output->enabled) {
@@ -592,9 +618,10 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) {
}
// Send frame done to all visible surfaces
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- send_frame_done(output, &now);
+ struct send_frame_done_data data = {0};
+ clock_gettime(CLOCK_MONOTONIC, &data.when);
+ data.msec_until_refresh = msec_until_refresh;
+ send_frame_done(output, &data);
}
void output_damage_whole(struct sway_output *output) {
@@ -605,7 +632,7 @@ void output_damage_whole(struct sway_output *output) {
}
}
-static void damage_surface_iterator(struct sway_output *output,
+static void damage_surface_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *_box, float rotation,
void *_data) {
bool *data = _data;
@@ -811,7 +838,7 @@ static void handle_scale(struct wl_listener *listener, void *data) {
update_output_manager_config(output->server);
}
-static void send_presented_iterator(struct sway_output *output,
+static void send_presented_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
void *data) {
struct wlr_presentation_event *event = data;
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 916d4eba..c432b476 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -97,7 +97,7 @@ damage_finish:
pixman_region32_fini(&damage);
}
-static void render_surface_iterator(struct sway_output *output,
+static void render_surface_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *_box, float rotation,
void *_data) {
struct render_data *data = _data;
@@ -214,11 +214,11 @@ static void render_view_toplevels(struct sway_view *view,
render_surface_iterator, &data);
}
-static void render_popup_iterator(struct sway_output *output,
+static void render_popup_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
void *data) {
// Render this popup's surface
- render_surface_iterator(output, surface, box, rotation, data);
+ render_surface_iterator(output, view, surface, box, rotation, data);
// Render this popup's child toplevels
output_surface_for_each_surface(output, surface, box->x, box->y,
diff --git a/sway/desktop/surface.c b/sway/desktop/surface.c
index 41d4ce3f..853c403d 100644
--- a/sway/desktop/surface.c
+++ b/sway/desktop/surface.c
@@ -1,4 +1,6 @@
+#define _POSIX_C_SOURCE 200112L
#include <stdlib.h>
+#include <time.h>
#include <wlr/types/wlr_surface.h>
#include "sway/server.h"
#include "sway/surface.h"
@@ -9,9 +11,21 @@ void handle_destroy(struct wl_listener *listener, void *data) {
surface->wlr_surface->data = NULL;
wl_list_remove(&surface->destroy.link);
+ wl_event_source_remove(surface->frame_done_timer);
+
free(surface);
}
+static int surface_frame_done_timer_handler(void *data) {
+ struct sway_surface *surface = data;
+
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ wlr_surface_send_frame_done(surface->wlr_surface, &now);
+
+ return 0;
+}
+
void handle_compositor_new_surface(struct wl_listener *listener, void *data) {
struct wlr_surface *wlr_surface = data;
@@ -21,4 +35,7 @@ void handle_compositor_new_surface(struct wl_listener *listener, void *data) {
surface->destroy.notify = handle_destroy;
wl_signal_add(&wlr_surface->events.destroy, &surface->destroy);
+
+ surface->frame_done_timer = wl_event_loop_add_timer(server.wl_event_loop,
+ surface_frame_done_timer_handler, surface);
}