more progresses

next
nixo 2020-05-10 18:31:26 +02:00
parent c8f383329d
commit 03cbf0a766
4 changed files with 289 additions and 300 deletions

View File

@ -2,35 +2,19 @@ static void GENERATED_call(const int call_identifier, struct CommandResultIR *re
switch (call_identifier) {
case 0:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_rename_workspace(&current_match, result, "to", get_string("new_name"));
#else
fprintf(stderr, "cmd_rename_workspace(%s, %s)\n", "to", get_string("new_name"));
#endif
break;
case 1:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_rename_workspace(&current_match, result, NULL, "to");
#else
fprintf(stderr, "cmd_rename_workspace(NULL, %s)\n", "to");
#endif
break;
case 2:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_rename_workspace(&current_match, result, get_string("old_name"), get_string("new_name"));
#else
fprintf(stderr, "cmd_rename_workspace(%s, %s)\n", get_string("old_name"), get_string("new_name"));
#endif
break;
case 3:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_rename_workspace(&current_match, result, NULL, get_string("new_name"));
#else
fprintf(stderr, "cmd_rename_workspace(NULL, %s)\n", get_string("new_name"));
#endif
break;
case 4:
result->next_state = INITIAL;
@ -186,43 +170,23 @@ static void GENERATED_call(const int call_identifier, struct CommandResultIR *re
break;
case 23:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_move_con_to_workspace(&current_match, result, get_string("workspace"));
#else
fprintf(stderr, "cmd_move_con_to_workspace(%s)\n", get_string("workspace"));
#endif
break;
case 24:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_move_con_to_workspace(&current_match, result, get_string("workspace"));
#else
fprintf(stderr, "cmd_move_con_to_workspace(%s)\n", get_string("workspace"));
#endif
break;
case 25:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_move_con_to_workspace(&current_match, result, get_string("workspace"));
#else
fprintf(stderr, "cmd_move_con_to_workspace(%s)\n", get_string("workspace"));
#endif
break;
case 26:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_move_con_to_workspace(&current_match, result, get_string("workspace"));
#else
fprintf(stderr, "cmd_move_con_to_workspace(%s)\n", get_string("workspace"));
#endif
break;
case 27:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_move_con_to_workspace(&current_match, result, get_string("workspace"));
#else
fprintf(stderr, "cmd_move_con_to_workspace(%s)\n", get_string("workspace"));
#endif
break;
case 28:
result->next_state = INITIAL;
@ -250,19 +214,11 @@ static void GENERATED_call(const int call_identifier, struct CommandResultIR *re
break;
case 31:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout_toggle(&current_match, result, get_string("toggle_mode"));
#else
fprintf(stderr, "cmd_layout_toggle(%s)\n", get_string("toggle_mode"));
#endif
break;
case 32:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout_toggle(&current_match, result, get_string("toggle_mode"));
#else
fprintf(stderr, "cmd_layout_toggle(%s)\n", get_string("toggle_mode"));
#endif
break;
case 33:
result->next_state = INITIAL;
@ -514,51 +470,27 @@ static void GENERATED_call(const int call_identifier, struct CommandResultIR *re
break;
case 64:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout(&current_match, result, get_string("layout_mode"));
#else
fprintf(stderr, "cmd_layout(%s)\n", get_string("layout_mode"));
#endif
break;
case 65:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout(&current_match, result, get_string("layout_mode"));
#else
fprintf(stderr, "cmd_layout(%s)\n", get_string("layout_mode"));
#endif
break;
case 66:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout(&current_match, result, get_string("layout_mode"));
#else
fprintf(stderr, "cmd_layout(%s)\n", get_string("layout_mode"));
#endif
break;
case 67:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout(&current_match, result, get_string("layout_mode"));
#else
fprintf(stderr, "cmd_layout(%s)\n", get_string("layout_mode"));
#endif
break;
case 68:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout(&current_match, result, get_string("layout_mode"));
#else
fprintf(stderr, "cmd_layout(%s)\n", get_string("layout_mode"));
#endif
break;
case 69:
result->next_state = INITIAL;
#ifndef TEST_PARSER
cmd_layout(&current_match, result, get_string("layout_mode"));
#else
fprintf(stderr, "cmd_layout(%s)\n", get_string("layout_mode"));
#endif
break;
case 70:
result->next_state = INITIAL;

View File

@ -44,7 +44,7 @@ void cmd_criteria_add(I3_CMD, const char *ctype, const char *cvalue);
* next|prev|next_on_output|prev_on_output'.
*
*/
void cmd_move_con_to_workspace(I3_CMD, const char *which);
SCM guile_move_con_to_workspace(SCM which);
/**
* Implementation of 'move [window|container] [to] workspace back_and_forth'.
@ -218,13 +218,13 @@ void cmd_move_direction(I3_CMD, const char *direction_str, long move_px);
* Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'.
*
*/
void cmd_layout(I3_CMD, const char *layout_str);
SCM guile_layout(SCM layout);
/**
* Implementation of 'layout toggle [all|split]'.
*
*/
void cmd_layout_toggle(I3_CMD, const char *toggle_mode);
SCM guile_layout_toggle(SCM toggle_mode);
/**
* Implementation of 'exit'.
@ -302,7 +302,7 @@ void cmd_title_format(I3_CMD, const char *format);
* Implementation of 'rename workspace <name> to <name>'
*
*/
void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name);
SCM guile_rename_workspace(SCM old_name, SCM new_name);
/**
* Implementation of 'bar mode dock|hide|invisible|toggle [<bar_id>]'

View File

@ -296,33 +296,66 @@ static void move_matches_to_workspace(Con *ws) {
* next|prev|next_on_output|prev_on_output|current'.
*
*/
void cmd_move_con_to_workspace(I3_CMD, const char *which) {
DLOG("which=%s\n", which);
// FIXME: NOT WORKING
SCM guile_move_con_to_workspace(SCM g_which) {
const char * which = scm_to_locale_string(g_which);
CHECK_MOVE_CON_TO_WORKSPACE;
DLOG("which=%s\n", which);
/* get the workspace */
Con *ws;
if (strcmp(which, "next") == 0)
ws = workspace_next();
else if (strcmp(which, "prev") == 0)
ws = workspace_prev();
else if (strcmp(which, "next_on_output") == 0)
ws = workspace_next_on_output();
else if (strcmp(which, "prev_on_output") == 0)
ws = workspace_prev_on_output();
else if (strcmp(which, "current") == 0)
ws = con_get_workspace(focused);
else {
yerror("BUG: called with which=%s", which);
return;
while (!TAILQ_EMPTY(&owindows)) {
owindow *ow = TAILQ_FIRST(&owindows);
TAILQ_REMOVE(&owindows, ow, owindows);
free(ow);
}
owindow *ow = smalloc(sizeof(owindow));
ow->con = focused;
TAILQ_INIT(&owindows);
TAILQ_INSERT_TAIL(&owindows, ow, owindows);
if (TAILQ_EMPTY(&owindows)) {
/* yerror("Nothing to move: specified criteria don't match any window"); */
return SCM_BOOL_F;
}
bool found = false;
owindow *current = TAILQ_FIRST(&owindows);
while (current) {
owindow *next = TAILQ_NEXT(current, owindows);
if (current->con->type == CT_WORKSPACE && !con_has_children(current->con)) {
TAILQ_REMOVE(&owindows, current, owindows);
} else {
found = true;
}
move_matches_to_workspace(ws);
current = next;
}
if (!found) {
/* yerror("Nothing to move: workspace empty"); */
return SCM_BOOL_F;
}
cmd_output->needs_tree_render = true;
// XXX: default reply for now, make this a better reply
ysuccess(true);
/* get the workspace */
Con *ws;
if (strcmp(which, "next") == 0)
ws = workspace_next();
else if (strcmp(which, "prev") == 0)
ws = workspace_prev();
else if (strcmp(which, "next_on_output") == 0)
ws = workspace_next_on_output();
else if (strcmp(which, "prev_on_output") == 0)
ws = workspace_prev_on_output();
else if (strcmp(which, "current") == 0)
ws = con_get_workspace(focused);
else {
/* yerror("BUG: called with which=%s", which); */
return SCM_BOOL_F;
}
move_matches_to_workspace(ws);
tree_render();
return SCM_BOOL_T;
}
/*
@ -1381,113 +1414,6 @@ void cmd_sticky(I3_CMD, const char *action) {
ysuccess(true);
}
/*
* Implementation of 'move <direction> [<pixels> [px]]'.
*
*/
void cmd_move_direction(I3_CMD, const char *direction_str, long move_px) {
owindow *current;
HANDLE_EMPTY_MATCH;
Con *initially_focused = focused;
direction_t direction = parse_direction(direction_str);
TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("moving in direction %s, px %ld\n", direction_str, move_px);
if (con_is_floating(current->con)) {
DLOG("floating move with %ld pixels\n", move_px);
Rect newrect = current->con->parent->rect;
switch (direction) {
case D_LEFT:
newrect.x -= move_px;
break;
case D_RIGHT:
newrect.x += move_px;
break;
case D_UP:
newrect.y -= move_px;
break;
case D_DOWN:
newrect.y += move_px;
break;
}
cmd_output->needs_tree_render = floating_reposition(current->con->parent, newrect);
} else {
tree_move(current->con, direction);
cmd_output->needs_tree_render = true;
}
}
/* The move command should not disturb focus. con_exists is called because
* tree_move calls tree_flatten. */
if (focused != initially_focused && con_exists(initially_focused)) {
con_activate(initially_focused);
}
// XXX: default reply for now, make this a better reply
ysuccess(true);
}
/*
* Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'.
*
*/
void cmd_layout(I3_CMD, const char *layout_str) {
HANDLE_EMPTY_MATCH;
layout_t layout;
if (!layout_from_name(layout_str, &layout)) {
yerror("Unknown layout \"%s\", this is a mismatch between code and parser spec.", layout_str);
return;
}
DLOG("changing layout to %s (%d)\n", layout_str, layout);
owindow *current;
TAILQ_FOREACH (current, &owindows, owindows) {
if (con_is_docked(current->con)) {
ELOG("cannot change layout of a docked container, skipping it.\n");
continue;
}
DLOG("matching: %p / %s\n", current->con, current->con->name);
con_set_layout(current->con, layout);
}
cmd_output->needs_tree_render = true;
// XXX: default reply for now, make this a better reply
ysuccess(true);
}
/*
* Implementation of 'layout toggle [all|split]'.
*
*/
void cmd_layout_toggle(I3_CMD, const char *toggle_mode) {
owindow *current;
if (toggle_mode == NULL)
toggle_mode = "default";
DLOG("toggling layout (mode = %s)\n", toggle_mode);
/* check if the match is empty, not if the result is empty */
if (match_is_empty(current_match))
con_toggle_layout(focused, toggle_mode);
else {
TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("matching: %p / %s\n", current->con, current->con->name);
con_toggle_layout(current->con, toggle_mode);
}
}
cmd_output->needs_tree_render = true;
// XXX: default reply for now, make this a better reply
ysuccess(true);
}
/*
* Implementation of 'exit'.
*
@ -1858,110 +1784,114 @@ void cmd_title_format(I3_CMD, const char *format) {
* Implementation of 'rename workspace [<name>] to <name>'
*
*/
void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
if (strncasecmp(new_name, "__", strlen("__")) == 0) {
yerror("Cannot rename workspace to \"%s\": names starting with __ are i3-internal.", new_name);
return;
}
if (old_name) {
LOG("Renaming workspace \"%s\" to \"%s\"\n", old_name, new_name);
} else {
LOG("Renaming current workspace to \"%s\"\n", new_name);
SCM guile_rename_workspace(SCM g_old_name, SCM g_new_name) {
char * old_name = scm_to_locale_string(g_old_name);
char * new_name = scm_to_locale_string(g_new_name);
if (strncasecmp(new_name, "__", strlen("__")) == 0) {
/* yerror("Cannot rename workspace to \"%s\": names starting with __ are i3-internal.", new_name); */
return SCM_BOOL_F;
}
// FIXME
if (old_name) {
LOG("Renaming workspace \"%s\" to \"%s\"\n", old_name, new_name);
} else {
LOG("Renaming current workspace to \"%s\"\n", new_name);
}
Con *workspace;
if (old_name) {
workspace = get_existing_workspace_by_name(old_name);
} else {
workspace = con_get_workspace(focused);
old_name = workspace->name;
}
if (!workspace) {
/* yerror("Old workspace \"%s\" not found", old_name); */
return SCM_BOOL_F;
}
Con *check_dest = get_existing_workspace_by_name(new_name);
/* If check_dest == workspace, the user might be changing the case of the
* workspace, or it might just be a no-op. */
if (check_dest != NULL && check_dest != workspace) {
/* yerror("New workspace \"%s\" already exists", new_name); */
return SCM_BOOL_F;
}
/* Change the name and try to parse it as a number. */
/* old_name might refer to workspace->name, so copy it before free()ing */
char *old_name_copy = sstrdup(old_name);
FREE(workspace->name);
workspace->name = sstrdup(new_name);
workspace->num = ws_name_to_number(new_name);
LOG("num = %d\n", workspace->num);
/* By re-attaching, the sort order will be correct afterwards. */
Con *previously_focused = focused;
Con *previously_focused_content = focused->type == CT_WORKSPACE ? focused->parent : NULL;
Con *parent = workspace->parent;
con_detach(workspace);
con_attach(workspace, parent, false);
ipc_send_workspace_event("rename", workspace, NULL);
/* Move the workspace to the correct output if it has an assignment */
struct Workspace_Assignment *assignment = NULL;
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
if (assignment->output == NULL)
continue;
if (strcmp(assignment->name, workspace->name) != 0 && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) {
continue;
}
Con *workspace;
if (old_name) {
workspace = get_existing_workspace_by_name(old_name);
} else {
workspace = con_get_workspace(focused);
old_name = workspace->name;
Output *target_output = get_output_by_name(assignment->output, true);
if (!target_output) {
LOG("Could not get output named \"%s\"\n", assignment->output);
continue;
}
if (!workspace) {
yerror("Old workspace \"%s\" not found", old_name);
return;
if (!output_triggers_assignment(target_output, assignment)) {
continue;
}
workspace_move_to_output(workspace, target_output);
Con *check_dest = get_existing_workspace_by_name(new_name);
break;
}
/* If check_dest == workspace, the user might be changing the case of the
* workspace, or it might just be a no-op. */
if (check_dest != NULL && check_dest != workspace) {
yerror("New workspace \"%s\" already exists", new_name);
return;
}
bool can_restore_focus = previously_focused != NULL;
/* NB: If previously_focused is a workspace we can't work directly with it
* since it might have been cleaned up by workspace_show() already,
* depending on the focus order/number of other workspaces on the output.
* Instead, we loop through the available workspaces and only focus
* previously_focused if we still find it. */
if (previously_focused_content) {
Con *workspace = NULL;
GREP_FIRST(workspace, previously_focused_content, child == previously_focused);
can_restore_focus &= (workspace != NULL);
}
/* Change the name and try to parse it as a number. */
/* old_name might refer to workspace->name, so copy it before free()ing */
char *old_name_copy = sstrdup(old_name);
FREE(workspace->name);
workspace->name = sstrdup(new_name);
if (can_restore_focus) {
/* Restore the previous focus since con_attach messes with the focus. */
workspace_show(con_get_workspace(previously_focused));
con_focus(previously_focused);
}
workspace->num = ws_name_to_number(new_name);
LOG("num = %d\n", workspace->num);
/* Let back-and-forth work after renaming the previous workspace.
* See #3694. */
if (previous_workspace_name && !strcmp(previous_workspace_name, old_name_copy)) {
FREE(previous_workspace_name);
previous_workspace_name = sstrdup(new_name);
}
/* By re-attaching, the sort order will be correct afterwards. */
Con *previously_focused = focused;
Con *previously_focused_content = focused->type == CT_WORKSPACE ? focused->parent : NULL;
Con *parent = workspace->parent;
con_detach(workspace);
con_attach(workspace, parent, false);
ipc_send_workspace_event("rename", workspace, NULL);
tree_render();
/* Move the workspace to the correct output if it has an assignment */
struct Workspace_Assignment *assignment = NULL;
TAILQ_FOREACH (assignment, &ws_assignments, ws_assignments) {
if (assignment->output == NULL)
continue;
if (strcmp(assignment->name, workspace->name) != 0 && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) {
continue;
}
ewmh_update_desktop_properties();
Output *target_output = get_output_by_name(assignment->output, true);
if (!target_output) {
LOG("Could not get output named \"%s\"\n", assignment->output);
continue;
}
if (!output_triggers_assignment(target_output, assignment)) {
continue;
}
workspace_move_to_output(workspace, target_output);
break;
}
bool can_restore_focus = previously_focused != NULL;
/* NB: If previously_focused is a workspace we can't work directly with it
* since it might have been cleaned up by workspace_show() already,
* depending on the focus order/number of other workspaces on the output.
* Instead, we loop through the available workspaces and only focus
* previously_focused if we still find it. */
if (previously_focused_content) {
Con *workspace = NULL;
GREP_FIRST(workspace, previously_focused_content, child == previously_focused);
can_restore_focus &= (workspace != NULL);
}
if (can_restore_focus) {
/* Restore the previous focus since con_attach messes with the focus. */
workspace_show(con_get_workspace(previously_focused));
con_focus(previously_focused);
}
/* Let back-and-forth work after renaming the previous workspace.
* See #3694. */
if (previous_workspace_name && !strcmp(previous_workspace_name, old_name_copy)) {
FREE(previous_workspace_name);
previous_workspace_name = sstrdup(new_name);
}
cmd_output->needs_tree_render = true;
ysuccess(true);
ewmh_update_desktop_properties();
startup_sequence_rename_workspace(old_name_copy, new_name);
free(old_name_copy);
startup_sequence_rename_workspace(old_name_copy, new_name);
free(old_name_copy);
return SCM_BOOL_T;
}
/*
@ -2221,13 +2151,27 @@ 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;
/* if (current_match->error != NULL) { */
/* /\* yerror("Invalid match: %s", current_match->error); *\/ */
/* return SCM_BOOL_F; */
/* } */
/* if (match_is_empty(current_match)) { */
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);
/* } */
TAILQ_FOREACH (current, &owindows, owindows) {
count++;
}
@ -2236,7 +2180,6 @@ SCM guile_focus_direction(SCM g_direction) {
"while only exactly one container can be focused at a time.\n",
count);
}
direction_t direction;
position_t position;
bool auto_direction = true;
@ -2264,3 +2207,112 @@ SCM guile_focus_direction(SCM g_direction) {
tree_render();
return SCM_BOOL_T;
}
/*
* Implementation of 'move <direction> [<pixels> [px]]'.
*
*/
void cmd_move_direction(I3_CMD, const char *direction_str, long move_px) {
owindow *current;
HANDLE_EMPTY_MATCH;
Con *initially_focused = focused;
direction_t direction = parse_direction(direction_str);
TAILQ_FOREACH (current, &owindows, owindows) {
DLOG("moving in direction %s, px %ld\n", direction_str, move_px);
if (con_is_floating(current->con)) {
DLOG("floating move with %ld pixels\n", move_px);
Rect newrect = current->con->parent->rect;
switch (direction) {
case D_LEFT:
newrect.x -= move_px;
break;
case D_RIGHT:
newrect.x += move_px;
break;
case D_UP:
newrect.y -= move_px;
break;
case D_DOWN:
newrect.y += move_px;
break;
}
cmd_output->needs_tree_render = floating_reposition(current->con->parent, newrect);
} else {
tree_move(current->con, direction);
cmd_output->needs_tree_render = true;
}
}
/* The move command should not disturb focus. con_exists is called because
* tree_move calls tree_flatten. */
if (focused != initially_focused && con_exists(initially_focused)) {
con_activate(initially_focused);
}
// XXX: default reply for now, make this a better reply
ysuccess(true);
}
/*
* Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'.
*
*/
SCM guile_layout(SCM g_layout) {
owindow *ow;
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);
char * layout_str = scm_to_locale_string(g_layout);
layout_t layout;
if (!layout_from_name(layout_str, &layout)) {
/* yerror("Unknown layout \"%s\", this is a mismatch between code and parser spec.", layout_str); */
return SCM_BOOL_F;
}
DLOG("changing layout to %s (%d)\n", layout_str, layout);
owindow *current;
TAILQ_FOREACH (current, &owindows, owindows) {
if (con_is_docked(current->con)) {
ELOG("cannot change layout of a docked container, skipping it.\n");
continue;
}
DLOG("matching: %p / %s\n", current->con, current->con->name);
con_set_layout(current->con, layout);
}
tree_render();
return SCM_BOOL_T;
}
/*
* Implementation of 'layout toggle [all|split]'.
*
*/
SCM guile_layout_toggle(SCM g_toggle_mode) {
owindow *current;
char * toggle_mode = scm_to_locale_string(g_toggle_mode);
DLOG("toggling layout (mode = %s)\n", toggle_mode);
/* check if the match is empty, not if the result is empty */
con_toggle_layout(focused, toggle_mode);
tree_render();
return SCM_BOOL_T;
}

View File

@ -337,6 +337,11 @@ register_functions (void* data) {
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);
scm_c_define_gsubr ("layout", 1, 0, 0, &guile_layout);
scm_c_define_gsubr ("toggle-layout", 1, 0, 0, &guile_layout_toggle);
scm_c_define_gsubr ("move-to-workspace", 1, 0, 0, &guile_move_con_to_workspace);
scm_c_define_gsubr ("rename-workspace", 2, 0, 0, &guile_rename_workspace);
return NULL;
}