mirror of
https://github.com/swaywm/sway.git
synced 2025-11-09 13:29:49 -05:00
Merge branch 'master' into pid-workspaces
This commit is contained in:
commit
f4b882475e
156 changed files with 5391 additions and 2147 deletions
199
sway/tree/view.c
199
sway/tree/view.c
|
|
@ -26,6 +26,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);
|
||||
}
|
||||
|
||||
|
|
@ -141,6 +142,19 @@ const char *view_get_shell(struct sway_view *view) {
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
void view_get_constraints(struct sway_view *view, double *min_width,
|
||||
double *max_width, double *min_height, double *max_height) {
|
||||
if (view->impl->get_constraints) {
|
||||
view->impl->get_constraints(view,
|
||||
min_width, max_width, min_height, max_height);
|
||||
} else {
|
||||
*min_width = DBL_MIN;
|
||||
*max_width = DBL_MAX;
|
||||
*min_height = DBL_MIN;
|
||||
*max_height = DBL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
|
||||
int height) {
|
||||
if (view->impl->configure) {
|
||||
|
|
@ -151,12 +165,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;
|
||||
|
||||
|
|
@ -165,9 +210,6 @@ void view_init_floating(struct sway_view *view) {
|
|||
view->border_left = view->border_right = true;
|
||||
|
||||
container_set_geometry_from_floating_view(view->swayc);
|
||||
|
||||
// Don't maximize floating windows
|
||||
view_set_tiled(view, false);
|
||||
}
|
||||
|
||||
void view_autoconfigure(struct sway_view *view) {
|
||||
|
|
@ -279,7 +321,6 @@ void view_autoconfigure(struct sway_view *view) {
|
|||
view->y = y;
|
||||
view->width = width;
|
||||
view->height = height;
|
||||
view_set_tiled(view, true);
|
||||
}
|
||||
|
||||
void view_set_activated(struct sway_view *view, bool activated) {
|
||||
|
|
@ -289,7 +330,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);
|
||||
}
|
||||
|
|
@ -352,6 +401,8 @@ void view_set_fullscreen(struct sway_view *view, bool fullscreen) {
|
|||
}
|
||||
}
|
||||
|
||||
container_end_mouse_operation(view->swayc);
|
||||
|
||||
ipc_event_window(view->swayc, "fullscreen_mode");
|
||||
}
|
||||
|
||||
|
|
@ -467,27 +518,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;
|
||||
|
|
@ -524,7 +593,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
|
|||
prev_focus = target_sibling;
|
||||
target_sibling = seat_get_focus_inactive(seat, workspace);
|
||||
} else {
|
||||
// TODO: CT_ASSIGN_OUTPUT
|
||||
// CT_ASSIGN_OUTPUT
|
||||
struct sway_container *output = output_by_name(criteria->target);
|
||||
if (output) {
|
||||
prev_focus = seat_get_focus_inactive(seat, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
list_free(criterias);
|
||||
|
|
@ -549,8 +622,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,
|
||||
|
|
@ -561,11 +632,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);
|
||||
}
|
||||
|
||||
if (prev_focus == target_sibling) {
|
||||
if (should_focus(view) && prev_focus == target_sibling) {
|
||||
input_manager_set_focus(input_manager, cont);
|
||||
if (workspace) {
|
||||
workspace_switch(workspace);
|
||||
}
|
||||
}
|
||||
|
||||
view_update_title(view, false);
|
||||
|
|
@ -581,16 +661,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,6 +692,8 @@ void view_update_position(struct sway_view *view, double lx, double ly) {
|
|||
container_damage_whole(view->swayc);
|
||||
view->x = lx;
|
||||
view->y = ly;
|
||||
view->swayc->current.view_x = lx;
|
||||
view->swayc->current.view_y = ly;
|
||||
if (container_is_floating(view->swayc)) {
|
||||
container_set_geometry_from_floating_view(view->swayc);
|
||||
}
|
||||
|
|
@ -614,6 +707,8 @@ void view_update_size(struct sway_view *view, int width, int height) {
|
|||
container_damage_whole(view->swayc);
|
||||
view->width = width;
|
||||
view->height = height;
|
||||
view->swayc->current.view_width = width;
|
||||
view->swayc->current.view_height = height;
|
||||
if (container_is_floating(view->swayc)) {
|
||||
container_set_geometry_from_floating_view(view->swayc);
|
||||
}
|
||||
|
|
@ -624,7 +719,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);
|
||||
|
|
@ -744,8 +839,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;
|
||||
}
|
||||
|
||||
|
|
@ -812,7 +908,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;
|
||||
}
|
||||
|
|
@ -946,7 +1042,7 @@ static void update_marks_texture(struct sway_view *view,
|
|||
|
||||
double scale = output->sway_output->wlr_output->scale;
|
||||
int width = 0;
|
||||
int height = config->font_height * scale;
|
||||
int height = view->swayc->title_height * scale;
|
||||
|
||||
cairo_t *c = cairo_create(NULL);
|
||||
get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer);
|
||||
|
|
@ -995,7 +1091,7 @@ void view_update_marks_textures(struct sway_view *view) {
|
|||
}
|
||||
|
||||
bool view_is_visible(struct sway_view *view) {
|
||||
if (!view->swayc || view->swayc->destroying) {
|
||||
if (!view->swayc || view->swayc->destroying || !view->swayc->parent) {
|
||||
return false;
|
||||
}
|
||||
struct sway_container *workspace =
|
||||
|
|
@ -1033,3 +1129,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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue