Skip to content

Commit

Permalink
Merge gaps support as-is
Browse files Browse the repository at this point in the history
This code was copied over unmodified from https://github.com/Airblader/i3-gaps.

I have split out the differences between i3-gaps and i3 into three areas:
1. Gaps
2. i3bar height
3. rgba colors
  • Loading branch information
stapelberg committed Nov 1, 2022
1 parent 0b89d4b commit b825dc1
Show file tree
Hide file tree
Showing 22 changed files with 668 additions and 33 deletions.
6 changes: 6 additions & 0 deletions include/commands.h
Expand Up @@ -332,6 +332,12 @@ void cmd_shmlog(I3_CMD, const char *argument);
*/
void cmd_debuglog(I3_CMD, const char *argument);

/**
* Implementation of 'gaps inner|outer|top|right|bottom|left|horizontal|vertical current|all set|plus|minus|toggle <px>'
*
*/
void cmd_gaps(I3_CMD, const char *type, const char *scope, const char *mode, const char *value);

/**
* Implementation of 'title_window_icon <yes|no|toggle>' and 'title_window_icon <padding|toggle> <px>'
*
Expand Down
7 changes: 7 additions & 0 deletions include/con.h
Expand Up @@ -525,6 +525,13 @@ void con_set_urgency(Con *con, bool urgent);
*/
char *con_get_tree_representation(Con *con);

/**
* Calculates the effective gap sizes for a container depending
* on whether it is adjacent to the edge of the screen or another
* container.
*/
gaps_t calculate_effective_gaps(Con *con);

/**
* force parent split containers to be redrawn
*
Expand Down
3 changes: 3 additions & 0 deletions include/config_directives.h
Expand Up @@ -43,6 +43,9 @@ CFGFUN(include, const char *pattern);
CFGFUN(font, const char *font);
CFGFUN(exec, const char *exectype, const char *no_startup_id, const char *command);
CFGFUN(for_window, const char *command);
CFGFUN(gaps, const char *workspace, const char *type, const long value);
CFGFUN(smart_borders, const char *enable);
CFGFUN(smart_gaps, const char *enable);
CFGFUN(floating_minimum_size, const long width, const long height);
CFGFUN(floating_maximum_size, const long width, const long height);
CFGFUN(default_orientation, const char *orientation);
Expand Down
9 changes: 9 additions & 0 deletions include/configuration.h
Expand Up @@ -268,6 +268,15 @@ struct Config {
int number_barconfigs;

tiling_drag_t tiling_drag;

/* Gap sizes */
gaps_t gaps;

/* Should single containers on a workspace receive a border? */
smart_borders_t smart_borders;

/* Disable gaps if there is only one container on the workspace */
smart_gaps_t smart_gaps;
};

/**
Expand Down
26 changes: 24 additions & 2 deletions include/data.h
Expand Up @@ -47,6 +47,7 @@ typedef struct Con Con;
typedef struct Match Match;
typedef struct Assignment Assignment;
typedef struct Window i3Window;
typedef struct gaps_t gaps_t;
typedef struct mark_t mark_t;

/******************************************************************************
Expand Down Expand Up @@ -80,11 +81,20 @@ typedef enum { ADJ_NONE = 0,
ADJ_UPPER_SCREEN_EDGE = (1 << 2),
ADJ_LOWER_SCREEN_EDGE = (1 << 4) } adjacent_t;

typedef enum { SMART_BORDERS_OFF,
SMART_BORDERS_ON,
SMART_BORDERS_NO_GAPS } smart_borders_t;

typedef enum { SMART_GAPS_OFF,
SMART_GAPS_ON,
SMART_GAPS_INVERSE_OUTER } smart_gaps_t;

typedef enum { HEBM_NONE = ADJ_NONE,
HEBM_VERTICAL = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE,
HEBM_HORIZONTAL = ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE,
HEBM_BOTH = HEBM_VERTICAL | HEBM_HORIZONTAL,
HEBM_SMART = (1 << 5) } hide_edge_borders_mode_t;
HEBM_SMART = (1 << 5),
HEBM_SMART_NO_GAPS = (1 << 6) } hide_edge_borders_mode_t;

typedef enum { MM_REPLACE,
MM_ADD } mark_mode_t;
Expand Down Expand Up @@ -137,6 +147,14 @@ typedef enum {
POINTER_WARPING_NONE = 1
} warping_t;

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

/**
* Focus wrapping modes.
*/
Expand Down Expand Up @@ -204,12 +222,13 @@ struct deco_render_params {
};

