mirror of
https://github.com/swaywm/sway.git
synced 2026-04-17 06:46:32 -04:00
Merge b23e670824 into b3dcde8d69
This commit is contained in:
commit
13ea679387
5 changed files with 206 additions and 1 deletions
|
|
@ -7,6 +7,7 @@ struct sway_container;
|
||||||
struct sway_node;
|
struct sway_node;
|
||||||
|
|
||||||
void arrange_container(struct sway_container *container);
|
void arrange_container(struct sway_container *container);
|
||||||
|
void next_sibling_container_geometry(struct sway_container *child, struct sway_container *sibling, bool fullscreen);
|
||||||
|
|
||||||
void arrange_workspace(struct sway_workspace *workspace);
|
void arrange_workspace(struct sway_workspace *workspace);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,21 @@ void view_begin_destroy(struct sway_view *view);
|
||||||
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
||||||
bool fullscreen, struct wlr_output *fullscreen_output, bool decoration);
|
bool fullscreen, struct wlr_output *fullscreen_output, bool decoration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the view for its upcoming mapping, sending the intended dimensions
|
||||||
|
* so that the first frame has a chance of being correct. If CSD preferences or
|
||||||
|
* floating tendency changes, this may turn out to be inaccurate but no worse
|
||||||
|
* than skipping the step.
|
||||||
|
*
|
||||||
|
* `fullscreen` should be set to true (and optionally `fullscreen_output`
|
||||||
|
* should be populated) if the view should be made fullscreen immediately.
|
||||||
|
*
|
||||||
|
* `decoration` should be set to true if the client prefers CSD. The client's
|
||||||
|
* preference may be ignored.
|
||||||
|
*/
|
||||||
|
void view_premap(struct sway_view *view, struct wlr_surface *wlr_surface,
|
||||||
|
bool fullscreen, struct wlr_output *fullscreen_output, bool decoration);
|
||||||
|
|
||||||
void view_unmap(struct sway_view *view);
|
void view_unmap(struct sway_view *view);
|
||||||
|
|
||||||
void view_update_size(struct sway_view *view);
|
void view_update_size(struct sway_view *view);
|
||||||
|
|
|
||||||
|
|
@ -298,10 +298,23 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
||||||
if (view->xdg_decoration != NULL) {
|
if (view->xdg_decoration != NULL) {
|
||||||
set_xdg_decoration_mode(view->xdg_decoration);
|
set_xdg_decoration_mode(view->xdg_decoration);
|
||||||
}
|
}
|
||||||
// XXX: https://github.com/swaywm/sway/issues/2176
|
|
||||||
|
bool csd = false;
|
||||||
|
if (view->xdg_decoration) {
|
||||||
|
enum wlr_xdg_toplevel_decoration_v1_mode mode =
|
||||||
|
view->xdg_decoration->wlr_xdg_decoration->requested_mode;
|
||||||
|
csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
|
||||||
|
} else {
|
||||||
|
struct sway_server_decoration *deco =
|
||||||
|
decoration_from_surface(xdg_surface->surface);
|
||||||
|
csd = !deco || deco->wlr_server_decoration->mode ==
|
||||||
|
WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
wlr_xdg_surface_schedule_configure(xdg_surface);
|
wlr_xdg_surface_schedule_configure(xdg_surface);
|
||||||
wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel,
|
wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel,
|
||||||
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||||
|
view_premap(&xdg_shell_view->view, xdg_surface->surface, false, NULL, csd);
|
||||||
// TODO: wlr_xdg_toplevel_set_bounds()
|
// TODO: wlr_xdg_toplevel_set_bounds()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -261,6 +262,87 @@ void arrange_container(struct sway_container *container) {
|
||||||
node_set_dirty(&container->node);
|
node_set_dirty(&container->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void next_sibling_container_geometry(struct sway_container *child, struct sway_container *sibling, bool fullscreen) {
|
||||||
|
assert(child->view);
|
||||||
|
struct sway_workspace *workspace = child->pending.workspace;
|
||||||
|
if (!workspace->output || workspace->width == 0 || workspace->height == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (workspace->fullscreen && !fullscreen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sway_output *output = workspace->output;
|
||||||
|
if (fullscreen) {
|
||||||
|
child->pending.x = output->lx;
|
||||||
|
child->pending.y = output->ly;
|
||||||
|
child->pending.width = output->width;
|
||||||
|
child->pending.height = output->height;
|
||||||
|
view_autoconfigure(child->view);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_t *siblings;
|
||||||
|
struct wlr_box box;
|
||||||
|
enum sway_container_layout layout;
|
||||||
|
|
||||||
|
if (sibling && sibling->pending.parent) {
|
||||||
|
struct sway_container *parent = sibling->pending.parent;
|
||||||
|
siblings = parent->pending.children;
|
||||||
|
layout = parent->pending.layout;
|
||||||
|
workspace_get_box(workspace, &box);
|
||||||
|
} else {
|
||||||
|
siblings = workspace->tiling;
|
||||||
|
layout = workspace->layout;
|
||||||
|
workspace_get_box(workspace, &box);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only want to mutate the specified child, not its siblings. Make a
|
||||||
|
// shallow cloned list of siblings and containers so that their updated
|
||||||
|
// geometry can be thrown away.
|
||||||
|
list_t *children = create_list();
|
||||||
|
if (!children) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct sway_container *cons = calloc(siblings->length-1, sizeof(*cons));
|
||||||
|
if (!cons) {
|
||||||
|
list_free(children);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int idx = 0, ydx = 0; idx < siblings->length; idx++, ydx++) {
|
||||||
|
if (siblings->items[idx] == child) {
|
||||||
|
list_add(children, child);
|
||||||
|
ydx--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cons[ydx] = *(struct sway_container *)siblings->items[idx];
|
||||||
|
list_add(children, &cons[ydx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the geometry
|
||||||
|
switch (layout) {
|
||||||
|
case L_HORIZ:
|
||||||
|
apply_horiz_layout(children, &box);
|
||||||
|
break;
|
||||||
|
case L_VERT:
|
||||||
|
apply_vert_layout(children, &box);
|
||||||
|
break;
|
||||||
|
case L_TABBED:
|
||||||
|
apply_tabbed_layout(children, &box);
|
||||||
|
break;
|
||||||
|
case L_STACKED:
|
||||||
|
apply_stacked_layout(children, &box);
|
||||||
|
break;
|
||||||
|
case L_NONE:
|
||||||
|
apply_horiz_layout(children, &box);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
view_autoconfigure(child->view);
|
||||||
|
list_free(children);
|
||||||
|
free(cons);
|
||||||
|
}
|
||||||
|
|
||||||
void arrange_workspace(struct sway_workspace *workspace) {
|
void arrange_workspace(struct sway_workspace *workspace) {
|
||||||
if (config->reloading) {
|
if (config->reloading) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -760,6 +760,100 @@ static void handle_foreign_destroy(
|
||||||
wl_list_remove(&view->foreign_destroy.link);
|
wl_list_remove(&view->foreign_destroy.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void view_premap(struct sway_view *view, struct wlr_surface *wlr_surface,
|
||||||
|
bool fullscreen, struct wlr_output *fullscreen_output,
|
||||||
|
bool decoration) {
|
||||||
|
|
||||||
|
// If there is a request to be opened fullscreen on a specific output, try
|
||||||
|
// to honor that request. Otherwise, fallback to assigns, pid mappings,
|
||||||
|
// focused workspace, etc
|
||||||
|
struct sway_workspace *ws = NULL;
|
||||||
|
if (fullscreen_output && fullscreen_output->data) {
|
||||||
|
struct sway_output *output = fullscreen_output->data;
|
||||||
|
ws = output_get_active_workspace(output);
|
||||||
|
}
|
||||||
|
if (!ws) {
|
||||||
|
ws = select_workspace(view);
|
||||||
|
}
|
||||||
|
if (!ws || !ws->output) {
|
||||||
|
// Nothing for us to do if we don't have a workspace on an output
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the output is determined, we can notify the client early about
|
||||||
|
// scale to reduce startup jitter.
|
||||||
|
float scale = ws->output->wlr_output->scale;
|
||||||
|
wlr_fractional_scale_v1_notify_scale(wlr_surface, scale);
|
||||||
|
wlr_surface_set_preferred_buffer_scale(wlr_surface, ceil(scale));
|
||||||
|
|
||||||
|
if (view->impl->wants_floating && view->impl->wants_floating(view)) {
|
||||||
|
// Nothing more to do for floating, let it pick its own dimensions
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sway_seat *seat = input_manager_current_seat();
|
||||||
|
struct sway_node *node = seat_get_focus_inactive(seat, &ws->node);
|
||||||
|
struct sway_container *target_sibling = NULL;
|
||||||
|
if (node && node->type == N_CONTAINER) {
|
||||||
|
if (container_is_floating(node->sway_container)) {
|
||||||
|
// If we're about to launch the view into the floating container, then
|
||||||
|
// launch it as a tiled view instead.
|
||||||
|
target_sibling = seat_get_focus_inactive_tiling(seat, ws);
|
||||||
|
if (target_sibling) {
|
||||||
|
struct sway_container *con =
|
||||||
|
seat_get_focus_inactive_view(seat, &target_sibling->node);
|
||||||
|
if (con) {
|
||||||
|
target_sibling = con;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target_sibling = node->sway_container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill out enough of a dummy container to satisfy configuration
|
||||||
|
struct sway_container con = {
|
||||||
|
.view = view,
|
||||||
|
.pending = (struct sway_container_state) {
|
||||||
|
.workspace = ws,
|
||||||
|
.parent = target_sibling ? target_sibling->pending.parent : NULL,
|
||||||
|
.border = config->border,
|
||||||
|
.border_thickness = config->border_thickness,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
view->container = &con;
|
||||||
|
|
||||||
|
// Insert the container into the appropriate children list so that smart
|
||||||
|
// gaps will work correctly
|
||||||
|
list_t *siblings;
|
||||||
|
int sibling_index;
|
||||||
|
if (target_sibling && target_sibling->pending.parent) {
|
||||||
|
struct sway_container *parent = target_sibling->pending.parent;
|
||||||
|
siblings = parent->pending.children;
|
||||||
|
sibling_index = list_find(siblings, target_sibling) + 1;
|
||||||
|
} else {
|
||||||
|
siblings = ws->tiling;
|
||||||
|
sibling_index = ws->tiling->length;
|
||||||
|
}
|
||||||
|
list_insert(siblings, sibling_index, &con);
|
||||||
|
|
||||||
|
view_set_tiled(view, true);
|
||||||
|
view_update_csd_from_client(view, decoration);
|
||||||
|
next_sibling_container_geometry(&con, target_sibling, fullscreen);
|
||||||
|
|
||||||
|
// Send the configure event for the calculated dimensions
|
||||||
|
view_configure(view,
|
||||||
|
con.pending.content_x,
|
||||||
|
con.pending.content_y,
|
||||||
|
con.pending.content_width,
|
||||||
|
con.pending.content_height);
|
||||||
|
|
||||||
|
sway_assert(siblings->items[sibling_index] == &con,
|
||||||
|
"container siblings mutated unexpectedly");
|
||||||
|
list_del(siblings, sibling_index);
|
||||||
|
view->container = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
||||||
bool fullscreen, struct wlr_output *fullscreen_output,
|
bool fullscreen, struct wlr_output *fullscreen_output,
|
||||||
bool decoration) {
|
bool decoration) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue