Skip to content
This repository has been archived by the owner on Nov 7, 2022. It is now read-only.

Converting outer gaps into side-specific gaps, also allowing outer/horizontal/vertical #211

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 115 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,37 @@ Please refer to the [wiki](https://github.com/Airblader/i3/wiki/Compiling-&-Inst

Note: Gaps will only work correctly if you disable window titlebars entirely. Unfortunately this is necessary due to the way i3 creates such bars on windows. You can disable them via `for_window [class="^.*"] border pixel 0` in your config. You can also use any non-zero value as long as you only use pixel-style borders.

Based on the patches provided by o4dev and jeanbroid, i3 supports gaps between containers. I extended those patches further to make changing the gaps size easier during runtime and also to expose more functionality for binding it to keys. Additionally, the gaps patch was fixed such that inner gaps (the gaps between adjacent containers) and outer gaps (gaps between the edge of the screen and a container) are the same. But I didn't stop there: these gaps are called "inner" gaps. This fork also allows setting "outer" gaps which inset all containers independently.
Based on the patches provided by o4dev and jeanbroid, i3 supports gaps between containers. I extended those patches further to make changing the gaps size easier during runtime and also to expose more functionality for binding it to keys. Additionally, the gaps patch was fixed such that inner gaps (the gaps between adjacent containers) and outer gaps (gaps between the edge of the screen and a container) are the same. But I didn't stop there: these gaps are called "inner" gaps. This fork also allows setting "outer," "horizontal," "vertical," "top," "right," "bottom," and "left" gaps which inset all containers independently. Note that outer gaps are stored per-side and "outer," "horizontal," and "vertical" are shortcuts for setting multiple sides at once.

In your i3 config, you can set a global gap size as shown below. This is the default value that will be used for all workspaces:
In your i3 config, you can set a global gap size as shown below. This is the default value that will be used for all workspaces. When setting side-specific values (e.g. horizontal or bottom), be sure to place them in the following order, otherwise your outer gaps will override any previously set values for single sides:

```
gaps inner <px>
gaps outer <px>
gaps horizontal <px>
gaps vertical <px>
gaps top <px>
gaps right <px>
gaps bottom <px>
gaps left <px>
```

Additionally, you can issue commands with the following syntax. This is useful, for example, to bind keys to changing the gap size:

```
gaps inner|outer current|all set|plus|minus <px>
gaps inner|outer|horizontal|vertical|top|right|bottom|left current|all set|plus|minus <px>

# Examples
gaps inner all set 20
gaps outer current plus 5
gaps horizontal current plus 40
```

Here are the individual parts explained:

* `inner|outer` specifies whether you want to modify inner gaps (gaps between adjacent containers) or outer gaps (gaps between the edge of a screen and a container).
* `inner|outer|horizontal|vertical|top|right|bottom|left` specifies whether you want to modify inner gaps (gaps between adjacent containers) or outer gaps (gaps between the edge of a screen and a container). Remember that outer gaps are per-side and outer, horizontal, and vertical are shortcuts for specifying multiple sides at once.
* `current|all` determines whether you want to modify the setting for the current workspace only or for all workspaces.
* `set|plus|minus` allows you to either set a new, fixed value or make a relative change (in-/decrement).
* `set|plus|minus` allows you to either set a new, fixed value or make a relative change (in-/decrement). Since 'outer,' 'horizontal,' and 'vertical' assignments are short-hand for all or some sides, specifying one of them and the 'set' command will override any side-specific values.

Note that outer gaps are an *addition* to inner gaps, so `gaps outer all set 0` will eliminate outer gaps, but if inner gaps are set, there will still be gaps on the edge of the screen.

Expand All @@ -61,6 +68,12 @@ Additionally, gaps can be specified on a per-workspace level by using the syntax
```
workspace <ws> gaps inner <px>
workspace <ws> gaps outer <px>
workspace <ws> gaps horizontal <px>
workspace <ws> gaps vertical <px>
workspace <ws> gaps top <px>
workspace <ws> gaps right <px>
workspace <ws> gaps bottom <px>
workspace <ws> gaps left <px>
```

It is important that these commands are specified after the global default since they are meant to override it.
Expand All @@ -71,21 +84,45 @@ workspace 1 gaps inner 0
workspace "www" gaps inner 0
```

Here is one possible idea on how you can use this feature within your i3 config. Simply press `$mod+Shift+g` to enter the gaps mode. Then choose between `o` and `i` for modifying outer / inner gaps. In this mode, you can press one of `+` / `-` (in-/decrement for current workspace) or `0` (remove gaps for current workspace). If you also press `Shift` with these keys, the change will be global for all workspaces.
Here is one possible idea on how you can use this feature within your i3 config. Simply press `$mod+Shift+g` to enter the gaps mode. Then choose between `o`, `i`, `h`, `v`, `t`, `b`, `l`, or `r` for modifying outer / inner / horizontal / vertical / top / right / bottom / left gaps. In this mode, you can press one of `+` / `-` (in-/decrement for current workspace) or `0` (remove gaps for current workspace). If you also press `Shift` with these keys, the change will be global for all workspaces.

```
set $mode_gaps Gaps: (o) outer, (i) inner
set $mode_gaps Gaps: (o)uter, (i)nner, (h)orizontal, (v)ertical, (t)op, (r)ight, (b)ottom, (l)eft
set $mode_gaps_outer Outer Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_inner Inner Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_horiz Horizontal Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_verti Vertical Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_top Top Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_right Right Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_bottom Bottom Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_left Left Gaps: +|-|0 (local), Shift + +|-|0 (global)
bindsym $mod+Shift+g mode "$mode_gaps"

mode "$mode_gaps" {
bindsym o mode "$mode_gaps_outer"
bindsym i mode "$mode_gaps_inner"
bindsym Return mode "default"
bindsym h mode "$mode_gaps_horiz"
bindsym v mode "$mode_gaps_verti"
bindsym t mode "$mode_gaps_top"
bindsym r mode "$mode_gaps_right"
bindsym b mode "$mode_gaps_bottom"
bindsym l mode "$mode_gaps_left"
bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}

mode "$mode_gaps_outer" {
bindsym plus gaps outer current plus 5
bindsym minus gaps outer current minus 5
bindsym 0 gaps outer current set 0

bindsym Shift+plus gaps outer all plus 5
bindsym Shift+minus gaps outer all minus 5
bindsym Shift+0 gaps outer all set 0

bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
mode "$mode_gaps_inner" {
bindsym plus gaps inner current plus 5
bindsym minus gaps inner current minus 5
Expand All @@ -95,19 +132,79 @@ mode "$mode_gaps_inner" {
bindsym Shift+minus gaps inner all minus 5
bindsym Shift+0 gaps inner all set 0

bindsym Return mode "default"
bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
mode "$mode_gaps_outer" {
bindsym plus gaps outer current plus 5
bindsym minus gaps outer current minus 5
bindsym 0 gaps outer current set 0
mode "$mode_gaps_horiz" {
bindsym plus gaps horizontal current plus 5
bindsym minus gaps horizontal current minus 5
bindsym 0 gaps horizontal current set 0

bindsym Shift+plus gaps outer all plus 5
bindsym Shift+minus gaps outer all minus 5
bindsym Shift+0 gaps outer all set 0
bindsym Shift+plus gaps horizontal all plus 5
bindsym Shift+minus gaps horizontal all minus 5
bindsym Shift+0 gaps horizontal all set 0

bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
mode "$mode_gaps_verti" {
bindsym plus gaps vertical current plus 5
bindsym minus gaps vertical current minus 5
bindsym 0 gaps vertical current set 0

bindsym Shift+plus gaps vertical all plus 5
bindsym Shift+minus gaps vertical all minus 5
bindsym Shift+0 gaps vertical all set 0

bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
mode "$mode_gaps_top" {
bindsym plus gaps top current plus 5
bindsym minus gaps top current minus 5
bindsym 0 gaps top current set 0

bindsym Shift+plus gaps top all plus 5
bindsym Shift+minus gaps top all minus 5
bindsym Shift+0 gaps top all set 0

bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
mode "$mode_gaps_right" {
bindsym plus gaps right current plus 5
bindsym minus gaps right current minus 5
bindsym 0 gaps right current set 0

bindsym Shift+plus gaps right all plus 5
bindsym Shift+minus gaps right all minus 5
bindsym Shift+0 gaps right all set 0

bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
mode "$mode_gaps_bottom" {
bindsym plus gaps bottom current plus 5
bindsym minus gaps bottom current minus 5
bindsym 0 gaps bottom current set 0

bindsym Shift+plus gaps bottom all plus 5
bindsym Shift+minus gaps bottom all minus 5
bindsym Shift+0 gaps bottom all set 0

bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
mode "$mode_gaps_left" {
bindsym plus gaps left current plus 5
bindsym minus gaps left current minus 5
bindsym 0 gaps left current set 0

bindsym Shift+plus gaps left all plus 5
bindsym Shift+minus gaps left all minus 5
bindsym Shift+0 gaps left all set 0

bindsym Return mode "default"
bindsym Return mode "$mode_gaps"
bindsym Escape mode "default"
}
```
Expand All @@ -120,7 +217,7 @@ If you want gaps to only be used if there is more than one container on the work
smart_gaps on
```

This will disable all gaps (outer and inner) on the workspace whenever only one container is on the current workspace.
This will disable all gaps (outer, inner, horizontal, vertical, top, right, bottom, left) on the workspace whenever only one container is on the current workspace.


### Smart Borders
Expand Down
2 changes: 1 addition & 1 deletion include/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ void cmd_shmlog(I3_CMD, const char *argument);
void cmd_debuglog(I3_CMD, const char *argument);

/**
* Implementation of 'gaps inner|outer current|all set|plus|minus <px>'
* Implementation of 'gaps inner|outer|top|right|bottom|left|horizontal|vertical current|all set|plus|minus <px>'
*
*/
void cmd_gaps(I3_CMD, const char *type, const char *scope, const char *mode, const char *value);
5 changes: 4 additions & 1 deletion include/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ typedef enum {

struct gaps_t {
int inner;
int outer;
int top;
int right;
int bottom;
int left;
};

/**
Expand Down
4 changes: 2 additions & 2 deletions parser-specs/commands.spec
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ state BORDER:
'1pixel'
-> call cmd_border("pixel", 1)

# gaps inner|outer [current] [plus|minus] <px>
# gaps inner|outer|horizontal|vertical|top|right|bottom|left [current] [set|plus|minus] <px>
state GAPS:
type = 'inner', 'outer'
type = 'inner', 'outer', 'horizontal', 'vertical', 'top', 'right', 'bottom', 'left'
-> GAPS_WITH_TYPE

state GAPS_WITH_TYPE:
Expand Down
4 changes: 2 additions & 2 deletions parser-specs/config.spec
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ state IGNORE_LINE:
line
-> INITIAL

# gaps inner|outer <px>
# gaps inner|outer|horizontal|vertical|top|right|bottom|left <px>
state GAPS:
scope = 'inner', 'outer'
scope = 'inner', 'outer', 'horizontal', 'vertical', 'top', 'right', 'bottom', 'left'
-> GAPS_WITH_SCOPE

state GAPS_WITH_SCOPE:
Expand Down
31 changes: 23 additions & 8 deletions src/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -2193,14 +2193,16 @@ void cmd_debuglog(I3_CMD, const char *argument) {
}

/**
* Implementation of 'gaps inner|outer current|all set|plus|minus <px>'
* Implementation of 'gaps inner|outer|top|right|bottom|left|horizontal|vertical current|all set|plus|minus <px>'
*
*/
void cmd_gaps(I3_CMD, const char *type, const char *scope, const char *mode, const char *value) {
#define CMD_GAPS(type, other) \
int pixels = logical_px(atoi(value)); \
Con *workspace = con_get_workspace(focused); \
\
int pixels = logical_px(atoi(value));
Con *workspace = con_get_workspace(focused);
bool invalid = true;

#define CMD_GAPS(type) \
invalid = false; \
int current_value = config.gaps.type; \
if (strcmp(scope, "current") == 0) \
current_value += workspace->gaps.type; \
Expand Down Expand Up @@ -2240,10 +2242,23 @@ void cmd_gaps(I3_CMD, const char *type, const char *scope, const char *mode, con
}

if (!strcmp(type, "inner")) {
CMD_GAPS(inner, outer);
} else if (!strcmp(type, "outer")) {
CMD_GAPS(outer, inner);
CMD_GAPS(inner);
} else {
if (!strcmp(type, "top") || !strcmp(type, "vertical") || !strcmp(type, "outer")) {
cameronleger marked this conversation as resolved.
Show resolved Hide resolved
CMD_GAPS(top);
}
if (!strcmp(type, "bottom") || !strcmp(type, "vertical") || !strcmp(type, "outer")) {
CMD_GAPS(bottom);
}
if (!strcmp(type, "right") || !strcmp(type, "horizontal") || !strcmp(type, "outer")) {
CMD_GAPS(right);
}
if (!strcmp(type, "left") || !strcmp(type, "horizontal") || !strcmp(type, "outer")) {
CMD_GAPS(left);
}
}

if (invalid) {
ELOG("Invalid type %s when changing gaps", type);
ysuccess(false);
return;
Expand Down
23 changes: 18 additions & 5 deletions src/con.c
Original file line number Diff line number Diff line change
Expand Up @@ -1631,6 +1631,13 @@ Con *con_descend_direction(Con *con, direction_t direction) {
return con_descend_direction(most, direction);
}

bool has_outer_gaps(gaps_t gaps) {
cameronleger marked this conversation as resolved.
Show resolved Hide resolved
return gaps.top > 0 ||
gaps.right > 0 ||
gaps.bottom > 0 ||
gaps.left > 0;
}

/*
* Returns a "relative" Rect which contains the amount of pixels that need to
* be added to the original Rect to get the final position (obviously the
Expand All @@ -1639,9 +1646,9 @@ Con *con_descend_direction(Con *con, direction_t direction) {
*/
Rect con_border_style_rect(Con *con) {
if ((config.smart_borders == ON && con_num_visible_children(con_get_workspace(con)) <= 1) ||
(config.smart_borders == NO_GAPS && calculate_effective_gaps(con).outer == 0) ||
(config.smart_borders == NO_GAPS && !has_outer_gaps(calculate_effective_gaps(con))) ||
(config.hide_edge_borders == HEBM_SMART && con_num_visible_children(con_get_workspace(con)) <= 1) ||
(config.hide_edge_borders == HEBM_SMART_NO_GAPS && con_num_visible_children(con_get_workspace(con)) <= 1 && calculate_effective_gaps(con).outer == 0)) {
(config.hide_edge_borders == HEBM_SMART_NO_GAPS && con_num_visible_children(con_get_workspace(con)) <= 1 && !has_outer_gaps(calculate_effective_gaps(con)))) {
if (!con_is_floating(con))
return (Rect){0, 0, 0, 0};
}
Expand Down Expand Up @@ -2286,7 +2293,7 @@ char *con_get_tree_representation(Con *con) {
gaps_t calculate_effective_gaps(Con *con) {
Con *workspace = con_get_workspace(con);
if (workspace == NULL || (config.smart_gaps && con_num_visible_children(workspace) <= 1))
return (gaps_t){0, 0};
return (gaps_t){0, 0, 0, 0, 0};

// if all visible children are in one tabbed container, disable gaps
if (config.smart_gaps && con_num_children(workspace) == 1 &&
Expand All @@ -2296,10 +2303,16 @@ gaps_t calculate_effective_gaps(Con *con) {

gaps_t gaps = {
.inner = (workspace->gaps.inner + config.gaps.inner) / 2,
.outer = workspace->gaps.outer + config.gaps.outer};
.top = workspace->gaps.top + config.gaps.top,
.right = workspace->gaps.right + config.gaps.right,
.bottom = workspace->gaps.bottom + config.gaps.bottom,
.left = workspace->gaps.left + config.gaps.left};

/* Outer gaps are added on top of inner gaps. */
gaps.outer += 2 * gaps.inner;
gaps.top += 2 * gaps.inner;
gaps.right += 2 * gaps.inner;
gaps.bottom += 2 * gaps.inner;
gaps.left += 2 * gaps.inner;

return gaps;
}
Expand Down
5 changes: 4 additions & 1 deletion src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,10 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
config.default_orientation = NO_ORIENTATION;

config.gaps.inner = 0;
config.gaps.outer = 0;
config.gaps.top = 0;
config.gaps.right = 0;
config.gaps.bottom = 0;
config.gaps.left = 0;

/* Set default urgency reset delay to 500ms */
if (config.workspace_urgency_timer == 0)
Expand Down
Loading