aboutsummaryrefslogtreecommitdiff
path: root/rootston
diff options
context:
space:
mode:
Diffstat (limited to 'rootston')
-rw-r--r--rootston/desktop.c79
-rw-r--r--rootston/output.c32
-rw-r--r--rootston/wl_shell.c20
-rw-r--r--rootston/xdg_shell_v6.c29
-rw-r--r--rootston/xwayland.c21
5 files changed, 174 insertions, 7 deletions
diff --git a/rootston/desktop.c b/rootston/desktop.c
index 65730807..7a780cb9 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -89,6 +89,19 @@ void view_move_resize(struct roots_view *view, double x, double y,
view_resize(view, width, height);
}
+static struct wlr_output *view_get_output(struct roots_view *view) {
+ struct wlr_box view_box;
+ view_get_box(view, &view_box);
+
+ double output_x, output_y;
+ wlr_output_layout_closest_point(view->desktop->layout, NULL,
+ view->x + (double)view_box.width/2,
+ view->y + (double)view_box.height/2,
+ &output_x, &output_y);
+ return wlr_output_layout_output_at(view->desktop->layout, output_x,
+ output_y);
+}
+
void view_maximize(struct roots_view *view, bool maximized) {
if (view->maximized == maximized) {
return;
@@ -109,13 +122,7 @@ void view_maximize(struct roots_view *view, bool maximized) {
view->saved.width = view_box.width;
view->saved.height = view_box.height;
- double output_x, output_y;
- wlr_output_layout_closest_point(view->desktop->layout, NULL,
- view->x + (double)view_box.width/2,
- view->y + (double)view_box.height/2,
- &output_x, &output_y);
- struct wlr_output *output = wlr_output_layout_output_at(
- view->desktop->layout, output_x, output_y);
+ struct wlr_output *output = view_get_output(view);
struct wlr_box *output_box =
wlr_output_layout_get_box(view->desktop->layout, output);
@@ -133,6 +140,60 @@ void view_maximize(struct roots_view *view, bool maximized) {
}
}
+void view_set_fullscreen(struct roots_view *view, bool fullscreen,
+ struct wlr_output *output) {
+ bool was_fullscreen = view->fullscreen_output != NULL;
+ if (was_fullscreen == fullscreen) {
+ // TODO: support changing the output?
+ return;
+ }
+
+ // TODO: check if client is focused?
+
+ if (view->set_fullscreen) {
+ view->set_fullscreen(view, fullscreen);
+ }
+
+ if (!was_fullscreen && fullscreen) {
+ if (output == NULL) {
+ output = view_get_output(view);
+ }
+
+ struct wlr_box view_box;
+ view_get_box(view, &view_box);
+
+ view->saved.x = view->x;
+ view->saved.y = view->y;
+ view->saved.rotation = view->rotation;
+ view->saved.width = view_box.width;
+ view->saved.height = view_box.height;
+
+ struct wlr_box *output_box =
+ 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;
+
+ struct roots_output *roots_output;
+ wl_list_for_each(roots_output, &view->desktop->outputs, link) {
+ if (roots_output->wlr_output == output) {
+ roots_output->fullscreen_view = view;
+ view->fullscreen_output = roots_output;
+ break;
+ }
+ }
+ }
+
+ 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->fullscreen_output->fullscreen_view = NULL;
+ view->fullscreen_output = NULL;
+ }
+}
+
void view_close(struct roots_view *view) {
if (view->close) {
view->close(view);
@@ -181,6 +242,10 @@ bool view_center(struct roots_view *view) {
void view_destroy(struct roots_view *view) {
wl_signal_emit(&view->events.destroy, view);
+ if (view->fullscreen_output) {
+ view->fullscreen_output->fullscreen_view = NULL;
+ }
+
free(view);
}
diff --git a/rootston/output.c b/rootston/output.c
index 83ff37fd..82618b06 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -174,6 +174,22 @@ static void render_view(struct roots_view *view, struct roots_desktop *desktop,
}
}
+static bool has_standalone_surface(struct roots_view *view) {
+ if (!wl_list_empty(&view->wlr_surface->subsurface_list)) {
+ wlr_log(L_DEBUG, "has subsurfaces");
+ return false;
+ }
+
+ switch (view->type) {
+ case ROOTS_XDG_SHELL_V6_VIEW:
+ return wl_list_empty(&view->xdg_surface_v6->popups);
+ case ROOTS_WL_SHELL_VIEW:
+ return wl_list_empty(&view->wl_shell_surface->popups);
+ case ROOTS_XWAYLAND_VIEW:
+ return true;
+ }
+}
+
static void output_frame_notify(struct wl_listener *listener, void *data) {
struct wlr_output *wlr_output = data;
struct roots_output *output = wl_container_of(listener, output, frame);
@@ -186,6 +202,22 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
wlr_output_make_current(wlr_output);
wlr_renderer_begin(server->renderer, wlr_output);
+ if (output->fullscreen_view != NULL) {
+ if (has_standalone_surface(output->fullscreen_view)) {
+ wlr_output_set_fullscreen_surface(wlr_output,
+ output->fullscreen_view->wlr_surface);
+ } else {
+ wlr_output_set_fullscreen_surface(wlr_output, NULL);
+ render_view(output->fullscreen_view, desktop, wlr_output, &now);
+ }
+ wlr_renderer_end(server->renderer);
+ wlr_output_swap_buffers(wlr_output);
+ output->last_frame = desktop->last_frame = now;
+ return;
+ } else {
+ wlr_output_set_fullscreen_surface(wlr_output, NULL);
+ }
+
struct roots_view *view;
wl_list_for_each_reverse(view, &desktop->views, link) {
render_view(view, desktop, wlr_output, &now);
diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c
index d0f5989b..e69f2dd9 100644
--- a/rootston/wl_shell.c
+++ b/rootston/wl_shell.c
@@ -59,6 +59,17 @@ static void handle_request_set_maximized(struct wl_listener *listener,
view_maximize(view, true);
}
+static void handle_request_set_fullscreen(struct wl_listener *listener,
+ void *data) {
+ struct roots_wl_shell_surface *roots_surface =
+ wl_container_of(listener, roots_surface, request_set_fullscreen);
+ struct roots_view *view = roots_surface->view;
+ struct wlr_wl_shell_surface_set_fullscreen_event *e = data;
+
+ // TODO: support e->method, e->framerate
+ view_set_fullscreen(view, true, e->output);
+}
+
static void handle_set_state(struct wl_listener *listener, void *data) {
struct roots_wl_shell_surface *roots_surface =
wl_container_of(listener, roots_surface, set_state);
@@ -68,6 +79,10 @@ static void handle_set_state(struct wl_listener *listener, void *data) {
surface->state != WLR_WL_SHELL_SURFACE_STATE_MAXIMIZED) {
view_maximize(view, false);
}
+ if (view->fullscreen_output != NULL &&
+ surface->state != WLR_WL_SHELL_SURFACE_STATE_FULLSCREEN) {
+ view_set_fullscreen(view, false, NULL);
+ }
}
static void handle_surface_commit(struct wl_listener *listener, void *data) {
@@ -81,6 +96,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&roots_surface->request_move.link);
wl_list_remove(&roots_surface->request_resize.link);
wl_list_remove(&roots_surface->request_set_maximized.link);
+ wl_list_remove(&roots_surface->request_set_fullscreen.link);
wl_list_remove(&roots_surface->set_state.link);
wl_list_remove(&roots_surface->surface_commit.link);
wl_list_remove(&roots_surface->view->link);
@@ -112,6 +128,10 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
roots_surface->request_set_maximized.notify = handle_request_set_maximized;
wl_signal_add(&surface->events.request_set_maximized,
&roots_surface->request_set_maximized);
+ roots_surface->request_set_fullscreen.notify =
+ handle_request_set_fullscreen;
+ wl_signal_add(&surface->events.request_set_fullscreen,
+ &roots_surface->request_set_fullscreen);
roots_surface->set_state.notify = handle_set_state;
wl_signal_add(&surface->events.set_state, &roots_surface->set_state);
roots_surface->surface_commit.notify = handle_surface_commit;
diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c
index ea19753b..f301a2e1 100644
--- a/rootston/xdg_shell_v6.c
+++ b/rootston/xdg_shell_v6.c
@@ -100,6 +100,16 @@ static void maximize(struct roots_view *view, bool maximized) {
wlr_xdg_toplevel_v6_set_maximized(surface, maximized);
}
+static void set_fullscreen(struct roots_view *view, bool fullscreen) {
+ assert(view->type == ROOTS_XDG_SHELL_V6_VIEW);
+ struct wlr_xdg_surface_v6 *surface = view->xdg_surface_v6;
+ if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
+ return;
+ }
+
+ wlr_xdg_toplevel_v6_set_fullscreen(surface, fullscreen);
+}
+
static void close(struct roots_view *view) {
assert(view->type == ROOTS_XDG_SHELL_V6_VIEW);
struct wlr_xdg_surface_v6 *surf = view->xdg_surface_v6;
@@ -150,6 +160,21 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) {
view_maximize(view, surface->toplevel_state->next.maximized);
}
+static void handle_request_fullscreen(struct wl_listener *listener,
+ void *data) {
+ struct roots_xdg_surface_v6 *roots_xdg_surface =
+ wl_container_of(listener, roots_xdg_surface, request_fullscreen);
+ struct roots_view *view = roots_xdg_surface->view;
+ struct wlr_xdg_surface_v6 *surface = view->xdg_surface_v6;
+ struct wlr_xdg_toplevel_v6_set_fullscreen_event *e = data;
+
+ if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
+ return;
+ }
+
+ view_set_fullscreen(view, e->fullscreen, e->output);
+}
+
static void handle_commit(struct wl_listener *listener, void *data) {
//struct roots_xdg_surface_v6 *roots_xdg_surface =
// wl_container_of(listener, roots_xdg_surface, commit);
@@ -203,6 +228,9 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
roots_surface->request_maximize.notify = handle_request_maximize;
wl_signal_add(&surface->events.request_maximize,
&roots_surface->request_maximize);
+ roots_surface->request_fullscreen.notify = handle_request_fullscreen;
+ wl_signal_add(&surface->events.request_fullscreen,
+ &roots_surface->request_fullscreen);
struct roots_view *view = calloc(1, sizeof(struct roots_view));
if (!view) {
@@ -218,6 +246,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
view->resize = resize;
view->move_resize = move_resize;
view->maximize = maximize;
+ view->set_fullscreen = set_fullscreen;
view->close = close;
roots_surface->view = view;
view_init(view, desktop);
diff --git a/rootston/xwayland.c b/rootston/xwayland.c
index dfa602b1..cdf2a2d9 100644
--- a/rootston/xwayland.c
+++ b/rootston/xwayland.c
@@ -92,6 +92,13 @@ static void maximize(struct roots_view *view, bool maximized) {
view->xwayland_surface, maximized);
}
+static void set_fullscreen(struct roots_view *view, bool fullscreen) {
+ assert(view->type == ROOTS_XWAYLAND_VIEW);
+
+ wlr_xwayland_surface_set_fullscreen(view->desktop->xwayland,
+ view->xwayland_surface, fullscreen);
+}
+
static void handle_destroy(struct wl_listener *listener, void *data) {
struct roots_xwayland_surface *roots_surface =
wl_container_of(listener, roots_surface, destroy);
@@ -175,6 +182,16 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) {
view_maximize(view, maximized);
}
+static void handle_request_fullscreen(struct wl_listener *listener,
+ void *data) {
+ struct roots_xwayland_surface *roots_surface =
+ wl_container_of(listener, roots_surface, request_fullscreen);
+ struct roots_view *view = roots_surface->view;
+ struct wlr_xwayland_surface *xwayland_surface = view->xwayland_surface;
+
+ view_set_fullscreen(view, xwayland_surface->fullscreen, NULL);
+}
+
static void handle_map_notify(struct wl_listener *listener, void *data) {
struct roots_xwayland_surface *roots_surface =
wl_container_of(listener, roots_surface, map_notify);
@@ -228,6 +245,9 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
roots_surface->request_maximize.notify = handle_request_maximize;
wl_signal_add(&surface->events.request_maximize,
&roots_surface->request_maximize);
+ roots_surface->request_fullscreen.notify = handle_request_fullscreen;
+ wl_signal_add(&surface->events.request_fullscreen,
+ &roots_surface->request_fullscreen);
struct roots_view *view = calloc(1, sizeof(struct roots_view));
if (view == NULL) {
@@ -245,6 +265,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
view->move = move;
view->move_resize = move_resize;
view->maximize = maximize;
+ view->set_fullscreen = set_fullscreen;
view->close = close;
roots_surface->view = view;
view_init(view, desktop);