4 test_parse_empty (void)
6 GtkCssProvider *provider;
10 provider = gtk_css_provider_new ();
12 res = gtk_css_provider_load_from_data (provider, "", -1, &error);
15 g_assert_no_error (error);
16 g_clear_error (&error);
18 g_object_unref (provider);
24 GtkCssProvider *provider;
28 const gchar *valid[] = {
29 "@import \"" SRCDIR "/test.css\";",
30 "@import '" SRCDIR "/test.css';",
31 "@import url(\"" SRCDIR "/test.css\");",
32 "@import url('" SRCDIR "/test.css');",
33 "@import\nurl (\t\"" SRCDIR "/test.css\" ) ;",
34 "@define-color bg_color #f9a039;",
35 "@define-color color @bg_color;",
36 "@define-color color rgb(100, 99, 88);",
37 "@define-color color rgba(50%, 50%, 50%, 0.5);",
38 "@define-color color lighter(#f9a039);",
39 "@define-color color darker ( @blue ) ;",
40 "@define-color color shade(@blue, 1.3);",
41 "@define-color color alpha(@blue, 1.3);",
42 "@define-color color mix(@blue, @red, 0.2);",
43 "@define-color color red;",
44 "@define-color color mix(shade (#121212, 0.5), mix (rgb(10%,20%,100%), @blue,0.5), 0.2);",
45 "@define-color blue @blue;",
46 "@define-color blue123_a-b #123;",
50 const gchar *invalid[] = {
51 "@import " SRCDIR "/test.css ;",
52 "@import url ( \"" SRCDIR "/test.css\" xyz );",
55 "@import url(\"abc');",
57 "@define_color blue red;",
58 "@define-color blue #12234;",
59 "@define-color blue #12g234;",
60 "@define-color blue @@;",
61 "@define-color blue 5!#%4@DG$##x;",
62 "@define-color color mix(@red, @blue, @green);",
63 "@define-color color mix(@blue, 0.2, @red);",
64 "@define-color color mix(0.2, @blue, @red);",
65 "@define-color color mix(@blue, @red);",
66 "@define-color color mix(@blue);",
67 "@define-color color mix();",
68 "@define-color color rgba(50%, 50%, 50%);",
69 "@define-color color rgb(50%, a);",
70 "@define-color 1col rgb(50%, a);",
71 "@three-dee { some other crap };",
76 for (i = 0; valid[i]; i++)
78 provider = gtk_css_provider_new ();
79 res = gtk_css_provider_load_from_data (provider, valid[i], -1, &error);
81 g_print ("parsing '%s': got unexpected error: %s\n", valid[i], error->message);
82 g_assert_no_error (error);
85 g_object_unref (provider);
88 for (i = 0; invalid[i]; i++)
90 provider = gtk_css_provider_new ();
91 res = gtk_css_provider_load_from_data (provider, invalid[i], -1, &error);
92 g_assert_error (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_FAILED);
94 g_object_unref (provider);
95 g_clear_error (&error);
100 test_parse_selectors (void)
102 GtkCssProvider *provider;
106 const gchar *valid[] = {
113 "tab:first-child {}",
115 "tab:nth-child(first) {}",
116 "tab:nth-child(last) {}",
117 "tab:nth-child(even) {}",
118 "tab:nth-child(odd) {}",
121 ".some-class.another-class {}",
122 ".some-class .another-class {}",
134 "E:active:prelight {}",
135 "* > .notebook tab:first-child .label:focused {}",
137 "E, F /* comment here */ {}",
138 "E,/* comment here */ F {}",
143 const gchar *invalid[] = {
144 /* nth-child and similar pseudo classes can only
145 * be used with regions, not with types
149 "E:nth-child(first) {}",
150 "E:nth-child(last) {}",
151 "E:nth-child(even) {}",
152 "E:nth-child(odd) {}",
154 /* widget state pseudo-classes can only be used for
162 for (i = 0; valid[i]; i++)
164 provider = gtk_css_provider_new ();
165 res = gtk_css_provider_load_from_data (provider, valid[i], -1, &error);
166 g_assert_no_error (error);
169 g_object_unref (provider);
172 for (i = 0; invalid[i]; i++)
174 provider = gtk_css_provider_new ();
175 res = gtk_css_provider_load_from_data (provider, invalid[i], -1, &error);
176 g_assert_error (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_FAILED);
178 g_object_unref (provider);
179 g_clear_error (&error);
184 test_parse_declarations (void)
186 GtkCssProvider *provider;
190 const gchar *valid[] = {
192 "* { font: Sans 15 }",
193 "* { font: Sans 15; }",
196 "* { /* just a comment */ }",
197 "* { /* multi\nline\ncomment */ }",
198 "* { font: /* comment here */ Sans 15 }",
199 "* { color: red; background-color: shade (@bg_color, 0.5) }",
201 "* { margin: 5 10 }",
202 "* { margin: 5 10 3 }",
203 "* { margin: 5 10 3 5 }",
205 "* { padding: 5 10 }",
206 "* { border-width: 5; border-radius: 10 }",
207 "* { border-color: #ff00ff }",
208 "* { engine: clearlooks }",
209 "* { background-image: -gtk-gradient (linear, \n"
210 " left top, right top, \n"
211 " from (#fff), to (#000)) }",
212 "* { background-image: -gtk-gradient (linear, \n"
213 " 0.0 0.5, 0.5 1.0, \n"
215 " color-stop (0.5, #f00),\n"
217 "* { background-image: -gtk-gradient (radial, \n"
218 " center center, 0.2, \n"
219 " center center, 0.8, \n"
220 " color-stop (0.0,#fff),\n"
221 " color-stop (1.0,#000))}\n",
222 "* { border-image: url (\"" SRCDIR "/test.png\") 3 4 3 4 stretch }",
223 "* { border-image: url (\"" SRCDIR "/test.png\") 3 4 3 4 repeat stretch}",
224 "* { transition: 150ms ease-in-out }",
225 "* { transition: 1s linear loop }",
229 const gchar *invalid[] = {
231 "* { color:green; color }",
232 "* { color:red; color; color:green }",
233 "* { color:green; color: }",
234 "* { color:red; color:; color:green }",
235 "* { color:green; color{;color:maroon} }",
236 "* { color:red; color{;color:maroon}; color:green }",
237 "* { content: 'Hello",
242 for (i = 0; valid[i]; i++)
244 provider = gtk_css_provider_new ();
245 res = gtk_css_provider_load_from_data (provider, valid[i], -1, &error);
246 g_assert_no_error (error);
249 g_object_unref (provider);
252 for (i = 0; invalid[i]; i++)
254 provider = gtk_css_provider_new ();
255 res = gtk_css_provider_load_from_data (provider, invalid[i], -1, &error);
256 g_assert_error (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_FAILED);
258 g_object_unref (provider);
259 g_clear_error (&error);
267 GtkWidgetPath *path2;
269 GtkRegionFlags flags;
271 path = gtk_widget_path_new ();
272 g_assert_cmpint (gtk_widget_path_length (path), ==, 0);
274 pos = gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
275 g_assert_cmpint (pos, ==, 0);
276 g_assert_cmpint (gtk_widget_path_length (path), ==, 1);
277 g_assert (gtk_widget_path_iter_get_widget_type (path, 0) == GTK_TYPE_WINDOW);
278 g_assert (gtk_widget_path_is_type (path, GTK_TYPE_WIDGET));
279 g_assert (gtk_widget_path_iter_get_name (path, 0) == NULL);
281 pos = gtk_widget_path_append_type (path, GTK_TYPE_WIDGET);
282 g_assert_cmpint (pos, ==, 1);
283 g_assert_cmpint (gtk_widget_path_length (path), ==, 2);
284 gtk_widget_path_iter_set_widget_type (path, pos, GTK_TYPE_BUTTON);
285 g_assert (gtk_widget_path_is_type (path, GTK_TYPE_BUTTON));
286 g_assert (gtk_widget_path_has_parent (path, GTK_TYPE_WIDGET));
287 g_assert (gtk_widget_path_has_parent (path, GTK_TYPE_WINDOW));
288 g_assert (!gtk_widget_path_has_parent (path, GTK_TYPE_DIALOG));
289 g_assert (gtk_widget_path_iter_get_name (path, 1) == NULL);
291 gtk_widget_path_iter_set_name (path, 1, "name");
292 g_assert (gtk_widget_path_iter_has_name (path, 1, "name"));
294 gtk_widget_path_iter_add_class (path, 1, "class1");
295 gtk_widget_path_iter_add_class (path, 1, "class2");
296 g_assert (gtk_widget_path_iter_has_class (path, 1, "class1"));
297 g_assert (gtk_widget_path_iter_has_class (path, 1, "class2"));
298 g_assert (!gtk_widget_path_iter_has_class (path, 1, "class3"));
300 path2 = gtk_widget_path_copy (path);
301 g_assert (gtk_widget_path_iter_has_class (path2, 1, "class1"));
302 g_assert (gtk_widget_path_iter_has_class (path2, 1, "class2"));
303 g_assert (!gtk_widget_path_iter_has_class (path2, 1, "class3"));
304 gtk_widget_path_free (path2);
306 gtk_widget_path_iter_remove_class (path, 1, "class2");
307 g_assert (gtk_widget_path_iter_has_class (path, 1, "class1"));
308 g_assert (!gtk_widget_path_iter_has_class (path, 1, "class2"));
309 gtk_widget_path_iter_clear_classes (path, 1);
310 g_assert (!gtk_widget_path_iter_has_class (path, 1, "class1"));
312 gtk_widget_path_iter_add_region (path, 1, "tab", 0);
313 gtk_widget_path_iter_add_region (path, 1, "title", GTK_REGION_EVEN | GTK_REGION_FIRST);
315 g_assert (gtk_widget_path_iter_has_region (path, 1, "tab", &flags) &&
317 g_assert (gtk_widget_path_iter_has_region (path, 1, "title", &flags) &&
318 flags == (GTK_REGION_EVEN | GTK_REGION_FIRST));
319 g_assert (!gtk_widget_path_iter_has_region (path, 1, "extension", NULL));
321 path2 = gtk_widget_path_copy (path);
322 g_assert (gtk_widget_path_iter_has_region (path2, 1, "tab", &flags) &&
324 g_assert (gtk_widget_path_iter_has_region (path2, 1, "title", &flags) &&
325 flags == (GTK_REGION_EVEN | GTK_REGION_FIRST));
326 g_assert (!gtk_widget_path_iter_has_region (path2, 1, "extension", NULL));
327 gtk_widget_path_free (path2);
329 gtk_widget_path_free (path);
335 GtkStyleContext *context;
337 GtkCssProvider *provider;
344 provider = gtk_css_provider_new ();
346 gdk_rgba_parse (&expected, "#fff");
348 context = gtk_style_context_new ();
350 path = gtk_widget_path_new ();
351 gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
352 gtk_widget_path_append_type (path, GTK_TYPE_BOX);
353 gtk_widget_path_append_type (path, GTK_TYPE_BUTTON);
354 gtk_widget_path_iter_set_name (path, 0, "mywindow");
355 gtk_widget_path_iter_add_class (path, 2, "button");
356 gtk_style_context_set_path (context, path);
357 gtk_widget_path_free (path);
359 gtk_style_context_add_provider (context,
360 GTK_STYLE_PROVIDER (provider),
361 GTK_STYLE_PROVIDER_PRIORITY_USER);
363 data = "* { color: #fff }";
364 gtk_css_provider_load_from_data (provider, data, -1, &error);
365 g_assert_no_error (error);
366 gtk_style_context_invalidate (context);
367 gtk_style_context_get (context, 0, "color", &color, NULL);
368 g_assert (gdk_rgba_equal (color, &expected));
369 gdk_rgba_free (color);
371 data = "* { color: #f00 }\n"
372 "GtkButton { color: #fff }";
373 gtk_css_provider_load_from_data (provider, data, -1, &error);
374 g_assert_no_error (error);
375 gtk_style_context_invalidate (context);
376 gtk_style_context_get (context, 0, "color", &color, NULL);
377 g_assert (gdk_rgba_equal (color, &expected));
378 gdk_rgba_free (color);
380 data = "* { color: #f00 }\n"
381 "GtkButton { color: #fff }\n"
382 "GtkWindow > GtkButton { color: #000 }";
383 gtk_css_provider_load_from_data (provider, data, -1, &error);
384 g_assert_no_error (error);
385 gtk_style_context_invalidate (context);
386 gtk_style_context_get (context, 0, "color", &color, NULL);
387 g_assert (gdk_rgba_equal (color, &expected));
388 gdk_rgba_free (color);
390 data = "* { color: #f00 }\n"
391 ".button { color: #fff }";
392 gtk_css_provider_load_from_data (provider, data, -1, &error);
393 g_assert_no_error (error);
394 gtk_style_context_invalidate (context);
395 gtk_style_context_get (context, 0, "color", &color, NULL);
396 g_assert (gdk_rgba_equal (color, &expected));
397 gdk_rgba_free (color);
399 data = "* { color: #f00 }\n"
400 "GtkButton { color: #000 }\n"
401 ".button { color: #fff }";
402 gtk_css_provider_load_from_data (provider, data, -1, &error);
403 g_assert_no_error (error);
404 gtk_style_context_invalidate (context);
405 gtk_style_context_get (context, 0, "color", &color, NULL);
406 g_assert (gdk_rgba_equal (color, &expected));
407 gdk_rgba_free (color);
409 data = "* { color: #f00 }\n"
410 "GtkButton { color: #000 }\n"
411 "GtkWindow GtkButton { color: #fff }";
412 gtk_css_provider_load_from_data (provider, data, -1, &error);
413 g_assert_no_error (error);
414 gtk_style_context_invalidate (context);
415 gtk_style_context_get (context, 0, "color", &color, NULL);
416 g_assert (gdk_rgba_equal (color, &expected));
417 gdk_rgba_free (color);
419 data = "* { color: #f00 }\n"
420 ".button { color: #000 }\n"
421 "GtkWindow .button { color: #fff }";
422 gtk_css_provider_load_from_data (provider, data, -1, &error);
423 g_assert_no_error (error);
424 gtk_style_context_invalidate (context);
425 gtk_style_context_get (context, 0, "color", &color, NULL);
426 g_assert (gdk_rgba_equal (color, &expected));
427 gdk_rgba_free (color);
429 data = "* { color: #f00 }\n"
430 "* .button { color: #000 }\n"
431 "#mywindow .button { color: #fff }";
432 gtk_css_provider_load_from_data (provider, data, -1, &error);
433 g_assert_no_error (error);
434 gtk_style_context_invalidate (context);
435 gtk_style_context_get (context, 0, "color", &color, NULL);
436 g_assert (gdk_rgba_equal (color, &expected));
437 gdk_rgba_free (color);
439 data = "* { color: #f00 }\n"
440 "GtkWindow .button { color: #000 }\n"
441 "GtkWindow#mywindow .button { color: #fff }";
442 gtk_css_provider_load_from_data (provider, data, -1, &error);
443 g_assert_no_error (error);
444 gtk_style_context_invalidate (context);
445 gtk_style_context_get (context, 0, "color", &color, NULL);
446 g_assert (gdk_rgba_equal (color, &expected));
447 gdk_rgba_free (color);
449 data = "* { color: #f00 }\n"
450 "GtkWindow .button { color: #fff }\n"
451 "GObject .button { color: #000 }";
452 gtk_css_provider_load_from_data (provider, data, -1, &error);
453 g_assert_no_error (error);
454 gtk_style_context_invalidate (context);
455 gtk_style_context_get (context, 0, "color", &color, NULL);
456 g_assert (gdk_rgba_equal (color, &expected));
457 gdk_rgba_free (color);
459 g_object_unref (provider);
460 g_object_unref (context);
464 test_style_property (void)
466 GtkStyleContext *context;
468 GtkCssProvider *provider;
476 provider = gtk_css_provider_new ();
478 context = gtk_style_context_new ();
480 path = gtk_widget_path_new ();
481 gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
482 gtk_widget_path_append_type (path, GTK_TYPE_BOX);
483 gtk_widget_path_append_type (path, GTK_TYPE_BUTTON);
484 gtk_style_context_set_path (context, path);
485 gtk_widget_path_free (path);
486 gtk_style_context_set_state (context, GTK_STATE_FLAG_PRELIGHT);
488 /* Since we set the prelight state on the context, we expect
489 * only the third selector to match, even though the second one
490 * has higher specificity, and the fourth one comes later.
492 * In particular, we want to verify that widget style properties and
493 * CSS properties follow the same matching rules, ie we expect
494 * color to be #003 and child-displacement-x to be 3.
496 data = "GtkButton:insensitive { color: #001; -GtkButton-child-displacement-x: 1 }\n"
497 "GtkBox GtkButton:selected { color: #002; -GtkButton-child-displacement-x: 2 }\n"
498 "GtkButton:prelight { color: #003; -GtkButton-child-displacement-x: 3 }\n"
499 "GtkButton:focused { color: #004; -GtkButton-child-displacement-x: 4 }\n";
500 gtk_css_provider_load_from_data (provider, data, -1, &error);
501 g_assert_no_error (error);
502 gtk_style_context_add_provider (context,
503 GTK_STYLE_PROVIDER (provider),
504 GTK_STYLE_PROVIDER_PRIORITY_USER);
506 gtk_style_context_invalidate (context);
508 gtk_style_context_get (context, GTK_STATE_FLAG_PRELIGHT, "color", &color, NULL);
509 gdk_rgba_parse (&expected, "#003");
510 g_assert (gdk_rgba_equal (color, &expected));
511 gdk_rgba_free (color);
513 gtk_style_context_get_style (context, "child-displacement-x", &x, NULL);
515 g_assert_cmpint (x, ==, 3);
517 g_object_unref (provider);
518 g_object_unref (context);
522 main (int argc, char *argv[])
524 gtk_init (NULL, NULL);
525 g_test_init (&argc, &argv, NULL);
527 g_test_add_func ("/style/parse/empty", test_parse_empty);
528 g_test_add_func ("/style/parse/at", test_parse_at);
529 g_test_add_func ("/style/parse/selectors", test_parse_selectors);
530 g_test_add_func ("/style/parse/declarations", test_parse_declarations);
531 g_test_add_func ("/style/path", test_path);
532 g_test_add_func ("/style/match", test_match);
533 g_test_add_func ("/style/style-property", test_style_property);
535 return g_test_run ();