Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the presentation-time protocol #2950

Merged
merged 1 commit into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/sway/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct sway_output {
struct wl_listener mode;
struct wl_listener transform;
struct wl_listener scale;
struct wl_listener present;
struct wl_listener damage_destroy;
struct wl_listener damage_frame;

Expand Down
6 changes: 4 additions & 2 deletions include/sway/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_xdg_shell_v6.h>
#include <wlr/types/wlr_xdg_shell.h>
// TODO WLR: make Xwayland optional
#include "list.h"
#include "config.h"
#include "list.h"
#ifdef HAVE_XWAYLAND
#include "sway/xwayland.h"
#endif
Expand Down Expand Up @@ -58,6 +58,8 @@ struct sway_server {
struct wl_listener xdg_decoration;
struct wl_list xdg_decorations; // sway_xdg_decoration::link

struct wlr_presentation *presentation;

size_t txn_timeout_ms;
list_t *transactions;
list_t *dirty_nodes;
Expand Down
185 changes: 98 additions & 87 deletions sway/desktop/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/util/region.h>
#include "log.h"
#include "config.h"
#include "log.h"
#include "sway/config.h"
#include "sway/desktop/transaction.h"
#include "sway/input/input-manager.h"
Expand Down Expand Up @@ -223,6 +224,75 @@ void output_drag_icons_for_each_surface(struct sway_output *output,
}
}

static void for_each_surface_container_iterator(struct sway_container *con,
void *_data) {
if (!con->view || !view_is_visible(con->view)) {
return;
}

struct surface_iterator_data *data = _data;
output_view_for_each_surface(data->output, con->view,
data->user_iterator, data->user_data);
}

static void output_for_each_surface(struct sway_output *output,
sway_surface_iterator_func_t iterator, void *user_data) {
if (output_has_opaque_overlay_layer_surface(output)) {
goto overlay;
}

struct surface_iterator_data data = {
.user_iterator = iterator,
.user_data = user_data,
.output = output,
};

struct sway_workspace *workspace = output_get_active_workspace(output);
if (workspace->current.fullscreen) {
for_each_surface_container_iterator(
workspace->current.fullscreen, &data);
container_for_each_child(workspace->current.fullscreen,
for_each_surface_container_iterator, &data);
for (int i = 0; i < workspace->current.floating->length; ++i) {
struct sway_container *floater =
workspace->current.floating->items[i];
if (container_is_transient_for(floater,
workspace->current.fullscreen)) {
for_each_surface_container_iterator(floater, &data);
}
}
#ifdef HAVE_XWAYLAND
output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged,
iterator, user_data);
#endif
} else {
output_layer_for_each_surface(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
iterator, user_data);
output_layer_for_each_surface(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
iterator, user_data);

workspace_for_each_container(workspace,
for_each_surface_container_iterator, &data);

#ifdef HAVE_XWAYLAND
output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged,
iterator, user_data);
#endif
output_layer_for_each_surface(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
iterator, user_data);
}

overlay:
output_layer_for_each_surface(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
iterator, user_data);
output_drag_icons_for_each_surface(output, &root->drag_icons,
iterator, user_data);
}

