]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: multiple criteria should use a logical AND (+test) (Thanks f8l)
authorMichael Stapelberg <michael@stapelberg.de>
Thu, 7 Jul 2011 22:21:29 +0000 (00:21 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Thu, 7 Jul 2011 22:21:29 +0000 (00:21 +0200)
src/match.c
testcases/t/19-match.t

index 2449bad7a7e67f2eb755a91679f01f82d73936c2..3a346117340a9c880d66a70f99fcd91bee242df4 100644 (file)
@@ -69,40 +69,66 @@ void match_copy(Match *dest, Match *src) {
  *
  */
 bool match_matches_window(Match *match, i3Window *window) {
+    LOG("checking window %d (%s)\n", window->id, window->class_class);
+
     /* TODO: pcre, full matching, … */
-    if (match->class != NULL && window->class_class != NULL && strcasecmp(match->class, window->class_class) == 0) {
-        LOG("match made by window class (%s)\n", window->class_class);
-        return true;
+    if (match->class != NULL) {
+        if (window->class_class != NULL && strcasecmp(match->class, window->class_class) == 0) {
+            LOG("window class matches (%s)\n", window->class_class);
+        } else {
+            LOG("window class does not match\n");
+            return false;
+        }
     }
 
-    if (match->instance != NULL && window->class_instance != NULL && strcasecmp(match->instance, window->class_instance) == 0) {
-        LOG("match made by window instance (%s)\n", window->class_instance);
-        return true;
+    if (match->instance != NULL) {
+        if (window->class_instance != NULL && strcasecmp(match->instance, window->class_instance) == 0) {
+            LOG("window instance matches (%s)\n", window->class_instance);
+        } else {
+            LOG("window instance does not match\n");
+            return false;
+        }
     }
 
-    if (match->id != XCB_NONE && window->id == match->id) {
-        LOG("match made by window id (%d)\n", window->id);
-        return true;
+    if (match->id != XCB_NONE) {
+        if (window->id == match->id) {
+            LOG("match made by window id (%d)\n", window->id);
+        } else {
+            LOG("window id does not match\n");
+            return false;
+        }
     }
 
     /* TODO: pcre match */
-    if (match->title != NULL && window->name_json != NULL && strcasecmp(match->title, window->name_json) == 0) {
-        LOG("match made by title (%s)\n", window->name_json);
-        return true;
+    if (match->title != NULL) {
+        if (window->name_json != NULL && strcasecmp(match->title, window->name_json) == 0) {
+            LOG("title matches (%s)\n", window->name_json);
+        } else {
+            LOG("title does not match\n");
+            return false;
+        }
     }
 
-    LOG("match->dock = %d, window->dock = %d\n", match->dock, window->dock);
-    if (match->dock != -1 &&
-        ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
+    if (match->dock != -1) {
+        LOG("match->dock = %d, window->dock = %d\n", match->dock, window->dock);
+        if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
          (window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) ||
          ((window->dock == W_DOCK_TOP || window->dock == W_DOCK_BOTTOM) &&
           match->dock == M_DOCK_ANY) ||
-         (window->dock == W_NODOCK && match->dock == M_NODOCK))) {
-        LOG("match made by dock\n");
-        return true;
+         (window->dock == W_NODOCK && match->dock == M_NODOCK)) {
+            LOG("dock status matches\n");
+        } else {
+            LOG("dock status does not match\n");
+            return false;
+        }
     }
 
-    LOG("window %d (%s) could not be matched\n", window->id, window->class_class);
+    /* We don’t check the mark because this function is not even called when
+     * the mark would have matched - it is checked in cmdparse.y itself */
+    if (match->mark != NULL) {
+        LOG("mark does not match\n");
+        return false;
+    }
 
-    return false;
+    return true;
 }
index 7efdd95cc4e10d2df4cbf3d2dd61ed7e57b08e4d..15f18891cbc5a6f96863b134d12d03931d5d5189 100644 (file)
@@ -56,4 +56,64 @@ ok(@{$content} == 0, 'window killed');
 
 # TODO: same test, but with pcre expressions
 
+######################################################################
+# check that multiple criteria work are checked with a logical AND,
+# not a logical OR (that is, matching is not cancelled after the first
+# criterion matches).
+######################################################################
+
+$tmp = fresh_workspace;
+
+# TODO: move to X11::XCB
+sub set_wm_class {
+    my ($id, $class, $instance) = @_;
+
+    # Add a _NET_WM_STRUT_PARTIAL hint
+    my $atomname = $x->atom(name => 'WM_CLASS');
+    my $atomtype = $x->atom(name => 'STRING');
+
+    $x->change_property(
+        PROP_MODE_REPLACE,
+        $id,
+        $atomname->id,
+        $atomtype->id,
+        8,
+        length($class) + length($instance) + 2,
+        "$instance\x00$class\x00"
+    );
+}
+
+my $left = $x->root->create_child(
+    class => WINDOW_CLASS_INPUT_OUTPUT,
+    rect => [ 0, 0, 30, 30 ],
+    background_color => '#0000ff',
+);
+
+$left->_create;
+set_wm_class($left->id, 'special', 'special');
+$left->name('left');
+$left->map;
+sleep 0.25;
+
+my $right = $x->root->create_child(
+    class => WINDOW_CLASS_INPUT_OUTPUT,
+    rect => [ 0, 0, 30, 30 ],
+    background_color => '#0000ff',
+);
+
+$right->_create;
+set_wm_class($right->id, 'special', 'special');
+$right->name('right');
+$right->map;
+sleep 0.25;
+
+# two windows should be here
+$content = get_ws_content($tmp);
+ok(@{$content} == 2, 'two windows opened');
+
+cmd '[class="special" title="left"] kill';
+
+$content = get_ws_content($tmp);
+is(@{$content}, 1, 'one window still there');
+
 done_testing;