Implement mark/goto, modify testcase

This commit is contained in:
Michael Stapelberg 2010-06-02 23:32:05 +02:00
parent 780e773a6a
commit 6897e15e72
6 changed files with 57 additions and 19 deletions

View File

@ -238,6 +238,7 @@ struct Match {
char *application; char *application;
char *class; char *class;
char *instance; char *instance;
char *mark;
xcb_window_t id; xcb_window_t id;
Con *con_id; Con *con_id;
enum { M_ANY = 0, M_TILING, M_FLOATING } floating; enum { M_ANY = 0, M_TILING, M_FLOATING } floating;
@ -268,6 +269,9 @@ struct Con {
char *name; char *name;
/* user-definable mark to jump to this container later */
char *mark;
double percent; double percent;
struct Window *window; struct Window *window;

View File

@ -112,10 +112,12 @@ down { return TOK_DOWN; }
before { return TOK_BEFORE; } before { return TOK_BEFORE; }
after { return TOK_AFTER; } after { return TOK_AFTER; }
restore { BEGIN(WANT_WS_STRING); return TOK_RESTORE; } restore { BEGIN(WANT_WS_STRING); return TOK_RESTORE; }
mark { BEGIN(WANT_WS_STRING); return TOK_MARK; }
class { BEGIN(WANT_QSTRING); return TOK_CLASS; } class { BEGIN(WANT_QSTRING); return TOK_CLASS; }
id { BEGIN(WANT_QSTRING); return TOK_ID; } id { BEGIN(WANT_QSTRING); return TOK_ID; }
con_id { BEGIN(WANT_QSTRING); return TOK_CON_ID; } con_id { BEGIN(WANT_QSTRING); return TOK_CON_ID; }
con_mark { BEGIN(WANT_QSTRING); return TOK_MARK; }
. { return (int)yytext[0]; } . { return (int)yytext[0]; }

View File

@ -124,6 +124,7 @@ void parse_cmd(const char *new) {
%token TOK_AFTER "after" %token TOK_AFTER "after"
%token TOK_BEFORE "before" %token TOK_BEFORE "before"
%token TOK_RESTORE "restore" %token TOK_RESTORE "restore"
%token TOK_MARK "mark"
%token TOK_CLASS "class" %token TOK_CLASS "class"
%token TOK_ID "id" %token TOK_ID "id"
@ -205,6 +206,11 @@ matchend:
TAILQ_INSERT_TAIL(&owindows, current, owindows); TAILQ_INSERT_TAIL(&owindows, current, owindows);
} }
} else if (current_match.mark != NULL && current->con->mark != NULL &&
strcasecmp(current_match.mark, current->con->mark) == 0) {
printf("match by mark\n");
TAILQ_INSERT_TAIL(&owindows, current, owindows);
} else { } else {
if (current->con->window == NULL) if (current->con->window == NULL)
continue; continue;
@ -245,6 +251,11 @@ criteria:
current_match.id = atoi($<string>3); current_match.id = atoi($<string>3);
printf("window id as int = %d\n", current_match.id); printf("window id as int = %d\n", current_match.id);
} }
| TOK_MARK '=' STR
{
printf("criteria: mark = %s\n", $<string>3);
current_match.mark = $<string>3;
}
; ;
operations: operations:
@ -274,6 +285,7 @@ operation:
| split | split
| mode | mode
| level | level
| mark
; ;
exec: exec:
@ -498,3 +510,23 @@ layout_mode:
| TOK_STACKED { $<number>$ = L_STACKED; } | TOK_STACKED { $<number>$ = L_STACKED; }
| TOK_TABBED { $<number>$ = L_TABBED; } | TOK_TABBED { $<number>$ = L_TABBED; }
; ;
mark:
TOK_MARK WHITESPACE STR
{
printf("marking window with str %s\n", $<string>3);
owindow *current;
/* check if the match is empty, not if the result is empty */
if (match_is_empty(&current_match))
focused->mark = sstrdup($<string>3);
else {
TAILQ_FOREACH(current, &owindows, owindows) {
printf("matching: %p / %s\n", current->con, current->con->name);
current->con->mark = sstrdup($<string>3);
}
}
free($<string>3);
}
;

View File

