mirror of
https://github.com/swaywm/sway.git
synced 2025-11-17 06:59:48 -05:00
Merge branch 'master' into destroy-output-destroy-empty-workspaces
This commit is contained in:
commit
8ce7e3b44e
131 changed files with 2676 additions and 1026 deletions
|
|
@ -47,11 +47,11 @@ static void apply_horiz_layout(struct sway_container *parent) {
|
|||
double scale = parent->width / total_width;
|
||||
|
||||
// Resize windows
|
||||
wlr_log(L_DEBUG, "Arranging %p horizontally", parent);
|
||||
wlr_log(WLR_DEBUG, "Arranging %p horizontally", parent);
|
||||
double child_x = parent->x;
|
||||
for (size_t i = 0; i < num_children; ++i) {
|
||||
struct sway_container *child = parent->children->items[i];
|
||||
wlr_log(L_DEBUG,
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Calculating arrangement for %p:%d (will scale %f by %f)",
|
||||
child, child->type, child->width, scale);
|
||||
child->x = child_x;
|
||||
|
|
@ -99,11 +99,11 @@ static void apply_vert_layout(struct sway_container *parent) {
|
|||
double scale = parent_height / total_height;
|
||||
|
||||
// Resize
|
||||
wlr_log(L_DEBUG, "Arranging %p vertically", parent);
|
||||
wlr_log(WLR_DEBUG, "Arranging %p vertically", parent);
|
||||
double child_y = parent->y + parent_offset;
|
||||
for (size_t i = 0; i < num_children; ++i) {
|
||||
struct sway_container *child = parent->children->items[i];
|
||||
wlr_log(L_DEBUG,
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Calculating arrangement for %p:%d (will scale %f by %f)",
|
||||
child, child->type, child->height, scale);
|
||||
child->x = parent->x;
|
||||
|
|
@ -144,42 +144,26 @@ static void apply_tabbed_or_stacked_layout(struct sway_container *parent) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a container has been deleted from the pending tree state, we must add it
|
||||
* to the transaction so it can be freed afterwards. To do this, we iterate the
|
||||
* server's destroying_containers list and add all of them. We may add more than
|
||||
* what we need to, but this is easy and has no negative consequences.
|
||||
*/
|
||||
static void add_deleted_containers(struct sway_transaction *transaction) {
|
||||
for (int i = 0; i < server.destroying_containers->length; ++i) {
|
||||
struct sway_container *child = server.destroying_containers->items[i];
|
||||
transaction_add_container(transaction, child);
|
||||
}
|
||||
}
|
||||
static void arrange_children_of(struct sway_container *parent);
|
||||
|
||||
static void arrange_children_of(struct sway_container *parent,
|
||||
struct sway_transaction *transaction);
|
||||
|
||||
static void arrange_floating(struct sway_container *floating,
|
||||
struct sway_transaction *transaction) {
|
||||
static void arrange_floating(struct sway_container *floating) {
|
||||
for (int i = 0; i < floating->children->length; ++i) {
|
||||
struct sway_container *floater = floating->children->items[i];
|
||||
if (floater->type == C_VIEW) {
|
||||
view_autoconfigure(floater->sway_view);
|
||||
} else {
|
||||
arrange_children_of(floater, transaction);
|
||||
arrange_children_of(floater);
|
||||
}
|
||||
transaction_add_container(transaction, floater);
|
||||
container_set_dirty(floater);
|
||||
}
|
||||
transaction_add_container(transaction, floating);
|
||||
container_set_dirty(floating);
|
||||
}
|
||||
|
||||
static void arrange_children_of(struct sway_container *parent,
|
||||
struct sway_transaction *transaction) {
|
||||
static void arrange_children_of(struct sway_container *parent) {
|
||||
if (config->reloading) {
|
||||
return;
|
||||
}
|
||||
wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent,
|
||||
wlr_log(WLR_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", parent,
|
||||
parent->name, parent->width, parent->height, parent->x, parent->y);
|
||||
|
||||
// Calculate x, y, width and height of children
|
||||
|
|
@ -198,7 +182,7 @@ static void arrange_children_of(struct sway_container *parent,
|
|||
apply_horiz_layout(parent);
|
||||
break;
|
||||
case L_FLOATING:
|
||||
arrange_floating(parent, transaction);
|
||||
arrange_floating(parent);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -213,20 +197,19 @@ static void arrange_children_of(struct sway_container *parent,
|
|||
if (child->type == C_VIEW) {
|
||||
view_autoconfigure(child->sway_view);
|
||||
} else {
|
||||
arrange_children_of(child, transaction);
|
||||
arrange_children_of(child);
|
||||
}
|
||||
transaction_add_container(transaction, child);
|
||||
container_set_dirty(child);
|
||||
}
|
||||
}
|
||||
|
||||
static void arrange_workspace(struct sway_container *workspace,
|
||||
struct sway_transaction *transaction) {
|
||||
static void arrange_workspace(struct sway_container *workspace) {
|
||||
if (config->reloading) {
|
||||
return;
|
||||
}
|
||||
struct sway_container *output = workspace->parent;
|
||||
struct wlr_box *area = &output->sway_output->usable_area;
|
||||
wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d",
|
||||
wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d",
|
||||
area->width, area->height, area->x, area->y);
|
||||
remove_gaps(workspace);
|
||||
workspace->width = area->width;
|
||||
|
|
@ -234,15 +217,14 @@ static void arrange_workspace(struct sway_container *workspace,
|
|||
workspace->x = output->x + area->x;
|
||||
workspace->y = output->y + area->y;
|
||||
add_gaps(workspace);
|
||||
transaction_add_container(transaction, workspace);
|
||||
wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name,
|
||||
container_set_dirty(workspace);
|
||||
wlr_log(WLR_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name,
|
||||
workspace->x, workspace->y);
|
||||
arrange_floating(workspace->sway_workspace->floating, transaction);
|
||||
arrange_children_of(workspace, transaction);
|
||||
arrange_floating(workspace->sway_workspace->floating);
|
||||
arrange_children_of(workspace);
|
||||
}
|
||||
|
||||
static void arrange_output(struct sway_container *output,
|
||||
struct sway_transaction *transaction) {
|
||||
static void arrange_output(struct sway_container *output) {
|
||||
if (config->reloading) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -253,16 +235,16 @@ static void arrange_output(struct sway_container *output,
|
|||
output->y = output_box->y;
|
||||
output->width = output_box->width;
|
||||
output->height = output_box->height;
|
||||
transaction_add_container(transaction, output);
|
||||
wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f",
|
||||
container_set_dirty(output);
|
||||
wlr_log(WLR_DEBUG, "Arranging output '%s' at %f,%f",
|
||||
output->name, output->x, output->y);
|
||||
for (int i = 0; i < output->children->length; ++i) {
|
||||
struct sway_container *workspace = output->children->items[i];
|
||||
arrange_workspace(workspace, transaction);
|
||||
arrange_workspace(workspace);
|
||||
}
|
||||
}
|
||||
|
||||
static void arrange_root(struct sway_transaction *transaction) {
|
||||
static void arrange_root() {
|
||||
if (config->reloading) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -274,48 +256,40 @@ static void arrange_root(struct sway_transaction *transaction) {
|
|||
root_container.y = layout_box->y;
|
||||
root_container.width = layout_box->width;
|
||||
root_container.height = layout_box->height;
|
||||
transaction_add_container(transaction, &root_container);
|
||||
container_set_dirty(&root_container);
|
||||
for (int i = 0; i < root_container.children->length; ++i) {
|
||||
struct sway_container *output = root_container.children->items[i];
|
||||
arrange_output(output, transaction);
|
||||
arrange_output(output);
|
||||
}
|
||||
}
|
||||
|
||||
void arrange_windows(struct sway_container *container,
|
||||
struct sway_transaction *transaction) {
|
||||
void arrange_windows(struct sway_container *container) {
|
||||
switch (container->type) {
|
||||
case C_ROOT:
|
||||
arrange_root(transaction);
|
||||
arrange_root();
|
||||
break;
|
||||
case C_OUTPUT:
|
||||
arrange_output(container, transaction);
|
||||
arrange_output(container);
|
||||
break;
|
||||
case C_WORKSPACE:
|
||||
arrange_workspace(container, transaction);
|
||||
arrange_workspace(container);
|
||||
break;
|
||||
case C_CONTAINER:
|
||||
arrange_children_of(container, transaction);
|
||||
transaction_add_container(transaction, container);
|
||||
arrange_children_of(container);
|
||||
container_set_dirty(container);
|
||||
break;
|
||||
case C_VIEW:
|
||||
view_autoconfigure(container->sway_view);
|
||||
transaction_add_container(transaction, container);
|
||||
container_set_dirty(container);
|
||||
break;
|
||||
case C_TYPES:
|
||||
break;
|
||||
}
|
||||
add_deleted_containers(transaction);
|
||||
}
|
||||
|
||||
void arrange_and_commit(struct sway_container *container) {
|
||||
struct sway_transaction *transaction = transaction_create();
|
||||
arrange_windows(container, transaction);
|
||||
transaction_commit(transaction);
|
||||
}
|
||||
|
||||
void remove_gaps(struct sway_container *c) {
|
||||
if (c->current_gaps == 0) {
|
||||
wlr_log(L_DEBUG, "Removing gaps: not gapped: %p", c);
|
||||
wlr_log(WLR_DEBUG, "Removing gaps: not gapped: %p", c);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -326,12 +300,12 @@ void remove_gaps(struct sway_container *c) {
|
|||
|
||||
c->current_gaps = 0;
|
||||
|
||||
wlr_log(L_DEBUG, "Removing gaps %p", c);
|
||||
wlr_log(WLR_DEBUG, "Removing gaps %p", c);
|
||||
}
|
||||
|
||||
void add_gaps(struct sway_container *c) {
|
||||
if (c->current_gaps > 0 || c->type == C_CONTAINER) {
|
||||
wlr_log(L_DEBUG, "Not adding gaps: %p", c);
|
||||
wlr_log(WLR_DEBUG, "Not adding gaps: %p", c);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -348,5 +322,5 @@ void add_gaps(struct sway_container *c) {
|
|||
c->height -= 2 * gaps;
|
||||
c->current_gaps = gaps;
|
||||
|
||||
wlr_log(L_DEBUG, "Adding gaps: %p", c);
|
||||
wlr_log(WLR_DEBUG, "Adding gaps: %p", c);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,14 @@
|
|||
#include "cairo.h"
|
||||
#include "pango.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/desktop.h"
|
||||
#include "sway/desktop/transaction.h"
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/ipc-server.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/server.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/layout.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
|
|
@ -28,7 +31,7 @@ static list_t *get_bfs_queue() {
|
|||
if (!bfs_queue) {
|
||||
bfs_queue = create_list();
|
||||
if (!bfs_queue) {
|
||||
wlr_log(L_ERROR, "could not allocate list for bfs queue");
|
||||
wlr_log(WLR_ERROR, "could not allocate list for bfs queue");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -156,14 +159,6 @@ void container_free(struct sway_container *cont) {
|
|||
wlr_texture_destroy(cont->title_focused_inactive);
|
||||
wlr_texture_destroy(cont->title_unfocused);
|
||||
wlr_texture_destroy(cont->title_urgent);
|
||||
|
||||
for (int i = 0; i < server.destroying_containers->length; ++i) {
|
||||
if (server.destroying_containers->items[i] == cont) {
|
||||
list_del(server.destroying_containers, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list_free(cont->instructions);
|
||||
list_free(cont->children);
|
||||
list_free(cont->current.children);
|
||||
|
|
@ -218,7 +213,7 @@ static struct sway_container *container_workspace_destroy(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name);
|
||||
wlr_log(WLR_DEBUG, "destroying workspace '%s'", workspace->name);
|
||||
|
||||
if (!workspace_is_empty(workspace)) {
|
||||
// Move children to a different workspace on this output
|
||||
|
|
@ -230,7 +225,7 @@ static struct sway_container *container_workspace_destroy(
|
|||
}
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'",
|
||||
wlr_log(WLR_DEBUG, "moving children to different workspace '%s' -> '%s'",
|
||||
workspace->name, new_workspace->name);
|
||||
for (int i = 0; i < workspace->children->length; i++) {
|
||||
container_move_to(workspace->children->items[i], new_workspace);
|
||||
|
|
@ -296,7 +291,7 @@ static struct sway_container *container_output_destroy(
|
|||
output->sway_output->swayc = NULL;
|
||||
output->sway_output = NULL;
|
||||
|
||||
wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
|
||||
wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
|
||||
|
||||
return &root_container;
|
||||
}
|
||||
|
|
@ -323,13 +318,13 @@ static struct sway_container *container_destroy_noreaping(
|
|||
// Workspaces will refuse to be destroyed if they're the last workspace
|
||||
// on their output.
|
||||
if (!container_workspace_destroy(con)) {
|
||||
wlr_log(L_ERROR, "workspace doesn't want to destroy");
|
||||
wlr_log(WLR_ERROR, "workspace doesn't want to destroy");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
con->destroying = true;
|
||||
list_add(server.destroying_containers, con);
|
||||
container_set_dirty(con);
|
||||
|
||||
if (!con->parent) {
|
||||
return NULL;
|
||||
|
|
@ -350,7 +345,7 @@ bool container_reap_empty(struct sway_container *con) {
|
|||
break;
|
||||
case C_WORKSPACE:
|
||||
if (!workspace_is_visible(con) && workspace_is_empty(con)) {
|
||||
wlr_log(L_DEBUG, "Destroying workspace via reaper");
|
||||
wlr_log(WLR_DEBUG, "Destroying workspace via reaper");
|
||||
container_destroy_noreaping(con);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -443,7 +438,7 @@ struct sway_container *container_view_create(struct sway_container *sibling,
|
|||
}
|
||||
const char *title = view_get_title(sway_view);
|
||||
struct sway_container *swayc = container_create(C_VIEW);
|
||||
wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d %s",
|
||||
wlr_log(WLR_DEBUG, "Adding new view %p:%s to container %p %d %s",
|
||||
swayc, title, sibling, sibling ? sibling->type : 0, sibling->name);
|
||||
// Setup values
|
||||
swayc->sway_view = sway_view;
|
||||
|
|
@ -686,16 +681,23 @@ struct sway_container *floating_container_at(double lx, double ly,
|
|||
void container_for_each_descendant_dfs(struct sway_container *container,
|
||||
void (*f)(struct sway_container *container, void *data),
|
||||
void *data) {
|
||||
if (container) {
|
||||
if (container->children) {
|
||||
for (int i = 0; i < container->children->length; ++i) {
|
||||
struct sway_container *child =
|
||||
container->children->items[i];
|
||||
container_for_each_descendant_dfs(child, f, data);
|
||||
}
|
||||
}
|
||||
f(container, data);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
if (container->children) {
|
||||
for (int i = 0; i < container->children->length; ++i) {
|
||||
struct sway_container *child = container->children->items[i];
|
||||
container_for_each_descendant_dfs(child, f, data);
|
||||
}
|
||||
}
|
||||
if (container->type == C_WORKSPACE) {
|
||||
struct sway_container *floating = container->sway_workspace->floating;
|
||||
for (int i = 0; i < floating->children->length; ++i) {
|
||||
struct sway_container *child = floating->children->items[i];
|
||||
container_for_each_descendant_dfs(child, f, data);
|
||||
}
|
||||
}
|
||||
f(container, data);
|
||||
}
|
||||
|
||||
void container_for_each_descendant_bfs(struct sway_container *con,
|
||||
|
|
@ -706,7 +708,7 @@ void container_for_each_descendant_bfs(struct sway_container *con,
|
|||
}
|
||||
|
||||
if (queue == NULL) {
|
||||
wlr_log(L_ERROR, "could not allocate list");
|
||||
wlr_log(WLR_ERROR, "could not allocate list");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -972,9 +974,14 @@ void container_set_geometry_from_floating_view(struct sway_container *con) {
|
|||
return;
|
||||
}
|
||||
struct sway_view *view = con->sway_view;
|
||||
size_t border_width = view->border_thickness * (view->border != B_NONE);
|
||||
size_t top =
|
||||
view->border == B_NORMAL ? container_titlebar_height() : border_width;
|
||||
size_t border_width = 0;
|
||||
size_t top = 0;
|
||||
|
||||
if (!view->using_csd) {
|
||||
border_width = view->border_thickness * (view->border != B_NONE);
|
||||
top = view->border == B_NORMAL ?
|
||||
container_titlebar_height() : border_width;
|
||||
}
|
||||
|
||||
con->x = view->x - border_width;
|
||||
con->y = view->y - top;
|
||||
|
|
@ -996,3 +1003,103 @@ void container_get_box(struct sway_container *container, struct wlr_box *box) {
|
|||
box->width = container->width;
|
||||
box->height = container->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the container's position as well as all children.
|
||||
*/
|
||||
static void container_floating_translate(struct sway_container *con,
|
||||
double x_amount, double y_amount) {
|
||||
con->x += x_amount;
|
||||
con->y += y_amount;
|
||||
con->current.swayc_x += x_amount;
|
||||
con->current.swayc_y += y_amount;
|
||||
if (con->type == C_VIEW) {
|
||||
con->sway_view->x += x_amount;
|
||||
con->sway_view->y += y_amount;
|
||||
con->current.view_x += x_amount;
|
||||
con->current.view_y += y_amount;
|
||||
} else {
|
||||
for (int i = 0; i < con->children->length; ++i) {
|
||||
struct sway_container *child = con->children->items[i];
|
||||
container_floating_translate(child, x_amount, y_amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose an output for the floating container's new position.
|
||||
*
|
||||
* If the center of the container intersects an output then we'll choose that
|
||||
* one, otherwise we'll choose whichever output is closest to the container's
|
||||
* center.
|
||||
*/
|
||||
static struct sway_container *container_floating_find_output(
|
||||
struct sway_container *con) {
|
||||
double center_x = con->x + con->width / 2;
|
||||
double center_y = con->y + con->height / 2;
|
||||
struct sway_container *closest_output = NULL;
|
||||
double closest_distance = DBL_MAX;
|
||||
for (int i = 0; i < root_container.children->length; ++i) {
|
||||
struct sway_container *output = root_container.children->items[i];
|
||||
struct wlr_box output_box;
|
||||
double closest_x, closest_y;
|
||||
container_get_box(output, &output_box);
|
||||
wlr_box_closest_point(&output_box, center_x, center_y,
|
||||
&closest_x, &closest_y);
|
||||
if (center_x == closest_x && center_y == closest_y) {
|
||||
// The center of the floating container is on this output
|
||||
return output;
|
||||
}
|
||||
double x_dist = closest_x - center_x;
|
||||
double y_dist = closest_y - center_y;
|
||||
double distance = x_dist * x_dist + y_dist * y_dist;
|
||||
if (distance < closest_distance) {
|
||||
closest_output = output;
|
||||
closest_distance = distance;
|
||||
}
|
||||
}
|
||||
return closest_output;
|
||||
}
|
||||
|
||||
void container_floating_move_to(struct sway_container *con,
|
||||
double lx, double ly) {
|
||||
if (!sway_assert(container_is_floating(con),
|
||||
"Expected a floating container")) {
|
||||
return;
|
||||
}
|
||||
desktop_damage_whole_container(con);
|
||||
container_floating_translate(con, lx - con->x, ly - con->y);
|
||||
desktop_damage_whole_container(con);
|
||||
struct sway_container *old_workspace = container_parent(con, C_WORKSPACE);
|
||||
struct sway_container *new_output = container_floating_find_output(con);
|
||||
if (!sway_assert(new_output, "Unable to find any output")) {
|
||||
return;
|
||||
}
|
||||
struct sway_container *new_workspace =
|
||||
output_get_active_workspace(new_output->sway_output);
|
||||
if (old_workspace != new_workspace) {
|
||||
container_remove_child(con);
|
||||
container_add_child(new_workspace->sway_workspace->floating, con);
|
||||
arrange_windows(old_workspace);
|
||||
arrange_windows(new_workspace);
|
||||
workspace_detect_urgent(old_workspace);
|
||||
workspace_detect_urgent(new_workspace);
|
||||
}
|
||||
}
|
||||
|
||||
void container_set_dirty(struct sway_container *container) {
|
||||
if (container->dirty) {
|
||||
return;
|
||||
}
|
||||
container->dirty = true;
|
||||
list_add(server.dirty_containers, container);
|
||||
}
|
||||
|
||||
static bool find_urgent_iterator(struct sway_container *con,
|
||||
void *data) {
|
||||
return con->type == C_VIEW && view_is_urgent(con->sway_view);
|
||||
}
|
||||
|
||||
bool container_has_urgent_child(struct sway_container *container) {
|
||||
return container_find(container, find_urgent_iterator, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ struct sway_container root_container;
|
|||
|
||||
static void output_layout_handle_change(struct wl_listener *listener,
|
||||
void *data) {
|
||||
arrange_and_commit(&root_container);
|
||||
arrange_windows(&root_container);
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
||||
void layout_init(void) {
|
||||
|
|
@ -101,7 +102,7 @@ void container_insert_child(struct sway_container *parent,
|
|||
if (old_parent) {
|
||||
container_remove_child(child);
|
||||
}
|
||||
wlr_log(L_DEBUG, "Inserting id:%zd at index %d", child->id, i);
|
||||
wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i);
|
||||
list_insert(parent->children, i, child);
|
||||
child->parent = parent;
|
||||
container_handle_fullscreen_reparent(child, old_parent);
|
||||
|
|
@ -127,7 +128,7 @@ struct sway_container *container_add_sibling(struct sway_container *fixed,
|
|||
|
||||
void container_add_child(struct sway_container *parent,
|
||||
struct sway_container *child) {
|
||||
wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
|
||||
wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
|
||||
child, child->type, child->width, child->height,
|
||||
parent, parent->type, parent->width, parent->height);
|
||||
struct sway_container *old_parent = child->parent;
|
||||
|
|
@ -168,7 +169,12 @@ void container_move_to(struct sway_container *container,
|
|||
struct sway_container *old_parent = container_remove_child(container);
|
||||
container->width = container->height = 0;
|
||||
container->saved_width = container->saved_height = 0;
|
||||
struct sway_container *new_parent;
|
||||
|
||||
struct sway_container *new_parent, *new_parent_focus;
|
||||
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
|
||||
|
||||
// Get the focus of the destination before we change it.
|
||||
new_parent_focus = seat_get_focus_inactive(seat, destination);
|
||||
if (destination->type == C_VIEW) {
|
||||
new_parent = container_add_sibling(destination, container);
|
||||
} else {
|
||||
|
|
@ -176,17 +182,20 @@ void container_move_to(struct sway_container *container,
|
|||
container_add_child(destination, container);
|
||||
}
|
||||
wl_signal_emit(&container->events.reparent, old_parent);
|
||||
|
||||
if (container->type == C_WORKSPACE) {
|
||||
// If moving a workspace to a new output, maybe create a new workspace
|
||||
// on the previous output
|
||||
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
|
||||
if (old_parent->children->length == 0) {
|
||||
char *ws_name = workspace_next_name(old_parent->name);
|
||||
struct sway_container *ws =
|
||||
workspace_create(old_parent, ws_name);
|
||||
struct sway_container *ws = workspace_create(old_parent, ws_name);
|
||||
free(ws_name);
|
||||
seat_set_focus(seat, ws);
|
||||
}
|
||||
|
||||
// Try to remove an empty workspace from the destination output.
|
||||
container_reap_empty_recursive(new_parent_focus);
|
||||
|
||||
container_sort_workspaces(new_parent);
|
||||
seat_set_focus(seat, new_parent);
|
||||
workspace_output_raise_priority(container, old_parent, new_parent);
|
||||
|
|
@ -216,6 +225,15 @@ void container_move_to(struct sway_container *container,
|
|||
}
|
||||
}
|
||||
}
|
||||
// Update workspace urgent state
|
||||
struct sway_container *old_workspace = old_parent;
|
||||
if (old_workspace->type != C_WORKSPACE) {
|
||||
old_workspace = container_parent(old_workspace, C_WORKSPACE);
|
||||
}
|
||||
if (new_workspace != old_workspace) {
|
||||
workspace_detect_urgent(new_workspace);
|
||||
workspace_detect_urgent(old_workspace);
|
||||
}
|
||||
}
|
||||
|
||||
static bool sway_dir_to_wlr(enum movement_direction dir,
|
||||
|
|
@ -311,13 +329,13 @@ static void move_out_of_tabs_stacks(struct sway_container *container,
|
|||
int offs) {
|
||||
if (container->parent == current->parent
|
||||
&& current->parent->children->length == 1) {
|
||||
wlr_log(L_DEBUG, "Changing layout of %zd", current->parent->id);
|
||||
wlr_log(WLR_DEBUG, "Changing layout of %zd", current->parent->id);
|
||||
current->parent->layout = move_dir ==
|
||||
MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT;
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "Moving out of tab/stack into a split");
|
||||
wlr_log(WLR_DEBUG, "Moving out of tab/stack into a split");
|
||||
bool is_workspace = current->parent->type == C_WORKSPACE;
|
||||
struct sway_container *new_parent = container_split(current->parent,
|
||||
move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT);
|
||||
|
|
@ -362,7 +380,7 @@ void container_move(struct sway_container *container,
|
|||
}
|
||||
|
||||
parent = current->parent;
|
||||
wlr_log(L_DEBUG, "Visiting %p %s '%s'", current,
|
||||
wlr_log(WLR_DEBUG, "Visiting %p %s '%s'", current,
|
||||
container_type_to_str(current->type), current->name);
|
||||
|
||||
int index = index_child(current);
|
||||
|
|
@ -380,12 +398,12 @@ void container_move(struct sway_container *container,
|
|||
root_container.sway_root->output_layout, wlr_dir,
|
||||
current->sway_output->wlr_output, ref_lx, ref_ly);
|
||||
if (!next) {
|
||||
wlr_log(L_DEBUG, "Hit edge of output, nowhere else to go");
|
||||
wlr_log(WLR_DEBUG, "Hit edge of output, nowhere else to go");
|
||||
return;
|
||||
}
|
||||
struct sway_output *next_output = next->data;
|
||||
current = next_output->swayc;
|
||||
wlr_log(L_DEBUG, "Selected next output (%s)", current->name);
|
||||
wlr_log(WLR_DEBUG, "Selected next output (%s)", current->name);
|
||||
// Select workspace and get outta here
|
||||
current = seat_get_focus_inactive(
|
||||
config->handler_context.seat, current);
|
||||
|
|
@ -398,20 +416,20 @@ void container_move(struct sway_container *container,
|
|||
case C_WORKSPACE:
|
||||
if (!is_parallel(current->layout, move_dir)) {
|
||||
if (current->children->length >= 2) {
|
||||
wlr_log(L_DEBUG, "Rejiggering the workspace (%d kiddos)",
|
||||
wlr_log(WLR_DEBUG, "Rejiggering the workspace (%d kiddos)",
|
||||
current->children->length);
|
||||
workspace_rejigger(current, container, move_dir);
|
||||
return;
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "Selecting output");
|
||||
wlr_log(WLR_DEBUG, "Selecting output");
|
||||
current = current->parent;
|
||||
}
|
||||
} else if (current->layout == L_TABBED
|
||||
|| current->layout == L_STACKED) {
|
||||
wlr_log(L_DEBUG, "Rejiggering out of tabs/stacks");
|
||||
wlr_log(WLR_DEBUG, "Rejiggering out of tabs/stacks");
|
||||
workspace_rejigger(current, container, move_dir);
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "Selecting output");
|
||||
wlr_log(WLR_DEBUG, "Selecting output");
|
||||
current = current->parent;
|
||||
}
|
||||
break;
|
||||
|
|
@ -427,11 +445,11 @@ void container_move(struct sway_container *container,
|
|||
move_dir, offs);
|
||||
return;
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "Hit limit, selecting parent");
|
||||
wlr_log(WLR_DEBUG, "Hit limit, selecting parent");
|
||||
current = current->parent;
|
||||
}
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "Hit limit, "
|
||||
wlr_log(WLR_DEBUG, "Hit limit, "
|
||||
"promoting descendant to sibling");
|
||||
// Special case
|
||||
container_insert_child(current->parent, container,
|
||||
|
|
@ -441,14 +459,14 @@ void container_move(struct sway_container *container,
|
|||
}
|
||||
} else {
|
||||
sibling = parent->children->items[index + offs];
|
||||
wlr_log(L_DEBUG, "Selecting sibling id:%zd", sibling->id);
|
||||
wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id);
|
||||
}
|
||||
} else if (parent->layout == L_TABBED
|
||||
|| parent->layout == L_STACKED) {
|
||||
move_out_of_tabs_stacks(container, current, move_dir, offs);
|
||||
return;
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "Moving up to find a parallel container");
|
||||
wlr_log(WLR_DEBUG, "Moving up to find a parallel container");
|
||||
current = current->parent;
|
||||
}
|
||||
break;
|
||||
|
|
@ -467,11 +485,11 @@ void container_move(struct sway_container *container,
|
|||
switch (sibling->type) {
|
||||
case C_VIEW:
|
||||
if (sibling->parent == container->parent) {
|
||||
wlr_log(L_DEBUG, "Swapping siblings");
|
||||
wlr_log(WLR_DEBUG, "Swapping siblings");
|
||||
sibling->parent->children->items[index + offs] = container;
|
||||
sibling->parent->children->items[index] = sibling;
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "Promoting to sibling of cousin");
|
||||
wlr_log(WLR_DEBUG, "Promoting to sibling of cousin");
|
||||
container_insert_child(sibling->parent, container,
|
||||
index_child(sibling) + (offs > 0 ? 0 : 1));
|
||||
container->width = container->height = 0;
|
||||
|
|
@ -482,31 +500,31 @@ void container_move(struct sway_container *container,
|
|||
case C_CONTAINER:
|
||||
if (is_parallel(sibling->layout, move_dir)) {
|
||||
int limit = container_limit(sibling, invert_movement(move_dir));
|
||||
wlr_log(L_DEBUG, "limit: %d", limit);
|
||||
wlr_log(L_DEBUG,
|
||||
wlr_log(WLR_DEBUG, "limit: %d", limit);
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Reparenting container (parallel) to index %d "
|
||||
"(move dir: %d)", limit, move_dir);
|
||||
container_insert_child(sibling, container, limit);
|
||||
container->width = container->height = 0;
|
||||
sibling = NULL;
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "Reparenting container (perpendicular)");
|
||||
wlr_log(WLR_DEBUG, "Reparenting container (perpendicular)");
|
||||
struct sway_container *focus_inactive = seat_get_focus_inactive(
|
||||
config->handler_context.seat, sibling);
|
||||
if (focus_inactive && focus_inactive != sibling) {
|
||||
while (focus_inactive->parent != sibling) {
|
||||
focus_inactive = focus_inactive->parent;
|
||||
}
|
||||
wlr_log(L_DEBUG, "Focus inactive: id:%zd",
|
||||
wlr_log(WLR_DEBUG, "Focus inactive: id:%zd",
|
||||
focus_inactive->id);
|
||||
sibling = focus_inactive;
|
||||
continue;
|
||||
} else if (sibling->children->length) {
|
||||
wlr_log(L_DEBUG, "No focus-inactive, adding arbitrarily");
|
||||
wlr_log(WLR_DEBUG, "No focus-inactive, adding arbitrarily");
|
||||
container_remove_child(container);
|
||||
container_add_sibling(sibling->children->items[0], container);
|
||||
} else {
|
||||
wlr_log(L_DEBUG, "No kiddos, adding container alone");
|
||||
wlr_log(WLR_DEBUG, "No kiddos, adding container alone");
|
||||
container_remove_child(container);
|
||||
container_add_child(sibling, container);
|
||||
}
|
||||
|
|
@ -539,6 +557,8 @@ void container_move(struct sway_container *container,
|
|||
}
|
||||
if (last_ws && next_ws && last_ws != next_ws) {
|
||||
ipc_event_workspace(last_ws, container, "focus");
|
||||
workspace_detect_urgent(last_ws);
|
||||
workspace_detect_urgent(next_ws);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +623,7 @@ static struct sway_container *get_swayc_in_output_direction(
|
|||
}
|
||||
|
||||
if (ws == NULL) {
|
||||
wlr_log(L_ERROR, "got an output without a workspace");
|
||||
wlr_log(WLR_ERROR, "got an output without a workspace");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -775,7 +795,7 @@ struct sway_container *container_get_in_direction(
|
|||
} else {
|
||||
struct sway_container *desired_con =
|
||||
parent->children->items[desired];
|
||||
wlr_log(L_DEBUG,
|
||||
wlr_log(WLR_DEBUG,
|
||||
"cont %d-%p dir %i sibling %d: %p", idx,
|
||||
container, dir, desired, desired_con);
|
||||
return seat_get_focus_inactive_view(seat, desired_con);
|
||||
|
|
@ -840,7 +860,7 @@ struct sway_container *container_split(struct sway_container *child,
|
|||
|
||||
struct sway_container *cont = container_create(C_CONTAINER);
|
||||
|
||||
wlr_log(L_DEBUG, "creating container %p around %p", cont, child);
|
||||
wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child);
|
||||
|
||||
remove_gaps(child);
|
||||
|
||||
|
|
@ -888,7 +908,7 @@ struct sway_container *container_split(struct sway_container *child,
|
|||
void container_recursive_resize(struct sway_container *container,
|
||||
double amount, enum resize_edge edge) {
|
||||
bool layout_match = true;
|
||||
wlr_log(L_DEBUG, "Resizing %p with amount: %f", container, amount);
|
||||
wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount);
|
||||
if (edge == RESIZE_EDGE_LEFT || edge == RESIZE_EDGE_RIGHT) {
|
||||
container->width += amount;
|
||||
layout_match = container->layout == L_HORIZ;
|
||||
|
|
@ -978,7 +998,7 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) {
|
|||
return;
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
|
||||
wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
|
||||
|
||||
int fs1 = con1->type == C_VIEW && con1->sway_view->is_fullscreen;
|
||||
int fs2 = con2->type == C_VIEW && con2->sway_view->is_fullscreen;
|
||||
|
|
|
|||
|
|
@ -43,11 +43,11 @@ struct sway_container *output_create(
|
|||
|
||||
if (strcasecmp(name, cur->name) == 0 ||
|
||||
strcasecmp(identifier, cur->name) == 0) {
|
||||
wlr_log(L_DEBUG, "Matched output config for %s", name);
|
||||
wlr_log(WLR_DEBUG, "Matched output config for %s", name);
|
||||
oc = cur;
|
||||
}
|
||||
if (strcasecmp("*", cur->name) == 0) {
|
||||
wlr_log(L_DEBUG, "Matched wildcard output config for %s", name);
|
||||
wlr_log(WLR_DEBUG, "Matched wildcard output config for %s", name);
|
||||
all = cur;
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ struct sway_container *output_create(
|
|||
if (!output->children->length) {
|
||||
// Create workspace
|
||||
char *ws_name = workspace_next_name(output->name);
|
||||
wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
|
||||
wlr_log(WLR_DEBUG, "Creating default workspace %s", ws_name);
|
||||
struct sway_container *ws = workspace_create(output, ws_name);
|
||||
// Set each seat's focus if not already set
|
||||
struct sway_seat *seat = NULL;
|
||||
|
|
|
|||
167
sway/tree/view.c
167
sway/tree/view.c
|
|
@ -25,6 +25,7 @@ void view_init(struct sway_view *view, enum sway_view_type type,
|
|||
view->impl = impl;
|
||||
view->executed_criteria = create_list();
|
||||
view->marks = create_list();
|
||||
view->allow_request_urgent = true;
|
||||
wl_signal_init(&view->events.unmap);
|
||||
}
|
||||
|
||||
|
|
@ -150,12 +151,43 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
|
|||
|
||||
void view_init_floating(struct sway_view *view) {
|
||||
struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
|
||||
int max_width = ws->width * 0.6666;
|
||||
int max_height = ws->height * 0.6666;
|
||||
view->width =
|
||||
view->natural_width > max_width ? max_width : view->natural_width;
|
||||
view->height =
|
||||
view->natural_height > max_height ? max_height : view->natural_height;
|
||||
int min_width, min_height;
|
||||
int max_width, max_height;
|
||||
|
||||
if (config->floating_minimum_width == -1) { // no minimum
|
||||
min_width = 0;
|
||||
} else if (config->floating_minimum_width == 0) { // automatic
|
||||
min_width = 75;
|
||||
} else {
|
||||
min_width = config->floating_minimum_width;
|
||||
}
|
||||
|
||||
if (config->floating_minimum_height == -1) { // no minimum
|
||||
min_height = 0;
|
||||
} else if (config->floating_minimum_height == 0) { // automatic
|
||||
min_height = 50;
|
||||
} else {
|
||||
min_height = config->floating_minimum_height;
|
||||
}
|
||||
|
||||
if (config->floating_maximum_width == -1) { // no maximum
|
||||
max_width = INT_MAX;
|
||||
} else if (config->floating_maximum_width == 0) { // automatic
|
||||
max_width = ws->width * 0.6666;
|
||||
} else {
|
||||
max_width = config->floating_maximum_width;
|
||||
}
|
||||
|
||||
if (config->floating_maximum_height == -1) { // no maximum
|
||||
max_height = INT_MAX;
|
||||
} else if (config->floating_maximum_height == 0) { // automatic
|
||||
max_height = ws->height * 0.6666;
|
||||
} else {
|
||||
max_height = config->floating_maximum_height;
|
||||
}
|
||||
|
||||
view->width = fmax(min_width, fmin(view->natural_width, max_width));
|
||||
view->height = fmax(min_height, fmin(view->natural_height, max_height));
|
||||
view->x = ws->x + (ws->width - view->width) / 2;
|
||||
view->y = ws->y + (ws->height - view->height) / 2;
|
||||
|
||||
|
|
@ -284,7 +316,15 @@ void view_set_activated(struct sway_view *view, bool activated) {
|
|||
}
|
||||
|
||||
void view_set_tiled(struct sway_view *view, bool tiled) {
|
||||
view->border = tiled ? config->border : B_NONE;
|
||||
if (!tiled) {
|
||||
view->using_csd = true;
|
||||
if (view->impl->has_client_side_decorations) {
|
||||
view->using_csd = view->impl->has_client_side_decorations(view);
|
||||
}
|
||||
} else {
|
||||
view->using_csd = false;
|
||||
}
|
||||
|
||||
if (view->impl->set_tiled) {
|
||||
view->impl->set_tiled(view, tiled);
|
||||
}
|
||||
|
|
@ -462,27 +502,45 @@ void view_execute_criteria(struct sway_view *view) {
|
|||
list_t *criterias = criteria_for_view(view, CT_COMMAND);
|
||||
for (int i = 0; i < criterias->length; i++) {
|
||||
struct criteria *criteria = criterias->items[i];
|
||||
wlr_log(L_DEBUG, "Checking criteria %s", criteria->raw);
|
||||
wlr_log(WLR_DEBUG, "Checking criteria %s", criteria->raw);
|
||||
if (view_has_executed_criteria(view, criteria)) {
|
||||
wlr_log(L_DEBUG, "Criteria already executed");
|
||||
wlr_log(WLR_DEBUG, "Criteria already executed");
|
||||
continue;
|
||||
}
|
||||
wlr_log(L_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
||||
wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
||||
criteria->raw, view, criteria->cmdlist);
|
||||
seat_set_focus(seat, view->swayc);
|
||||
list_add(view->executed_criteria, criteria);
|
||||
struct cmd_results *res = execute_command(criteria->cmdlist, NULL);
|
||||
if (res->status != CMD_SUCCESS) {
|
||||
wlr_log(L_ERROR, "Command '%s' failed: %s", res->input, res->error);
|
||||
wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error);
|
||||
}
|
||||
free_cmd_results(res);
|
||||
// view must be focused for commands to affect it,
|
||||
// so always refocus in-between command lists
|
||||
seat_set_focus(seat, view->swayc);
|
||||
}
|
||||
list_free(criterias);
|
||||
seat_set_focus(seat, prior_focus);
|
||||
}
|
||||
|
||||
static bool should_focus(struct sway_view *view) {
|
||||
// If the view is the only one in the focused workspace, it'll get focus
|
||||
// regardless of any no_focus criteria.
|
||||
struct sway_container *parent = view->swayc->parent;
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
if (parent->type == C_WORKSPACE && seat_get_focus(seat) == parent) {
|
||||
size_t num_children = parent->children->length +
|
||||
parent->sway_workspace->floating->children->length;
|
||||
if (num_children == 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check no_focus criteria
|
||||
list_t *criterias = criteria_for_view(view, CT_NO_FOCUS);
|
||||
size_t len = criterias->length;
|
||||
list_free(criterias);
|
||||
return len == 0;
|
||||
}
|
||||
|
||||
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
|
||||
if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
|
||||
return;
|
||||
|
|
@ -519,8 +577,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
|
|||
|
||||
view->surface = wlr_surface;
|
||||
view->swayc = cont;
|
||||
view->border = config->border;
|
||||
view->border_thickness = config->border_thickness;
|
||||
|
||||
view_init_subsurfaces(view, wlr_surface);
|
||||
wl_signal_add(&wlr_surface->events.new_subsurface,
|
||||
|
|
@ -531,14 +587,20 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
|
|||
view->container_reparent.notify = view_handle_container_reparent;
|
||||
|
||||
if (view->impl->wants_floating && view->impl->wants_floating(view)) {
|
||||
view->border = config->floating_border;
|
||||
view->border_thickness = config->floating_border_thickness;
|
||||
container_set_floating(view->swayc, true);
|
||||
} else {
|
||||
view->border = config->border;
|
||||
view->border_thickness = config->border_thickness;
|
||||
view_set_tiled(view, true);
|
||||
}
|
||||
|
||||
input_manager_set_focus(input_manager, cont);
|
||||
if (workspace) {
|
||||
workspace_switch(workspace);
|
||||
if (should_focus(view)) {
|
||||
input_manager_set_focus(input_manager, cont);
|
||||
if (workspace) {
|
||||
workspace_switch(workspace);
|
||||
}
|
||||
}
|
||||
|
||||
view_update_title(view, false);
|
||||
|
|
@ -554,16 +616,27 @@ void view_unmap(struct sway_view *view) {
|
|||
wl_list_remove(&view->surface_new_subsurface.link);
|
||||
wl_list_remove(&view->container_reparent.link);
|
||||
|
||||
if (view->is_fullscreen) {
|
||||
struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
|
||||
ws->sway_workspace->fullscreen = NULL;
|
||||
container_destroy(view->swayc);
|
||||
|
||||
arrange_and_commit(ws->parent);
|
||||
} else {
|
||||
struct sway_container *parent = container_destroy(view->swayc);
|
||||
arrange_and_commit(parent);
|
||||
if (view->urgent_timer) {
|
||||
wl_event_source_remove(view->urgent_timer);
|
||||
view->urgent_timer = NULL;
|
||||
}
|
||||
|
||||
struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
|
||||
|
||||
struct sway_container *parent;
|
||||
if (view->is_fullscreen) {
|
||||
ws->sway_workspace->fullscreen = NULL;
|
||||
parent = container_destroy(view->swayc);
|
||||
|
||||
arrange_windows(ws->parent);
|
||||
} else {
|
||||
parent = container_destroy(view->swayc);
|
||||
arrange_windows(parent);
|
||||
}
|
||||
if (parent->type >= C_WORKSPACE) { // if the workspace still exists
|
||||
workspace_detect_urgent(ws);
|
||||
}
|
||||
transaction_commit_dirty();
|
||||
view->surface = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -601,7 +674,7 @@ static void view_subsurface_create(struct sway_view *view,
|
|||
struct wlr_subsurface *subsurface) {
|
||||
struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child));
|
||||
if (child == NULL) {
|
||||
wlr_log(L_ERROR, "Allocation failed");
|
||||
wlr_log(WLR_ERROR, "Allocation failed");
|
||||
return;
|
||||
}
|
||||
view_child_init(child, NULL, view, subsurface->surface);
|
||||
|
|
@ -721,8 +794,9 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "Surface of unknown type (role %s): %p",
|
||||
wlr_surface->role, wlr_surface);
|
||||
const char *role = wlr_surface->role ? wlr_surface->role->name : NULL;
|
||||
wlr_log(WLR_DEBUG, "Surface of unknown type (role %s): %p",
|
||||
role, wlr_surface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -789,7 +863,7 @@ static char *escape_title(char *buffer) {
|
|||
char *escaped_title = calloc(length + 1, sizeof(char));
|
||||
int result = escape_markup_text(buffer, escaped_title, length);
|
||||
if (result != length) {
|
||||
wlr_log(L_ERROR, "Could not escape title: %s", buffer);
|
||||
wlr_log(WLR_ERROR, "Could not escape title: %s", buffer);
|
||||
free(escaped_title);
|
||||
return buffer;
|
||||
}
|
||||
|
|
@ -1010,3 +1084,32 @@ bool view_is_visible(struct sway_view *view) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void view_set_urgent(struct sway_view *view, bool enable) {
|
||||
if (view_is_urgent(view) == enable) {
|
||||
return;
|
||||
}
|
||||
if (enable) {
|
||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
||||
if (seat_get_focus(seat) == view->swayc) {
|
||||
return;
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &view->urgent);
|
||||
} else {
|
||||
view->urgent = (struct timespec){ 0 };
|
||||
if (view->urgent_timer) {
|
||||
wl_event_source_remove(view->urgent_timer);
|
||||
view->urgent_timer = NULL;
|
||||
}
|
||||
}
|
||||
container_damage_whole(view->swayc);
|
||||
|
||||
ipc_event_window(view->swayc, "urgent");
|
||||
|
||||
struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
|
||||
workspace_detect_urgent(ws);
|
||||
}
|
||||
|
||||
bool view_is_urgent(struct sway_view *view) {
|
||||
return view->urgent.tv_sec || view->urgent.tv_nsec;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "sway/ipc-server.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/container.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
|
|
@ -49,7 +50,7 @@ struct sway_container *workspace_create(struct sway_container *output,
|
|||
output = get_workspace_initial_output(name);
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name);
|
||||
wlr_log(WLR_DEBUG, "Added workspace %s for output %s", name, output->name);
|
||||
struct sway_container *workspace = container_create(C_WORKSPACE);
|
||||
|
||||
workspace->x = output->x;
|
||||
|
|
@ -107,7 +108,7 @@ static bool workspace_valid_on_output(const char *output_name,
|
|||
}
|
||||
|
||||
char *workspace_next_name(const char *output_name) {
|
||||
wlr_log(L_DEBUG, "Workspace: Generating new workspace name for output %s",
|
||||
wlr_log(WLR_DEBUG, "Workspace: Generating new workspace name for output %s",
|
||||
output_name);
|
||||
// Scan all workspace bindings to find the next available workspace name,
|
||||
// if none are found/available then default to a number
|
||||
|
|
@ -135,7 +136,7 @@ char *workspace_next_name(const char *output_name) {
|
|||
while (isspace(*_target)) {
|
||||
memmove(_target, _target+1, strlen(_target+1));
|
||||
}
|
||||
wlr_log(L_DEBUG, "Got valid workspace command for target: '%s'",
|
||||
wlr_log(WLR_DEBUG, "Got valid workspace command for target: '%s'",
|
||||
_target);
|
||||
|
||||
// Make sure that the command references an actual workspace
|
||||
|
|
@ -161,7 +162,7 @@ char *workspace_next_name(const char *output_name) {
|
|||
temp[length - 1] = '\0';
|
||||
free(_target);
|
||||
_target = temp;
|
||||
wlr_log(L_DEBUG, "Isolated name from workspace number: '%s'", _target);
|
||||
wlr_log(WLR_DEBUG, "Isolated name from workspace number: '%s'", _target);
|
||||
|
||||
// Make sure the workspace number doesn't already exist
|
||||
if (workspace_by_number(_target)) {
|
||||
|
|
@ -190,7 +191,7 @@ char *workspace_next_name(const char *output_name) {
|
|||
order = binding->order;
|
||||
free(target);
|
||||
target = _target;
|
||||
wlr_log(L_DEBUG, "Workspace: Found free name %s", _target);
|
||||
wlr_log(WLR_DEBUG, "Workspace: Found free name %s", _target);
|
||||
} else {
|
||||
free(_target);
|
||||
}
|
||||
|
|
@ -387,7 +388,7 @@ bool workspace_switch(struct sway_container *workspace) {
|
|||
free(prev_workspace_name);
|
||||
prev_workspace_name = malloc(strlen(active_ws->name) + 1);
|
||||
if (!prev_workspace_name) {
|
||||
wlr_log(L_ERROR, "Unable to allocate previous workspace name");
|
||||
wlr_log(WLR_ERROR, "Unable to allocate previous workspace name");
|
||||
return false;
|
||||
}
|
||||
strcpy(prev_workspace_name, active_ws->name);
|
||||
|
|
@ -409,7 +410,7 @@ bool workspace_switch(struct sway_container *workspace) {
|
|||
}
|
||||
}
|
||||
|
||||
wlr_log(L_DEBUG, "Switching to workspace %p:%s",
|
||||
wlr_log(WLR_DEBUG, "Switching to workspace %p:%s",
|
||||
workspace, workspace->name);
|
||||
struct sway_container *next = seat_get_focus_inactive(seat, workspace);
|
||||
if (next == NULL) {
|
||||
|
|
@ -427,7 +428,7 @@ bool workspace_switch(struct sway_container *workspace) {
|
|||
}
|
||||
seat_set_focus(seat, next);
|
||||
struct sway_container *output = container_parent(workspace, C_OUTPUT);
|
||||
arrange_and_commit(output);
|
||||
arrange_windows(output);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -518,3 +519,13 @@ struct sway_container *workspace_output_get_highest_available(
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void workspace_detect_urgent(struct sway_container *workspace) {
|
||||
bool new_urgent = container_has_urgent_child(workspace);
|
||||
|
||||
if (workspace->sway_workspace->urgent != new_urgent) {
|
||||
workspace->sway_workspace->urgent = new_urgent;
|
||||
ipc_event_workspace(NULL, workspace, "urgent");
|
||||
container_damage_whole(workspace);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue