i3
config_directives.c
Go to the documentation of this file.
1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
6  *
7  * config_directives.c: all config storing functions (see config_parser.c)
8  *
9  */
10 #include "all.h"
11 
12 #include <float.h>
13 #include <stdarg.h>
14 
15 /*******************************************************************************
16  * Criteria functions.
17  ******************************************************************************/
18 
20 
21 /*
22  * Initializes the specified 'Match' data structure and the initial state of
23  * commands.c for matching target windows of a command.
24  *
25  */
26 CFGFUN(criteria_init, int _state) {
27  criteria_next_state = _state;
28 
29  DLOG("Initializing criteria, current_match = %p, state = %d\n", current_match, _state);
32 }
33 
34 CFGFUN(criteria_pop_state) {
35  result->next_state = criteria_next_state;
36 }
37 
38 /*
39  * Interprets a ctype=cvalue pair and adds it to the current match
40  * specification.
41  *
42  */
43 CFGFUN(criteria_add, const char *ctype, const char *cvalue) {
44  match_parse_property(current_match, ctype, cvalue);
45 }
46 
47 /*******************************************************************************
48  * Utility functions
49  ******************************************************************************/
50 
51 static bool eval_boolstr(const char *str) {
52  return (strcasecmp(str, "1") == 0 ||
53  strcasecmp(str, "yes") == 0 ||
54  strcasecmp(str, "true") == 0 ||
55  strcasecmp(str, "on") == 0 ||
56  strcasecmp(str, "enable") == 0 ||
57  strcasecmp(str, "active") == 0);
58 }
59 
60 /*
61  * A utility function to convert a string containing the group and modifiers to
62  * the corresponding bit mask.
63  */
65  /* It might be better to use strtok() here, but the simpler strstr() should
66  * do for now. */
67  i3_event_state_mask_t result = 0;
68  if (str == NULL)
69  return result;
70  if (strstr(str, "Mod1") != NULL)
71  result |= XCB_KEY_BUT_MASK_MOD_1;
72  if (strstr(str, "Mod2") != NULL)
73  result |= XCB_KEY_BUT_MASK_MOD_2;
74  if (strstr(str, "Mod3") != NULL)
75  result |= XCB_KEY_BUT_MASK_MOD_3;
76  if (strstr(str, "Mod4") != NULL)
77  result |= XCB_KEY_BUT_MASK_MOD_4;
78  if (strstr(str, "Mod5") != NULL)
79  result |= XCB_KEY_BUT_MASK_MOD_5;
80  if (strstr(str, "Control") != NULL ||
81  strstr(str, "Ctrl") != NULL)
82  result |= XCB_KEY_BUT_MASK_CONTROL;
83  if (strstr(str, "Shift") != NULL)
84  result |= XCB_KEY_BUT_MASK_SHIFT;
85 
86  if (strstr(str, "Group1") != NULL)
87  result |= (I3_XKB_GROUP_MASK_1 << 16);
88  if (strstr(str, "Group2") != NULL ||
89  strstr(str, "Mode_switch") != NULL)
90  result |= (I3_XKB_GROUP_MASK_2 << 16);
91  if (strstr(str, "Group3") != NULL)
92  result |= (I3_XKB_GROUP_MASK_3 << 16);
93  if (strstr(str, "Group4") != NULL)
94  result |= (I3_XKB_GROUP_MASK_4 << 16);
95  return result;
96 }
97 
98 static char *font_pattern;
99 
100 CFGFUN(font, const char *font) {
101  config.font = load_font(font, true);
102  set_font(&config.font);
103 
104  /* Save the font pattern for using it as bar font later on */
106  font_pattern = sstrdup(font);
107 }
108 
109 CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command) {
110  configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, DEFAULT_BINDING_MODE, false);
111 }
112 
113 /*******************************************************************************
114  * Mode handling
115  ******************************************************************************/
116 
117 static char *current_mode;
119 
120 CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command) {
121  configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, command, current_mode, current_mode_pango_markup);
122 }
123 
124 CFGFUN(enter_mode, const char *pango_markup, const char *modename) {
125  if (strcmp(modename, DEFAULT_BINDING_MODE) == 0) {
126  ELOG("You cannot use the name %s for your mode\n", DEFAULT_BINDING_MODE);
127  return;
128  }
129 
130  struct Mode *mode;
131  SLIST_FOREACH(mode, &modes, modes) {
132  if (strcmp(mode->name, modename) == 0) {
133  ELOG("The binding mode with name \"%s\" is defined at least twice.\n", modename);
134  }
135  }
136 
137  DLOG("\t now in mode %s\n", modename);
139  current_mode = sstrdup(modename);
141 }
142 
143 CFGFUN(exec, const char *exectype, const char *no_startup_id, const char *command) {
144  struct Autostart *new = smalloc(sizeof(struct Autostart));
145  new->command = sstrdup(command);
146  new->no_startup_id = (no_startup_id != NULL);
147  if (strcmp(exectype, "exec") == 0) {
149  } else {
151  }
152 }
153 
154 CFGFUN(for_window, const char *command) {
156  ELOG("Match is empty, ignoring this for_window statement\n");
157  return;
158  }
159  DLOG("\t should execute command %s for the criteria mentioned above\n", command);
160  Assignment *assignment = scalloc(1, sizeof(Assignment));
161  assignment->type = A_COMMAND;
162  match_copy(&(assignment->match), current_match);
163  assignment->dest.command = sstrdup(command);
165 }
166 
167 static void create_gaps_assignment(const char *workspace, const char *scope, gaps_t gaps) {
168  DLOG("Setting gaps for workspace %s", workspace);
169 
170  struct Workspace_Assignment *assignment;
172  if (strcasecmp(assignment->name, workspace) == 0) {
173  if (!strcmp(scope, "inner")) {
174  assignment->gaps.inner = gaps.inner;
175  } else if (!strcmp(scope, "outer")) {
176  assignment->gaps.top = gaps.top;
177  assignment->gaps.right = gaps.right;
178  assignment->gaps.bottom = gaps.bottom;
179  assignment->gaps.left = gaps.left;
180  } else if (!strcmp(scope, "vertical")) {
181  assignment->gaps.top = gaps.top;
182  assignment->gaps.bottom = gaps.bottom;
183  } else if (!strcmp(scope, "horizontal")) {
184  assignment->gaps.right = gaps.right;
185  assignment->gaps.left = gaps.left;
186  } else if (!strcmp(scope, "top")) {
187  assignment->gaps.top = gaps.top;
188  } else if (!strcmp(scope, "right")) {
189  assignment->gaps.right = gaps.right;
190  } else if (!strcmp(scope, "bottom")) {
191  assignment->gaps.bottom = gaps.bottom;
192  } else if (!strcmp(scope, "left")) {
193  assignment->gaps.left = gaps.left;
194  } else {
195  ELOG("Invalid command, cannot process scope %s", scope);
196  }
197 
198  return;
199  }
200  }
201 
202  // Assignment does not yet exist, let's create it.
203  assignment = scalloc(1, sizeof(struct Workspace_Assignment));
204  assignment->name = sstrdup(workspace);
205  assignment->output = NULL;
206  if (!strcmp(scope, "inner")) {
207  assignment->gaps.inner = gaps.inner;
208  } else if (!strcmp(scope, "outer")) {
209  assignment->gaps.top = gaps.top;
210  assignment->gaps.right = gaps.right;
211  assignment->gaps.bottom = gaps.bottom;
212  assignment->gaps.left = gaps.left;
213  } else if (!strcmp(scope, "vertical")) {
214  assignment->gaps.top = gaps.top;
215  assignment->gaps.bottom = gaps.bottom;
216  } else if (!strcmp(scope, "horizontal")) {
217  assignment->gaps.right = gaps.right;
218  assignment->gaps.left = gaps.left;
219  } else if (!strcmp(scope, "top")) {
220  assignment->gaps.top = gaps.top;
221  } else if (!strcmp(scope, "right")) {
222  assignment->gaps.right = gaps.right;
223  } else if (!strcmp(scope, "bottom")) {
224  assignment->gaps.bottom = gaps.bottom;
225  } else if (!strcmp(scope, "left")) {
226  assignment->gaps.left = gaps.left;
227  } else {
228  ELOG("Invalid command, cannot process scope %s", scope);
229  }
231 }
232 
233 CFGFUN(gaps, const char *workspace, const char *scope, const long value) {
234  int pixels = logical_px(value);
235  gaps_t gaps = (gaps_t){0, 0, 0, 0, 0};
236  if (!strcmp(scope, "inner")) {
237  if (workspace == NULL)
238  config.gaps.inner = pixels;
239  else {
240  gaps.inner = pixels - config.gaps.inner;
241  create_gaps_assignment(workspace, scope, gaps);
242  }
243  } else if (!strcmp(scope, "outer")) {
244  if (workspace == NULL) {
245  config.gaps.top = pixels;
246  config.gaps.right = pixels;
247  config.gaps.bottom = pixels;
248  config.gaps.left = pixels;
249  } else {
250  gaps.top = pixels - config.gaps.top;
251  gaps.right = pixels - config.gaps.right;
252  gaps.bottom = pixels - config.gaps.bottom;
253  gaps.left = pixels - config.gaps.left;
254  create_gaps_assignment(workspace, scope, gaps);
255  }
256  } else if (!strcmp(scope, "vertical")) {
257  if (workspace == NULL) {
258  config.gaps.top = pixels;
259  config.gaps.bottom = pixels;
260  } else {
261  gaps.top = pixels - config.gaps.top;
262  gaps.bottom = pixels - config.gaps.bottom;
263  create_gaps_assignment(workspace, scope, gaps);
264  }
265  } else if (!strcmp(scope, "horizontal")) {
266  if (workspace == NULL) {
267  config.gaps.right = pixels;
268  config.gaps.left = pixels;
269  } else {
270  gaps.right = pixels - config.gaps.right;
271  gaps.left = pixels - config.gaps.left;
272  create_gaps_assignment(workspace, scope, gaps);
273  }
274  } else if (!strcmp(scope, "top")) {
275  if (workspace == NULL)
276  config.gaps.top = pixels;
277  else {
278  gaps.top = pixels - config.gaps.top;
279  create_gaps_assignment(workspace, scope, gaps);
280  }
281  } else if (!strcmp(scope, "right")) {
282  if (workspace == NULL)
283  config.gaps.right = pixels;
284  else {
285  gaps.right = pixels - config.gaps.right;
286  create_gaps_assignment(workspace, scope, gaps);
287  }
288  } else if (!strcmp(scope, "bottom")) {
289  if (workspace == NULL)
290  config.gaps.bottom = pixels;
291  else {
292  gaps.bottom = pixels - config.gaps.bottom;
293  create_gaps_assignment(workspace, scope, gaps);
294  }
295  } else if (!strcmp(scope, "left")) {
296  if (workspace == NULL)
297  config.gaps.left = pixels;
298  else {
299  gaps.left = pixels - config.gaps.left;
300  create_gaps_assignment(workspace, scope, gaps);
301  }
302  } else {
303  ELOG("Invalid command, cannot process scope %s", scope);
304  }
305 }
306 
307 CFGFUN(smart_borders, const char *enable) {
308  if (!strcmp(enable, "no_gaps"))
310  else
312 }
313 
314 CFGFUN(smart_gaps, const char *enable) {
315  if (!strcmp(enable, "inverse_outer"))
317  else
319 }
320 
321 CFGFUN(floating_minimum_size, const long width, const long height) {
324 }
325 
326 CFGFUN(floating_maximum_size, const long width, const long height) {
329 }
330 
331 CFGFUN(floating_modifier, const char *modifiers) {
333 }
334 
335 CFGFUN(default_orientation, const char *orientation) {
336  if (strcmp(orientation, "horizontal") == 0)
338  else if (strcmp(orientation, "vertical") == 0)
340  else
342 }
343 
344 CFGFUN(workspace_layout, const char *layout) {
345  if (strcmp(layout, "default") == 0)
347  else if (strcmp(layout, "stacking") == 0 ||
348  strcmp(layout, "stacked") == 0)
350  else
352 }
353 
354 CFGFUN(default_border, const char *windowtype, const char *border, const long width) {
355  int border_style;
356  int border_width;
357 
358  if (strcmp(border, "1pixel") == 0) {
359  border_style = BS_PIXEL;
360  border_width = 1;
361  } else if (strcmp(border, "none") == 0) {
362  border_style = BS_NONE;
363  border_width = 0;
364  } else if (strcmp(border, "pixel") == 0) {
365  border_style = BS_PIXEL;
366  border_width = width;
367  } else {
368  border_style = BS_NORMAL;
369  border_width = width;
370  }
371 
372  if ((strcmp(windowtype, "default_border") == 0) ||
373  (strcmp(windowtype, "new_window") == 0)) {
374  DLOG("default tiled border style = %d and border width = %d (%d physical px)\n",
375  border_style, border_width, logical_px(border_width));
376  config.default_border = border_style;
377  config.default_border_width = logical_px(border_width);
378  } else {
379  DLOG("default floating border style = %d and border width = %d (%d physical px)\n",
380  border_style, border_width, logical_px(border_width));
381  config.default_floating_border = border_style;
383  }
384 }
385 
386 CFGFUN(hide_edge_borders, const char *borders) {
387  if (strcmp(borders, "smart_no_gaps") == 0)
389  else if (strcmp(borders, "smart") == 0)
391  else if (strcmp(borders, "vertical") == 0)
393  else if (strcmp(borders, "horizontal") == 0)
395  else if (strcmp(borders, "both") == 0)
397  else if (strcmp(borders, "none") == 0)
399  else if (eval_boolstr(borders))
401  else
403 }
404 
405 CFGFUN(focus_follows_mouse, const char *value) {
407 }
408 
409 CFGFUN(mouse_warping, const char *value) {
410  if (strcmp(value, "none") == 0)
412  else if (strcmp(value, "output") == 0)
414 }
415 
416 CFGFUN(force_xinerama, const char *value) {
418 }
419 
420 CFGFUN(disable_randr15, const char *value) {
422 }
423 
424 CFGFUN(focus_wrapping, const char *value) {
425  if (strcmp(value, "force") == 0) {
427  } else if (strcmp(value, "workspace") == 0) {
429  } else if (eval_boolstr(value)) {
431  } else {
433  }
434 }
435 
436 CFGFUN(force_focus_wrapping, const char *value) {
437  /* Legacy syntax. */
438  if (eval_boolstr(value)) {
440  } else {
441  /* For "force_focus_wrapping off", don't enable or disable
442  * focus wrapping, just ensure it's not forced. */
445  }
446  }
447 }
448 
449 CFGFUN(workspace_back_and_forth, const char *value) {
451 }
452 
453 CFGFUN(fake_outputs, const char *outputs) {
454  free(config.fake_outputs);
456 }
457 
458 CFGFUN(force_display_urgency_hint, const long duration_ms) {
459  config.workspace_urgency_timer = duration_ms / 1000.0;
460 }
461 
462 CFGFUN(focus_on_window_activation, const char *mode) {
463  if (strcmp(mode, "smart") == 0)
464  config.focus_on_window_activation = FOWA_SMART;
465  else if (strcmp(mode, "urgent") == 0)
466  config.focus_on_window_activation = FOWA_URGENT;
467  else if (strcmp(mode, "focus") == 0)
468  config.focus_on_window_activation = FOWA_FOCUS;
469  else if (strcmp(mode, "none") == 0)
471  else {
472  ELOG("Unknown focus_on_window_activation mode \"%s\", ignoring it.\n", mode);
473  return;
474  }
475 
476  DLOG("Set new focus_on_window_activation mode = %i.\n", config.focus_on_window_activation);
477 }
478 
479 CFGFUN(title_align, const char *alignment) {
480  if (strcmp(alignment, "left") == 0) {
481  config.title_align = ALIGN_LEFT;
482  } else if (strcmp(alignment, "center") == 0) {
483  config.title_align = ALIGN_CENTER;
484  } else if (strcmp(alignment, "right") == 0) {
485  config.title_align = ALIGN_RIGHT;
486  } else {
487  assert(false);
488  }
489 }
490 
491 CFGFUN(show_marks, const char *value) {
492  config.show_marks = eval_boolstr(value);
493 }
494 
495 static char *current_workspace = NULL;
496 
497 CFGFUN(workspace, const char *workspace, const char *output) {
498  struct Workspace_Assignment *assignment;
499 
500  /* When a new workspace line is encountered, for the first output word,
501  * $workspace from the config.spec is non-NULL. Afterwards, the parser calls
502  * clear_stack() because of the call line. Thus, we have to preserve the
503  * workspace string. */
504  if (workspace) {
506 
508  if (strcasecmp(assignment->name, workspace) == 0) {
509  if (assignment->output != NULL) {
510  ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n",
511  workspace);
512  return;
513  }
514  }
515  }
516 
517  current_workspace = sstrdup(workspace);
518  } else {
519  if (!current_workspace) {
520  DLOG("Both workspace and current_workspace are NULL, assuming we had an error before\n");
521  return;
522  }
523  workspace = current_workspace;
524  }
525 
526  DLOG("Assigning workspace \"%s\" to output \"%s\"\n", workspace, output);
527 
528  assignment = scalloc(1, sizeof(struct Workspace_Assignment));
529  assignment->name = sstrdup(workspace);
530  assignment->output = sstrdup(output);
532 }
533 
534 CFGFUN(ipc_socket, const char *path) {
535  free(config.ipc_socket_path);
537 }
538 
539 CFGFUN(restart_state, const char *path) {
542 }
543 
544 CFGFUN(popup_during_fullscreen, const char *value) {
545  if (strcmp(value, "ignore") == 0) {
546  config.popup_during_fullscreen = PDF_IGNORE;
547  } else if (strcmp(value, "leave_fullscreen") == 0) {
548  config.popup_during_fullscreen = PDF_LEAVE_FULLSCREEN;
549  } else {
550  config.popup_during_fullscreen = PDF_SMART;
551  }
552 }
553 
554 CFGFUN(color_single, const char *colorclass, const char *color) {
555  /* used for client.background only currently */
557 }
558 
559 CFGFUN(color, const char *colorclass, const char *border, const char *background, const char *text, const char *indicator, const char *child_border) {
560 #define APPLY_COLORS(classname) \
561  do { \
562  if (strcmp(colorclass, "client." #classname) == 0) { \
563  config.client.classname.border = draw_util_hex_to_color(border); \
564  config.client.classname.background = draw_util_hex_to_color(background); \
565  config.client.classname.text = draw_util_hex_to_color(text); \
566  if (indicator != NULL) { \
567  config.client.classname.indicator = draw_util_hex_to_color(indicator); \
568  } \
569  if (child_border != NULL) { \
570  config.client.classname.child_border = draw_util_hex_to_color(child_border); \
571  } else { \
572  config.client.classname.child_border = config.client.classname.background; \
573  } \
574  } \
575  } while (0)
576 
577  APPLY_COLORS(focused_inactive);
579  APPLY_COLORS(unfocused);
580  APPLY_COLORS(urgent);
581  APPLY_COLORS(placeholder);
582 
583 #undef APPLY_COLORS
584 }
585 
586 CFGFUN(assign_output, const char *output) {
588  ELOG("Match is empty, ignoring this assignment\n");
589  return;
590  }
591 
592  if (current_match->window_mode != WM_ANY) {
593  ELOG("Assignments using window mode (floating/tiling) is not supported\n");
594  return;
595  }
596 
597  DLOG("New assignment, using above criteria, to output \"%s\".\n", output);
598  Assignment *assignment = scalloc(1, sizeof(Assignment));
599  match_copy(&(assignment->match), current_match);
600  assignment->type = A_TO_OUTPUT;
601  assignment->dest.output = sstrdup(output);
603 }
604 
605 CFGFUN(assign, const char *workspace, bool is_number) {
607  ELOG("Match is empty, ignoring this assignment\n");
608  return;
609  }
610 
611  if (current_match->window_mode != WM_ANY) {
612  ELOG("Assignments using window mode (floating/tiling) is not supported\n");
613  return;
614  }
615 
616  if (is_number && ws_name_to_number(workspace) == -1) {
617  ELOG("Could not parse initial part of \"%s\" as a number.\n", workspace);
618  return;
619  }
620 
621  DLOG("New assignment, using above criteria, to workspace \"%s\".\n", workspace);
622  Assignment *assignment = scalloc(1, sizeof(Assignment));
623  match_copy(&(assignment->match), current_match);
624  assignment->type = is_number ? A_TO_WORKSPACE_NUMBER : A_TO_WORKSPACE;
625  assignment->dest.workspace = sstrdup(workspace);
627 }
628 
629 CFGFUN(no_focus) {
631  ELOG("Match is empty, ignoring this assignment\n");
632  return;
633  }
634 
635  DLOG("New assignment, using above criteria, to ignore focus on manage.\n");
636  Assignment *assignment = scalloc(1, sizeof(Assignment));
637  match_copy(&(assignment->match), current_match);
638  assignment->type = A_NO_FOCUS;
640 }
641 
642 CFGFUN(ipc_kill_timeout, const long timeout_ms) {
643  ipc_set_kill_timeout(timeout_ms / 1000.0);
644 }
645 
646 /*******************************************************************************
647  * Bar configuration (i3bar)
648  ******************************************************************************/
649 
651 
652 CFGFUN(bar_font, const char *font) {
654  current_bar->font = sstrdup(font);
655 }
656 
657 CFGFUN(bar_separator_symbol, const char *separator) {
659  current_bar->separator_symbol = sstrdup(separator);
660 }
661 
662 CFGFUN(bar_mode, const char *mode) {
663  current_bar->mode = (strcmp(mode, "dock") == 0 ? M_DOCK : (strcmp(mode, "hide") == 0 ? M_HIDE : M_INVISIBLE));
664 }
665 
666 CFGFUN(bar_hidden_state, const char *hidden_state) {
667  current_bar->hidden_state = (strcmp(hidden_state, "hide") == 0 ? S_HIDE : S_SHOW);
668 }
669 
670 CFGFUN(bar_id, const char *bar_id) {
671  current_bar->id = sstrdup(bar_id);
672 }
673 
674 CFGFUN(bar_output, const char *output) {
675  int new_outputs = current_bar->num_outputs + 1;
676  current_bar->outputs = srealloc(current_bar->outputs, sizeof(char *) * new_outputs);
678  current_bar->num_outputs = new_outputs;
679 }
680 
681 CFGFUN(bar_verbose, const char *verbose) {
683 }
684 
685 CFGFUN(bar_height, const long height) {
686  current_bar->bar_height = (uint32_t)height;
687 }
688 
689 CFGFUN(bar_modifier, const char *modifiers) {
690  current_bar->modifier = modifiers ? event_state_from_str(modifiers) : XCB_NONE;
691 }
692 
693 static void bar_configure_binding(const char *button, const char *release, const char *command) {
694  if (strncasecmp(button, "button", strlen("button")) != 0) {
695  ELOG("Bindings for a bar can only be mouse bindings, not \"%s\", ignoring.\n", button);
696  return;
697  }
698 
699  int input_code = atoi(button + strlen("button"));
700  if (input_code < 1) {
701  ELOG("Button \"%s\" does not seem to be in format 'buttonX'.\n", button);
702  return;
703  }
704  const bool release_bool = release != NULL;
705 
706  struct Barbinding *current;
708  if (current->input_code == input_code && current->release == release_bool) {
709  ELOG("command for button %s was already specified, ignoring.\n", button);
710  return;
711  }
712  }
713 
714  struct Barbinding *new_binding = scalloc(1, sizeof(struct Barbinding));
715  new_binding->release = release_bool;
716  new_binding->input_code = input_code;
717  new_binding->command = sstrdup(command);
719 }
720 
721 CFGFUN(bar_wheel_up_cmd, const char *command) {
722  ELOG("'wheel_up_cmd' is deprecated. Please us 'bindsym button4 %s' instead.\n", command);
723  bar_configure_binding("button4", NULL, command);
724 }
725 
726 CFGFUN(bar_wheel_down_cmd, const char *command) {
727  ELOG("'wheel_down_cmd' is deprecated. Please us 'bindsym button5 %s' instead.\n", command);
728  bar_configure_binding("button5", NULL, command);
729 }
730 
731 CFGFUN(bar_bindsym, const char *button, const char *release, const char *command) {
733 }
734 
735 CFGFUN(bar_position, const char *position) {
736  current_bar->position = (strcmp(position, "top") == 0 ? P_TOP : P_BOTTOM);
737 }
738 
739 CFGFUN(bar_i3bar_command, const char *i3bar_command) {
741  current_bar->i3bar_command = sstrdup(i3bar_command);
742 }
743 
744 CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text) {
745 #define APPLY_COLORS(classname) \
746  do { \
747  if (strcmp(colorclass, #classname) == 0) { \
748  if (text != NULL) { \
749  /* New syntax: border, background, text */ \
750  current_bar->colors.classname##_border = sstrdup(border); \
751  current_bar->colors.classname##_bg = sstrdup(background); \
752  current_bar->colors.classname##_text = sstrdup(text); \
753  } else { \
754  /* Old syntax: text, background */ \
755  current_bar->colors.classname##_bg = sstrdup(background); \
756  current_bar->colors.classname##_text = sstrdup(border); \
757  } \
758  } \
759  } while (0)
760 
761  APPLY_COLORS(focused_workspace);
762  APPLY_COLORS(active_workspace);
763  APPLY_COLORS(inactive_workspace);
764  APPLY_COLORS(urgent_workspace);
765  APPLY_COLORS(binding_mode);
766 
767 #undef APPLY_COLORS
768 }
769 
770 CFGFUN(bar_socket_path, const char *socket_path) {
772  current_bar->socket_path = sstrdup(socket_path);
773 }
774 
775 CFGFUN(bar_tray_output, const char *output) {
776  struct tray_output_t *tray_output = scalloc(1, sizeof(struct tray_output_t));
777  tray_output->output = sstrdup(output);
779 }
780 
781 CFGFUN(bar_tray_padding, const long padding_px) {
782  current_bar->tray_padding = padding_px;
783 }
784 
785 CFGFUN(bar_color_single, const char *colorclass, const char *color) {
786  if (strcmp(colorclass, "background") == 0)
788  else if (strcmp(colorclass, "separator") == 0)
790  else if (strcmp(colorclass, "statusline") == 0)
792  else if (strcmp(colorclass, "focused_background") == 0)
794  else if (strcmp(colorclass, "focused_separator") == 0)
796  else
798 }
799 
800 CFGFUN(bar_status_command, const char *command) {
802  current_bar->status_command = sstrdup(command);
803 }
804 
805 CFGFUN(bar_binding_mode_indicator, const char *value) {
807 }
808 
809 CFGFUN(bar_workspace_buttons, const char *value) {
811 }
812 
813 CFGFUN(bar_workspace_min_width, const long width) {
815 }
816 
817 CFGFUN(bar_strip_workspace_numbers, const char *value) {
819 }
820 
821 CFGFUN(bar_strip_workspace_name, const char *value) {
823 }
824 
825 CFGFUN(bar_start) {
826  current_bar = scalloc(1, sizeof(struct Barconfig));
830  current_bar->modifier = XCB_KEY_BUT_MASK_MOD_4;
831 }
832 
833 CFGFUN(bar_finish) {
834  DLOG("\t new bar configuration finished, saving.\n");
835  /* Generate a unique ID for this bar if not already configured */
836  if (current_bar->id == NULL)
838 
840 
841  /* If no font was explicitly set, we use the i3 font as default */
842  if (current_bar->font == NULL && font_pattern != NULL)
844 
846  /* Simply reset the pointer, but don't free the resources. */
847  current_bar = NULL;
848 }
gaps_t::left
int left
Definition: data.h:153
Autostart::command
char * command
Command, like in command mode.
Definition: data.h:369
Barbinding
Defines a mouse command to be executed instead of the default behavior when clicking on the non-statu...
Definition: configuration.h:397
Workspace_Assignment::output
char * output
Definition: data.h:228
VERT
@ VERT
Definition: data.h:62
Workspace_Assignment
Stores which workspace (by name or number) goes to which output and its gaps config.
Definition: data.h:226
SLIST_FOREACH
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:114
POINTER_WARPING_NONE
@ POINTER_WARPING_NONE
Definition: data.h:145
Barconfig::colors
struct Barconfig::bar_colors colors
APPLY_COLORS
#define APPLY_COLORS(classname)
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:360
Barconfig::modifier
uint32_t modifier
Bar modifier (to show bar when in hide mode).
Definition: configuration.h:308
L_DEFAULT
@ L_DEFAULT
Definition: data.h:104
gaps_t::inner
int inner
Definition: data.h:149
force_xinerama
bool force_xinerama
Definition: main.c:94
Barbinding::input_code
int input_code
The button to be used (e.g., 1 for "button1").
Definition: configuration.h:399
Barconfig::position
enum Barconfig::@11 position
Bar position (bottom by default).
SMART_GAPS_OFF
@ SMART_GAPS_OFF
Definition: data.h:86
Barconfig
Holds the status bar configuration (i3bar).
Definition: configuration.h:273
match_init
void match_init(Match *match)
Initializes the Match data structure.
Definition: match.c:26
gaps_t::bottom
int bottom
Definition: data.h:152
bar_configure_binding
static void bar_configure_binding(const char *button, const char *release, const char *command)
Definition: config_directives.c:693
gaps_t
Definition: data.h:148
srealloc
void * srealloc(void *ptr, size_t size)
Safe-wrapper around realloc which exits if realloc returns NULL (meaning that there is no more memory...
scalloc
void * scalloc(size_t num, size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
Config::show_marks
bool show_marks
Specifies whether or not marks should be displayed in the window decoration.
Definition: configuration.h:202
Barconfig::hide_workspace_buttons
bool hide_workspace_buttons
Hide workspace buttons? Configuration option is 'workspace_buttons no' but we invert the bool to get ...
Definition: configuration.h:335
HEBM_SMART
@ HEBM_SMART
Definition: data.h:94
Barconfig::id
char * id
Automatically generated ID for this bar config.
Definition: configuration.h:276
NO_ORIENTATION
@ NO_ORIENTATION
Definition: data.h:60
Config::default_orientation
int default_orientation
Default orientation for new containers.
Definition: configuration.h:110
Config::restart_state_path
char * restart_state_path
Definition: configuration.h:101
autostarts
struct autostarts_head autostarts
Definition: main.c:77
match_copy
void match_copy(Match *dest, Match *src)
Copies the data of a match from src to dest.
Definition: match.c:62
Config::default_border
border_style_t default_border
The default border style for new windows.
Definition: configuration.h:212
Barconfig::tray_outputs
tray_outputs
Definition: configuration.h:288
set_font
void set_font(i3Font *font)
Defines the font to be used for the forthcoming calls.
Barconfig::bar_colors::background
char * background
Definition: configuration.h:359
BS_PIXEL
@ BS_PIXEL
Definition: data.h:67
Config::floating_maximum_width
int32_t floating_maximum_width
Maximum and minimum dimensions of a floating window.
Definition: configuration.h:222
Config::floating_minimum_height
int32_t floating_minimum_height
Definition: configuration.h:225
SMART_BORDERS_OFF
@ SMART_BORDERS_OFF
Definition: data.h:82
ws_assignments
struct ws_assignments_head ws_assignments
Definition: main.c:87
Barconfig::num_outputs
int num_outputs
Number of outputs in the outputs array.
Definition: configuration.h:279
Config::floating_modifier
uint32_t floating_modifier
The modifier which needs to be pressed in combination with your mouse buttons to do things with float...
Definition: configuration.h:219
verbose
static bool verbose
Definition: log.c:38
Mode::pango_markup
bool pango_markup
Definition: configuration.h:84
Config::default_floating_border_width
int default_floating_border_width
Definition: configuration.h:107
POINTER_WARPING_OUTPUT
@ POINTER_WARPING_OUTPUT
Definition: data.h:144
ws_name_to_number
long ws_name_to_number(const char *name)
Parses the workspace name as a number.
Definition: util.c:106
match_is_empty
bool match_is_empty(Match *match)
Check if a match is empty.
Definition: match.c:39
font_pattern
static char * font_pattern
Definition: config_directives.c:98
all.h
Config::number_barconfigs
int number_barconfigs
Definition: configuration.h:256
I3_XKB_GROUP_MASK_3
@ I3_XKB_GROUP_MASK_3
Definition: data.h:128
DEFAULT_BINDING_MODE
const char * DEFAULT_BINDING_MODE
The name of the default mode.
Definition: bindings.c:23
L_TABBED
@ L_TABBED
Definition: data.h:106
HEBM_HORIZONTAL
@ HEBM_HORIZONTAL
Definition: data.h:92
DLOG
#define DLOG(fmt,...)
Definition: libi3.h:104
ELOG
#define ELOG(fmt,...)
Definition: libi3.h:99
Barconfig::strip_workspace_name
bool strip_workspace_name
Strip workspace name? Configuration option is 'strip_workspace_name yes'.
Definition: configuration.h:346
current_workspace
static char * current_workspace
Definition: config_directives.c:495
draw_util_hex_to_color
color_t draw_util_hex_to_color(const char *color)
Parses the given color in hex format to an internal color representation.
FOCUS_WRAPPING_OFF
@ FOCUS_WRAPPING_OFF
Definition: data.h:160
I3_XKB_GROUP_MASK_4
@ I3_XKB_GROUP_MASK_4
Definition: data.h:129
I3_XKB_GROUP_MASK_2
@ I3_XKB_GROUP_MASK_2
Definition: data.h:127
Assignment::match
Match match
the criteria to check if a window matches
Definition: data.h:608
Autostart::no_startup_id
bool no_startup_id
no_startup_id flag for start_application().
Definition: data.h:372
CFGFUN
CFGFUN(criteria_init, int _state)
Definition: config_directives.c:26
i3_event_state_mask_t
uint32_t i3_event_state_mask_t
The lower 16 bits contain a xcb_key_but_mask_t, the higher 16 bits contain an i3_xkb_group_mask_t.
Definition: data.h:138
Barconfig::bar_colors::focused_background
char * focused_background
Definition: configuration.h:363
Config::focus_wrapping
focus_wrapping_t focus_wrapping
When focus wrapping is enabled (the default), attempting to move focus past the edge of the screen (i...
Definition: configuration.h:157
HEBM_NONE
@ HEBM_NONE
Definition: data.h:90
Config::ipc_socket_path
char * ipc_socket_path
Definition: configuration.h:100
FOCUS_WRAPPING_ON
@ FOCUS_WRAPPING_ON
Definition: data.h:161
Barconfig::bar_colors::focused_separator
char * focused_separator
Definition: configuration.h:365
Config::smart_borders
smart_borders_t smart_borders
Definition: configuration.h:262
Config::default_border_width
int default_border_width
Definition: configuration.h:106
sstrdup
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
FREE
#define FREE(pointer)
Definition: util.h:47
Assignment::dest
union Assignment::@19 dest
destination workspace/command/output, depending on the type
Barconfig::tray_padding
int tray_padding
Definition: configuration.h:291
Barconfig::i3bar_command
char * i3bar_command
Command that should be run to execute i3bar, give a full path if i3bar is not in your $PATH.
Definition: configuration.h:320
Barconfig::separator_symbol
char * separator_symbol
A custom separator to use instead of a vertical line.
Definition: configuration.h:330
sasprintf
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
Config::floating_maximum_height
int32_t floating_maximum_height
Definition: configuration.h:223
workspace_back_and_forth
void workspace_back_and_forth(void)
Focuses the previously focused workspace.
Definition: workspace.c:829
Assignment
An Assignment makes specific windows go to a specific workspace/output or run a command for that wind...
Definition: data.h:586
gaps_t::right
int right
Definition: data.h:151
current_match
static Match current_match
Definition: commands_parser.c:174
create_gaps_assignment
static void create_gaps_assignment(const char *workspace, const char *scope, gaps_t gaps)
Definition: config_directives.c:167
Config::focus_on_window_activation
enum Config::@6 focus_on_window_activation
Behavior when a window sends a NET_ACTIVE_WINDOW message.
Config::font
i3Font font
Definition: configuration.h:98
SMART_GAPS_ON
@ SMART_GAPS_ON
Definition: data.h:87
gaps_t::top
int top
Definition: data.h:150
Config::workspace_urgency_timer
float workspace_urgency_timer
By default, urgency is cleared immediately when switching to another workspace leads to focusing the ...
Definition: configuration.h:186
Barconfig::status_command
char * status_command
Command that should be run to get a statusline, for example 'i3status'.
Definition: configuration.h:324
Config::fake_outputs
char * fake_outputs
Overwrites output detection (for testing), see src/fake_outputs.c.
Definition: configuration.h:173
tray_output_t::tray_outputs
tray_outputs
Definition: configuration.h:415
Config::gaps
gaps_t gaps
Definition: configuration.h:259
L_STACKED
@ L_STACKED
Definition: data.h:105
match_free
void match_free(Match *match)
Frees the given match.
Definition: match.c:241
Barconfig::bar_colors::statusline
char * statusline
Definition: configuration.h:360
Barbinding::command
char * command
The command which is to be executed for this button.
Definition: configuration.h:402
Config::disable_randr15
bool disable_randr15
Don’t use RandR 1.5 for querying outputs.
Definition: configuration.h:170
Autostart
Holds a command specified by either an:
Definition: data.h:367
Config::smart_gaps
smart_gaps_t smart_gaps
Definition: configuration.h:265
Config::default_floating_border
border_style_t default_floating_border
The default border style for new floating windows.
Definition: configuration.h:215
Config::default_layout
layout_t default_layout
Definition: configuration.h:103
autostarts_always
struct autostarts_always_head autostarts_always
Definition: main.c:80
gaps_t
struct gaps_t gaps_t
Definition: data.h:50
match_parse_property
void match_parse_property(Match *match, const char *ctype, const char *cvalue)
Interprets a ctype=cvalue pair and adds it to the given match specification.
Definition: match.c:256
criteria_next_state
static int criteria_next_state
Definition: config_directives.c:19
Barconfig::strip_workspace_numbers
bool strip_workspace_numbers
Strip workspace numbers? Configuration option is 'strip_workspace_numbers yes'.
Definition: configuration.h:342
Config::title_align
enum Config::@7 title_align
Title alignment options.
Assignment::type
enum Assignment::@18 type
type of this assignment:
smalloc
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
SMART_GAPS_INVERSE_OUTER
@ SMART_GAPS_INVERSE_OUTER
Definition: data.h:88
HEBM_BOTH
@ HEBM_BOTH
Definition: data.h:93
Workspace_Assignment::gaps
gaps_t gaps
Definition: data.h:229
Config::force_xinerama
bool force_xinerama
By default, use the RandR API for multi-monitor setups.
Definition: configuration.h:167
focused
struct Con * focused
Definition: tree.c:13
current_bar
static Barconfig * current_bar
Definition: config_directives.c:650
Workspace_Assignment::name
char * name
Definition: data.h:227
HEBM_VERTICAL
@ HEBM_VERTICAL
Definition: data.h:91
Barconfig::bar_bindings
bar_bindings
Definition: configuration.h:311
outputs
struct outputs_head outputs
Definition: randr.c:21
I3_XKB_GROUP_MASK_1
@ I3_XKB_GROUP_MASK_1
Definition: data.h:126
load_font
i3Font load_font(const char *pattern, const bool fallback)
Loads a font for usage, also getting its height.
Assignment::output
char * output
Definition: data.h:614
Config::floating_minimum_width
int32_t floating_minimum_width
Definition: configuration.h:224
bindings
struct bindings_head * bindings
Definition: main.c:74
Barconfig::verbose
bool verbose
Enable verbose mode? Useful for debugging purposes.
Definition: configuration.h:353
Mode::name
char * name
Definition: configuration.h:83
config
Config config
Definition: config.c:17
tray_output_t
Definition: configuration.h:411
tray_output_t::output
char * output
Definition: configuration.h:412
HEBM_SMART_NO_GAPS
@ HEBM_SMART_NO_GAPS
Definition: data.h:95
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:347
Config::mouse_warping
warping_t mouse_warping
By default, when switching focus to a window on a different output (e.g.
Definition: configuration.h:126
BS_NONE
@ BS_NONE
Definition: data.h:66
SMART_BORDERS_ON
@ SMART_BORDERS_ON
Definition: data.h:83
Barconfig::font
char * font
Font specification for all text rendered on the bar.
Definition: configuration.h:327
Barconfig::hide_binding_mode_indicator
bool hide_binding_mode_indicator
Hide mode button? Configuration option is 'binding_mode_indicator no' but we invert the bool for the ...
Definition: configuration.h:350
Assignment::command
char * command
Definition: data.h:612
Assignment::workspace
char * workspace
Definition: data.h:613
Barconfig::bar_colors::focused_statusline
char * focused_statusline
Definition: configuration.h:364
Config::client
struct Config::config_client client
Config::disable_focus_follows_mouse
bool disable_focus_follows_mouse
By default, focus follows mouse.
Definition: configuration.h:116
Barconfig::hidden_state
enum Barconfig::@10 hidden_state
assignments
struct assignments_head assignments
Definition: main.c:83
current_mode
static char * current_mode
Definition: config_directives.c:117
Barconfig::socket_path
char * socket_path
Path to the i3 IPC socket.
Definition: configuration.h:296
modes
struct modes_head modes
Definition: config.c:18
Config::config_client::background
color_t background
Definition: configuration.h:229
barconfigs
struct barconfig_head barconfigs
Definition: config.c:19
Config::hide_edge_borders
hide_edge_borders_mode_t hide_edge_borders
Remove borders if they are adjacent to the screen edge.
Definition: configuration.h:132
logical_px
int logical_px(const int logical)
Convert a logical amount of pixels (e.g.
SMART_BORDERS_NO_GAPS
@ SMART_BORDERS_NO_GAPS
Definition: data.h:84
BS_NORMAL
@ BS_NORMAL
Definition: data.h:65
ipc_set_kill_timeout
void ipc_set_kill_timeout(ev_tstamp new)
Set the maximum duration that we allow for a connection with an unwriteable socket.
Definition: ipc.c:49
eval_boolstr
static bool eval_boolstr(const char *str)
Definition: config_directives.c:51
Match::window_mode
enum Match::@16 window_mode
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:376
FOCUS_WRAPPING_FORCE
@ FOCUS_WRAPPING_FORCE
Definition: data.h:162
Barconfig::outputs
char ** outputs
Outputs on which this bar should show up on.
Definition: configuration.h:282
Barconfig::bar_height
uint32_t bar_height
Defines the height of the bar in pixels.
Definition: configuration.h:356
HORIZ
@ HORIZ
Definition: data.h:61
Config::workspace_auto_back_and_forth
bool workspace_auto_back_and_forth
Automatic workspace back and forth switching.
Definition: configuration.h:179
event_state_from_str
i3_event_state_mask_t event_state_from_str(const char *str)
A utility function to convert a string containing the group and modifiers to the corresponding bit ma...
Definition: config_directives.c:64
current_mode_pango_markup
static bool current_mode_pango_markup
Definition: config_directives.c:118
Barbinding::release
bool release
If true, the command will be executed after the button is released.
Definition: configuration.h:405
Barconfig::workspace_min_width
int workspace_min_width
The minimal width for workspace buttons.
Definition: configuration.h:338
FOCUS_WRAPPING_WORKSPACE
@ FOCUS_WRAPPING_WORKSPACE
Definition: data.h:163
configure_binding
Binding * configure_binding(const char *bindtype, const char *modifiers, const char *input_code, const char *release, const char *border, const char *whole_window, const char *exclude_titlebar, const char *command, const char *modename, bool pango_markup)
Adds a binding from config parameters given as strings and returns a pointer to the binding structure...
Definition: bindings.c:57
Barconfig::mode
enum Barconfig::@9 mode
Bar display mode (hide unless modifier is pressed or show in dock mode or always hide in invisible mo...
Mode
The configuration file can contain multiple sets of bindings.
Definition: configuration.h:82
Barconfig::bar_colors::separator
char * separator
Definition: configuration.h:361
Config::popup_during_fullscreen
enum Config::@8 popup_during_fullscreen
What should happen when a new popup is opened during fullscreen mode.