/**
* Stores which workspace (by name or number) goes to which output.
* Stores which workspace (by name or number) goes to which output and its gaps config.
*
*/
struct Workspace_Assignment {
char *name;
char *output;
gaps_t gaps;

TAILQ_ENTRY(Workspace_Assignment) ws_assignments;
};
Expand Down Expand Up @@ -645,6 +664,9 @@ struct Con {
* workspace is not a named workspace (for named workspaces, num == -1) */
int num;

/** Only applicable for containers of type CT_WORKSPACE. */
gaps_t gaps;

struct Con *parent;

/* The position and size for this con. These coordinates are absolute. Note
Expand Down
2 changes: 1 addition & 1 deletion include/render.h
Expand Up @@ -40,7 +40,7 @@ typedef struct render_params {
* updated in X11.
*
*/
void render_con(Con *con);
void render_con(Con *con, bool already_inset);

/**
* Returns the height for the decorations
Expand Down
18 changes: 18 additions & 0 deletions parser-specs/commands.spec
Expand Up @@ -43,6 +43,7 @@ state INITIAL:
'title_window_icon' -> TITLE_WINDOW_ICON
'mode' -> MODE
'bar' -> BAR
'gaps' -> GAPS

state CRITERIA:
ctype = 'class' -> CRITERION
Expand Down Expand Up @@ -95,6 +96,23 @@ state BORDER:
'1pixel'
-> call cmd_border("pixel", 1)

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

state GAPS_WITH_TYPE:
scope = 'current', 'all'
-> GAPS_WITH_SCOPE

state GAPS_WITH_SCOPE:
mode = 'plus', 'minus', 'set', 'toggle'
-> GAPS_WITH_MODE

state GAPS_WITH_MODE:
value = word
-> call cmd_gaps($type, $scope, $mode, $value)

state BORDER_WIDTH:
end
-> call cmd_border($border_style, -1)
Expand Down
40 changes: 36 additions & 4 deletions parser-specs/config.spec
Expand Up @@ -25,6 +25,9 @@ state INITIAL:
'bar' -> BARBRACE
'font' -> FONT
'mode' -> MODENAME
'gaps' -> GAPS
'smart_borders' -> SMART_BORDERS
'smart_gaps' -> SMART_GAPS
'floating_minimum_size' -> FLOATING_MINIMUM_SIZE_WIDTH
'floating_maximum_size' -> FLOATING_MAXIMUM_SIZE_WIDTH
'floating_modifier' -> FLOATING_MODIFIER
Expand Down Expand Up @@ -65,6 +68,32 @@ state IGNORE_LINE:
line
-> INITIAL

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

state GAPS_WITH_SCOPE:
value = number
-> call cfg_gaps($workspace, $scope, &value)

# smart_borders true|false
# smart_borders no_gaps
state SMART_BORDERS:
enabled = '1', 'yes', 'true', 'on', 'enable', 'active'
-> call cfg_smart_borders($enabled)
enabled = 'no_gaps'
-> call cfg_smart_borders($enabled)

# smart_gaps on|off
state SMART_GAPS:
enabled = '1', 'yes', 'true', 'on', 'enable', 'active'
-> call cfg_smart_gaps($enabled)
enabled = '0', 'no', 'false', 'off', 'disable', 'inactive'
-> call cfg_smart_gaps($enabled)
enabled = 'inverse_outer'
-> call cfg_smart_gaps($enabled)

# include <pattern>
state INCLUDE:
pattern = string
Expand Down Expand Up @@ -135,10 +164,10 @@ state DEFAULT_BORDER_PIXELS_PX:
end
-> call cfg_default_border($windowtype, $border, &width)

# hide_edge_borders <none|vertical|horizontal|both|smart>
# hide_edge_borders <none|vertical|horizontal|both|smart|no_gaps>
# also hide_edge_borders <bool> for compatibility
state HIDE_EDGE_BORDERS:
hide_borders = 'none', 'vertical', 'horizontal', 'both', 'smart'
hide_borders = 'none', 'vertical', 'horizontal', 'both', 'smart_no_gaps', 'smart'
-> call cfg_hide_edge_borders($hide_borders)
hide_borders = '1', 'yes', 'true', 'on', 'enable', 'active'
-> call cfg_hide_edge_borders($hide_borders)
Expand Down Expand Up @@ -297,13 +326,16 @@ state FOCUS_ON_WINDOW_ACTIVATION:
-> call cfg_focus_on_window_activation($mode)

# workspace <workspace> output <output>
# workspace <workspace> gaps inner|outer <px>
state WORKSPACE:
workspace = word
-> WORKSPACE_OUTPUT
-> WORKSPACE_COMMAND

state WORKSPACE_OUTPUT:
state WORKSPACE_COMMAND:
'output'
-> WORKSPACE_OUTPUT_WORD
'gaps'
-> GAPS

state WORKSPACE_OUTPUT_WORD:
output = word
Expand Down
114 changes: 113 additions & 1 deletion src/commands.c
Expand Up @@ -831,7 +831,7 @@ void cmd_append_layout(I3_CMD, const char *cpath) {
// is not executed yet and will be batched with append_layout’s
// needs_tree_render after the parser finished. We should check if that is
// necessary at all.
render_con(croot);
render_con(croot, false);

restore_open_placeholder_windows(parent);

Expand Down Expand Up @@ -2374,3 +2374,115 @@ void cmd_debuglog(I3_CMD, const char *argument) {
// XXX: default reply for now, make this a better reply
ysuccess(true);
}

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

#define CMD_SET_GAPS_VALUE(type, value, reset) \
do { \
if (!strcmp(scope, "all")) { \
Con *output, *cur_ws = NULL; \
TAILQ_FOREACH (output, &(croot->nodes_head), nodes) { \
Con *content = output_get_content(output); \
TAILQ_FOREACH (cur_ws, &(content->nodes_head), nodes) { \
if (reset) \
cur_ws->gaps.type = 0; \
else if (value + cur_ws->gaps.type < 0) \
cur_ws->gaps.type = -value; \
} \
} \
\
config.gaps.type = value; \
} else { \
workspace->gaps.type = value - config.gaps.type; \
} \
} while (0)

#define CMD_GAPS(type) \
do { \
int current_value = config.gaps.type; \
if (strcmp(scope, "current") == 0) \
current_value += workspace->gaps.type; \
\
bool reset = false; \
if (!strcmp(mode, "plus")) \
current_value += pixels; \
else if (!strcmp(mode, "minus")) \
current_value -= pixels; \
else if (!strcmp(mode, "set")) { \
current_value = pixels; \
reset = true; \
} else if (!strcmp(mode, "toggle")) { \
current_value = !current_value * pixels; \
reset = true; \
} else { \
ELOG("Invalid mode %s when changing gaps", mode); \
ysuccess(false); \
return; \
} \
\
/* see issue 262 */ \
int min_value = 0; \
if (strcmp(#type, "inner") != 0) { \
min_value = strcmp(scope, "all") ? -config.gaps.inner - workspace->gaps.inner : -config.gaps.inner; \
} \
\
if (current_value < min_value) \
current_value = min_value; \
\
CMD_SET_GAPS_VALUE(type, current_value, reset); \
} while (0)

#define CMD_UPDATE_GAPS(type) \
do { \
if (!strcmp(scope, "all")) { \
if (config.gaps.type + config.gaps.inner < 0) \
CMD_SET_GAPS_VALUE(type, -config.gaps.inner, true); \
} else { \
if (config.gaps.type + workspace->gaps.type + config.gaps.inner + workspace->gaps.inner < 0) { \
CMD_SET_GAPS_VALUE(type, -config.gaps.inner - workspace->gaps.inner, true); \
} \
} \
} while (0)

if (!strcmp(type, "inner")) {
CMD_GAPS(inner);
// update inconsistent values
CMD_UPDATE_GAPS(top);
CMD_UPDATE_GAPS(bottom);
CMD_UPDATE_GAPS(right);
CMD_UPDATE_GAPS(left);
} else if (!strcmp(type, "outer")) {
CMD_GAPS(top);
CMD_GAPS(bottom);
CMD_GAPS(right);
CMD_GAPS(left);
} else if (!strcmp(type, "vertical")) {
CMD_GAPS(top);
CMD_GAPS(bottom);
} else if (!strcmp(type, "horizontal")) {
CMD_GAPS(right);
CMD_GAPS(left);
} else if (!strcmp(type, "top")) {
CMD_GAPS(top);
} else if (!strcmp(type, "bottom")) {
CMD_GAPS(bottom);
} else if (!strcmp(type, "right")) {
CMD_GAPS(right);
} else if (!strcmp(type, "left")) {
CMD_GAPS(left);
} else {
ELOG("Invalid type %s when changing gaps", type);
ysuccess(false);
return;
}

cmd_output->needs_tree_render = true;
// XXX: default reply for now, make this a better reply
ysuccess(true);
}

0 comments on commit b825dc1

Please sign in to comment.