markup::
A string that indicates how the text of the block should be parsed. Set to
+"pango"+ to use https://developer.gnome.org/pango/stable/PangoMarkupFormat.html[Pango markup].
- Set to +"none"+ to not use any markup (default).
+ Set to +"none"+ to not use any markup (default). Pango markup only works
+ if you use a pango font.
If you want to put in your own entries into a block, prefix the key with an
underscore (_). i3bar will ignore all keys it doesn’t understand, and prefixing
how many pixels a *floating container* should be grown or shrunk (the default
is 10 pixels). The ppt argument means percentage points and specifies by how
many percentage points a *tiling container* should be grown or shrunk (the
-default is 10 percentage points). Note that +resize set+ will only work for
-floating containers.
+default is 10 percentage points).
+
+Notes about +resize set+: a value of 0 for <width> or <height> means "do
+not resize in this direction", and resizing a tiling container by +px+ is not
+implemented.
It is recommended to define bindings for resizing in a dedicated binding mode.
See <<binding_modes>> and the example in the i3
# If there are multiple scratchpad windows, this command cycles through them.
bindsym Mod1+minus scratchpad show
+# Define names for default workspaces for which we configure key bindings later on.
+# We use variables to avoid repeating the names in multiple places.
+set $ws1 "1"
+set $ws2 "2"
+set $ws3 "3"
+set $ws4 "4"
+set $ws5 "5"
+set $ws6 "6"
+set $ws7 "7"
+set $ws8 "8"
+set $ws9 "9"
+set $ws10 "10"
+
+
# switch to workspace
-bindsym Mod1+1 workspace 1
-bindsym Mod1+2 workspace 2
-bindsym Mod1+3 workspace 3
-bindsym Mod1+4 workspace 4
-bindsym Mod1+5 workspace 5
-bindsym Mod1+6 workspace 6
-bindsym Mod1+7 workspace 7
-bindsym Mod1+8 workspace 8
-bindsym Mod1+9 workspace 9
-bindsym Mod1+0 workspace 10
+bindsym Mod1+1 workspace $ws1
+bindsym Mod1+2 workspace $ws2
+bindsym Mod1+3 workspace $ws3
+bindsym Mod1+4 workspace $ws4
+bindsym Mod1+5 workspace $ws5
+bindsym Mod1+6 workspace $ws6
+bindsym Mod1+7 workspace $ws7
+bindsym Mod1+8 workspace $ws8
+bindsym Mod1+9 workspace $ws9
+bindsym Mod1+0 workspace $ws10
# move focused container to workspace
-bindsym Mod1+Shift+1 move container to workspace 1
-bindsym Mod1+Shift+2 move container to workspace 2
-bindsym Mod1+Shift+3 move container to workspace 3
-bindsym Mod1+Shift+4 move container to workspace 4
-bindsym Mod1+Shift+5 move container to workspace 5
-bindsym Mod1+Shift+6 move container to workspace 6
-bindsym Mod1+Shift+7 move container to workspace 7
-bindsym Mod1+Shift+8 move container to workspace 8
-bindsym Mod1+Shift+9 move container to workspace 9
-bindsym Mod1+Shift+0 move container to workspace 10
+bindsym Mod1+Shift+1 move container to workspace $ws1
+bindsym Mod1+Shift+2 move container to workspace $ws2
+bindsym Mod1+Shift+3 move container to workspace $ws3
+bindsym Mod1+Shift+4 move container to workspace $ws4
+bindsym Mod1+Shift+5 move container to workspace $ws5
+bindsym Mod1+Shift+6 move container to workspace $ws6
+bindsym Mod1+Shift+7 move container to workspace $ws7
+bindsym Mod1+Shift+8 move container to workspace $ws8
+bindsym Mod1+Shift+9 move container to workspace $ws9
+bindsym Mod1+Shift+0 move container to workspace $ws10
# reload the configuration file
bindsym Mod1+Shift+c reload
bindsym Up resize shrink height 10 px or 10 ppt
bindsym Right resize grow width 10 px or 10 ppt
- # back to normal: Enter or Escape
+ # back to normal: Enter or Escape or Mod1+r
bindsym Return mode "default"
bindsym Escape mode "default"
bindsym Mod1+r mode "default"
# focus the child container
#bindsym $mod+d focus child
+# Define names for default workspaces for which we configure key bindings later on.
+# We use variables to avoid repeating the names in multiple places.
+set $ws1 "1"
+set $ws2 "2"
+set $ws3 "3"
+set $ws4 "4"
+set $ws5 "5"
+set $ws6 "6"
+set $ws7 "7"
+set $ws8 "8"
+set $ws9 "9"
+set $ws10 "10"
+
# switch to workspace
-bindcode $mod+10 workspace 1
-bindcode $mod+11 workspace 2
-bindcode $mod+12 workspace 3
-bindcode $mod+13 workspace 4
-bindcode $mod+14 workspace 5
-bindcode $mod+15 workspace 6
-bindcode $mod+16 workspace 7
-bindcode $mod+17 workspace 8
-bindcode $mod+18 workspace 9
-bindcode $mod+19 workspace 10
+bindcode $mod+10 workspace $ws1
+bindcode $mod+11 workspace $ws2
+bindcode $mod+12 workspace $ws3
+bindcode $mod+13 workspace $ws4
+bindcode $mod+14 workspace $ws5
+bindcode $mod+15 workspace $ws6
+bindcode $mod+16 workspace $ws7
+bindcode $mod+17 workspace $ws8
+bindcode $mod+18 workspace $ws9
+bindcode $mod+19 workspace $ws10
# move focused container to workspace
-bindcode $mod+Shift+10 move container to workspace 1
-bindcode $mod+Shift+11 move container to workspace 2
-bindcode $mod+Shift+12 move container to workspace 3
-bindcode $mod+Shift+13 move container to workspace 4
-bindcode $mod+Shift+14 move container to workspace 5
-bindcode $mod+Shift+15 move container to workspace 6
-bindcode $mod+Shift+16 move container to workspace 7
-bindcode $mod+Shift+17 move container to workspace 8
-bindcode $mod+Shift+18 move container to workspace 9
-bindcode $mod+Shift+19 move container to workspace 10
+bindcode $mod+Shift+10 move container to workspace $ws1
+bindcode $mod+Shift+11 move container to workspace $ws2
+bindcode $mod+Shift+12 move container to workspace $ws3
+bindcode $mod+Shift+13 move container to workspace $ws4
+bindcode $mod+Shift+14 move container to workspace $ws5
+bindcode $mod+Shift+15 move container to workspace $ws6
+bindcode $mod+Shift+16 move container to workspace $ws7
+bindcode $mod+Shift+17 move container to workspace $ws8
+bindcode $mod+Shift+18 move container to workspace $ws9
+bindcode $mod+Shift+19 move container to workspace $ws10
# reload the configuration file
bindcode $mod+Shift+54 reload
bindcode 111 resize shrink height 10 px or 10 ppt
bindcode 114 resize grow width 10 px or 10 ppt
- # back to normal: Enter or Escape
+ # back to normal: Enter or Escape or $mod+r
bindcode 36 mode "default"
bindcode 9 mode "default"
bindcode $mod+27 mode "default"
void cmd_move_con_to_workspace_number(I3_CMD, const char *which, const char *no_auto_back_and_forth);
/**
- * Implementation of 'resize set <px> [px] <px> [px]'.
+ * Implementation of 'resize set <width> [px | ppt] <height> [px | ppt]'.
*
*/
void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, const char *mode_height);
*/
void con_focus(Con *con);
+/**
+ * Sets input focus to the given container and raises it to the top.
+ *
+ */
+void con_activate(Con *con);
+
/**
* Closes the given container.
*
#include <config.h>
-bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction);
+bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides);
int resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event);
break;
}
- bool res = resize_find_tiling_participants(&first, &second, search_direction);
+ bool res = resize_find_tiling_participants(&first, &second, search_direction, false);
if (!res) {
LOG("No second container in this direction found.\n");
return false;
* The splitv container will be focused. */
Con *focused = con->parent;
focused = TAILQ_FIRST(&(focused->focus_head));
- con_focus(focused);
+ con_activate(focused);
/* To prevent scrolling from going outside the container (see ticket
* #557), we first check if scrolling is possible at all. */
bool scroll_prev_possible = (TAILQ_PREV(focused, nodes_head, nodes) != NULL);
}
/* 2: focus this con. */
- con_focus(con);
+ con_activate(con);
/* 3: For floating containers, we also want to raise them on click.
* We will skip handling events on floating cons in fullscreen mode */
else
search_direction = D_DOWN;
- bool res = resize_find_tiling_participants(&first, &second, search_direction);
+ bool res = resize_find_tiling_participants(&first, &second, search_direction, false);
if (!res) {
LOG("No second container in this direction found.\n");
ysuccess(false);
static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *way, const char *direction, int ppt) {
LOG("width/height resize\n");
- /* get the appropriate current container (skip stacked/tabbed cons) */
- while (current->parent->layout == L_STACKED ||
- current->parent->layout == L_TABBED)
- current = current->parent;
-
- /* Then further go up until we find one with the matching orientation. */
- orientation_t search_orientation =
- (strcmp(direction, "width") == 0 ? HORIZ : VERT);
- while (current->type != CT_WORKSPACE &&
- current->type != CT_FLOATING_CON &&
- (con_orientation(current->parent) != search_orientation || con_num_children(current->parent) == 1))
- current = current->parent;
+ /* get the appropriate current container (skip stacked/tabbed cons) */
+ Con *dummy = NULL;
+ direction_t search_direction = (strcmp(direction, "width") == 0 ? D_LEFT : D_DOWN);
+ bool search_result = resize_find_tiling_participants(¤t, &dummy, search_direction, true);
+ if (search_result == false) {
+ ysuccess(false);
+ return false;
+ }
/* get the default percentage */
int children = con_num_children(current->parent);
double percentage = 1.0 / children;
LOG("default percentage = %f\n", percentage);
- orientation_t orientation = con_orientation(current->parent);
-
- if ((orientation == HORIZ &&
- strcmp(direction, "height") == 0) ||
- (orientation == VERT &&
- strcmp(direction, "width") == 0)) {
- LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n",
- (orientation == HORIZ ? "horizontal" : "vertical"));
- ysuccess(false);
- return false;
- }
-
- if (children == 1) {
- LOG("This is the only container, cannot resize.\n");
- ysuccess(false);
- return false;
- }
-
/* Ensure all the other children have a percentage set. */
Con *child;
TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) {
*/
void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, const char *mode_height) {
DLOG("resizing to %ld %s x %ld %s\n", cwidth, mode_width, cheight, mode_height);
- if (cwidth <= 0 || cheight <= 0) {
+ if (cwidth < 0 || cheight < 0) {
ELOG("Resize failed: dimensions cannot be negative (was %ld %s x %ld %s)\n", cwidth, mode_width, cheight, mode_height);
return;
}
HANDLE_EMPTY_MATCH;
owindow *current;
+ bool success = true;
TAILQ_FOREACH(current, &owindows, owindows) {
Con *floating_con;
if ((floating_con = con_inside_floating(current->con))) {
Con *output = con_get_output(floating_con);
- if (mode_width && strcmp(mode_width, "ppt") == 0) {
+ if (cwidth == 0) {
+ cwidth = output->rect.width;
+ } else if (mode_width && strcmp(mode_width, "ppt") == 0) {
cwidth = output->rect.width * ((double)cwidth / 100.0);
}
- if (mode_height && strcmp(mode_height, "ppt") == 0) {
+ if (cheight == 0) {
+ cheight = output->rect.height;
+ } else if (mode_height && strcmp(mode_height, "ppt") == 0) {
cheight = output->rect.height * ((double)cheight / 100.0);
}
floating_resize(floating_con, cwidth, cheight);
} else {
- ELOG("Resize failed: %p not a floating container\n", current->con);
+ if (current->con->window && current->con->window->dock) {
+ DLOG("This is a dock window. Not resizing (con = %p)\n)", current->con);
+ continue;
+ }
+
+ if (cwidth > 0 && mode_width && strcmp(mode_width, "ppt") == 0) {
+ /* get the appropriate current container (skip stacked/tabbed cons) */
+ Con *target = current->con;
+ Con *dummy;
+ resize_find_tiling_participants(&target, &dummy, D_LEFT, true);
+
+ /* Calculate new size for the target container */
+ double current_percent = target->percent;
+ char *action_string;
+ long adjustment;
+
+ if (current_percent > cwidth) {
+ action_string = "shrink";
+ adjustment = (int)(current_percent * 100) - cwidth;
+ } else {
+ action_string = "grow";
+ adjustment = cwidth - (int)(current_percent * 100);
+ }
+
+ /* perform resizing and report failure if not possible */
+ if (!cmd_resize_tiling_width_height(current_match, cmd_output,
+ target, action_string, "width", adjustment)) {
+ success = false;
+ }
+ }
+
+ if (cheight > 0 && mode_width && strcmp(mode_width, "ppt") == 0) {
+ /* get the appropriate current container (skip stacked/tabbed cons) */
+ Con *target = current->con;
+ Con *dummy;
+ resize_find_tiling_participants(&target, &dummy, D_DOWN, true);
+
+ /* Calculate new size for the target container */
+ double current_percent = target->percent;
+ char *action_string;
+ long adjustment;
+
+ if (current_percent > cheight) {
+ action_string = "shrink";
+ adjustment = (int)(current_percent * 100) - cheight;
+ } else {
+ action_string = "grow";
+ adjustment = cheight - (int)(current_percent * 100);
+ }
+
+ /* perform resizing and report failure if not possible */
+ if (!cmd_resize_tiling_width_height(current_match, cmd_output,
+ target, action_string, "height", adjustment)) {
+ success = false;
+ }
+ }
}
}
cmd_output->needs_tree_render = true;
- // XXX: default reply for now, make this a better reply
- ysuccess(true);
+ ysuccess(success);
}
/*
LOG("-------------------------------------------------\n");
LOG(" NOP: %s\n", comment);
LOG("-------------------------------------------------\n");
+ ysuccess(true);
}
/*
if (fullscreen_on_ws && fullscreen_on_ws != con && !con_has_parent(con, fullscreen_on_ws)) {
con_disable_fullscreen(fullscreen_on_ws);
}
- con_focus(con);
+ con_activate(con);
}
/*
* the target workspace, then revert focus. */
Con *currently_focused = focused;
cmd_focus_force_focus(current->con);
- con_focus(currently_focused);
+ con_activate(currently_focused);
/* Now switch to the workspace, then focus */
workspace_show(ws);
LOG("focusing %p / %s\n", current->con, current->con->name);
- con_focus(current->con);
+ con_activate(current->con);
count++;
}
/* the move command should not disturb focus */
if (focused != initially_focused)
- con_focus(initially_focused);
+ con_activate(initially_focused);
// XXX: default reply for now, make this a better reply
ysuccess(true);
LOG("opening new container\n");
Con *con = tree_open_con(NULL, NULL);
con->layout = L_SPLITH;
- con_focus(con);
+ con_activate(con);
y(map_open);
ystr("success");
}
/* Restore the previous focus since con_attach messes with the focus. */
- con_focus(previously_focused);
+ con_activate(previously_focused);
cmd_output->needs_tree_render = true;
ysuccess(true);
workspace_update_urgent_flag(con_get_workspace(con));
ipc_send_window_event("urgent", con);
}
+}
- /* Focusing a container with a floating parent should raise it to the top. Since
- * con_focus is called recursively for each parent we don't need to use
- * con_inside_floating(). */
- if (con->type == CT_FLOATING_CON) {
- floating_raise_con(con);
+/*
+ * Raise container to the top if it is floating or inside some floating
+ * container.
+ *
+ */
+static void con_raise(Con *con) {
+ Con *floating = con_inside_floating(con);
+ if (floating) {
+ floating_raise_con(floating);
}
}
+/*
+ * Sets input focus to the given container and raises it to the top.
+ *
+ */
+void con_activate(Con *con) {
+ con_focus(con);
+ con_raise(con);
+}
+
/*
* Closes the given container.
*
Con *old_focused = focused;
if (fullscreen_mode == CF_GLOBAL && cur_ws != con_ws)
workspace_show(con_ws);
- con_focus(con);
+ con_activate(con);
if (fullscreen_mode != CF_GLOBAL && cur_ws != con_ws)
- con_focus(old_focused);
+ con_activate(old_focused);
con_set_fullscreen_mode(con, fullscreen_mode);
}
* new workspace is hidden and it's necessary to immediately switch
* back to the originally-focused workspace. */
Con *old_focus = TAILQ_FIRST(&(output_get_content(dest_output)->focus_head));
- con_focus(con_descend_focused(con));
+ con_activate(con_descend_focused(con));
/* Restore focus if the output's focused workspace has changed. */
if (con_get_workspace(focused) != old_focus)
- con_focus(old_focus);
+ con_activate(old_focus);
}
/* 7: when moving to another workspace, we leave the focus on the current
/* Set focus only if con was on current workspace before moving.
* Otherwise we would give focus to some window on different workspace. */
if (!ignore_focus && source_ws == current_ws)
- con_focus(con_descend_focused(focus_next));
+ con_activate(con_descend_focused(focus_next));
/* 8. If anything within the container is associated with a startup sequence,
* delete it so child windows won't be created on the old workspace. */
con_attach(new, con, false);
if (old_focused)
- con_focus(old_focused);
+ con_activate(old_focused);
tree_flatten(croot);
}
* We don't need to check this for the second container because we've only
* moved the first one at this point.*/
if (first_ws != second_ws && focused_within_first) {
- con_focus(con_descend_focused(current_ws));
+ con_activate(con_descend_focused(current_ws));
}
/* Move second to where first has been originally. */
*/
if (focused_within_first) {
if (first_ws == second_ws) {
- con_focus(old_focus);
+ con_activate(old_focus);
} else {
- con_focus(con_descend_focused(second));
+ con_activate(con_descend_focused(second));
}
} else if (focused_within_second) {
if (first_ws == second_ws) {
- con_focus(old_focus);
+ con_activate(old_focus);
} else {
- con_focus(con_descend_focused(first));
+ con_activate(con_descend_focused(first));
}
}
render_con(con, false);
if (set_focus)
- con_focus(con);
+ con_activate(con);
/* Check if we need to re-assign it to a different workspace because of its
* coordinates and exit if that was done successfully. */
con_fix_percent(con->parent);
if (set_focus)
- con_focus(con);
+ con_activate(con);
floating_set_hint_atom(con, false);
ipc_send_window_event("floating", con);
DLOG("Moving con %p / %s to workspace %p / %s\n", con, con->name, ws, ws->name);
con_move_to_workspace(con, ws, false, true, false);
workspace_show(ws);
- con_focus(con_descend_focused(con));
+ con_activate(con_descend_focused(con));
return true;
}
if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(ws))) {
DLOG("Focusing con = %p\n", con);
workspace_show(ws);
- con_focus(con);
+ con_activate(con);
tree_render();
} else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(ws))) {
DLOG("Marking con = %p urgent\n", con);
workspace_show(ws);
/* Re-set focus, even if unchanged from i3’s perspective. */
focused_id = XCB_NONE;
- con_focus(con);
+ con_activate(con);
}
} else {
/* Request is from an application. */
if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(ws))) {
DLOG("Focusing con = %p\n", con);
workspace_show(ws);
- con_focus(con);
+ con_activate(con);
} else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(ws))) {
DLOG("Marking con = %p urgent\n", con);
con_set_urgency(con, true);
if (ws != con_get_workspace(focused))
workspace_show(ws);
- con_focus(con);
+ con_activate(con);
/* We update focused_id because we don’t need to set focus again */
focused_id = event->event;
tree_render();
yajl_free(hand);
if (to_focus) {
- con_focus(to_focus);
+ con_activate(to_focus);
}
}
output = get_first_output();
}
- con_focus(con_descend_focused(output_get_content(output->con)));
+ con_activate(con_descend_focused(output_get_content(output->con)));
free(pointerreply);
}
* proper window event sequence. */
if (set_focus && nc->mapped) {
DLOG("Now setting focus.\n");
- con_focus(nc);
+ con_activate(nc);
}
tree_render();
attach_to_workspace(con, ws, direction);
/* fix the focus stack */
- con_focus(con);
+ con_activate(con);
/* force re-painting the indicators */
FREE(con->deco_render_params);
Con *ws = create_workspace_on_output(output, content);
/* TODO: Set focus in main.c */
- con_focus(ws);
+ con_activate(ws);
}
/*
continue;
DLOG("Focusing primary output %s\n", output_primary_name(output));
- con_focus(con_descend_focused(output->con));
+ con_activate(con_descend_focused(output->con));
}
/* render_layout flushes */
if (next) {
DLOG("now focusing next = %p\n", next);
- con_focus(next);
+ con_activate(next);
workspace_show(con_get_workspace(next));
}
xcb_flush(conn);
}
-bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction) {
+bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides) {
DLOG("Find two participants for resizing container=%p in direction=%i\n", other, direction);
Con *first = *current;
Con *second = NULL;
/* get the counterpart for this resizement */
if (dir_backwards) {
second = TAILQ_PREV(first, nodes_head, nodes);
+ if (second == NULL && both_sides == true) {
+ second = TAILQ_NEXT(first, nodes);
+ }
} else {
second = TAILQ_NEXT(first, nodes);
+ if (second == NULL && both_sides == true) {
+ second = TAILQ_PREV(first, nodes_head, nodes);
+ }
}
if (second == NULL) {
/* use con_descend_tiling_focused to get the last focused
* window inside this scratch container in order to
* keep the focus the same within this container */
- con_focus(con_descend_tiling_focused(walk_con));
+ con_activate(con_descend_tiling_focused(walk_con));
return;
}
}
workspace_show(active);
}
- con_focus(con_descend_focused(con));
+ con_activate(con_descend_focused(con));
}
/*
DLOG("focusing %p / %s\n", next, next->name);
if (next->type == CT_DOCKAREA) {
/* Instead of focusing the dockarea, we need to restore focus to the workspace */
- con_focus(con_descend_focused(output_get_content(next->parent)));
+ con_activate(con_descend_focused(output_get_content(next->parent)));
} else {
if (!force_set_focus && con != focused)
DLOG("not changing focus, the container was not focused before\n");
else
- con_focus(next);
+ con_activate(next);
}
} else {
DLOG("not focusing because we're not killing anybody\n");
/* Skip over floating containers and go directly to the grandparent
* (which should always be a workspace) */
if (focused->parent->type == CT_FLOATING_CON) {
- con_focus(focused->parent->parent);
+ con_activate(focused->parent->parent);
return true;
}
ELOG("'focus parent': Focus is already on the workspace, cannot go higher than that.\n");
return false;
}
- con_focus(focused->parent);
+ con_activate(focused->parent);
return true;
}
next = TAILQ_FIRST(&(next->focus_head));
}
- con_focus(next);
+ con_activate(next);
return true;
}
}
workspace_show(workspace);
- con_focus(focus);
+ con_activate(focus);
x_set_warp_to(&(focus->rect));
return true;
}
TAILQ_INSERT_HEAD(&(parent->floating_head), last, floating_windows);
}
- con_focus(con_descend_focused(next));
+ con_activate(con_descend_focused(next));
return true;
}
/* 3: focus choice comes in here. at the moment we will go down
* until we find a window */
/* TODO: check for window, atm we only go down as far as possible */
- con_focus(con_descend_focused(next));
+ con_activate(con_descend_focused(next));
return true;
}
if (next->urgent && (int)(config.workspace_urgency_timer * 1000) > 0) {
/* focus for now… */
next->urgent = false;
- con_focus(next);
+ con_activate(next);
/* … but immediately reset urgency flags; they will be set to false by
* the timer callback in case the container is focused at the time of
ev_timer_again(main_loop, focused->urgency_timer);
}
} else
- con_focus(next);
+ con_activate(next);
ipc_send_workspace_event("focus", workspace, current);
con_fix_percent(ws);
if (old_focused)
- con_focus(old_focused);
+ con_activate(old_focused);
}
/*
cmd 'move right';
cmd '[id="' . $w3->id . '"] focus';
sync_with_i3;
- my $ws = get_ws($tmp);
+ $ws = get_ws($tmp);
ok(!$ws->{urgent}, 'urgent flag not set on workspace');
##############################################################################
kill_all_windows;
$tmp = fresh_workspace;
-my $first = open_floating_window;
-my $second = open_window;
+$first = open_floating_window;
+$second = open_window;
cmd 'fullscreen';
is($x->input_focus, $second->id, 'fullscreen window focused');
is_num_fullscreen($tmp, 1, '1 fullscreen window');
kill_all_windows;
$tmp = fresh_workspace;
-my $first = open_window;
-my $second = open_floating_window;
+$first = open_window;
+$second = open_floating_window;
cmd 'fullscreen';
is($x->input_focus, $second->id, 'fullscreen window focused');
is_num_fullscreen($tmp, 1, '1 fullscreen window');
kill_all_windows;
$tmp = fresh_workspace;
-my $first = open_window;
+$first = open_window;
$tmp2 = fresh_workspace;
-my $second = open_window;
+$second = open_window;
cmd 'fullscreen';
is($x->input_focus, $second->id, 'fullscreen window focused');
is_num_fullscreen($tmp2, 1, '1 fullscreen window');
################################################################################
clear_scratchpad;
-my $ws = fresh_workspace;
+$ws = fresh_workspace;
open_window;
my $scratch = get_focused($ws);
# 7: check floating_maximum_size with cmd_size
################################################################################
-my $config = <<EOT;
+$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
$pid = launch_with_config($config);
-my $window = open_floating_window(rect => [ 0, 0, 90, 80 ]);
+$window = open_floating_window(rect => [ 0, 0, 90, 80 ]);
cmd 'border none';
cmd 'resize set 101 91';
sync_with_i3;
-my $rect = $window->rect;
+$rect = $window->rect;
is($rect->{width}, 100, 'width did not exceed maximum width');
is($rect->{height}, 90, 'height did not exceed maximum height');
sub send_net_active_window {
my ($id, $source) = @_;
- $source = ($source eq 'pager' ? 2 : 0);
+ $source = (((defined $source) && ($source eq 'pager')) ? 2 : 0);
my $msg = pack "CCSLLLLLLL",
X11::XCB::CLIENT_MESSAGE, # response_type
# is received.
################################################################################
-my $scratch = open_window;
+$scratch = open_window;
is($x->input_focus, $scratch->id, 'to-scratchpad window has focus');
$pid = launch_with_config($config);
-my $ws = fresh_workspace;
+$ws = fresh_workspace;
$first = open_window;
$second = open_window;
$pid = launch_with_config($config);
-my $ws = fresh_workspace;
+$ws = fresh_workspace;
$first = open_window;
$second = open_window;
################################################################################
cmd 'resize set 44 ppt 111 px';
-my $expected_width = int(0.44 * 1333);
-my $expected_height = 111;
+$expected_width = int(0.44 * 1333);
+$expected_height = 111;
@content = @{get_ws($tmp)->{floating_nodes}};
cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x untouched');
cmp_ok($content[0]->{rect}->{height}, '==', $expected_height, "height changed to $expected_height px");
cmd 'resize set 222 px 100 ppt';
-my $expected_width = 222;
-my $expected_height = 999;
+$expected_width = 222;
+$expected_height = 999;
@content = @{get_ws($tmp)->{floating_nodes}};
cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x untouched');
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Tests the focus_follows_mouse setting.
+use i3test i3_config => <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+fake-outputs 1000x1000+0+0
+EOT
+
+my ($first, $second);
+
+sub synced_warp_pointer {
+ my ($x_px, $y_px) = @_;
+ sync_with_i3;
+ $x->root->warp_pointer($x_px, $y_px);
+ sync_with_i3;
+}
+
+###################################################################
+# Test a simple case with 2 windows.
+###################################################################
+
+synced_warp_pointer(600, 600);
+$first = open_window;
+$second = open_window;
+is($x->input_focus, $second->id, 'second window focused');
+
+synced_warp_pointer(0, 0);
+is($x->input_focus, $first->id, 'first window focused');
+
+###################################################################
+# Test that focus isn't changed with tabbed windows.
+###################################################################
+
+fresh_workspace;
+synced_warp_pointer(600, 600);
+$first = open_window;
+cmd 'layout tabbed';
+$second = open_window;
+is($x->input_focus, $second->id, 'second (tabbed) window focused');
+
+synced_warp_pointer(0, 0);
+is($x->input_focus, $second->id, 'second window still focused');
+
+###################################################################
+# Test that floating windows are focused but not raised to the top.
+# See issue #2990.
+###################################################################
+
+my $ws;
+my $tmp = fresh_workspace;
+my ($first_floating, $second_floating);
+
+synced_warp_pointer(0, 0);
+$first_floating = open_floating_window;
+$first_floating->rect(X11::XCB::Rect->new(x => 1, y => 1, width => 100, height => 100));
+$second_floating = open_floating_window;
+$second_floating->rect(X11::XCB::Rect->new(x => 50, y => 50, width => 100, height => 100));
+sync_with_i3;
+$first = open_window;
+
+is($x->input_focus, $first->id, 'first (tiling) window focused');
+$ws = get_ws($tmp);
+is($ws->{floating_nodes}->[1]->{nodes}->[0]->{window}, $second_floating->id, 'second floating on top');
+is($ws->{floating_nodes}->[0]->{nodes}->[0]->{window}, $first_floating->id, 'first floating behind');
+
+synced_warp_pointer(40, 40);
+is($x->input_focus, $first_floating->id, 'first floating window focused');
+$ws = get_ws($tmp);
+is($ws->{floating_nodes}->[1]->{nodes}->[0]->{window}, $second_floating->id, 'second floating still on top');
+is($ws->{floating_nodes}->[0]->{nodes}->[0]->{window}, $first_floating->id, 'first floating still behind');
+
+done_testing;
my $__i3_scratch = get_ws('__i3_scratch');
is(scalar @{$__i3_scratch->{floating_nodes}}, 0, 'scratchpad is empty');
-my $ws0 = fresh_workspace(output => 0);
+$ws0 = fresh_workspace(output => 0);
open_window(wm_class => 'a');
-my $ws1 = fresh_workspace(output => 1);
+$ws1 = fresh_workspace(output => 1);
open_window(wm_class => 'b');
my $scratchpad_window = open_window(wm_class => 'c');
cmd 'move to scratchpad';
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • https://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • https://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • https://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+# Tests resizing tiling containers
+use i3test;
+
+############################################################
+# resize horizontally
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+
+my $left = open_window;
+my $right = open_window;
+
+diag("left = " . $left->id . ", right = " . $right->id);
+
+is($x->input_focus, $right->id, 'Right window focused');
+
+cmd 'resize set 75 ppt 0 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left window got only 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right window got 75%');
+
+############################################################
+# resize vertically
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split v';
+
+my $top = open_window;
+my $bottom = open_window;
+
+diag("top = " . $top->id . ", bottom = " . $bottom->id);
+
+is($x->input_focus, $bottom->id, 'Bottom window focused');
+
+cmd 'resize set 0 ppt 75 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'top window got only 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'bottom window got 75%');
+
+
+############################################################
+# resize horizontally and vertically
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+my $left = open_window;
+my $top_right = open_window;
+cmd 'split v';
+my $bottom_right = open_window;
+
+diag("left = " . $left->id . ", top-right = " . $top_right->id . ", bottom-right = " . $bottom_right->id);
+
+is($x->input_focus, $bottom_right->id, 'Bottom-right window focused');
+
+cmd 'resize set 75 ppt 75 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%');
+cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.25, 'top-right window got 25%');
+cmp_float($nodes->[1]->{nodes}->[1]->{percent}, 0.75, 'bottom-right window got 75%');
+
+
+############################################################
+# resize from inside a tabbed container
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+
+my $left = open_window;
+my $right1 = open_window;
+
+cmd 'split h';
+cmd 'layout tabbed';
+
+my $right2 = open_window;
+
+diag("left = " . $left->id . ", right1 = " . $right1->id . ", right2 = " . $right2->id);
+
+is($x->input_focus, $right2->id, '2nd right window focused');
+
+cmd 'resize set 75 ppt 0 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%');
+
+
+############################################################
+# resize from inside a stacked container
+############################################################
+
+my $tmp = fresh_workspace;
+
+cmd 'split h';
+
+my $left = open_window;
+my $right1 = open_window;
+
+cmd 'split h';
+cmd 'layout stacked';
+
+my $right2 = open_window;
+
+diag("left = " . $left->id . ", right1 = " . $right1->id . ", right2 = " . $right2->id);
+
+is($x->input_focus, $right2->id, '2nd right window focused');
+
+cmd 'resize set 75 ppt 0 ppt';
+
+my ($nodes, $focus) = get_ws_content($tmp);
+
+cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%');
+cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%');
+
+
+done_testing;