aboutsummaryrefslogtreecommitdiff
path: root/rootston
diff options
context:
space:
mode:
Diffstat (limited to 'rootston')
-rw-r--r--rootston/config.c2
-rw-r--r--rootston/desktop.c3
-rw-r--r--rootston/keyboard.c14
-rw-r--r--rootston/output.c180
4 files changed, 130 insertions, 69 deletions
diff --git a/rootston/config.c b/rootston/config.c
index 5c168679..119a9e2c 100644
--- a/rootston/config.c
+++ b/rootston/config.c
@@ -577,7 +577,7 @@ void roots_config_destroy(struct roots_config *config) {
struct roots_output_config *roots_config_get_output(struct roots_config *config,
struct wlr_output *output) {
- char name[83];
+ char name[88];
snprintf(name, sizeof(name), "%s %s %s", output->make, output->model,
output->serial);
diff --git a/rootston/desktop.c b/rootston/desktop.c
index c180c839..7f749050 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -969,6 +969,9 @@ struct roots_desktop *desktop_create(struct roots_server *server,
wl_signal_add(&desktop->pointer_constraints->events.new_constraint,
&desktop->pointer_constraint);
+ desktop->presentation =
+ wlr_presentation_create(server->wl_display, server->backend);
+
return desktop;
}
diff --git a/rootston/keyboard.c b/rootston/keyboard.c
index 6ba0bd6d..66c373cf 100644
--- a/rootston/keyboard.c
+++ b/rootston/keyboard.c
@@ -5,7 +5,6 @@
#include <sys/wait.h>
#include <unistd.h>
#include <wayland-server.h>
-#include <wlr/backend/multi.h>
#include <wlr/backend/session.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
@@ -201,14 +200,13 @@ static bool keyboard_execute_compositor_binding(struct roots_keyboard *keyboard,
if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
keysym <= XKB_KEY_XF86Switch_VT_12) {
struct roots_server *server = keyboard->input->server;
- if (wlr_backend_is_multi(server->backend)) {
- struct wlr_session *session =
- wlr_multi_get_session(server->backend);
- if (session) {
- unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
- wlr_session_change_vt(session, vt);
- }
+
+ struct wlr_session *session = wlr_backend_get_session(server->backend);
+ if (session) {
+ unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
+ wlr_session_change_vt(session, vt);
}
+
return true;
}
diff --git a/rootston/output.c b/rootston/output.c
index e85612fa..9d376f8e 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -5,9 +5,10 @@
#include <time.h>
#include <wlr/backend/drm.h>
#include <wlr/config.h>
-#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_compositor.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_wl_shell.h>
#include <wlr/types/wlr_xdg_shell_v6.h>
#include <wlr/types/wlr_xdg_shell.h>
@@ -127,6 +128,65 @@ static void drag_icons_for_each_surface(struct roots_input *input,
}
}
+static void layer_for_each_surface(struct wl_list *layer,
+ const struct wlr_box *output_layout_box,
+ wlr_surface_iterator_func_t iterator, struct layout_data *layout_data,
+ void *user_data) {
+ struct roots_layer_surface *roots_surface;
+ wl_list_for_each(roots_surface, layer, link) {
+ struct wlr_layer_surface_v1 *layer = roots_surface->layer_surface;
+
+ layout_data->x = roots_surface->geo.x + output_layout_box->x;
+ layout_data->y = roots_surface->geo.y + output_layout_box->y;
+ layout_data->width = roots_surface->geo.width;
+ layout_data->height = roots_surface->geo.height;
+ layout_data->rotation = 0;
+ wlr_layer_surface_v1_for_each_surface(layer, iterator, user_data);
+ }
+}
+
+static void output_for_each_surface(struct roots_output *output,
+ wlr_surface_iterator_func_t iterator, struct layout_data *layout_data,
+ void *user_data) {
+ struct wlr_output *wlr_output = output->wlr_output;
+ struct roots_desktop *desktop = output->desktop;
+ struct roots_server *server = desktop->server;
+
+ const struct wlr_box *output_box =
+ wlr_output_layout_get_box(desktop->layout, wlr_output);
+
+ if (output->fullscreen_view != NULL) {
+ struct roots_view *view = output->fullscreen_view;
+ if (wlr_output->fullscreen_surface == view->wlr_surface) {
+ // The surface is managed by the wlr_output
+ return;
+ }
+
+ view_for_each_surface(view, layout_data, iterator, user_data);
+
+#ifdef WLR_HAS_XWAYLAND
+ if (view->type == ROOTS_XWAYLAND_VIEW) {
+ xwayland_children_for_each_surface(view->xwayland_surface,
+ iterator, layout_data, user_data);
+ }
+#endif
+ } else {
+ struct roots_view *view;
+ wl_list_for_each_reverse(view, &desktop->views, link) {
+ view_for_each_surface(view, layout_data, iterator, user_data);
+ }
+
+ drag_icons_for_each_surface(server->input, iterator,
+ layout_data, user_data);
+ }
+
+ size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
+ for (size_t i = 0; i < len; ++i) {
+ layer_for_each_surface(&output->layers[i], output_box,
+ iterator, layout_data, user_data);
+ }
+}
+
struct render_data {
struct layout_data layout;
@@ -320,6 +380,14 @@ static void render_view(struct roots_view *view, struct render_data *data) {
view_for_each_surface(view, &data->layout, render_surface, data);
}
+static void render_layer(struct roots_output *output,
+ const struct wlr_box *output_layout_box, struct render_data *data,
+ struct wl_list *layer) {
+ data->alpha = 1;
+ layer_for_each_surface(layer, output_layout_box, render_surface,
+ &data->layout, data);
+}
+
static bool has_standalone_surface(struct roots_view *view) {
if (!wl_list_empty(&view->wlr_surface->subsurfaces)) {
return false;
@@ -358,38 +426,6 @@ static void surface_send_frame_done(struct wlr_surface *surface, int sx, int sy,
wlr_surface_send_frame_done(surface, when);
}
-static void render_layer(struct roots_output *output,
- const struct wlr_box *output_layout_box, struct render_data *data,
- struct wl_list *layer) {
- struct roots_layer_surface *roots_surface;
- wl_list_for_each(roots_surface, layer, link) {
- struct wlr_layer_surface_v1 *layer = roots_surface->layer_surface;
-
- surface_for_each_surface(layer->surface,
- roots_surface->geo.x + output_layout_box->x,
- roots_surface->geo.y + output_layout_box->y,
- 0, &data->layout, render_surface, data);
-
- wlr_layer_surface_v1_for_each_surface(layer, render_surface, data);
- }
-}
-
-static void layers_send_done(
- struct roots_output *output, struct timespec *when) {
- size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
- for (size_t i = 0; i < len; ++i) {
- struct roots_layer_surface *roots_surface;
- wl_list_for_each(roots_surface, &output->layers[i], link) {
- struct wlr_layer_surface_v1 *layer = roots_surface->layer_surface;
- wlr_surface_send_frame_done(layer->surface, when);
- struct wlr_xdg_popup *popup;
- wl_list_for_each(popup, &roots_surface->layer_surface->popups, link) {
- wlr_surface_send_frame_done(popup->base->surface, when);
- }
- }
- }
-}
-
static void render_output(struct roots_output *output) {
struct wlr_output *wlr_output = output->wlr_output;
struct roots_desktop *desktop = output->desktop;
@@ -537,33 +573,8 @@ damage_finish:
pixman_region32_fini(&damage);
// Send frame done events to all surfaces
- if (output->fullscreen_view != NULL) {
- struct roots_view *view = output->fullscreen_view;
- if (wlr_output->fullscreen_surface == view->wlr_surface) {
- // The surface is managed by the wlr_output
- return;
- }
-
- view_for_each_surface(view, &data.layout, surface_send_frame_done,
- &data);
-
-#ifdef WLR_HAS_XWAYLAND
- if (view->type == ROOTS_XWAYLAND_VIEW) {
- xwayland_children_for_each_surface(view->xwayland_surface,
- surface_send_frame_done, &data.layout, &data);
- }
-#endif
- } else {
- struct roots_view *view;
- wl_list_for_each_reverse(view, &desktop->views, link) {
- view_for_each_surface(view, &data.layout, surface_send_frame_done,
- &data);
- }
-
- drag_icons_for_each_surface(server->input, surface_send_frame_done,
- &data.layout, &data);
- }
- layers_send_done(output, data.when);
+ output_for_each_surface(output, surface_send_frame_done,
+ &data.layout, &data);
}
void output_damage_whole(struct roots_output *output) {
@@ -774,6 +785,7 @@ static void output_destroy(struct roots_output *output) {
wl_list_remove(&output->destroy.link);
wl_list_remove(&output->mode.link);
wl_list_remove(&output->transform.link);
+ wl_list_remove(&output->present.link);
wl_list_remove(&output->damage_frame.link);
wl_list_remove(&output->damage_destroy.link);
free(output);
@@ -810,6 +822,52 @@ static void output_handle_transform(struct wl_listener *listener, void *data) {
arrange_layers(output);
}
+struct presentation_data {
+ struct layout_data layout;
+ struct roots_output *output;
+ struct wlr_presentation_event *event;
+};
+
+static void surface_send_presented(struct wlr_surface *surface, int sx, int sy,
+ void *_data) {
+ struct presentation_data *data = _data;
+ struct roots_output *output = data->output;
+ float rotation = data->layout.rotation;
+
+ double lx, ly;
+ get_layout_position(&data->layout, &lx, &ly, surface, sx, sy);
+
+ if (!surface_intersect_output(surface, output->desktop->layout,
+ output->wlr_output, lx, ly, rotation, NULL)) {
+ return;
+ }
+
+ wlr_presentation_send_surface_presented(output->desktop->presentation,
+ surface, data->event);
+}
+
+static void output_handle_present(struct wl_listener *listener, void *data) {
+ struct roots_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,
+ };
+
+ struct presentation_data presentation_data = {
+ .output = output,
+ .event = &event,
+ };
+ output_for_each_surface(output, surface_send_presented,
+ &presentation_data.layout, &presentation_data);
+}
+
void handle_new_output(struct wl_listener *listener, void *data) {
struct roots_desktop *desktop = wl_container_of(listener, desktop,
new_output);
@@ -837,6 +895,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
wl_signal_add(&wlr_output->events.mode, &output->mode);
output->transform.notify = output_handle_transform;
wl_signal_add(&wlr_output->events.transform, &output->transform);
+ output->present.notify = output_handle_present;
+ wl_signal_add(&wlr_output->events.present, &output->present);
output->damage_frame.notify = output_damage_handle_frame;
wl_signal_add(&output->damage->events.frame, &output->damage_frame);