@ -13,6 +13,7 @@ bool match_is_empty(Match *match) {
* TAILQ and I dont want to start with things like assuming that the * TAILQ and I dont want to start with things like assuming that the
* last member of a struct really is at the end in memory */ * last member of a struct really is at the end in memory */
return (match->title == NULL && return (match->title == NULL &&
match->mark == NULL &&
match->application == NULL && match->application == NULL &&
match->class == NULL && match->class == NULL &&
match->instance == NULL && match->instance == NULL &&
@ -33,7 +34,6 @@ bool match_matches_window(Match *match, i3Window *window) {
return true; return true;
} }
if (match->id != XCB_NONE && window->id == match->id) { if (match->id != XCB_NONE && window->id == match->id) {
LOG("match made by window id (%d)\n", window->id); LOG("match made by window id (%d)\n", window->id);
return true; return true;

View File

@ -201,6 +201,7 @@ void tree_close_con() {
void tree_split(Con *con, orientation_t orientation) { void tree_split(Con *con, orientation_t orientation) {
/* for a workspace, we just need to change orientation */ /* for a workspace, we just need to change orientation */
if (con->type == CT_WORKSPACE) { if (con->type == CT_WORKSPACE) {
DLOG("Workspace, simply changing orientation to %d\n", orientation);
con->orientation = orientation; con->orientation = orientation;
return; return;
} }
@ -210,8 +211,12 @@ void tree_split(Con *con, orientation_t orientation) {
* child and has the same orientation like we are trying to * child and has the same orientation like we are trying to
* set, this operation is a no-op to not confuse the user */ * set, this operation is a no-op to not confuse the user */
if (parent->orientation == orientation && if (parent->orientation == orientation &&
TAILQ_NEXT(con, nodes) == TAILQ_END(&(parent->nodes_head))) TAILQ_NEXT(con, nodes) == TAILQ_END(&(parent->nodes_head))) {
DLOG("Not splitting the same way again\n");
return; return;
}
DLOG("Splitting in orientation %d\n", orientation);
/* 2: replace it with a new Con */ /* 2: replace it with a new Con */
Con *new = con_new(NULL); Con *new = con_new(NULL);

View File

@ -1,10 +1,7 @@
#!perl #!perl
# vim:ts=4:sw=4:expandtab # vim:ts=4:sw=4:expandtab
# Beware that this test uses workspace 9 to perform some tests (it expects
# the workspace to be empty).
# TODO: skip it by default?
use i3test tests => 7; use i3test tests => 6;
use X11::XCB qw(:all); use X11::XCB qw(:all);
use Time::HiRes qw(sleep); use Time::HiRes qw(sleep);
use Digest::SHA1 qw(sha1_base64); use Digest::SHA1 qw(sha1_base64);
@ -15,21 +12,22 @@ BEGIN {
my $x = X11::XCB::Connection->new; my $x = X11::XCB::Connection->new;
my $i3 = i3; my $i3 = i3("/tmp/nestedcons");
my $tmp = get_unused_workspace();
$i3->command("workspace $tmp")->recv;
# Switch to the nineth workspace $i3->command('split h')->recv;
$i3->command('9')->recv;
##################################################################### #####################################################################
# Create two windows and make sure focus switching works # Create two windows and make sure focus switching works
##################################################################### #####################################################################
my $top = i3test::open_standard_window($x); my $top = i3test::open_standard_window($x);
sleep(0.25); sleep 0.25;
my $mid = i3test::open_standard_window($x); my $mid = i3test::open_standard_window($x);
sleep(0.25); sleep 0.25;
my $bottom = i3test::open_standard_window($x); my $bottom = i3test::open_standard_window($x);
sleep(0.25); sleep 0.25;
diag("top id = " . $top->id); diag("top id = " . $top->id);
diag("mid id = " . $mid->id); diag("mid id = " . $mid->id);
@ -49,10 +47,7 @@ sub focus_after {
$focus = $x->input_focus; $focus = $x->input_focus;
is($focus, $bottom->id, "Latest window focused"); is($focus, $bottom->id, "Latest window focused");
$focus = focus_after("ml"); $focus = focus_after("prev h");
is($focus, $bottom->id, "Right window still focused");
$focus = focus_after("h");
is($focus, $mid->id, "Middle window focused"); is($focus, $mid->id, "Middle window focused");
##################################################################### #####################################################################
@ -61,14 +56,14 @@ is($focus, $mid->id, "Middle window focused");
my $random_mark = sha1_base64(rand()); my $random_mark = sha1_base64(rand());
$focus = focus_after("goto $random_mark"); $focus = focus_after(qq|[con_mark="$random_mark"] focus|);
is($focus, $mid->id, "focus unchanged"); is($focus, $mid->id, "focus unchanged");
$i3->command("mark $random_mark")->recv; $i3->command("mark $random_mark")->recv;
$focus = focus_after("k"); $focus = focus_after("prev h");
is($focus, $top->id, "Top window focused"); is($focus, $top->id, "Top window focused");
$focus = focus_after("goto $random_mark"); $focus = focus_after(qq|[con_mark="$random_mark"] focus|);
is($focus, $mid->id, "goto worked"); is($focus, $mid->id, "goto worked");