many progresses
This commit is contained in:
parent
29f551626e
commit
c8f383329d
|
@ -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);
|
||||
|
|
|
@ -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 <comment>'.
|
||||
*
|
||||
*/
|
||||
void cmd_nop(I3_CMD, const char *comment);
|
||||
|
||||
/**
|
||||
* Implementation of 'append_layout <path>'.
|
||||
*
|
||||
|
@ -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] <command>'.
|
||||
*
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
131
src/click.c
131
src/click.c
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
273
src/commands.c
273
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 <comment>'.
|
||||
*
|
||||
*/
|
||||
void cmd_nop(I3_CMD, const char *comment) {
|
||||
LOG("-------------------------------------------------\n");
|
||||
LOG(" NOP: %.4000s\n", comment);
|
||||
LOG("-------------------------------------------------\n");
|
||||
ysuccess(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of 'append_layout <path>'.
|
||||
*
|
||||
|
@ -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] <command>'.
|
||||
*
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
|
15
src/config.c
15
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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
SCM guile_split(SCM direction);
|
58
src/main.c
58
src/main.c
|
@ -26,6 +26,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <libguile.h>
|
||||
#include "guile-objects.h"
|
||||
|
||||
#ifdef I3_ASAN_ENABLED
|
||||
#include <sanitizer/lsan_interface.h>
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue