aboutsummaryrefslogtreecommitdiff
path: root/sway/tree/view.c
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2018-07-23 20:27:56 -0400
committerDrew DeVault <sir@cmpwn.com>2018-07-23 20:31:11 -0400
commitf4b882475eee7a81c206c7825616cc4656b2f60b (patch)
tree38e6ebf81b235424f105dcbcbb194e5e9eac70c0 /sway/tree/view.c
parentacd79e1505c06089e4fb9fb6c0c6e1d351ba9176 (diff)
parent224ade138208e9aa525423cbfbd643aa9d9b63c3 (diff)
downloadsway-f4b882475eee7a81c206c7825616cc4656b2f60b.tar.xz
Merge branch 'master' into pid-workspaces
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r--sway/tree/view.c191
1 files changed, 158 insertions, 33 deletions
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 24fb6864..a55c8a29 100644
--- a/sway/tree/view.c
+++ b/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->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) {
- struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
ws->sway_workspace->fullscreen = NULL;
- container_destroy(view->swayc);
+ parent = container_destroy(view->swayc);
- arrange_and_commit(ws->parent);
+ arrange_windows(ws->parent);
} else {
- struct sway_container *parent = container_destroy(view->swayc);
- arrange_and_commit(parent);
+ 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;
+}