diff --git a/include/data.h b/include/data.h index 4f7983dc..13ce08b4 100644 --- a/include/data.h +++ b/include/data.h @@ -239,6 +239,7 @@ struct Match { char *class; char *instance; xcb_window_t id; + Con *con_id; bool floating; enum { M_GLOBAL, M_OUTPUT, M_WORKSPACE } levels; diff --git a/src/cmdparse.l b/src/cmdparse.l index 684a588c..079aa8f9 100644 --- a/src/cmdparse.l +++ b/src/cmdparse.l @@ -95,11 +95,14 @@ none { return TOK_NONE; } mode { return TOK_MODE; } tiling { return TOK_TILING; } floating { return TOK_FLOATING; } -workspace { return TOK_WORKSPACE; } +workspace { BEGIN(WANT_WS_STRING); return TOK_WORKSPACE; } focus { return TOK_FOCUS; } move { return TOK_MOVE; } +open { return TOK_OPEN; } class { BEGIN(WANT_QSTRING); return TOK_CLASS; } +id { BEGIN(WANT_QSTRING); return TOK_ID; } +con_id { BEGIN(WANT_QSTRING); return TOK_CON_ID; } . { return (int)yytext[0]; } diff --git a/src/cmdparse.y b/src/cmdparse.y index eb5ab71f..81dd148d 100644 --- a/src/cmdparse.y +++ b/src/cmdparse.y @@ -109,8 +109,11 @@ void parse_cmd(const char *new) { %token TOK_WORKSPACE "workspace" %token TOK_FOCUS "focus" %token TOK_MOVE "move" +%token TOK_OPEN "open" %token TOK_CLASS "class" +%token TOK_ID "id" +%token TOK_CON_ID "con_id" %token WHITESPACE "" %token STR "" @@ -156,9 +159,6 @@ matchstart: /* copy all_cons */ Con *con; TAILQ_FOREACH(con, &all_cons, all_cons) { - if (con->window == NULL) - continue; - owindow *ow = smalloc(sizeof(owindow)); ow->con = con; TAILQ_INSERT_TAIL(&owindows, ow, owindows); @@ -184,12 +184,22 @@ matchend: next = TAILQ_NEXT(next, owindows); printf("checking if con %p / %s matches\n", current->con, current->con->name); - if (match_matches_window(¤t_match, current->con->window)) { - printf("matches!\n"); - TAILQ_INSERT_TAIL(&owindows, current, owindows); + if (current_match.con_id != NULL) { + if (current_match.con_id == current->con) { + printf("matches container!\n"); + TAILQ_INSERT_TAIL(&owindows, current, owindows); + + } } else { - printf("doesnt match\n"); - free(current); + if (current->con->window == NULL) + continue; + if (match_matches_window(¤t_match, current->con->window)) { + printf("matches window!\n"); + TAILQ_INSERT_TAIL(&owindows, current, owindows); + } else { + printf("doesnt match\n"); + free(current); + } } } @@ -206,6 +216,13 @@ criteria: printf("criteria: class = %s\n", $3); current_match.class = $3; } + | TOK_CON_ID '=' STR + { + printf("criteria: id = %s\n", $3); + /* TODO: correctly parse number */ + current_match.con_id = atoi($3); + printf("id as int = %d\n", current_match.con_id); + } ; operations: @@ -226,9 +243,11 @@ operation: | mode | workspace | move*/ + | workspace | attach | focus | kill + | open ; exec: @@ -265,10 +284,32 @@ kill: owindow *current; printf("killing!\n"); + /* TODO: check if the match is empty, not if the result is empty */ + if (TAILQ_EMPTY(&owindows)) + tree_close(focused); + else { TAILQ_FOREACH(current, &owindows, owindows) { printf("matching: %p / %s\n", current->con, current->con->name); tree_close(current->con); } + } } ; + +workspace: + TOK_WORKSPACE WHITESPACE STR + { + printf("should switch to workspace %s\n", $3); + workspace_show($3); + free($3); + } + ; + +open: + TOK_OPEN + { + printf("opening new container\n"); + tree_open_con(NULL); + } + ; diff --git a/src/ipc.c b/src/ipc.c index 0412bdae..704c0d47 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -114,7 +114,7 @@ IPC_HANDLER(command) { * message_size bytes out of the buffer */ char *command = scalloc(message_size); strncpy(command, (const char*)message, message_size); - parse_command((const char*)command); + parse_cmd((const char*)command); free(command); /* For now, every command gets a positive acknowledge diff --git a/testcases/t/18-openkill.t b/testcases/t/18-openkill.t index e13ca873..935523d4 100644 --- a/testcases/t/18-openkill.t +++ b/testcases/t/18-openkill.t @@ -3,7 +3,8 @@ # # Tests whether opening an empty container and killing it again works # -use Test::More tests => 3; +use Test::More tests => 6; +use Data::Dumper; use FindBin; use lib "$FindBin::Bin/lib"; use i3test; @@ -25,4 +26,25 @@ ok(@{get_ws_content($tmp)} == 1, 'container opened'); $i3->command("kill")->recv; ok(@{get_ws_content($tmp)} == 0, 'container killed'); +############################################################## +# open two containers and kill the one which is not focused +# by its ID to test if the parser correctly matches the window +############################################################## + +$i3->command('open')->recv; +$i3->command('open')->recv; +ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); + +my $content = get_ws_content($tmp); +# TODO: get the focused window, don’t assume that it is +# the latest one +my $id = $content->[0]->{id}; +diag('id of not focused = ' . $id); + +$i3->command("[con_id=\"$id\"] kill")->recv; + +$content = get_ws_content($tmp); +ok(@{$content} == 1, 'one container killed'); +ok($content->[0]->{id} != $id, 'correct window killed'); + diag( "Testing i3, Perl $], $^X" );