static int scale_length(int length, int offset, float scale) {
return round((offset + length) * scale) - round(offset * scale);
}
Expand Down Expand Up @@ -274,96 +344,13 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {

static void send_frame_done_iterator(struct sway_output *output,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
void *_data) {
struct timespec *when = _data;
void *data) {
struct timespec *when = data;
wlr_surface_send_frame_done(surface, when);
}

static void send_frame_done_layer(struct sway_output *output,
struct wl_list *layer_surfaces, struct timespec *when) {
output_layer_for_each_surface(output, layer_surfaces,
send_frame_done_iterator, when);
}

#ifdef HAVE_XWAYLAND
static void send_frame_done_unmanaged(struct sway_output *output,
struct wl_list *unmanaged, struct timespec *when) {
output_unmanaged_for_each_surface(output, unmanaged,
send_frame_done_iterator, when);
}
#endif

static void send_frame_done_drag_icons(struct sway_output *output,
struct wl_list *drag_icons, struct timespec *when) {
output_drag_icons_for_each_surface(output, drag_icons,
send_frame_done_iterator, when);
}

struct send_frame_done_data {
struct sway_output *output;
struct timespec *when;
};

static void send_frame_done_container_iterator(struct sway_container *con,
void *_data) {
if (!con->view) {
return;
}
if (!view_is_visible(con->view)) {
return;
}

struct send_frame_done_data *data = _data;
output_view_for_each_surface(data->output, con->view,
send_frame_done_iterator, data->when);
}

static void send_frame_done(struct sway_output *output, struct timespec *when) {
if (output_has_opaque_overlay_layer_surface(output)) {
goto send_frame_overlay;
}

struct send_frame_done_data data = {
.output = output,
.when = when,
};
struct sway_workspace *workspace = output_get_active_workspace(output);
if (workspace->current.fullscreen) {
send_frame_done_container_iterator(
workspace->current.fullscreen, &data);
container_for_each_child(workspace->current.fullscreen,
send_frame_done_container_iterator, &data);
for (int i = 0; i < workspace->current.floating->length; ++i) {
struct sway_container *floater =
workspace->current.floating->items[i];
if (container_is_transient_for(floater,
workspace->current.fullscreen)) {
send_frame_done_container_iterator(floater, &data);
}
}
#ifdef HAVE_XWAYLAND
send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when);
#endif
} else {
send_frame_done_layer(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], when);
send_frame_done_layer(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], when);

workspace_for_each_container(workspace,
send_frame_done_container_iterator, &data);

#ifdef HAVE_XWAYLAND
send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when);
#endif
send_frame_done_layer(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when);
}

send_frame_overlay:
send_frame_done_layer(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when);
send_frame_done_drag_icons(output, &root->drag_icons, when);
output_for_each_surface(output, send_frame_done_iterator, when);
}

static void damage_handle_frame(struct wl_listener *listener, void *data) {
Expand Down Expand Up @@ -545,6 +532,29 @@ static void handle_scale(struct wl_listener *listener, void *data) {
transaction_commit_dirty();
}

static void send_presented_iterator(struct sway_output *output,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
void *data) {
struct wlr_presentation_event *event = data;
wlr_presentation_send_surface_presented(server.presentation,
surface, event);
}

static void handle_present(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, present);
struct wlr_output_event_present *output_event = data;

struct wlr_presentation_event event = {
.output = output->wlr_output,
.tv_sec = (uint64_t)output_event->when->tv_sec,
.tv_nsec = (uint32_t)output_event->when->tv_nsec,
.refresh = (uint32_t)output_event->refresh,
.seq = (uint64_t)output_event->seq,
.flags = output_event->flags,
};
output_for_each_surface(output, send_presented_iterator, &event);
}

void handle_new_output(struct wl_listener *listener, void *data) {
struct sway_server *server = wl_container_of(listener, server, new_output);
struct wlr_output *wlr_output = data;
Expand All @@ -571,6 +581,7 @@ void output_add_listeners(struct sway_output *output) {
output->mode.notify = handle_mode;
output->transform.notify = handle_transform;
output->scale.notify = handle_scale;
output->present.notify = handle_present;
output->damage_frame.notify = damage_handle_frame;
output->damage_destroy.notify = damage_handle_destroy;
}
3 changes: 3 additions & 0 deletions sway/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ bool server_init(struct sway_server *server) {
server->xdg_decoration.notify = handle_xdg_decoration;
wl_list_init(&server->xdg_decorations);

server->presentation =
wlr_presentation_create(server->wl_display, server->backend);

wlr_export_dmabuf_manager_v1_create(server->wl_display);
wlr_screencopy_manager_v1_create(server->wl_display);

Expand Down
2 changes: 2 additions & 0 deletions sway/tree/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
wl_signal_add(&wlr_output->events.mode, &output->mode);
wl_signal_add(&wlr_output->events.transform, &output->transform);
wl_signal_add(&wlr_output->events.scale, &output->scale);
wl_signal_add(&wlr_output->events.present, &output->present);
wl_signal_add(&output->damage->events.frame, &output->damage_frame);
wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);

Expand Down Expand Up @@ -214,6 +215,7 @@ void output_disable(struct sway_output *output) {
wl_list_remove(&output->mode.link);
wl_list_remove(&output->transform.link);
wl_list_remove(&output->scale.link);
wl_list_remove(&output->present.link);
wl_list_remove(&output->damage_destroy.link);
wl_list_remove(&output->damage_frame.link);

Expand Down