diff --git a/generated/GENERATED_command_call.h b/generated/GENERATED_command_call.h index 04a103c9..4b2407a3 100644 --- a/generated/GENERATED_command_call.h +++ b/generated/GENERATED_command_call.h @@ -610,35 +610,19 @@ static void GENERATED_call(const int call_identifier, struct CommandResultIR *re break; case 76: result->next_state = INITIAL; -#ifndef TEST_PARSER - cmd_focus_direction(¤t_match, result, get_string("direction")); -#else fprintf(stderr, "cmd_focus_direction(%s)\n", get_string("direction")); -#endif break; case 77: result->next_state = INITIAL; -#ifndef TEST_PARSER - cmd_focus_direction(¤t_match, result, get_string("direction")); -#else fprintf(stderr, "cmd_focus_direction(%s)\n", get_string("direction")); -#endif break; case 78: result->next_state = INITIAL; -#ifndef TEST_PARSER - cmd_focus_direction(¤t_match, result, get_string("direction")); -#else fprintf(stderr, "cmd_focus_direction(%s)\n", get_string("direction")); -#endif break; case 79: result->next_state = INITIAL; -#ifndef TEST_PARSER - cmd_focus_direction(¤t_match, result, get_string("direction")); -#else fprintf(stderr, "cmd_focus_direction(%s)\n", get_string("direction")); -#endif break; case 80: result->next_state = INITIAL; @@ -762,19 +746,9 @@ static void GENERATED_call(const int call_identifier, struct CommandResultIR *re break; case 95: result->next_state = INITIAL; -#ifndef TEST_PARSER - cmd_nop(¤t_match, result, get_string("comment")); -#else - fprintf(stderr, "cmd_nop(%s)\n", get_string("comment")); -#endif break; case 96: result->next_state = INITIAL; -#ifndef TEST_PARSER - cmd_nop(¤t_match, result, NULL); -#else - fprintf(stderr, "cmd_nop(NULL)\n"); -#endif break; default: printf("BUG in the parser. state = %d\n", call_identifier); diff --git a/include/commands.h b/include/commands.h index 9a2a20b2..c055cb28 100644 --- a/include/commands.h +++ b/include/commands.h @@ -13,6 +13,8 @@ #include "commands_parser.h" +#include "libguile.h" + /** The beginning of the prototype for every cmd_ function. */ #define I3_CMD Match *current_match, struct CommandResultIR *cmd_output @@ -80,12 +82,6 @@ void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px, */ void cmd_border(I3_CMD, const char *border_style_str, long border_width); -/** - * Implementation of 'nop '. - * - */ -void cmd_nop(I3_CMD, const char *comment); - /** * Implementation of 'append_layout '. * @@ -164,12 +160,6 @@ void cmd_move_workspace_to_output(I3_CMD, const char *name); */ void cmd_split(I3_CMD, const char *direction); -/** - * Implementation of 'kill [window|client]'. - * - */ -void cmd_kill(I3_CMD, const char *kill_mode_str); - /** * Implementation of 'exec [--no-startup-id] '. * @@ -180,7 +170,7 @@ void cmd_exec(I3_CMD, const char *nosn, const char *command); * Implementation of 'focus left|right|up|down'. * */ -void cmd_focus_direction(I3_CMD, const char *direction); +SCM guile_focus_direction(SCM direction); /** * Implementation of 'focus next|prev sibling' @@ -337,3 +327,6 @@ void cmd_shmlog(I3_CMD, const char *argument); * */ void cmd_debuglog(I3_CMD, const char *argument); + + +SCM guile_kill(SCM kill_mode); diff --git a/include/config_directives.h b/include/config_directives.h index 06fbd3b0..c8e0e9f4 100644 --- a/include/config_directives.h +++ b/include/config_directives.h @@ -39,7 +39,6 @@ CFGFUN(criteria_init, int _state); CFGFUN(criteria_add, const char *ctype, const char *cvalue); CFGFUN(criteria_pop_state); -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(floating_minimum_size, const long width, const long height); diff --git a/include/config_parser.h b/include/config_parser.h index 009538f2..d2786340 100644 --- a/include/config_parser.h +++ b/include/config_parser.h @@ -40,11 +40,10 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context); void start_config_error_nagbar(const char *configpath, bool has_errors); /** - * Parses the given file by first replacing the variables, then calling - * parse_config and launching i3-nagbar if use_nagbar is true. + * Parses the given scheme file. * * The return value is a boolean indicating whether there were errors during * parsing. * */ -bool parse_file(const char *f, bool use_nagbar); +bool parse_file(const char *f); diff --git a/src/click.c b/src/click.c index 64d78315..726c6296 100644 --- a/src/click.c +++ b/src/click.c @@ -11,6 +11,8 @@ #include +#include "guile-objects.h" + typedef enum { CLICK_BORDER = 0, CLICK_DECORATION = 1, CLICK_INSIDE = 2 } click_destination_t; @@ -299,74 +301,83 @@ done: * */ void handle_button_press(xcb_button_press_event_t *event) { - Con *con; - DLOG("Button %d (state %d) %s on window 0x%08x (child 0x%08x) at (%d, %d) (root %d, %d)\n", - event->detail, event->state, (event->response_type == XCB_BUTTON_PRESS ? "press" : "release"), - event->event, event->child, event->event_x, event->event_y, event->root_x, - event->root_y); + Con *con; + DLOG("Button %d (state %d) %s on window 0x%08x (child 0x%08x) at (%d, %d) (root %d, %d)\n", + event->detail, event->state, (event->response_type == XCB_BUTTON_PRESS ? "press" : "release"), + event->event, event->child, event->event_x, event->event_y, event->root_x, + event->root_y); - last_timestamp = event->time; + last_timestamp = event->time; - const uint32_t mod = (config.floating_modifier & 0xFFFF); - const bool mod_pressed = (mod != 0 && (event->state & mod) == mod); - DLOG("floating_mod = %d, detail = %d\n", mod_pressed, event->detail); - if ((con = con_by_window_id(event->event))) { - route_click(con, event, mod_pressed, CLICK_INSIDE); - return; + // Click hook + SCM hook = scm_variable_ref(scm_c_lookup("button-press-hook")); + if (scm_is_true(hook)) { + scm_call_6(hook, + scm_from_int(event->root_x), scm_from_int(event->root_y), + scm_from_int(event->event_x), scm_from_int(event->event_y), + scm_from_int(event->state), scm_from_int(event->same_screen)); + } + + const uint32_t mod = (config.floating_modifier & 0xFFFF); + const bool mod_pressed = (mod != 0 && (event->state & mod) == mod); + DLOG("floating_mod = %d, detail = %d\n", mod_pressed, event->detail); + if ((con = con_by_window_id(event->event))) { + route_click(con, event, mod_pressed, CLICK_INSIDE); + return; + } + + if (!(con = con_by_frame_id(event->event))) { + /* Run bindings on the root window as well, see #2097. We only run it + * if --whole-window was set as that's the equivalent for a normal + * window. */ + if (event->event == root) { + Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); + if (bind != NULL && bind->whole_window) { + CommandResult *result = run_binding(bind, NULL); + command_result_free(result); + } } - if (!(con = con_by_frame_id(event->event))) { - /* Run bindings on the root window as well, see #2097. We only run it - * if --whole-window was set as that's the equivalent for a normal - * window. */ - if (event->event == root) { - Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event); - if (bind != NULL && bind->whole_window) { - CommandResult *result = run_binding(bind, NULL); - command_result_free(result); - } - } + /* If the root window is clicked, find the relevant output from the + * click coordinates and focus the output's active workspace. */ + if (event->event == root && event->response_type == XCB_BUTTON_PRESS) { + Con *output, *ws; + TAILQ_FOREACH (output, &(croot->nodes_head), nodes) { + if (con_is_internal(output) || + !rect_contains(output->rect, event->event_x, event->event_y)) + continue; - /* If the root window is clicked, find the relevant output from the - * click coordinates and focus the output's active workspace. */ - if (event->event == root && event->response_type == XCB_BUTTON_PRESS) { - Con *output, *ws; - TAILQ_FOREACH (output, &(croot->nodes_head), nodes) { - if (con_is_internal(output) || - !rect_contains(output->rect, event->event_x, event->event_y)) - continue; - - ws = TAILQ_FIRST(&(output_get_content(output)->focus_head)); - if (ws != con_get_workspace(focused)) { - workspace_show(ws); - tree_render(); - } - return; - } - return; - } - - ELOG("Clicked into unknown window?!\n"); - xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time); - xcb_flush(conn); - return; + ws = TAILQ_FIRST(&(output_get_content(output)->focus_head)); + if (ws != con_get_workspace(focused)) { + workspace_show(ws); + tree_render(); + } + return; + } + return; } - /* Check if the click was on the decoration of a child */ - Con *child; - TAILQ_FOREACH_REVERSE (child, &(con->nodes_head), nodes_head, nodes) { - if (!rect_contains(child->deco_rect, event->event_x, event->event_y)) - continue; + ELOG("Clicked into unknown window?!\n"); + xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time); + xcb_flush(conn); + return; + } - route_click(child, event, mod_pressed, CLICK_DECORATION); - return; - } + /* Check if the click was on the decoration of a child */ + Con *child; + TAILQ_FOREACH_REVERSE (child, &(con->nodes_head), nodes_head, nodes) { + if (!rect_contains(child->deco_rect, event->event_x, event->event_y)) + continue; - if (event->child != XCB_NONE) { - DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n"); - route_click(con, event, mod_pressed, CLICK_INSIDE); - return; - } + route_click(child, event, mod_pressed, CLICK_DECORATION); + return; + } - route_click(con, event, mod_pressed, CLICK_BORDER); + if (event->child != XCB_NONE) { + DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n"); + route_click(con, event, mod_pressed, CLICK_INSIDE); + return; + } + + route_click(con, event, mod_pressed, CLICK_BORDER); } diff --git a/src/commands.c b/src/commands.c index d61511cd..3e6b227d 100644 --- a/src/commands.c +++ b/src/commands.c @@ -757,17 +757,6 @@ void cmd_border(I3_CMD, const char *border_style_str, long border_width) { ysuccess(true); } -/* - * Implementation of 'nop '. - * - */ -void cmd_nop(I3_CMD, const char *comment) { - LOG("-------------------------------------------------\n"); - LOG(" NOP: %.4000s\n", comment); - LOG("-------------------------------------------------\n"); - ysuccess(true); -} - /* * Implementation of 'append_layout '. * @@ -1165,67 +1154,6 @@ void cmd_split(I3_CMD, const char *direction) { ysuccess(true); } -/* - * Implementation of 'kill [window|client]'. - * - */ -void cmd_kill(I3_CMD, const char *kill_mode_str) { - if (kill_mode_str == NULL) - kill_mode_str = "window"; - - DLOG("kill_mode=%s\n", kill_mode_str); - - int kill_mode; - if (strcmp(kill_mode_str, "window") == 0) - kill_mode = KILL_WINDOW; - else if (strcmp(kill_mode_str, "client") == 0) - kill_mode = KILL_CLIENT; - else { - yerror("BUG: called with kill_mode=%s", kill_mode_str); - return; - } - - HANDLE_EMPTY_MATCH; - - owindow *current; - TAILQ_FOREACH (current, &owindows, owindows) { - con_close(current->con, kill_mode); - } - - cmd_output->needs_tree_render = true; - // XXX: default reply for now, make this a better reply - ysuccess(true); -} - -/* - * Implementation of 'exec [--no-startup-id] '. - * - */ -void cmd_exec(I3_CMD, const char *nosn, const char *command) { - bool no_startup_id = (nosn != NULL); - - HANDLE_EMPTY_MATCH; - - int count = 0; - owindow *current; - TAILQ_FOREACH (current, &owindows, owindows) { - count++; - } - - if (count > 1) { - LOG("WARNING: Your criteria for the exec command match %d containers, " - "so the command will execute this many times.\n", - count); - } - - TAILQ_FOREACH (current, &owindows, owindows) { - DLOG("should execute %s, no_startup_id = %d\n", command, no_startup_id); - start_application(command, no_startup_id); - } - - ysuccess(true); -} - #define CMD_FOCUS_WARN_CHILDREN \ do { \ int count = 0; \ @@ -1241,44 +1169,6 @@ void cmd_exec(I3_CMD, const char *nosn, const char *command) { } \ } while (0) -/* - * Implementation of 'focus left|right|up|down|next|prev'. - * - */ -void cmd_focus_direction(I3_CMD, const char *direction_str) { - HANDLE_EMPTY_MATCH; - CMD_FOCUS_WARN_CHILDREN; - - direction_t direction; - position_t position; - bool auto_direction = true; - if (strcmp(direction_str, "prev") == 0) { - position = BEFORE; - } else if (strcmp(direction_str, "next") == 0) { - position = AFTER; - } else { - auto_direction = false; - direction = parse_direction(direction_str); - } - - owindow *current; - TAILQ_FOREACH (current, &owindows, owindows) { - Con *ws = con_get_workspace(current->con); - if (!ws || con_is_internal(ws)) { - continue; - } - if (auto_direction) { - orientation_t o = con_orientation(current->con->parent); - direction = direction_from_orientation_position(o, position); - } - tree_next(current->con, direction); - } - - cmd_output->needs_tree_render = true; - // XXX: default reply for now, make this a better reply - ysuccess(true); -} - /* * Implementation of 'focus next|prev sibling' * @@ -2211,3 +2101,166 @@ void cmd_debuglog(I3_CMD, const char *argument) { // XXX: default reply for now, make this a better reply ysuccess(true); } + +static struct CommandResultIR subcommand_output; +SCM guile_kill(SCM g_direction) { + Con * con; + owindow * ow; + while (!TAILQ_EMPTY(&owindows)) { + ow = TAILQ_FIRST(&owindows); + TAILQ_REMOVE(&owindows, ow, owindows); + free(ow); + } + + TAILQ_INIT(&owindows); + /* copy all_cons */ + TAILQ_FOREACH (con, &all_cons, all_cons) { + ow = smalloc(sizeof(owindow)); + ow->con = con; + TAILQ_INSERT_TAIL(&owindows, ow, owindows); + } + + while (!TAILQ_EMPTY(&owindows)) { + ow = TAILQ_FIRST(&owindows); + TAILQ_REMOVE(&owindows, ow, owindows); + free(ow); + } + ow = smalloc(sizeof(owindow)); + ow->con = focused; + TAILQ_INIT(&owindows); + TAILQ_INSERT_TAIL(&owindows, ow, owindows); + + owindow *current; + + const char * kill_mode_str = "window"; + // TODO: DEFATULT TO WINDOW + + int kill_mode; + if (strcmp(kill_mode_str, "window") == 0) + kill_mode = KILL_WINDOW; + else if (strcmp(kill_mode_str, "client") == 0) + kill_mode = KILL_CLIENT; + else { + //yerror("BUG: called with kill_mode=%s", kill_mode_str); + return SCM_BOOL_F; + } + + TAILQ_FOREACH (current, &owindows, owindows) { + con_close(current->con, kill_mode); + } + + tree_render(); + return SCM_BOOL_T; +} + +// WORKING!! +SCM guile_split(SCM g_direction) { + char * direction = scm_to_locale_string(g_direction); + Con * con; + owindow * ow; + while (!TAILQ_EMPTY(&owindows)) { + ow = TAILQ_FIRST(&owindows); + TAILQ_REMOVE(&owindows, ow, owindows); + free(ow); + } + + TAILQ_INIT(&owindows); + /* copy all_cons */ + TAILQ_FOREACH (con, &all_cons, all_cons) { + ow = smalloc(sizeof(owindow)); + ow->con = con; + TAILQ_INSERT_TAIL(&owindows, ow, owindows); + } + + while (!TAILQ_EMPTY(&owindows)) { + ow = TAILQ_FIRST(&owindows); + TAILQ_REMOVE(&owindows, ow, owindows); + free(ow); + } + ow = smalloc(sizeof(owindow)); + ow->con = focused; + TAILQ_INIT(&owindows); + TAILQ_INSERT_TAIL(&owindows, ow, owindows); + + owindow *current; + LOG("splitting in direction %c\n", direction[0]); + TAILQ_FOREACH (current, &owindows, owindows) { + if (con_is_docked(current->con)) { + ELOG("Cannot split a docked container, skipping.\n"); + continue; + } + + DLOG("matching: %p / %s\n", current->con, current->con->name); + if (direction[0] == 't') { + layout_t current_layout; + if (current->con->type == CT_WORKSPACE) { + current_layout = current->con->layout; + } else { + current_layout = current->con->parent->layout; + } + /* toggling split orientation */ + if (current_layout == L_SPLITH) { + tree_split(current->con, VERT); + } else { + tree_split(current->con, HORIZ); + } + } else { + tree_split(current->con, (direction[0] == 'v' ? VERT : HORIZ)); + } + } + + tree_render(); + return SCM_BOOL_T; +} + +/* + * Implementation of 'focus left|right|up|down|next|prev'. + * + */ +SCM guile_focus_direction(SCM g_direction) { + char * direction_str = scm_to_locale_string(g_direction); + Con * con; + owindow * ow; + while (!TAILQ_EMPTY(&owindows)) { + ow = TAILQ_FIRST(&owindows); + TAILQ_REMOVE(&owindows, ow, owindows); + free(ow); + } + int count = 0; + owindow *current; + TAILQ_FOREACH (current, &owindows, owindows) { + count++; + } + if (count > 1) { + LOG("WARNING: Your criteria for the focus command matches %d containers, " + "while only exactly one container can be focused at a time.\n", + count); + } + + direction_t direction; + position_t position; + bool auto_direction = true; + if (strcmp(direction_str, "prev") == 0) { + position = BEFORE; + } else if (strcmp(direction_str, "next") == 0) { + position = AFTER; + } else { + auto_direction = false; + direction = parse_direction(direction_str); + } + + TAILQ_FOREACH (current, &owindows, owindows) { + Con *ws = con_get_workspace(current->con); + if (!ws || con_is_internal(ws)) { + continue; + } + if (auto_direction) { + orientation_t o = con_orientation(current->con->parent); + direction = direction_from_orientation_position(o, position); + } + tree_next(current->con, direction); + } + + tree_render(); + return SCM_BOOL_T; +} diff --git a/src/config.c b/src/config.c index 75802abd..2e1b64c6 100644 --- a/src/config.c +++ b/src/config.c @@ -223,19 +223,16 @@ bool load_configuration(const char *override_configpath, config_load_t load_type current_configpath = get_config_path(override_configpath, true); if (current_configpath == NULL) { die("Unable to find the configuration file (looked at " - "$XDG_CONFIG_HOME/i3/config, ~/.i3/config, $XDG_CONFIG_DIRS/i3/config " - "and " SYSCONFDIR "/i3/config)"); + "$XDG_CONFIG_HOME/i3/config.scm, ~/.i3/config.scm, $XDG_CONFIG_DIRS/i3/config.scm " + "and " SYSCONFDIR "/i3/config.scm)"); } LOG("Parsing configfile %s\n", current_configpath); - const bool result = parse_file(current_configpath, load_type != C_VALIDATE); - - config.font = load_font("fixed", true); + const bool result = parse_file(current_configpath); + + config.font = load_font + (scm_to_locale_string(scm_variable_ref(scm_c_lookup("font"))), false); set_font(&config.font); - /* /\* i3Font font = load_font(scm_to_locale_string(scm_variable_ref(scm_c_lookup("font"))), false); *\/ */ - /* i3Font font = load_font("pango:monospace 20", false); */ - /* set_font(&font); */ - if (load_type == C_RELOAD) { translate_keysyms(); grab_all_keys(conn); diff --git a/src/config_parser.c b/src/config_parser.c index 7dea2e6f..9253654a 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -564,72 +564,6 @@ struct ConfigResultIR *parse_config(const char *input, struct context *context) return &command_output; } -/* - * Goes through each line of buf (separated by \n) and checks for statements / - * commands which only occur in i3 v4 configuration files. If it finds any, it - * returns version 4, otherwise it returns version 3. - * - */ -static int detect_version(char *buf) { - char *walk = buf; - char *line = buf; - while (*walk != '\0') { - if (*walk != '\n') { - walk++; - continue; - } - - /* check for some v4-only statements */ - if (strncasecmp(line, "bindcode", strlen("bindcode")) == 0 || - strncasecmp(line, "force_focus_wrapping", strlen("force_focus_wrapping")) == 0 || - strncasecmp(line, "# i3 config file (v4)", strlen("# i3 config file (v4)")) == 0 || - strncasecmp(line, "workspace_layout", strlen("workspace_layout")) == 0) { - LOG("deciding for version 4 due to this line: %.*s\n", (int)(walk - line), line); - return 4; - } - - /* if this is a bind statement, we can check the command */ - if (strncasecmp(line, "bind", strlen("bind")) == 0) { - char *bind = strchr(line, ' '); - if (bind == NULL) - goto next; - while ((*bind == ' ' || *bind == '\t') && *bind != '\0') - bind++; - if (*bind == '\0') - goto next; - if ((bind = strchr(bind, ' ')) == NULL) - goto next; - while ((*bind == ' ' || *bind == '\t') && *bind != '\0') - bind++; - if (*bind == '\0') - goto next; - if (strncasecmp(bind, "layout", strlen("layout")) == 0 || - strncasecmp(bind, "floating", strlen("floating")) == 0 || - strncasecmp(bind, "workspace", strlen("workspace")) == 0 || - strncasecmp(bind, "focus left", strlen("focus left")) == 0 || - strncasecmp(bind, "focus right", strlen("focus right")) == 0 || - strncasecmp(bind, "focus up", strlen("focus up")) == 0 || - strncasecmp(bind, "focus down", strlen("focus down")) == 0 || - strncasecmp(bind, "border normal", strlen("border normal")) == 0 || - strncasecmp(bind, "border 1pixel", strlen("border 1pixel")) == 0 || - strncasecmp(bind, "border pixel", strlen("border pixel")) == 0 || - strncasecmp(bind, "border borderless", strlen("border borderless")) == 0 || - strncasecmp(bind, "--no-startup-id", strlen("--no-startup-id")) == 0 || - strncasecmp(bind, "bar", strlen("bar")) == 0) { - LOG("deciding for version 4 due to this line: %.*s\n", (int)(walk - line), line); - return 4; - } - } - - next: - /* advance to the next line */ - walk++; - line = walk; - } - - return 3; -} - /** * Launch nagbar to indicate errors in the configuration file. */ @@ -658,74 +592,12 @@ void start_config_error_nagbar(const char *configpath, bool has_errors) { free(pageraction); } -/* - * Inserts or updates a variable assignment depending on whether it already exists. - * - */ -static void upsert_variable(struct variables_head *variables, char *key, char *value) { - struct Variable *current; - SLIST_FOREACH (current, variables, variables) { - if (strcmp(current->key, key) != 0) { - continue; - } - - DLOG("Updated variable: %s = %s -> %s\n", key, current->value, value); - FREE(current->value); - current->value = sstrdup(value); - return; - } - - DLOG("Defined new variable: %s = %s\n", key, value); - struct Variable *new = scalloc(1, sizeof(struct Variable)); - struct Variable *test = NULL, *loc = NULL; - new->key = sstrdup(key); - new->value = sstrdup(value); - /* ensure that the correct variable is matched in case of one being - * the prefix of another */ - SLIST_FOREACH (test, variables, variables) { - if (strlen(new->key) >= strlen(test->key)) - break; - loc = test; - } - - if (loc == NULL) { - SLIST_INSERT_HEAD(variables, new, variables); - } else { - SLIST_INSERT_AFTER(loc, new, variables); - } -} - -static char *get_resource(char *name) { - if (conn == NULL) { - return NULL; - } - - /* Load the resource database lazily. */ - if (database == NULL) { - database = xcb_xrm_database_from_default(conn); - - if (database == NULL) { - ELOG("Failed to open the resource database.\n"); - - /* Load an empty database so we don't keep trying to load the - * default database over and over again. */ - database = xcb_xrm_database_from_string(""); - - return NULL; - } - } - - char *resource; - xcb_xrm_resource_get_string(database, name, NULL, &resource); - return resource; -} - /* * Parses the given file by first replacing the variables, then calling * parse_config and possibly launching i3-nagbar. * */ -bool parse_file(const char *f, bool use_nagbar) { +bool parse_file(const char *f) { if (database != NULL) { xcb_xrm_database_free(database); /* Explicitly set the database to NULL again in case the config gets reloaded. */ diff --git a/src/guile-objects.h b/src/guile-objects.h new file mode 100644 index 00000000..ab5323ed --- /dev/null +++ b/src/guile-objects.h @@ -0,0 +1,2 @@ + +SCM guile_split(SCM direction); diff --git a/src/main.c b/src/main.c index 231482cd..f8efc3f3 100644 --- a/src/main.c +++ b/src/main.c @@ -26,6 +26,7 @@ #include #include +#include "guile-objects.h" #ifdef I3_ASAN_ENABLED #include @@ -264,6 +265,8 @@ void set_defaults(void){ scm_c_define("font", scm_from_locale_string("fixed")); } +void define_objects(void) { } + SCM guile_binding(SCM g_bindtype, SCM g_modifiers, SCM g_key, SCM g_release, SCM g_border, SCM g_whole_window, SCM g_exclude_titlebar, SCM g_command) { @@ -276,14 +279,64 @@ SCM guile_binding(SCM g_bindtype, SCM g_modifiers, SCM g_key, SCM g_release, const char * exclude_titlebar = scm_to_locale_string (g_exclude_titlebar); // procedure configure_binding(bindtype, modifiers, key, release, border, whole_window, exclude_titlebar, g_command, DEFAULT_BINDING_MODE, false); - return scm_from_bool(true); + return SCM_BOOL_T; } +SCM guile_change_workspace(SCM g_which) { + const char * which = scm_to_locale_string(g_which); + + if (con_get_fullscreen_con(croot, CF_GLOBAL)) { + return scm_list_2(SCM_BOOL_F, + scm_from_locale_string("Cannot switch workspace while in global fullscreen")); + } + + // TODO: We don't need to parse anything! + long parsed_num = ws_name_to_number(which); + if (parsed_num == -1) { + /* scm_simple_format */ + /* (SCM_BOOL_F, */ + /* "Could not parse initial part of ~A as a number.", */ + /* scm_list_1(which)) */ + return scm_list_2(SCM_BOOL_F, scm_from_locale_string("NaN")); + } + + Con *workspace = get_existing_workspace_by_num(parsed_num); + if (!workspace) { + workspace_show_by_name(which); + tree_render(); + return scm_list_2 + (SCM_BOOL_T, + scm_simple_format(SCM_BOOL_F, + scm_from_locale_string("There is no workspace with number ~S, creating a new one.\n"), + scm_list_1(scm_from_int(parsed_num)))); + } + workspace_show(workspace); + + tree_render(); + + return SCM_BOOL_T; +} + +// Force display update when a variable is changed +// (eg. fonts) +SCM guile_refresh() { + config.font = load_font + (scm_to_locale_string(scm_variable_ref(scm_c_lookup("font"))), false); + set_font(&config.font); + tree_render(); + return SCM_BOOL_T; +} static void* register_functions (void* data) { set_defaults(); + define_objects(); scm_c_define_gsubr ("set-binding", 8, 0, 0, &guile_binding); + scm_c_define_gsubr ("change-workspace", 1, 0, 0, &guile_change_workspace); + scm_c_define_gsubr ("refresh", 0, 0, 0, &guile_refresh); + scm_c_define_gsubr ("kill", 0, 0, 0, &guile_kill); + scm_c_define_gsubr ("split", 1, 0, 0, &guile_split); + scm_c_define_gsubr ("focus-direction", 1, 0, 0, &guile_focus_direction); return NULL; } @@ -525,7 +578,6 @@ int main(int argc, char *argv[]) { FREE(payload); uint32_t reply_length; - uint32_t reply_type; uint8_t *reply; int ret; if ((ret = ipc_recv_message(sockfd, &reply_length, &reply)) != 0) { @@ -533,8 +585,6 @@ int main(int argc, char *argv[]) { err(EXIT_FAILURE, "IPC: read()"); return 1; } - if (reply_type != I3_IPC_REPLY_TYPE_COMMAND) - errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_REPLY_TYPE_COMMAND); printf("%.*s\n", reply_length, reply); FREE(reply); return 0;