selector: Make :not() selectors not radical
authorBenjamin Otte <otte@redhat.com>
Mon, 27 Jan 2020 01:49:36 +0000 (02:49 +0100)
committerBenjamin Otte <otte@redhat.com>
Tue, 28 Jan 2020 01:17:03 +0000 (02:17 +0100)
:not() selectors cannot be radical because the bloomfilter only knows if
a value is set in any of the nodes, but cannot determine the opposite
(if a value is not set in at least one node), but that would be required
for:not() selectors.
However, this is very unlikely to happen in the real world, so it's not
worth optimizing.

Unfortunately, change tracking could know this, so by excluding the
:not() selectors from radical changes, the change tracking will now pick
them up. If that turns out to be a performance problem, we need to add a
special category for radical not filters, so change tracking and bloom
filters can deal with them.

The testcase demonstrating the problem in widget-factory has been
extrated and added.

gtk/gtkcssselector.c
testsuite/css/change/test4.nodes
testsuite/css/style/bloomfilter-not.css [new file with mode: 0644]
testsuite/css/style/bloomfilter-not.nodes [new file with mode: 0644]
testsuite/css/style/bloomfilter-not.ui [new file with mode: 0644]
testsuite/css/style/meson.build

index bd1edb124070aaa7e0294cd97b7e95955e314166..8f4bbf0113ef5b729d4cdda908a4eefa6337661f 100644 (file)
@@ -540,7 +540,7 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
 \
 static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
   "not_" G_STRINGIFY(n), \
-  ignore_for_change ? GTK_CSS_SELECTOR_CATEGORY_SIMPLE : GTK_CSS_SELECTOR_CATEGORY_SIMPLE_RADICAL, \
+  GTK_CSS_SELECTOR_CATEGORY_SIMPLE, \
   gtk_css_selector_not_ ## n ## _print, \
   gtk_css_selector_default_foreach_matcher, \
   gtk_css_selector_not_ ## n ## _match_one, \
index 2919416d1a8aee9cc07ef03738d86021f211650a..79cf087303c237b47c445f02062aedcbb689215b 100644 (file)
@@ -5,4 +5,4 @@ window.background:dir(ltr)
     label.b:dir(ltr)    class|name|hover|backdrop
     label.c:dir(ltr)    class|name|parent-name|parent-hover
     label.d:dir(ltr)    class|name|parent-name|parent-hover|parent-backdrop
-    label.e.f:dir(ltr)    
+    label.e.f:dir(ltr)    class|name|parent-name|parent-hover|parent-backdrop
diff --git a/testsuite/css/style/bloomfilter-not.css b/testsuite/css/style/bloomfilter-not.css
new file mode 100644 (file)
index 0000000..8ffa713
--- /dev/null
@@ -0,0 +1 @@
+.linked:not(.vertical) > button:dir(ltr):not(:last-child) { color: pink; }
diff --git a/testsuite/css/style/bloomfilter-not.nodes b/testsuite/css/style/bloomfilter-not.nodes
new file mode 100644 (file)
index 0000000..ac98aa8
--- /dev/null
@@ -0,0 +1,20 @@
+window.background.solid-csd:dir(ltr)
+  decoration:dir(ltr)
+  headerbar.titlebar:dir(ltr)
+    box.horizontal.start:dir(ltr)
+    stackswitcher.linked:dir(ltr)
+      button.text-button.toggle:dir(ltr):checked
+        color: rgb(255,192,203); /* bloomfilter-not.css:1:61-73 */
+
+        label:dir(ltr)
+      button.text-button.toggle:dir(ltr)
+        color: rgb(255,192,203); /* bloomfilter-not.css:1:61-73 */
+
+        label:dir(ltr)
+      button.text-button.toggle:dir(ltr)
+        label:dir(ltr)
+    box.end.horizontal:dir(ltr)
+  stack:dir(ltr)
+    box.horizontal:dir(ltr)
+    box.horizontal:dir(ltr)
+    box.horizontal:dir(ltr)
diff --git a/testsuite/css/style/bloomfilter-not.ui b/testsuite/css/style/bloomfilter-not.ui
new file mode 100644 (file)
index 0000000..cdbbfeb
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <object class="GtkApplicationWindow" id="window1">
+    <child type="titlebar">
+      <object class="GtkHeaderBar">
+        <child type="title">
+          <object class="GtkStackSwitcher" id="stack_switcher">
+            <property name="stack">toplevel_stack</property>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkStack" id="toplevel_stack">
+        <property name="transition-duration">1000</property>
+        <child>
+          <object class="GtkStackPage">
+            <property name="title" translatable="yes">Page 1</property>
+            <property name="child">
+              <object class="GtkBox" />
+            </property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStackPage">
+            <property name="title" translatable="yes">Page 2</property>
+            <property name="child">
+              <object class="GtkBox" />
+            </property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStackPage">
+            <property name="title" translatable="yes">Page 3</property>
+            <property name="child">
+              <object class="GtkBox" />
+            </property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
index fa2515f31375e2b048c53b7d98e82cd687323d03..3198b85c055d3bed1bb16299502994fb6b2d08ac 100644 (file)
@@ -30,6 +30,9 @@ test_data = [
   'adjacent-states.css',
   'adjacent-states.nodes',
   'adjacent-states.ui',
+  'bloomfilter-not.css',
+  'bloomfilter-not.nodes',
+  'bloomfilter-not.ui',
   'colornames.css',
   'colornames.nodes',
   'colornames.ui',