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);
22 test_parse_selectors (void)
24 GtkCssProvider *provider;
28 const gchar *valid[] = {
37 "tab:nth-child(first) {}",
38 "tab:nth-child(last) {}",
39 "tab:nth-child(even) {}",
40 "tab:nth-child(odd) {}",
43 ".some-class.another-class {}",
44 ".some-class .another-class {}",
56 "E:active:prelight {}",
57 "* > .notebook tab:first-child .label:focused {}",
59 "E, F /* comment here */ {}",
60 "E,/* comment here */ F {}",
65 const gchar *invalid[] = {
66 /* nth-child and similar pseudo classes can only
67 * be used with regions, not with types
71 "E:nth-child(first) {}",
72 "E:nth-child(last) {}",
73 "E:nth-child(even) {}",
74 "E:nth-child(odd) {}",
76 /* widget state pseudo-classes can only be used for
84 for (i = 0; valid[i]; i++)
86 provider = gtk_css_provider_new ();
87 res = gtk_css_provider_load_from_data (provider, valid[i], -1, &error);
89 g_print ("parsing '%s': got unexpected error: %s\n", valid[i], error->message);
90 g_assert_no_error (error);
93 g_object_unref (provider);
96 for (i = 0; invalid[i]; i++)
98 provider = gtk_css_provider_new ();
99 res = gtk_css_provider_load_from_data (provider, invalid[i], -1, &error);
100 g_assert_error (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_FAILED);
102 g_object_unref (provider);
103 g_clear_error (&error);
108 test_parse_declarations (void)
110 GtkCssProvider *provider;
114 const gchar *valid[] = {
116 "* { font: Sans 15 }",
117 "* { font: Sans 15; }",
120 "* { /* just a comment */ }",
121 "* { /* multi\nline\ncomment */ }",
122 "* { font: /* comment here */ Sans 15 }",
123 "* { color: red; background-color: shade (@bg_color, 0.5) }",
125 "* { margin: 5 10 }",
126 "* { margin: 5 10 3 }",
127 "* { margin: 5 10 3 5 }",
129 "* { padding: 5 10 }",
130 "* { border-width: 5; border-radius: 10 }",
131 "* { border-color: #ff00ff }",
132 "* { engine: clearlooks }",
133 "* { background-image: -gtk-gradient (linear, \n"
134 " left top, right top, \n"
135 " from (#fff), to (#000)) }",
136 "* { background-image: -gtk-gradient (linear, \n"
137 " 0.0 0.5, 0.5 1.0, \n"
139 " color-stop (0.5, #f00),\n"
141 "* { background-image: -gtk-gradient (radial, \n"
142 " center center, 0.2, \n"
143 " center center, 0.8, \n"
144 " color-stop (0.0,#fff),\n"
145 " color-stop (1.0,#000))}\n",
146 "* { border-image: url (\"" SRCDIR "/test.png\") 3 4 3 4 stretch }",
147 "* { border-image: url (\"" SRCDIR "/test.png\") 3 4 3 4 repeat stretch}",
148 "* { transition: 150ms ease-in-out }",
149 "* { transition: 1s linear loop }",
153 const gchar *invalid[] = {
155 "* { color:green; color }",
156 "* { color:red; color; color:green }",
157 "* { color:green; color: }",
158 "* { color:red; color:; color:green }",
159 "* { color:green; color{;color:maroon} }",
160 "* { color:red; color{;color:maroon}; color:green }",
161 "* { content: 'Hello",
166 for (i = 0; valid[i]; i++)
168 provider = gtk_css_provider_new ();
169 res = gtk_css_provider_load_from_data (provider, valid[i], -1, &error);
171 g_print ("parsing '%s': got unexpected error: %s\n", valid[i], error->message);
172 g_assert_no_error (error);
175 g_object_unref (provider);
178 for (i = 0; invalid[i]; i++)
180 provider = gtk_css_provider_new ();
181 res = gtk_css_provider_load_from_data (provider, invalid[i], -1, &error);
182 g_assert_error (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_FAILED);
184 g_object_unref (provider);
185 g_clear_error (&error);
193 GtkWidgetPath *path2;
195 GtkRegionFlags flags;
197 path = gtk_widget_path_new ();
198 g_assert_cmpint (gtk_widget_path_length (path), ==, 0);
200 pos = gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
201 g_assert_cmpint (pos, ==, 0);
202 g_assert_cmpint (gtk_widget_path_length (path), ==, 1);
203 g_assert (gtk_widget_path_iter_get_object_type (path, 0) == GTK_TYPE_WINDOW);
204 g_assert (gtk_widget_path_is_type (path, GTK_TYPE_WIDGET));
205 g_assert (gtk_widget_path_iter_get_name (path, 0) == NULL);
207 pos = gtk_widget_path_append_type (path, GTK_TYPE_WIDGET);
208 g_assert_cmpint (pos, ==, 1);
209 g_assert_cmpint (gtk_widget_path_length (path), ==, 2);
210 gtk_widget_path_iter_set_object_type (path, pos, GTK_TYPE_BUTTON);
211 g_assert (gtk_widget_path_is_type (path, GTK_TYPE_BUTTON));
212 g_assert (gtk_widget_path_has_parent (path, GTK_TYPE_WIDGET));
213 g_assert (gtk_widget_path_has_parent (path, GTK_TYPE_WINDOW));
214 g_assert (!gtk_widget_path_has_parent (path, GTK_TYPE_DIALOG));
215 g_assert (gtk_widget_path_iter_get_name (path, 1) == NULL);
217 gtk_widget_path_iter_set_name (path, 1, "name");
218 g_assert (gtk_widget_path_iter_has_name (path, 1, "name"));
220 gtk_widget_path_iter_add_class (path, 1, "class1");
221 gtk_widget_path_iter_add_class (path, 1, "class2");
222 g_assert (gtk_widget_path_iter_has_class (path, 1, "class1"));
223 g_assert (gtk_widget_path_iter_has_class (path, 1, "class2"));
224 g_assert (!gtk_widget_path_iter_has_class (path, 1, "class3"));
226 path2 = gtk_widget_path_copy (path);
227 g_assert (gtk_widget_path_iter_has_class (path2, 1, "class1"));
228 g_assert (gtk_widget_path_iter_has_class (path2, 1, "class2"));
229 g_assert (!gtk_widget_path_iter_has_class (path2, 1, "class3"));
230 gtk_widget_path_free (path2);
232 gtk_widget_path_iter_remove_class (path, 1, "class2");
233 g_assert (gtk_widget_path_iter_has_class (path, 1, "class1"));
234 g_assert (!gtk_widget_path_iter_has_class (path, 1, "class2"));
235 gtk_widget_path_iter_clear_classes (path, 1);
236 g_assert (!gtk_widget_path_iter_has_class (path, 1, "class1"));
238 gtk_widget_path_iter_add_region (path, 1, "tab", 0);
239 gtk_widget_path_iter_add_region (path, 1, "title", GTK_REGION_EVEN | GTK_REGION_FIRST);
241 g_assert (gtk_widget_path_iter_has_region (path, 1, "tab", &flags) &&
243 g_assert (gtk_widget_path_iter_has_region (path, 1, "title", &flags) &&
244 flags == (GTK_REGION_EVEN | GTK_REGION_FIRST));
245 g_assert (!gtk_widget_path_iter_has_region (path, 1, "extension", NULL));
247 path2 = gtk_widget_path_copy (path);
248 g_assert (gtk_widget_path_iter_has_region (path2, 1, "tab", &flags) &&
250 g_assert (gtk_widget_path_iter_has_region (path2, 1, "title", &flags) &&
251 flags == (GTK_REGION_EVEN | GTK_REGION_FIRST));
252 g_assert (!gtk_widget_path_iter_has_region (path2, 1, "extension", NULL));
253 gtk_widget_path_free (path2);
255 gtk_widget_path_free (path);
261 GtkStyleContext *context;
263 GtkCssProvider *provider;
270 provider = gtk_css_provider_new ();
272 gdk_rgba_parse (&expected, "#fff");
274 context = gtk_style_context_new ();
276 path = gtk_widget_path_new ();
277 gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
278 gtk_widget_path_append_type (path, GTK_TYPE_BOX);
279 gtk_widget_path_append_type (path, GTK_TYPE_BUTTON);
280 gtk_widget_path_iter_set_name (path, 0, "mywindow");
281 gtk_widget_path_iter_add_class (path, 2, "button");
282 gtk_style_context_set_path (context, path);
283 gtk_widget_path_free (path);
285 gtk_style_context_add_provider (context,
286 GTK_STYLE_PROVIDER (provider),
287 GTK_STYLE_PROVIDER_PRIORITY_USER);
289 data = "* { color: #fff }";
290 gtk_css_provider_load_from_data (provider, data, -1, &error);
291 g_assert_no_error (error);
292 gtk_style_context_invalidate (context);
293 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
294 g_assert (gdk_rgba_equal (&color, &expected));
296 data = "* { color: #f00 }\n"
297 "GtkButton { color: #fff }";
298 gtk_css_provider_load_from_data (provider, data, -1, &error);
299 g_assert_no_error (error);
300 gtk_style_context_invalidate (context);
301 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
302 g_assert (gdk_rgba_equal (&color, &expected));
304 data = "* { color: #f00 }\n"
305 "GtkButton { color: #fff }\n"
306 "GtkWindow > GtkButton { color: #000 }";
307 gtk_css_provider_load_from_data (provider, data, -1, &error);
308 g_assert_no_error (error);
309 gtk_style_context_invalidate (context);
310 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
311 g_assert (gdk_rgba_equal (&color, &expected));
313 data = "* { color: #f00 }\n"
314 ".button { color: #fff }";
315 gtk_css_provider_load_from_data (provider, data, -1, &error);
316 g_assert_no_error (error);
317 gtk_style_context_invalidate (context);
318 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
319 g_assert (gdk_rgba_equal (&color, &expected));
321 data = "* { color: #f00 }\n"
322 "GtkButton { color: #000 }\n"
323 ".button { color: #fff }";
324 gtk_css_provider_load_from_data (provider, data, -1, &error);
325 g_assert_no_error (error);
326 gtk_style_context_invalidate (context);
327 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
328 g_assert (gdk_rgba_equal (&color, &expected));
330 data = "* { color: #f00 }\n"
331 "GtkButton { color: #000 }\n"
332 "GtkWindow GtkButton { color: #fff }";
333 gtk_css_provider_load_from_data (provider, data, -1, &error);
334 g_assert_no_error (error);
335 gtk_style_context_invalidate (context);
336 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
337 g_assert (gdk_rgba_equal (&color, &expected));
339 data = "* { color: #f00 }\n"
340 ".button { color: #000 }\n"
341 "GtkWindow .button { color: #fff }";
342 gtk_css_provider_load_from_data (provider, data, -1, &error);
343 g_assert_no_error (error);
344 gtk_style_context_invalidate (context);
345 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
346 g_assert (gdk_rgba_equal (&color, &expected));
348 data = "* { color: #f00 }\n"
349 "* .button { color: #000 }\n"
350 "#mywindow .button { color: #fff }";
351 gtk_css_provider_load_from_data (provider, data, -1, &error);
352 g_assert_no_error (error);
353 gtk_style_context_invalidate (context);
354 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
355 g_assert (gdk_rgba_equal (&color, &expected));
357 data = "* { color: #f00 }\n"
358 "GtkWindow .button { color: #000 }\n"
359 "GtkWindow#mywindow .button { color: #fff }";
360 gtk_css_provider_load_from_data (provider, data, -1, &error);
361 g_assert_no_error (error);
362 gtk_style_context_invalidate (context);
363 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
364 g_assert (gdk_rgba_equal (&color, &expected));
366 data = "* { color: #f00 }\n"
367 "GtkWindow .button { color: #fff }\n"
368 "GObject .button { color: #000 }";
369 gtk_css_provider_load_from_data (provider, data, -1, &error);
370 g_assert_no_error (error);
371 gtk_style_context_invalidate (context);
372 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
373 g_assert (gdk_rgba_equal (&color, &expected));
375 g_object_unref (provider);
376 g_object_unref (context);
380 test_style_property (void)
382 GtkStyleContext *context;
384 GtkCssProvider *provider;
392 provider = gtk_css_provider_new ();
394 context = gtk_style_context_new ();
396 path = gtk_widget_path_new ();
397 gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
398 gtk_widget_path_append_type (path, GTK_TYPE_BOX);
399 gtk_widget_path_append_type (path, GTK_TYPE_BUTTON);
400 gtk_style_context_set_path (context, path);
401 gtk_widget_path_free (path);
402 gtk_style_context_set_state (context, GTK_STATE_FLAG_PRELIGHT);
404 /* Since we set the prelight state on the context, we expect
405 * only the third selector to match, even though the second one
406 * has higher specificity, and the fourth one comes later.
408 * In particular, we want to verify that widget style properties and
409 * CSS properties follow the same matching rules, ie we expect
410 * color to be #003 and child-displacement-x to be 3.
412 data = "GtkButton:insensitive { color: #001; -GtkButton-child-displacement-x: 1 }\n"
413 "GtkBox GtkButton:selected { color: #002; -GtkButton-child-displacement-x: 2 }\n"
414 "GtkButton:prelight { color: #003; -GtkButton-child-displacement-x: 3 }\n"
415 "GtkButton:focused { color: #004; -GtkButton-child-displacement-x: 4 }\n";
416 gtk_css_provider_load_from_data (provider, data, -1, &error);
417 g_assert_no_error (error);
418 gtk_style_context_add_provider (context,
419 GTK_STYLE_PROVIDER (provider),
420 GTK_STYLE_PROVIDER_PRIORITY_USER);
422 gtk_style_context_invalidate (context);
424 gtk_style_context_get_color (context, GTK_STATE_FLAG_PRELIGHT, &color);
425 gdk_rgba_parse (&expected, "#003");
426 g_assert (gdk_rgba_equal (&color, &expected));
428 gtk_style_context_get_style (context, "child-displacement-x", &x, NULL);
430 g_assert_cmpint (x, ==, 3);
432 g_object_unref (provider);
433 g_object_unref (context);
437 test_basic_properties (void)
439 GtkStyleContext *context;
443 PangoFontDescription *font;
445 context = gtk_style_context_new ();
446 path = gtk_widget_path_new ();
447 gtk_style_context_set_path (context, path);
448 gtk_widget_path_free (path);
450 gtk_style_context_get (context, 0,
452 "background-color", &bg_color,
455 g_assert (color != NULL);
456 g_assert (bg_color != NULL);
457 g_assert (font != NULL);
459 gdk_rgba_free (color);
460 gdk_rgba_free (bg_color);
461 pango_font_description_free (font);
463 g_object_unref (context);
467 main (int argc, char *argv[])
469 gtk_init (NULL, NULL);
470 g_test_init (&argc, &argv, NULL);
472 g_test_add_func ("/style/parse/empty", test_parse_empty);
473 g_test_add_func ("/style/parse/selectors", test_parse_selectors);
474 g_test_add_func ("/style/parse/declarations", test_parse_declarations);
475 g_test_add_func ("/style/path", test_path);
476 g_test_add_func ("/style/match", test_match);
477 g_test_add_func ("/style/style-property", test_style_property);
478 g_test_add_func ("/style/basic", test_basic_properties);
480 return g_test_run ();