i3/src/config.c
Ingo Bürk 029d78c0bf Only grab scrollwheel buttons if necessary.
With this patch, we only grab the scrollwheel buttons (4 and 5) when
managing a window if a whole window key binding exists for these buttons.

This allows both of these usecases:
  - Bindings to scrollwheel buttons using --whole-window (see #1701).
  - Scrolling in a window without focusing it if no such binding
    exists (see #2049).

Furthermore, we drop all button grabs and regrab them after a config
reload in order to reevaluate the new bindings correctly.

fixes #2049
2015-11-15 22:08:47 +01:00

265 lines
9.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#undef I3__FILE__
#define I3__FILE__ "config.c"
/*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
* © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* config.c: Configuration file (calling the parser (src/config_parser.c) with
* the correct path, switching key bindings mode).
*
*/
#include "all.h"
#include <xkbcommon/xkbcommon.h>
char *current_configpath = NULL;
Config config;
struct modes_head modes;
struct barconfig_head barconfigs = TAILQ_HEAD_INITIALIZER(barconfigs);
/**
* Ungrabs all keys, to be called before re-grabbing the keys because of a
* mapping_notify event or a configuration file reload
*
*/
void ungrab_all_keys(xcb_connection_t *conn) {
DLOG("Ungrabbing all keys\n");
xcb_ungrab_key(conn, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY);
}
/*
* Sends the current bar configuration as an event to all barconfig_update listeners.
*
*/
void update_barconfig() {
Barconfig *current;
TAILQ_FOREACH(current, &barconfigs, configs) {
ipc_send_barconfig_update_event(current);
}
}
/*
* Finds the configuration file to use (either the one specified by
* override_configpath), the users one or the system default) and calls
* parse_file().
*
*/
bool parse_configuration(const char *override_configpath, bool use_nagbar) {
char *path = get_config_path(override_configpath, true);
if (path == NULL) {
die("Unable to find the configuration file (looked at "
"~/.i3/config, $XDG_CONFIG_HOME/i3/config, " SYSCONFDIR "/i3/config and $XDG_CONFIG_DIRS/i3/config)");
}
LOG("Parsing configfile %s\n", path);
FREE(current_configpath);
current_configpath = path;
/* initialize default bindings if we're just validating the config file */
if (!use_nagbar && bindings == NULL) {
bindings = scalloc(1, sizeof(struct bindings_head));
TAILQ_INIT(bindings);
}
return parse_file(path, use_nagbar);
}
/*
* (Re-)loads the configuration file (sets useful defaults before).
*
*/
void load_configuration(xcb_connection_t *conn, const char *override_configpath, bool reload) {
if (reload) {
/* First ungrab the keys */
ungrab_all_keys(conn);
struct Mode *mode;
while (!SLIST_EMPTY(&modes)) {
mode = SLIST_FIRST(&modes);
FREE(mode->name);
/* Clear the old binding list */
while (!TAILQ_EMPTY(mode->bindings)) {
Binding *bind = TAILQ_FIRST(mode->bindings);
TAILQ_REMOVE(mode->bindings, bind, bindings);
binding_free(bind);
}
FREE(mode->bindings);
SLIST_REMOVE(&modes, mode, Mode, modes);
FREE(mode);
}
struct Assignment *assign;
while (!TAILQ_EMPTY(&assignments)) {
assign = TAILQ_FIRST(&assignments);
if (assign->type == A_TO_WORKSPACE)
FREE(assign->dest.workspace);
else if (assign->type == A_COMMAND)
FREE(assign->dest.command);
match_free(&(assign->match));
TAILQ_REMOVE(&assignments, assign, assignments);
FREE(assign);
}
/* Clear bar configs */
Barconfig *barconfig;
while (!TAILQ_EMPTY(&barconfigs)) {
barconfig = TAILQ_FIRST(&barconfigs);
FREE(barconfig->id);
for (int c = 0; c < barconfig->num_outputs; c++)
free(barconfig->outputs[c]);
while (!TAILQ_EMPTY(&(barconfig->bar_bindings))) {
struct Barbinding *binding = TAILQ_FIRST(&(barconfig->bar_bindings));
FREE(binding->command);
TAILQ_REMOVE(&(barconfig->bar_bindings), binding, bindings);
FREE(binding);
}
while (!TAILQ_EMPTY(&(barconfig->tray_outputs))) {
struct tray_output_t *tray_output = TAILQ_FIRST(&(barconfig->tray_outputs));
FREE(tray_output->output);
TAILQ_REMOVE(&(barconfig->tray_outputs), tray_output, tray_outputs);
FREE(tray_output);
}
FREE(barconfig->outputs);
FREE(barconfig->socket_path);
FREE(barconfig->status_command);
FREE(barconfig->i3bar_command);
FREE(barconfig->font);
FREE(barconfig->colors.background);
FREE(barconfig->colors.statusline);
FREE(barconfig->colors.separator);
FREE(barconfig->colors.focused_background);
FREE(barconfig->colors.focused_statusline);
FREE(barconfig->colors.focused_separator);
FREE(barconfig->colors.focused_workspace_border);
FREE(barconfig->colors.focused_workspace_bg);
FREE(barconfig->colors.focused_workspace_text);
FREE(barconfig->colors.active_workspace_border);
FREE(barconfig->colors.active_workspace_bg);
FREE(barconfig->colors.active_workspace_text);
FREE(barconfig->colors.inactive_workspace_border);
FREE(barconfig->colors.inactive_workspace_bg);
FREE(barconfig->colors.inactive_workspace_text);
FREE(barconfig->colors.urgent_workspace_border);
FREE(barconfig->colors.urgent_workspace_bg);
FREE(barconfig->colors.urgent_workspace_text);
FREE(barconfig->colors.binding_mode_border);
FREE(barconfig->colors.binding_mode_bg);
FREE(barconfig->colors.binding_mode_text);
TAILQ_REMOVE(&barconfigs, barconfig, configs);
FREE(barconfig);
}
/* Clear workspace names */
#if 0
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces)
workspace_set_name(ws, NULL);
#endif
/* Invalidate pixmap caches in case font or colors changed */
Con *con;
TAILQ_FOREACH(con, &all_cons, all_cons)
FREE(con->deco_render_params);
/* Get rid of the current font */
free_font();
}
SLIST_INIT(&modes);
struct Mode *default_mode = scalloc(1, sizeof(struct Mode));
default_mode->name = sstrdup("default");
default_mode->bindings = scalloc(1, sizeof(struct bindings_head));
TAILQ_INIT(default_mode->bindings);
SLIST_INSERT_HEAD(&modes, default_mode, modes);
bindings = default_mode->bindings;
#define REQUIRED_OPTION(name) \
if (config.name == NULL) \
die("You did not specify required configuration option " #name "\n");
/* Clear the old config or initialize the data structure */
memset(&config, 0, sizeof(config));
/* Initialize default colors */
#define INIT_COLOR(x, cborder, cbackground, ctext, cindicator) \
do { \
x.border = get_colorpixel(cborder); \
x.background = get_colorpixel(cbackground); \
x.text = get_colorpixel(ctext); \
x.indicator = get_colorpixel(cindicator); \
} while (0)
config.client.background = get_colorpixel("#000000");
INIT_COLOR(config.client.focused, "#4c7899", "#285577", "#ffffff", "#2e9ef4");
INIT_COLOR(config.client.focused_inactive, "#333333", "#5f676a", "#ffffff", "#484e50");
INIT_COLOR(config.client.unfocused, "#333333", "#222222", "#888888", "#292d2e");
INIT_COLOR(config.client.urgent, "#2f343a", "#900000", "#ffffff", "#900000");
/* border and indicator color are ignored for placeholder contents */
INIT_COLOR(config.client.placeholder, "#000000", "#0c0c0c", "#ffffff", "#000000");
/* the last argument (indicator color) is ignored for bar colors */
INIT_COLOR(config.bar.focused, "#4c7899", "#285577", "#ffffff", "#000000");
INIT_COLOR(config.bar.unfocused, "#333333", "#222222", "#888888", "#000000");
INIT_COLOR(config.bar.urgent, "#2f343a", "#900000", "#ffffff", "#000000");
config.show_marks = true;
config.default_border = BS_NORMAL;
config.default_floating_border = BS_NORMAL;
config.default_border_width = logical_px(2);
config.default_floating_border_width = logical_px(2);
/* Set default_orientation to NO_ORIENTATION for auto orientation. */
config.default_orientation = NO_ORIENTATION;
/* Set default urgency reset delay to 500ms */
if (config.workspace_urgency_timer == 0)
config.workspace_urgency_timer = 0.5;
parse_configuration(override_configpath, true);
if (reload) {
translate_keysyms();
grab_all_keys(conn);
regrab_all_buttons(conn);
}
if (config.font.type == FONT_TYPE_NONE) {
ELOG("You did not specify required configuration option \"font\"\n");
config.font = load_font("fixed", true);
set_font(&config.font);
}
/* Redraw the currently visible decorations on reload, so that
* the possibly new drawing parameters changed. */
if (reload) {
x_deco_recurse(croot);
xcb_flush(conn);
}
#if 0
/* Set an empty name for every workspace which got no name */
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->name != NULL) {
/* If the font was not specified when the workspace name
* was loaded, we need to predict the text width now */
if (ws->text_width == 0)
ws->text_width = predict_text_width(global_conn,
config.font, ws->name, ws->name_len);
continue;
}
workspace_set_name(ws, NULL);
}
#endif
}