diff options
64 files changed, 775 insertions, 319 deletions
diff --git a/demos/icon-browser/iconbrowserwin.c b/demos/icon-browser/iconbrowserwin.c index 876c09a0d1..11c9c53234 100644 --- a/demos/icon-browser/iconbrowserwin.c +++ b/demos/icon-browser/iconbrowserwin.c @@ -279,11 +279,31 @@ drag_prepare_texture (GtkDragSource *source, GtkWidget *widget) { GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget)); + GtkSnapshot *snapshot; + double width, height; + GskRenderNode *node; + GskRenderer *renderer; + GdkTexture *texture; + GdkContentProvider *ret; if (!GDK_IS_PAINTABLE (paintable)) return NULL; - return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable); + snapshot = gtk_snapshot_new (); + width = gdk_paintable_get_intrinsic_width (paintable); + height = gdk_paintable_get_intrinsic_height (paintable); + gdk_paintable_snapshot (paintable, snapshot, width, height); + node = gtk_snapshot_free_to_node (snapshot); + + renderer = gtk_native_get_renderer (gtk_widget_get_native (widget)); + texture = gsk_renderer_render_texture (renderer, node, &GRAPHENE_RECT_INIT (0, 0, width, height)); + + ret = gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, texture); + + g_object_unref (texture); + gsk_render_node_unref (node); + + return ret; } static GdkContentProvider * @@ -173,7 +173,7 @@ stash_desktop_startup_notification_id (void) if (!g_utf8_validate (desktop_startup_id, -1, NULL)) g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8"); else - startup_notification_id = g_strdup (desktop_startup_id ? desktop_startup_id : ""); + startup_notification_id = g_strdup (desktop_startup_id); } /* Clear the environment variable so it won't be inherited by diff --git a/gdk/x11/gdkdrag-x11.c b/gdk/x11/gdkdrag-x11.c index 606cef0f0c..d8c9ac28b8 100644 --- a/gdk/x11/gdkdrag-x11.c +++ b/gdk/x11/gdkdrag-x11.c @@ -296,15 +296,20 @@ gdk_x11_drag_find (GdkDisplay *display, static void precache_target_list (GdkDrag *drag) { - GdkContentFormats *formats = gdk_drag_get_formats (drag); + GdkContentFormats *formats; const char * const *atoms; gsize n_atoms; + formats = gdk_content_formats_ref (gdk_drag_get_formats (drag)); + formats = gdk_content_formats_union_serialize_mime_types (formats); + atoms = gdk_content_formats_get_mime_types (formats, &n_atoms); _gdk_x11_precache_atoms (gdk_drag_get_display (drag), (const char **) atoms, n_atoms); + + gdk_content_formats_unref (formats); } /* Utility functions */ @@ -917,8 +922,12 @@ xdnd_set_targets (GdkX11Drag *drag_x11) const char * const *atoms; gsize i, n_atoms; GdkDisplay *display = gdk_drag_get_display (drag); + GdkContentFormats *formats; - atoms = gdk_content_formats_get_mime_types (gdk_drag_get_formats (drag), &n_atoms); + formats = gdk_content_formats_ref (gdk_drag_get_formats (drag)); + formats = gdk_content_formats_union_serialize_mime_types (formats); + + atoms = gdk_content_formats_get_mime_types (formats, &n_atoms); atomlist = g_new (Atom, n_atoms); for (i = 0; i < n_atoms; i++) atomlist[i] = gdk_x11_get_xatom_by_name_for_display (display, atoms[i]); @@ -932,6 +941,8 @@ xdnd_set_targets (GdkX11Drag *drag_x11) g_free (atomlist); drag_x11->xdnd_targets_set = 1; + + gdk_content_formats_unref (formats); } static void @@ -1095,6 +1106,8 @@ xdnd_send_enter (GdkX11Drag *drag_x11) } xdnd_send_xevent (drag_x11, &xev); + + gdk_content_formats_unref (formats); } static void @@ -1334,7 +1347,7 @@ _gdk_x11_display_get_drag_protocol (GdkDisplay *display, static GdkSurfaceCache * drag_find_window_cache (GdkX11Drag *drag_x11, - GdkDisplay *display) + GdkDisplay *display) { if (!drag_x11->cache) drag_x11->cache = gdk_surface_cache_get (display); @@ -1365,7 +1378,7 @@ gdk_x11_drag_find_surface (GdkDrag *drag, drag_surface && GDK_IS_X11_SURFACE (drag_surface) ? GDK_SURFACE_XID (drag_surface) : None, x_root * screen_x11->surface_scale, - y_root * screen_x11->surface_scale); + y_root * screen_x11->surface_scale); if (drag_x11->dest_xid != dest) { @@ -1395,8 +1408,8 @@ gdk_x11_drag_find_surface (GdkDrag *drag, static void move_drag_surface (GdkDrag *drag, - guint x_root, - guint y_root) + guint x_root, + guint y_root) { GdkX11Drag *drag_x11 = GDK_X11_DRAG (drag); @@ -1407,14 +1420,14 @@ move_drag_surface (GdkDrag *drag, } static gboolean -gdk_x11_drag_drag_motion (GdkDrag *drag, - Window proxy_xid, - GdkDragProtocol protocol, - int x_root, - int y_root, - GdkDragAction suggested_action, - GdkDragAction possible_actions, - guint32 time) +gdk_x11_drag_drag_motion (GdkDrag *drag, + Window proxy_xid, + GdkDragProtocol protocol, + int x_root, + int y_root, + GdkDragAction suggested_action, + GdkDragAction possible_actions, + guint32 time) { GdkX11Drag *drag_x11 = GDK_X11_DRAG (drag); @@ -1606,8 +1619,8 @@ gdk_x11_drag_get_drag_surface (GdkDrag *drag) static void gdk_x11_drag_set_hotspot (GdkDrag *drag, - int hot_x, - int hot_y) + int hot_x, + int hot_y) { GdkX11Drag *x11_drag = GDK_X11_DRAG (drag); @@ -1623,8 +1636,8 @@ gdk_x11_drag_set_hotspot (GdkDrag *drag, static void gdk_x11_drag_default_output_done (GObject *drag, - GAsyncResult *result, - gpointer user_data) + GAsyncResult *result, + gpointer user_data) { GError *error = NULL; @@ -1636,17 +1649,17 @@ gdk_x11_drag_default_output_done (GObject *drag, } static void -gdk_x11_drag_default_output_handler (GOutputStream *stream, - const char *mime_type, - gpointer user_data) +gdk_x11_drag_default_output_handler (GOutputStream *stream, + const char *mime_type, + gpointer user_data) { gdk_drag_write_async (GDK_DRAG (user_data), - mime_type, - stream, - G_PRIORITY_DEFAULT, - NULL, - gdk_x11_drag_default_output_done, - NULL); + mime_type, + stream, + G_PRIORITY_DEFAULT, + NULL, + gdk_x11_drag_default_output_done, + NULL); g_object_unref (stream); } @@ -1675,7 +1688,7 @@ gdk_x11_drag_xevent (GdkDisplay *display, if (xevent->xselectionclear.time < x11_drag->timestamp) { GDK_DISPLAY_NOTE (display, CLIPBOARD, g_printerr ("ignoring SelectionClear with too old timestamp (%lu vs %lu)\n", - xevent->xselectionclear.time, x11_drag->timestamp)); + xevent->xselectionclear.time, x11_drag->timestamp)); return FALSE; } @@ -1685,6 +1698,7 @@ gdk_x11_drag_xevent (GdkDisplay *display, case SelectionRequest: { + GdkContentFormats *formats; #ifdef G_ENABLE_DEBUG const char *target, *property; #endif @@ -1703,23 +1717,30 @@ gdk_x11_drag_xevent (GdkDisplay *display, if (xevent->xselectionrequest.requestor == None) { GDK_DISPLAY_NOTE (display, CLIPBOARD, g_printerr ("got SelectionRequest for %s @ %s with NULL window, ignoring\n", - target, property)); + target, property)); return TRUE; } GDK_DISPLAY_NOTE (display, CLIPBOARD, g_printerr ("got SelectionRequest for %s @ %s\n", - target, property)); + target, property)); + + formats = gdk_content_formats_ref (gdk_drag_get_formats (drag)); + formats = gdk_content_formats_union_serialize_mime_types (formats); gdk_x11_selection_output_streams_create (display, - gdk_drag_get_formats (drag), + formats, xevent->xselectionrequest.requestor, xevent->xselectionrequest.selection, xevent->xselectionrequest.target, - xevent->xselectionrequest.property ? xevent->xselectionrequest.property - : xevent->xselectionrequest.target, + xevent->xselectionrequest.property + ? xevent->xselectionrequest.property + : xevent->xselectionrequest.target, xevent->xselectionrequest.time, gdk_x11_drag_default_output_handler, drag); + + gdk_content_formats_unref (formats); + return TRUE; } diff --git a/gdk/x11/gdkdrop-x11.c b/gdk/x11/gdkdrop-x11.c index 7bbb6cc78f..d9c1c4157f 100644 --- a/gdk/x11/gdkdrop-x11.c +++ b/gdk/x11/gdkdrop-x11.c @@ -39,6 +39,7 @@ #include "gdkscreen-x11.h" #include "gdkselectioninputstream-x11.h" #include "gdkselectionoutputstream-x11.h" +#include "gdktextlistconverter-x11.h" #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -103,6 +104,49 @@ static const struct { G_DEFINE_TYPE (GdkX11Drop, gdk_x11_drop, GDK_TYPE_DROP) +static GInputStream * +text_list_convert (GdkDisplay *display, + GInputStream *stream, + const char *encoding, + int format) +{ + GInputStream *converter_stream; + GConverter *converter; + + converter = gdk_x11_text_list_converter_to_utf8_new (display, encoding, format); + converter_stream = g_converter_input_stream_new (stream, converter); + + g_object_unref (converter); + g_object_unref (stream); + + return converter_stream; +} + +static GInputStream * +no_convert (GdkDisplay *display, + GInputStream *stream, + const char *encoding, + int format) +{ + return stream; +} + +static const struct { + const char *x_target; + const char *mime_type; + GInputStream * (* convert) (GdkDisplay *, GInputStream *, const char *, int); + const char *type; + int format; +} special_targets[] = { + { "UTF8_STRING", "text/plain;charset=utf-8", no_convert, "UTF8_STRING", 8 }, + { "COMPOUND_TEXT", "text/plain;charset=utf-8", text_list_convert, "COMPOUND_TEXT", 8 }, + { "TEXT", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 }, + { "STRING", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 }, + { "TARGETS", NULL, NULL, "ATOM", 32 }, + { "TIMESTAMP", NULL, NULL, "INTEGER", 32 }, + { "SAVE_TARGETS", NULL, NULL, "NULL", 32 } +}; + static void gdk_x11_drop_read_got_stream (GObject *source, GAsyncResult *res, @@ -145,9 +189,9 @@ gdk_x11_drop_read_got_stream (GObject *source, } else { -#if 0 gsize i; const char *mime_type = ((GSList *) g_task_get_task_data (task))->data; + GdkDrop *drop = GDK_DROP (g_task_get_source_object (task)); for (i = 0; i < G_N_ELEMENTS (special_targets); i++) { @@ -155,15 +199,12 @@ gdk_x11_drop_read_got_stream (GObject *source, { g_assert (special_targets[i].mime_type != NULL); - GDK_DISPLAY_NOTE (CLIPBOARD, g_printerr ("%s: reading with converter from %s to %s\n", - cb->selection, mime_type, special_targets[i].mime_type)); mime_type = g_intern_string (special_targets[i].mime_type); g_task_set_task_data (task, g_slist_prepend (NULL, (gpointer) mime_type), (GDestroyNotify) g_slist_free); - stream = special_targets[i].convert (cb, stream, type, format); + stream = special_targets[i].convert (gdk_drop_get_display (drop), stream, type, format); break; } } -#endif GDK_NOTE (DND, g_printerr ("reading DND as %s now\n", (const char *)((GSList *) g_task_get_task_data (task))->data)); diff --git a/gdk/x11/gdkkeys-x11.c b/gdk/x11/gdkkeys-x11.c index b58371e702..2d2318f3d7 100644 --- a/gdk/x11/gdkkeys-x11.c +++ b/gdk/x11/gdkkeys-x11.c @@ -1383,7 +1383,7 @@ gdk_x11_keymap_translate_keyboard_state (GdkKeymap *keymap, tmp_keyval = translate_keysym (keymap_x11, hardware_keycode, group, state, - level, effective_group); + effective_group, level); } if (consumed_modifiers) diff --git a/gsk/vulkan/gskvulkanimage.c b/gsk/vulkan/gskvulkanimage.c index 64e780bb7f..b73578afde 100644 --- a/gsk/vulkan/gskvulkanimage.c +++ b/gsk/vulkan/gskvulkanimage.c @@ -718,7 +718,7 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self, } else { - for (gsize r = 0; r < regions[i].height; i++) + for (gsize r = 0; r < regions[i].height; r++) memcpy (m + r * regions[i].width * 4, regions[i].data + r * regions[i].stride, regions[i].width * 4); } diff --git a/gtk/a11y/gtkatspiaction.c b/gtk/a11y/gtkatspiaction.c index fb39abf8d5..d31cda147b 100644 --- a/gtk/a11y/gtkatspiaction.c +++ b/gtk/a11y/gtkatspiaction.c @@ -68,10 +68,8 @@ action_handle_method (GtkAtSpiContext *self, g_variant_get (parameters, "(i)", &idx); - const Action *action = &actions[idx]; - if (idx >= 0 && idx < n_actions) - g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->name)); + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].name)); else g_dbus_method_invocation_return_error (invocation, G_IO_ERROR, @@ -129,10 +127,8 @@ action_handle_method (GtkAtSpiContext *self, g_variant_get (parameters, "(i)", &idx); - const Action *action = &actions[idx]; - if (idx >= 0 && idx < n_actions) - g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->keybinding)); + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].keybinding)); else g_dbus_method_invocation_return_error (invocation, G_IO_ERROR, diff --git a/gtk/gtkcomposetable.c b/gtk/gtkcomposetable.c index a07f5da06f..c5261f8a63 100644 --- a/gtk/gtkcomposetable.c +++ b/gtk/gtkcomposetable.c @@ -1038,7 +1038,7 @@ gtk_compose_table_compact_check (const GtkComposeTableCompact *table, if (!seq_index) return FALSE; - if (seq_index && n_compose == 1) + if (n_compose == 1) return TRUE; seq = NULL; diff --git a/gtk/gtkcssbordervalue.c b/gtk/gtkcssbordervalue.c index 7e5c32b86b..a9b9ef0001 100644 --- a/gtk/gtkcssbordervalue.c +++ b/gtk/gtkcssbordervalue.c @@ -218,7 +218,7 @@ _gtk_css_border_value_parse (GtkCssParser *parser, } result->is_computed = TRUE; - for (; i < 4; i++) + for (i = 0; i < 4; i++) if (result->values[i] && !gtk_css_value_is_computed (result->values[i])) { result->is_computed = FALSE; diff --git a/gtk/gtkcssfiltervalue.c b/gtk/gtkcssfiltervalue.c index 3269368c69..c1c281c1e2 100644 --- a/gtk/gtkcssfiltervalue.c +++ b/gtk/gtkcssfiltervalue.c @@ -24,6 +24,7 @@ #include "gtkcssfiltervalueprivate.h" #include "gtkcssnumbervalueprivate.h" +#include "gtkcssshadowvalueprivate.h" typedef union _GtkCssFilter GtkCssFilter; @@ -46,7 +47,7 @@ union _GtkCssFilter { struct { GtkCssFilterType type; GtkCssValue *value; - } brightness, contrast, grayscale, hue_rotate, invert, opacity, saturate, sepia, blur; + } blur, brightness, contrast, drop_shadow, grayscale, hue_rotate, invert, opacity, saturate, sepia; }; struct _GtkCssValue { @@ -90,8 +91,10 @@ gtk_css_filter_clear (GtkCssFilter *filter) case GTK_CSS_FILTER_BLUR: _gtk_css_value_unref (filter->blur.value); break; - case GTK_CSS_FILTER_NONE: case GTK_CSS_FILTER_DROP_SHADOW: + _gtk_css_value_unref (filter->drop_shadow.value); + break; + case GTK_CSS_FILTER_NONE: default: g_assert_not_reached (); break; @@ -131,8 +134,10 @@ gtk_css_filter_init_identity (GtkCssFilter *filter, case GTK_CSS_FILTER_BLUR: filter->blur.value = _gtk_css_number_value_new (0, GTK_CSS_PX); break; - case GTK_CSS_FILTER_NONE: case GTK_CSS_FILTER_DROP_SHADOW: + filter->drop_shadow.value = gtk_css_shadow_value_new_filter (); + break; + case GTK_CSS_FILTER_NONE: default: g_assert_not_reached (); break; @@ -347,8 +352,11 @@ gtk_css_filter_compute (GtkCssFilter *dest, dest->blur.value = _gtk_css_value_compute (src->blur.value, property_id, provider, style, parent_style); return dest->blur.value == src->blur.value; - case GTK_CSS_FILTER_NONE: case GTK_CSS_FILTER_DROP_SHADOW: + dest->drop_shadow.value = _gtk_css_value_compute (src->drop_shadow.value, property_id, provider, style, parent_style); + return dest->drop_shadow.value == src->drop_shadow.value; + + case GTK_CSS_FILTER_NONE: default: g_assert_not_reached (); return FALSE; @@ -428,8 +436,10 @@ gtk_css_filter_equal (const GtkCssFilter *filter1, case GTK_CSS_FILTER_BLUR: return _gtk_css_value_equal (filter1->blur.value, filter2->blur.value); - case GTK_CSS_FILTER_NONE: case GTK_CSS_FILTER_DROP_SHADOW: + return _gtk_css_value_equal (filter1->drop_shadow.value, filter2->drop_shadow.value); + + case GTK_CSS_FILTER_NONE: default: g_assert_not_reached (); return FALSE; @@ -517,8 +527,11 @@ gtk_css_filter_transition (GtkCssFilter *result, result->blur.value = _gtk_css_value_transition (start->blur.value, end->blur.value, property_id, progress); break; - case GTK_CSS_FILTER_NONE: case GTK_CSS_FILTER_DROP_SHADOW: + result->drop_shadow.value = _gtk_css_value_transition (start->drop_shadow.value, end->drop_shadow.value, property_id, progress); + break; + + case GTK_CSS_FILTER_NONE: default: g_assert_not_reached (); break; @@ -663,8 +676,13 @@ gtk_css_filter_print (const GtkCssFilter *filter, g_string_append (string, ")"); break; - case GTK_CSS_FILTER_NONE: case GTK_CSS_FILTER_DROP_SHADOW: + g_string_append (string, "drop-shadow("); + _gtk_css_value_print (filter->drop_shadow.value, string); + g_string_append (string, ")"); + break; + + case GTK_CSS_FILTER_NONE: default: g_assert_not_reached (); break; @@ -709,12 +727,12 @@ static GtkCssValue * gtk_css_filter_value_alloc (guint n_filters) { GtkCssValue *result; - + g_return_val_if_fail (n_filters > 0, NULL); - + result = _gtk_css_value_alloc (>K_CSS_VALUE_FILTER, sizeof (GtkCssValue) + sizeof (GtkCssFilter) * (n_filters - 1)); result->n_filters = n_filters; - + return result; } @@ -737,7 +755,7 @@ gtk_css_filter_parse_number (GtkCssParser *parser, { GtkCssValue **values = data; - values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT); + values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY); if (values[n] == NULL) return 0; @@ -751,7 +769,7 @@ gtk_css_filter_parse_length (GtkCssParser *parser, { GtkCssValue **values = data; - values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH); + values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_POSITIVE_ONLY); if (values[n] == NULL) return 0; @@ -772,6 +790,20 @@ gtk_css_filter_parse_angle (GtkCssParser *parser, return 1; } +static guint +gtk_css_filter_parse_shadow (GtkCssParser *parser, + guint n, + gpointer data) +{ + GtkCssValue **values = data; + + values[n] = gtk_css_shadow_value_parse_filter (parser); + if (values[n] == NULL) + return 0; + + return 1; +} + GtkCssValue * gtk_css_filter_value_parse (GtkCssParser *parser) { @@ -861,6 +893,14 @@ gtk_css_filter_value_parse (GtkCssParser *parser) filter.type = GTK_CSS_FILTER_SEPIA; computed = computed && gtk_css_value_is_computed (filter.sepia.value); } + else if (gtk_css_parser_has_function (parser, "drop-shadow")) + { + if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_shadow, &filter.drop_shadow.value)) + goto fail; + + filter.type = GTK_CSS_FILTER_DROP_SHADOW; + computed = computed && gtk_css_value_is_computed (filter.drop_shadow.value); + } else { break; @@ -899,7 +939,6 @@ gtk_css_filter_value_push_snapshot (const GtkCssValue *filter, graphene_matrix_t matrix; graphene_vec4_t offset; int i, j; - double radius; if (gtk_css_filter_value_is_none (filter)) return; @@ -909,16 +948,18 @@ gtk_css_filter_value_push_snapshot (const GtkCssValue *filter, { j = gtk_css_filter_value_compute_matrix (filter, i, &matrix, &offset); if (i < j) - gtk_snapshot_push_color_matrix (snapshot, - &matrix, - &offset); + gtk_snapshot_push_color_matrix (snapshot, &matrix, &offset); if (j < filter->n_filters) { if (filter->filters[j].type == GTK_CSS_FILTER_BLUR) { - radius = _gtk_css_number_value_get (filter->filters[j].blur.value, 100.0); - gtk_snapshot_push_blur (snapshot, radius); + double std_dev = _gtk_css_number_value_get (filter->filters[j].blur.value, 100.0); + gtk_snapshot_push_blur (snapshot, 2 * std_dev); + } + else if (filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW) + { + gtk_css_shadow_value_push_snapshot (filter->filters[j].drop_shadow.value, snapshot); } else g_warning ("Don't know how to handle filter type %d", filter->filters[j].type); @@ -942,15 +983,18 @@ gtk_css_filter_value_pop_snapshot (const GtkCssValue *filter, { for (j = i; j < filter->n_filters; j++) { - if (filter->filters[j].type == GTK_CSS_FILTER_BLUR) + if (filter->filters[j].type == GTK_CSS_FILTER_BLUR || + filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW) break; } if (i < j) gtk_snapshot_pop (snapshot); - if (j < filter->n_filters) + if (filter->filters[j].type == GTK_CSS_FILTER_BLUR) gtk_snapshot_pop (snapshot); + else if (filter->filters[j].type == GTK_CSS_FILTER_DROP_SHADOW) + gtk_css_shadow_value_pop_snapshot (filter->filters[j].drop_shadow.value, snapshot); i = j + 1; } diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c index f04a6fe7c5..951fbd1060 100644 --- a/gtk/gtkcssselector.c +++ b/gtk/gtkcssselector.c @@ -1073,11 +1073,8 @@ parse_n_plus_b (GtkCssParser *parser, *a = 0; return TRUE; } - - gtk_css_parser_error_syntax (parser, "Not a valid an+b type"); - return FALSE; } - + static gboolean parse_a_n_plus_b (GtkCssParser *parser, int seen_sign, diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c index 9ad69b9182..86dfcafdfb 100644 --- a/gtk/gtkcssshadowvalue.c +++ b/gtk/gtkcssshadowvalue.c @@ -44,12 +44,14 @@ typedef struct { struct _GtkCssValue { GTK_CSS_VALUE_BASE + guint is_filter : 1; /* values stored in radius are std_dev, for drop-shadow */ guint n_shadows; ShadowValue shadows[1]; }; static GtkCssValue * gtk_css_shadow_value_new (ShadowValue *shadows, - guint n_shadows); + guint n_shadows, + gboolean is_filter); static void shadow_value_for_transition (ShadowValue *result, @@ -133,7 +135,7 @@ gtk_css_value_shadow_compute (GtkCssValue *value, shadows[i].inset = shadow->inset; } - return gtk_css_shadow_value_new (shadows, value->n_shadows); + return gtk_css_shadow_value_new (shadows, value->n_shadows, value->is_filter); } static gboolean @@ -151,11 +153,11 @@ gtk_css_value_shadow_equal (const GtkCssValue *value1, const ShadowValue *shadow2 = &value2->shadows[i]; if (shadow1->inset != shadow2->inset || - _gtk_css_value_equal (shadow1->hoffset, shadow2->hoffset) || - _gtk_css_value_equal (shadow1->voffset, shadow2->voffset) || - _gtk_css_value_equal (shadow1->radius, shadow2->radius) || - _gtk_css_value_equal (shadow1->spread, shadow2->spread) || - _gtk_css_value_equal (shadow1->color, shadow2->color)) + !_gtk_css_value_equal (shadow1->hoffset, shadow2->hoffset) || + !_gtk_css_value_equal (shadow1->voffset, shadow2->voffset) || + !_gtk_css_value_equal (shadow1->radius, shadow2->radius) || + !_gtk_css_value_equal (shadow1->spread, shadow2->spread) || + !_gtk_css_value_equal (shadow1->color, shadow2->color)) return FALSE; } @@ -227,7 +229,7 @@ gtk_css_value_shadow_transition (GtkCssValue *start, } } - return gtk_css_shadow_value_new (shadows, len); + return gtk_css_shadow_value_new (shadows, len, start->is_filter); } static void @@ -284,7 +286,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_SHADOW = { gtk_css_value_shadow_print }; -static GtkCssValue shadow_none_singleton = { >K_CSS_VALUE_SHADOW, 1, TRUE, 0 }; +static GtkCssValue shadow_none_singleton = { >K_CSS_VALUE_SHADOW, 1, TRUE, FALSE, 0 }; GtkCssValue * gtk_css_shadow_value_new_none (void) @@ -294,7 +296,8 @@ gtk_css_shadow_value_new_none (void) static GtkCssValue * gtk_css_shadow_value_new (ShadowValue *shadows, - guint n_shadows) + guint n_shadows, + gboolean is_filter) { GtkCssValue *retval; guint i; @@ -304,6 +307,7 @@ gtk_css_shadow_value_new (ShadowValue *shadows, retval = _gtk_css_value_alloc (>K_CSS_VALUE_SHADOW, sizeof (GtkCssValue) + sizeof (ShadowValue) * (n_shadows - 1)); retval->n_shadows = n_shadows; + retval->is_filter = is_filter; memcpy (retval->shadows, shadows, sizeof (ShadowValue) * n_shadows); @@ -326,6 +330,21 @@ gtk_css_shadow_value_new (ShadowValue *shadows, return retval; } +GtkCssValue * +gtk_css_shadow_value_new_filter (void) +{ + ShadowValue value; + + value.inset = FALSE; + value.hoffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER); + value.voffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER); + value.radius = _gtk_css_number_value_new (0, GTK_CSS_NUMBER); + value.spread = _gtk_css_number_value_new (0, GTK_CSS_NUMBER); + value.color = _gtk_css_color_value_new_current_color (); + + return gtk_css_shadow_value_new (&value, 1, TRUE); +} + enum { HOFFSET, VOFFSET, @@ -416,9 +435,9 @@ parse_color (GtkCssParser *parser, } static gboolean -_gtk_css_shadow_value_parse_one (GtkCssParser *parser, - gboolean box_shadow_mode, - ShadowValue *result) +gtk_css_shadow_value_parse_one (GtkCssParser *parser, + gboolean box_shadow_mode, + ShadowValue *result) { GtkCssValue *values[N_VALUES] = { NULL, }; GtkCssValue *color = NULL; @@ -464,8 +483,8 @@ fail: #define MAX_SHADOWS 64 GtkCssValue * -_gtk_css_shadow_value_parse (GtkCssParser *parser, - gboolean box_shadow_mode) +gtk_css_shadow_value_parse (GtkCssParser *parser, + gboolean box_shadow_mode) { ShadowValue shadows[MAX_SHADOWS]; int n_shadows = 0; @@ -475,7 +494,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser, return gtk_css_shadow_value_new_none (); do { - if (_gtk_css_shadow_value_parse_one (parser, box_shadow_mode, &shadows[n_shadows])) + if (gtk_css_shadow_value_parse_one (parser, box_shadow_mode, &shadows[n_shadows])) n_shadows++; if (n_shadows > MAX_SHADOWS) @@ -485,7 +504,7 @@ _gtk_css_shadow_value_parse (GtkCssParser *parser, } } while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA)); - return gtk_css_shadow_value_new (shadows, n_shadows); + return gtk_css_shadow_value_new (shadows, n_shadows, FALSE); fail: for (i = 0; i < n_shadows; i++) @@ -497,6 +516,17 @@ fail: return NULL; } +GtkCssValue * +gtk_css_shadow_value_parse_filter (GtkCssParser *parser) +{ + ShadowValue shadow; + + if (gtk_css_shadow_value_parse_one (parser, FALSE, &shadow)) + return gtk_css_shadow_value_new (&shadow, 1, TRUE); + else + return NULL; +} + void gtk_css_shadow_value_get_extents (const GtkCssValue *value, GtkBorder *border) @@ -512,6 +542,8 @@ gtk_css_shadow_value_get_extents (const GtkCssValue *value, spread = _gtk_css_number_value_get (shadow->spread, 0); radius = _gtk_css_number_value_get (shadow->radius, 0); + if (value->is_filter) + radius = radius * 2; clip_radius = gsk_cairo_blur_compute_pixels (radius); hoffset = _gtk_css_number_value_get (shadow->hoffset, 0); voffset = _gtk_css_number_value_get (shadow->voffset, 0); @@ -529,6 +561,8 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *value, const GskRoundedRect *border_box) { guint i; + double dx, dy, spread, radius; + const GdkRGBA *color; g_return_if_fail (value->class == >K_CSS_VALUE_SHADOW); @@ -539,17 +573,20 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *value, if (shadow->inset) continue; + color = gtk_css_color_value_get_rgba (shadow->color); + /* We don't need to draw invisible shadows */ - if (gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color))) + if (gdk_rgba_is_clear (color)) continue; - gtk_snapshot_append_outset_shadow (snapshot, - border_box, - gtk_css_color_value_get_rgba (shadow->color), - _gtk_css_number_value_get (shadow->hoffset, 0), - _gtk_css_number_value_get (shadow->voffset, 0), - _gtk_css_number_value_get (shadow->spread, 0), - _gtk_css_number_value_get (shadow->radius, 0)); + dx = _gtk_css_number_value_get (shadow->hoffset, 0); + dy = _gtk_css_number_value_get (shadow->voffset, 0); + spread = _gtk_css_number_value_get (shadow->spread, 0); + radius = _gtk_css_number_value_get (shadow->radius, 0); + if (value->is_filter) + radius = 2 * radius; + + gtk_snapshot_append_outset_shadow (snapshot, border_box, color, dx, dy, spread, radius); } } @@ -571,15 +608,18 @@ gtk_css_shadow_value_snapshot_inset (const GtkCssValue *value, if (!shadow->inset) continue; + color = gtk_css_color_value_get_rgba (shadow->color); + /* We don't need to draw invisible shadows */ - if (gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color))) + if (gdk_rgba_is_clear (color)) continue; dx = _gtk_css_number_value_get (shadow->hoffset, 0); dy = _gtk_css_number_value_get (shadow->voffset, 0); spread = _gtk_css_number_value_get (shadow->spread, 0); radius = _gtk_css_number_value_get (shadow->radius, 0); - color = gtk_css_color_value_get_rgba (shadow->color); + if (value->is_filter) + radius = 2 * radius; /* These are trivial to do with a color node */ if (spread == 0 && radius == 0 && @@ -675,7 +715,6 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value, gboolean need_shadow = FALSE; guint i; - /* TODO: We can save this as a flag once and then reuse it */ for (i = 0; i < value->n_shadows; i++) { const ShadowValue *shadow = &value->shadows[i]; @@ -699,6 +738,8 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value, shadows[i].dy = _gtk_css_number_value_get (shadow->voffset, 0); shadows[i].color = *gtk_css_color_value_get_rgba (shadow->color); shadows[i].radius = _gtk_css_number_value_get (shadow->radius, 0); + if (value->is_filter) + shadows[i].radius *= 2; } gtk_snapshot_push_shadow (snapshot, shadows, value->n_shadows); @@ -706,3 +747,25 @@ gtk_css_shadow_value_push_snapshot (const GtkCssValue *value, return need_shadow; } + +void +gtk_css_shadow_value_pop_snapshot (const GtkCssValue *value, + GtkSnapshot *snapshot) +{ + gboolean need_shadow = FALSE; + guint i; + + for (i = 0; i < value->n_shadows; i++) + { + const ShadowValue *shadow = &value->shadows[i]; + + if (!gdk_rgba_is_clear (gtk_css_color_value_get_rgba (shadow->color))) + { + need_shadow = TRUE; + break; + } + } + + if (need_shadow) + gtk_snapshot_pop (snapshot); +} diff --git a/gtk/gtkcssshadowvalueprivate.h b/gtk/gtkcssshadowvalueprivate.h index 5784dfa516..21efac1908 100644 --- a/gtk/gtkcssshadowvalueprivate.h +++ b/gtk/gtkcssshadowvalueprivate.h @@ -34,10 +34,12 @@ G_BEGIN_DECLS -GtkCssValue * gtk_css_shadow_value_new_none (void); +GtkCssValue * gtk_css_shadow_value_new_none (void); +GtkCssValue * gtk_css_shadow_value_new_filter (void); -GtkCssValue * _gtk_css_shadow_value_parse (GtkCssParser *parser, +GtkCssValue * gtk_css_shadow_value_parse (GtkCssParser *parser, gboolean box_shadow_mode); +GtkCssValue * gtk_css_shadow_value_parse_filter (GtkCssParser *parser); void gtk_css_shadow_value_get_extents (const GtkCssValue *shadow, GtkBorder *border); @@ -53,6 +55,8 @@ gboolean gtk_css_shadow_value_is_none (const GtkCssValue gboolean gtk_css_shadow_value_push_snapshot (const GtkCssValue *value, GtkSnapshot *snapshot); +void gtk_css_shadow_value_pop_snapshot (const GtkCssValue *value, + GtkSnapshot *snapshot); G_END_DECLS diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c index 8e5d4bf796..6df32116a8 100644 --- a/gtk/gtkcssstylepropertyimpl.c +++ b/gtk/gtkcssstylepropertyimpl.c @@ -512,14 +512,14 @@ static GtkCssValue * box_shadow_value_parse (GtkCssStyleProperty *property, GtkCssParser *parser) { - return _gtk_css_shadow_value_parse (parser, TRUE); + return gtk_css_shadow_value_parse (parser, TRUE); } static GtkCssValue * shadow_value_parse (GtkCssStyleProperty *property, GtkCssParser *parser) { - return _gtk_css_shadow_value_parse (parser, FALSE); + return gtk_css_shadow_value_parse (parser, FALSE); } static GtkCssValue * diff --git a/gtk/gtkcssvalue.c b/gtk/gtkcssvalue.c index dddfce8c40..b0c32c8e82 100644 --- a/gtk/gtkcssvalue.c +++ b/gtk/gtkcssvalue.c @@ -260,8 +260,8 @@ _gtk_css_value_transition (GtkCssValue *start, guint property_id, double progress) { - gtk_internal_return_val_if_fail (start != NULL, FALSE); - gtk_internal_return_val_if_fail (end != NULL, FALSE); + gtk_internal_return_val_if_fail (start != NULL, NULL); + gtk_internal_return_val_if_fail (end != NULL, NULL); if (start->class != end->class) return NULL; diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c index 800119cf94..ad8a1e3116 100644 --- a/gtk/gtkdialog.c +++ b/gtk/gtkdialog.c @@ -48,20 +48,32 @@ * SECTION:gtkdialog * @Short_description: Create popup windows * @Title: GtkDialog - * @See_also: #GtkBox, #GtkWindow, #GtkButton + * @See_also: #GtkWindow, #GtkMessageDialog * - * Dialog boxes are a convenient way to prompt the user for a small amount + * Dialogs are a convenient way to prompt the user for a small amount * of input, e.g. to display a message, ask a question, or anything else * that does not require extensive effort on the user’s part. * - * GTK treats a dialog as a window split vertically. The top section is a - * #GtkBox, and is where widgets such as a #GtkLabel or a #GtkEntry should - * be packed. The bottom area is known as the - * “action area”. This is generally used for - * packing buttons into the dialog which may perform functions such as - * cancel, ok, or apply. + * The main area of a GtkDialog is called the "content area", and is yours + * to populate with widgets such a #GtkLabel or #GtkEntry, to present + * your information, questions, or tasks to the user. In addition, dialogs + * allow you to add "action widgets". Most commonly, action widgets are + * buttons. Depending on the platform, action widgets may be presented + * in the header bar at the top of the window, or at the bottom of the window. + * To add action widgets, use GtkDialog using gtk_dialog_new_with_buttons(), + * gtk_dialog_add_button(), gtk_dialog_add_buttons(), or + * gtk_dialog_add_action_widget(). + * + * Clicking a button that was added as an action widget will emit the + * #GtkDialog::response signal with a response ID that you specified. + * GTK will never assign a meaning to positive response IDs; these are + * entirely user-defined. But for convenience, you can use the response + * IDs in the #GtkResponseType enumeration (these all have values less + * than zero). If a dialog receives a delete event, the + * #GtkDialog::response signal will be emitted with the + * #GTK_RESPONSE_DELETE_EVENT response ID. * - * #GtkDialog boxes are created with a call to gtk_dialog_new() or + * Dialogs are created with a call to gtk_dialog_new() or * gtk_dialog_new_with_buttons(). gtk_dialog_new_with_buttons() is * recommended; it allows you to set the dialog title, some convenient * flags, and add simple buttons. @@ -72,20 +84,9 @@ * gtk_dialog_new() into a #GtkWindow. When using gtk_dialog_new_with_buttons() * you can also pass the #GTK_DIALOG_MODAL flag to make a dialog modal. * - * If you add buttons to #GtkDialog using gtk_dialog_new_with_buttons(), - * gtk_dialog_add_button(), gtk_dialog_add_buttons(), or - * gtk_dialog_add_action_widget(), clicking the button will emit a signal - * called #GtkDialog::response with a response ID that you specified. GTK - * will never assign a meaning to positive response IDs; these are entirely - * user-defined. But for convenience, you can use the response IDs in the - * #GtkResponseType enumeration (these all have values less than zero). If - * a dialog receives a delete event, the #GtkDialog::response signal will - * be emitted with a response ID of #GTK_RESPONSE_DELETE_EVENT. - * - * For the simple dialog in the following example, in reality you’d probably - * use #GtkMessageDialog to save yourself some effort. But you’d need to - * create the dialog contents manually if you had more than a simple message - * in the dialog. + * For the simple dialog in the following example, a #GtkMessageDialog would + * save some effort. But you’d need to create the dialog contents manually if + * you had more than a simple message in the dialog. * * An example for simple GtkDialog usage: * |[<!-- language="C" --> @@ -124,8 +125,7 @@ * # GtkDialog as GtkBuildable * * The GtkDialog implementation of the #GtkBuildable interface exposes the - * @content_area and @action_area as internal children with the names - * “content_area” and “action_area”. + * @content_area as an internal child with the name “content_area”. * * GtkDialog supports a custom <action-widgets> element, which can contain * multiple <action-widget> elements. The “response” attribute specifies a diff --git a/gtk/gtkgrid.c b/gtk/gtkgrid.c index f5909b7f2f..00ffd6643e 100644 --- a/gtk/gtkgrid.c +++ b/gtk/gtkgrid.c @@ -48,6 +48,65 @@ * from the grid, use gtk_grid_remove(). The behaviour of GtkGrid when * several children occupy the same grid cell is undefined. * + * # GtkGrid as GtkBuildable + * + * Every child in a GtkGrid has access to a custom #GtkBuildable element, called ´<layout>´. + * It can by used to specify a position in the grid and optionally spans. + * All properties that can be used in the ´<layout>´ element are implemented by #GtkGridLayoutChild. + * + * It is implemented by #GtkWidget using #GtkLayoutManager. + * + * To showcase it, here is a simple example: + * + * |[ + * <object class="GtkGrid" id="my_grid"> + * <child> + * <object class="GtkButton" id="button1"> + * <property name="label">Button 1</property> + * <layout> + * <property name="column">0</property> + * <property name="row">0</property> + * </layout> + * </object> + * </child> + * <child> + * <object class="GtkButton" id="button2"> + * <property name="label">Button 2</property> + * <layout> + * <property name="column">1</property> + * <property name="row">0</property> + * </layout> + * </object> + * </child> + * <child> + * <object class="GtkButton" id="button3"> + * <property name="label">Button 3</property> + * <layout> + * <property name="column">2</property> + * <property name="row">0</property> + * <property name="row-span">2</property> + * </layout> + * </object> + * </child> + * <child> + * <object class="GtkButton" id="button4"> + * <property name="label">Button 4</property> + * <layout> + * <property name="column">0</property> + * <property name="row">1</property> + * <property name="column-span">2</property> + * </layout> + * </object> + * </child> + * </object> + * ]| + * + * It organizes the first two buttons side-by-side in one cell each. + * The third button is in the last column but spans across two rows. + * This is defined by the ´row-span´ property. + * The last button is located in the second row and spans across two columns, + * which is defined by the ´column-span´ property. + * * # CSS nodes * * GtkGrid uses a single CSS node with name `grid`. diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index 53bf995c77..41e25858f5 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -1147,7 +1147,7 @@ gtk_list_base_class_init (GtkListBaseClass *klass) P_("The orientation of the orientable"), GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL, - G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_EXPLICIT_NOTIFY); + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); g_object_class_install_properties (gobject_class, N_PROPS, properties); diff --git a/gtk/gtkmessagedialog.c b/gtk/gtkmessagedialog.c index faa100354e..af61f8cb55 100644 --- a/gtk/gtkmessagedialog.c +++ b/gtk/gtkmessagedialog.c @@ -456,8 +456,6 @@ gtk_message_dialog_init (GtkMessageDialog *dialog) priv->has_primary_markup = FALSE; priv->has_secondary_text = FALSE; - priv->has_primary_markup = FALSE; - priv->has_secondary_text = FALSE; priv->message_type = GTK_MESSAGE_OTHER; gtk_widget_add_css_class (GTK_WIDGET (dialog), "message"); diff --git a/gtk/gtkshow.c b/gtk/gtkshow.c index 9ecfeb7d84..2362c8165e 100644 --- a/gtk/gtkshow.c +++ b/gtk/gtkshow.c @@ -139,7 +139,7 @@ gtk_show_uri_full (GtkWindow *parent, * @result: #GAsyncResult that was passed to @callback * @error: return location for an error * - * Finished the gtk_show_uri() call and returns the result + * Finishes the gtk_show_uri() call and returns the result * of the operation. * * Returns: %TRUE if the URI was shown successfully. diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index 3714b6a7e3..5f87ae70ad 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -257,8 +257,8 @@ static void gtk_text_btree_rebalance (GtkTextBTree static GtkTextLine * get_last_line (GtkTextBTree *tree); static void post_insert_fixup (GtkTextBTree *tree, GtkTextLine *insert_line, - int char_count_delta, - int line_count_delta); + int line_count_delta, + int char_count_delta); static void gtk_text_btree_node_adjust_toggle_count (GtkTextBTreeNode *node, GtkTextTagInfo *info, int adjust); diff --git a/gtk/gtktreemodelfilter.c b/gtk/gtktreemodelfilter.c index a72c6ea476..4d686c744f 100644 --- a/gtk/gtktreemodelfilter.c +++ b/gtk/gtktreemodelfilter.c @@ -3285,9 +3285,6 @@ gtk_tree_model_filter_iter_children (GtkTreeModel *model, return TRUE; } - - iter->stamp = 0; - return FALSE; } static gboolean diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index ba02a6af93..990d7c27ab 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -257,7 +257,7 @@ * custom `<layout>` element, used to define layout properties: * * |[<!-- language="xml" --> - * <object class="MyGrid" id="grid1"> + * <object class="GtkGrid" id="my_grid"> * <child> * <object class="GtkLabel" id="label1"> * <property name="label">Description</property> diff --git a/gtk/meson.build b/gtk/meson.build index c1b2186e89..42cb07a205 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -1142,12 +1142,6 @@ if build_gir # the installed one gdk_gir_inc = [ 'cairo-1.0', 'Gio-2.0', ] - if graphene_dep.type_name() == 'internal' - gdk_gir_inc += subproject('graphene').get_variable('graphene_gir').get(0) - else - gdk_gir_inc += 'Graphene-1.0' - endif - if pixbuf_dep.type_name() == 'internal' gdk_gir_inc += subproject('gdk-pixbuf').get_variable('gdkpixbuf_gir').get(0) else @@ -1211,6 +1205,12 @@ if build_gir gsk_gir_inc = [ gdk_gir[0] ] + if graphene_dep.type_name() == 'internal' + gsk_gir_inc += subproject('graphene').get_variable('graphene_gir').get(0) + else + gsk_gir_inc += 'Graphene-1.0' + endif + gsk_gir = gnome.generate_gir(libgtk, sources: gsk_public_headers + gsk_public_sources + [ gskenum_h ], namespace: 'Gsk', diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss index 77790d7528..5588e4fb40 100644 --- a/gtk/theme/Adwaita/_common.scss +++ b/gtk/theme/Adwaita/_common.scss @@ -933,6 +933,14 @@ list > row button.image-button:not(.flat) { &:hover { @include button(hover); } &:active, &:checked { @include button(active); } + + @each $b_type, $b_color in (suggested-action, $selected_bg_color), + (destructive-action, $destructive_color) { + &.#{$b_type} { // allow colored buttons in lists #3643 + @include button(normal, $b_color, white); + @include focus-ring($fc: $alt_focus_border_color); + } + } } /********* diff --git a/meson.build b/meson.build index d13408bf95..729aa3ea19 100644 --- a/meson.build +++ b/meson.build @@ -85,6 +85,13 @@ gtk_library_version = '1.@0@.@1@'.format(gtk_binary_age - gtk_interface_age, gtk gtk_api_version = '4.0' +module_suffix = [] +# GModule requires file extension to be .so, not .dylib on Mac. +# https://gitlab.gnome.org/GNOME/glib/issues/520 +if ['darwin', 'ios'].contains(host_machine.system()) + module_suffix = 'so' +endif + x11_enabled = get_option('x11-backend') wayland_enabled = get_option('wayland-backend') broadway_enabled = get_option('broadway-backend') diff --git a/modules/media/meson.build b/modules/media/meson.build index aa5c0280e6..154390e7fe 100644 --- a/modules/media/meson.build +++ b/modules/media/meson.build @@ -35,6 +35,7 @@ if ffmpeg_found sources: 'gtkffmediafile.c', c_args: extra_c_args, dependencies: [ libgtk_dep, ffmpeg_deps ], + name_suffix: module_suffix, install_dir: media_install_dir, install: true, ) @@ -56,6 +57,7 @@ if gstplayer_dep.found() and gstgl_dep.found() ], c_args: extra_c_args, dependencies: [ libm, libgtk_dep, gstplayer_dep, gstgl_dep ], + name_suffix: module_suffix, install_dir: media_install_dir, install: true, ) diff --git a/modules/printbackends/meson.build b/modules/printbackends/meson.build index 64d8a41974..fa55d60e3b 100644 --- a/modules/printbackends/meson.build +++ b/modules/printbackends/meson.build @@ -22,6 +22,7 @@ if cups_dep.found() ], c_args: printbackends_args, dependencies: [libgtk_dep, cups_dep, colord_dep], + name_suffix: module_suffix, install_dir: printbackends_install_dir, install: true, ) @@ -32,6 +33,7 @@ else sources: 'gtkprintbackendlpr.c', c_args: printbackends_args, dependencies: libgtk_dep, + name_suffix: module_suffix, install_dir: printbackends_install_dir, install: true, ) @@ -49,6 +51,7 @@ if rest_dep.found() and json_glib_dep.found() ], c_args: printbackends_args, dependencies: [ libgtk_dep, rest_dep, json_glib_dep ], + name_suffix: module_suffix, install_dir: printbackends_install_dir, install: true) endif @@ -59,6 +62,7 @@ shared_module('printbackend-file', sources: 'gtkprintbackendfile.c', c_args: printbackends_args, dependencies: libgtk_dep, + name_suffix: module_suffix, install_dir: printbackends_install_dir, install: true, ) @@ -97,7 +97,7 @@ msgstr "Backspace" #: gdk/keyname-table.h:6844 msgctxt "keyboard label" msgid "Tab" -msgstr "Tabulátor" +msgstr "Tab" #: gdk/keyname-table.h:6845 msgctxt "keyboard label" @@ -122,7 +122,7 @@ msgstr "Sys_Req" #: gdk/keyname-table.h:6849 msgctxt "keyboard label" msgid "Escape" -msgstr "Escape" +msgstr "Esc" #: gdk/keyname-table.h:6850 msgctxt "keyboard label" diff --git a/testsuite/css/data.test.in b/testsuite/css/data.test.in new file mode 100644 index 0000000000..11e0e3950d --- /dev/null +++ b/testsuite/css/data.test.in @@ -0,0 +1,4 @@ +[Test] +Exec=/bin/sh -c "env G_ENABLE_DIAGNOSTIC=0 GTK_A11Y=test @libexecdir@/installed-tests/gtk-4.0/css/data --tap -k" +Type=session +Output=TAP diff --git a/testsuite/css/meson.build b/testsuite/css/meson.build index f8d13fe548..20c031410d 100644 --- a/testsuite/css/meson.build +++ b/testsuite/css/meson.build @@ -6,6 +6,7 @@ csstest_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) csstest_env.set('GIO_USE_VFS', 'local') csstest_env.set('GSETTINGS_BACKEND', 'memory') csstest_env.set('G_ENABLE_DIAGNOSTIC', '0') +csstest_env.set('GDK_DEBUG', 'default-settings') subdir('parser') subdir('nodes') @@ -44,14 +45,14 @@ test('data', test_data, suite: 'css', ) -test_parser = executable('test-css-value', 'test-css-value.c', +transition = executable('transition', 'transition.c', c_args: common_cflags, dependencies: libgtk_static_dep, install: get_option('install-tests'), install_dir: testexecdir, ) -test('css value', test_parser, +test('transition', transition, args: [ '--tap', '-k' ], protocol: 'tap', env: csstest_env, @@ -66,6 +67,14 @@ if get_option('install-tests') configuration: conf, install_dir: testdatadir, ) + + conf = configuration_data() + conf.set('libexecdir', gtk_libexecdir) + configure_file(input: 'data.test.in', + output: 'data.test', + configuration: conf, + install_dir: testdatadir, + ) endif if false and get_option ('profiler') diff --git a/testsuite/css/parser/filter-invalid1.css b/testsuite/css/parser/filter-invalid1.css new file mode 100644 index 0000000000..52580b853e --- /dev/null +++ b/testsuite/css/parser/filter-invalid1.css @@ -0,0 +1,3 @@ +a { + filter: blur(-1px); +} diff --git a/testsuite/css/parser/filter-invalid1.errors b/testsuite/css/parser/filter-invalid1.errors new file mode 100644 index 0000000000..abed7c492d --- /dev/null +++ b/testsuite/css/parser/filter-invalid1.errors @@ -0,0 +1 @@ +filter-invalid1.css:2:16-20: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid1.ref.css b/testsuite/css/parser/filter-invalid1.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid1.ref.css diff --git a/testsuite/css/parser/filter-invalid2.css b/testsuite/css/parser/filter-invalid2.css new file mode 100644 index 0000000000..3d83236fb0 --- /dev/null +++ b/testsuite/css/parser/filter-invalid2.css @@ -0,0 +1,3 @@ +a { + filter: brightness(-100%); +} diff --git a/testsuite/css/parser/filter-invalid2.errors b/testsuite/css/parser/filter-invalid2.errors new file mode 100644 index 0000000000..7f6e672933 --- /dev/null +++ b/testsuite/css/parser/filter-invalid2.errors @@ -0,0 +1 @@ +filter-invalid2.css:2:22-27: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid2.ref.css b/testsuite/css/parser/filter-invalid2.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid2.ref.css diff --git a/testsuite/css/parser/filter-invalid3.css b/testsuite/css/parser/filter-invalid3.css new file mode 100644 index 0000000000..49640bf7fe --- /dev/null +++ b/testsuite/css/parser/filter-invalid3.css @@ -0,0 +1,3 @@ +a { + filter: contrast(-100%); +} diff --git a/testsuite/css/parser/filter-invalid3.errors b/testsuite/css/parser/filter-invalid3.errors new file mode 100644 index 0000000000..974ad14139 --- /dev/null +++ b/testsuite/css/parser/filter-invalid3.errors @@ -0,0 +1 @@ +filter-invalid3.css:2:20-25: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid3.ref.css b/testsuite/css/parser/filter-invalid3.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid3.ref.css diff --git a/testsuite/css/parser/filter-invalid4.css b/testsuite/css/parser/filter-invalid4.css new file mode 100644 index 0000000000..0cd2ab68b2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid4.css @@ -0,0 +1,3 @@ +a { + filter: grayscale(-100%); +} diff --git a/testsuite/css/parser/filter-invalid4.errors b/testsuite/css/parser/filter-invalid4.errors new file mode 100644 index 0000000000..93544a8c1c --- /dev/null +++ b/testsuite/css/parser/filter-invalid4.errors @@ -0,0 +1 @@ +filter-invalid4.css:2:21-26: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid4.ref.css b/testsuite/css/parser/filter-invalid4.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid4.ref.css diff --git a/testsuite/css/parser/filter-invalid5.css b/testsuite/css/parser/filter-invalid5.css new file mode 100644 index 0000000000..ccdc682b8e --- /dev/null +++ b/testsuite/css/parser/filter-invalid5.css @@ -0,0 +1,3 @@ +a { + filter: invert(-100%); +} diff --git a/testsuite/css/parser/filter-invalid5.errors b/testsuite/css/parser/filter-invalid5.errors new file mode 100644 index 0000000000..5d385e479a --- /dev/null +++ b/testsuite/css/parser/filter-invalid5.errors @@ -0,0 +1 @@ +filter-invalid5.css:2:18-23: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid5.ref.css b/testsuite/css/parser/filter-invalid5.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid5.ref.css diff --git a/testsuite/css/parser/filter-invalid6.css b/testsuite/css/parser/filter-invalid6.css new file mode 100644 index 0000000000..3aa37e0e51 --- /dev/null +++ b/testsuite/css/parser/filter-invalid6.css @@ -0,0 +1,3 @@ +a { + filter: opacity(-100%); +} diff --git a/testsuite/css/parser/filter-invalid6.errors b/testsuite/css/parser/filter-invalid6.errors new file mode 100644 index 0000000000..4b2f261867 --- /dev/null +++ b/testsuite/css/parser/filter-invalid6.errors @@ -0,0 +1 @@ +filter-invalid6.css:2:19-24: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid6.ref.css b/testsuite/css/parser/filter-invalid6.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid6.ref.css diff --git a/testsuite/css/parser/filter-invalid7.css b/testsuite/css/parser/filter-invalid7.css new file mode 100644 index 0000000000..7e0e7a3835 --- /dev/null +++ b/testsuite/css/parser/filter-invalid7.css @@ -0,0 +1,3 @@ +a { + filter: saturate(-100%); +} diff --git a/testsuite/css/parser/filter-invalid7.errors b/testsuite/css/parser/filter-invalid7.errors new file mode 100644 index 0000000000..615c191e9c --- /dev/null +++ b/testsuite/css/parser/filter-invalid7.errors @@ -0,0 +1 @@ +filter-invalid7.css:2:20-25: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid7.ref.css b/testsuite/css/parser/filter-invalid7.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid7.ref.css diff --git a/testsuite/css/parser/filter-invalid8.css b/testsuite/css/parser/filter-invalid8.css new file mode 100644 index 0000000000..c5d000c349 --- /dev/null +++ b/testsuite/css/parser/filter-invalid8.css @@ -0,0 +1,3 @@ +a { + filter: sepia(-100%); +} diff --git a/testsuite/css/parser/filter-invalid8.errors b/testsuite/css/parser/filter-invalid8.errors new file mode 100644 index 0000000000..5dde01fad0 --- /dev/null +++ b/testsuite/css/parser/filter-invalid8.errors @@ -0,0 +1 @@ +filter-invalid8.css:2:17-22: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/css/parser/filter-invalid8.ref.css b/testsuite/css/parser/filter-invalid8.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid8.ref.css diff --git a/testsuite/css/parser/filter-invalid9.css b/testsuite/css/parser/filter-invalid9.css new file mode 100644 index 0000000000..beaf0b2ef3 --- /dev/null +++ b/testsuite/css/parser/filter-invalid9.css @@ -0,0 +1,3 @@ +a { + filter: drop-shadow(none); +} diff --git a/testsuite/css/parser/filter-invalid9.errors b/testsuite/css/parser/filter-invalid9.errors new file mode 100644 index 0000000000..47893d496e --- /dev/null +++ b/testsuite/css/parser/filter-invalid9.errors @@ -0,0 +1 @@ +filter-invalid9.css:2:23-27: error: GTK_CSS_PARSER_ERROR_SYNTAX diff --git a/testsuite/css/parser/filter-invalid9.ref.css b/testsuite/css/parser/filter-invalid9.ref.css new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/css/parser/filter-invalid9.ref.css diff --git a/testsuite/css/parser/filter.css b/testsuite/css/parser/filter.css new file mode 100644 index 0000000000..8a114e590a --- /dev/null +++ b/testsuite/css/parser/filter.css @@ -0,0 +1,23 @@ +a { + filter: initial; +} + +b { + filter: inherit; +} + +c { + filter: unset; +} + +d { + filter: none; +} + +e { + filter: blur(2px) brightness(20%) contrast(120%) grayscale(100%) hue-rotate(45deg) invert(50%) opacity(25%) saturate(90%) sepia(100%); +} + +f { + filter: drop-shadow(rgb(255,0,0) 1px 2px); +} diff --git a/testsuite/css/parser/filter.ref.css b/testsuite/css/parser/filter.ref.css new file mode 100644 index 0000000000..6e9c6ca6ac --- /dev/null +++ b/testsuite/css/parser/filter.ref.css @@ -0,0 +1,23 @@ +a { + filter: initial; +} + +b { + filter: inherit; +} + +c { + filter: unset; +} + +d { + filter: none; +} + +e { + filter: blur(2px) brightness(20%) contrast(120%) grayscale(100%) hue-rotate(45deg) invert(50%) opacity(25%) saturate(90%) sepia(100%); +} + +f { + filter: drop-shadow(1px 2px rgb(255,0,0)); +} diff --git a/testsuite/css/parser/meson.build b/testsuite/css/parser/meson.build index b398251450..2d476f018d 100644 --- a/testsuite/css/parser/meson.build +++ b/testsuite/css/parser/meson.build @@ -311,6 +311,35 @@ test_data = [ 'doubled.css', 'doubled.ref.css', 'empty.css', + 'filter.css', + 'filter.ref.css', + 'filter-invalid1.css', + 'filter-invalid1.errors', + 'filter-invalid1.ref.css', + 'filter-invalid2.css', + 'filter-invalid2.errors', + 'filter-invalid2.ref.css', + 'filter-invalid3.css', + 'filter-invalid3.errors', + 'filter-invalid3.ref.css', + 'filter-invalid4.css', + 'filter-invalid4.errors', + 'filter-invalid4.ref.css', + 'filter-invalid5.css', + 'filter-invalid5.errors', + 'filter-invalid5.ref.css', + 'filter-invalid6.css', + 'filter-invalid6.errors', + 'filter-invalid6.ref.css', + 'filter-invalid7.css', + 'filter-invalid7.errors', + 'filter-invalid7.ref.css', + 'filter-invalid8.css', + 'filter-invalid8.errors', + 'filter-invalid8.ref.css', + 'filter-invalid9.css', + 'filter-invalid9.errors', + 'filter-invalid9.ref.css', 'font-family.css', 'font-family.ref.css', 'font-size.css', diff --git a/testsuite/css/test-css-value.c b/testsuite/css/test-css-value.c deleted file mode 100644 index acbaf37397..0000000000 --- a/testsuite/css/test-css-value.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * Author: - * Matthias Clasen <mclasen@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "config.h" - -#include <gtk/gtk.h> -#include "gtk/gtkcssvalueprivate.h" -#include "gtk/gtkcsscolorvalueprivate.h" -#include "gtk/gtkcssstylepropertyprivate.h" - -static gboolean -color_is_near (const GdkRGBA *color1, - const GdkRGBA *color2) -{ - if (fabs (color1->red - color2->red) > FLT_EPSILON) - return FALSE; - if (fabs (color1->green - color2->green) > FLT_EPSILON) - return FALSE; - if (fabs (color1->blue- color2->blue) > FLT_EPSILON) - return FALSE; - if (fabs (color1->alpha- color2->alpha) > FLT_EPSILON) - return FALSE; - return TRUE; -} - -static gboolean -value_is_near (int prop, - GtkCssValue *value1, - GtkCssValue *value2) -{ - if (_gtk_css_value_equal (value1, value2)) - return TRUE; - - switch (prop) - { - case GTK_CSS_PROPERTY_COLOR: - { - GtkCssValue *v1, *v2; - const GdkRGBA *c1, *c2; - gboolean res; - - v1 = _gtk_css_value_compute (value1, prop, NULL, NULL, NULL); - v2 = _gtk_css_value_compute (value2, prop, NULL, NULL, NULL); - c1 = gtk_css_color_value_get_rgba (v1); - c2 = gtk_css_color_value_get_rgba (v2); - - res = color_is_near (c1, c2); - - gtk_css_value_unref (v1); - gtk_css_value_unref (v2); - - return res; - } - break; - - default: - break; - } - - return FALSE; -} - -typedef struct { - int prop; - const char *value1; - const char *value2; - double progress; - const char *expected; -} ValueTransitionTest; - -static ValueTransitionTest tests[] = { - { GTK_CSS_PROPERTY_COLOR, "transparent", "rgb(255,0,0)", 0.25, "rgba(255,0,0,0.25)" }, - { GTK_CSS_PROPERTY_BOX_SHADOW, "none", "2px 2px 10px 4px rgb(200,200,200)", 0.5, "1px 1px 5px 2px rgb(100,100,100)" }, - { GTK_CSS_PROPERTY_BOX_SHADOW, "2px 2px 10px 4px rgb(200,200,200)", "none", 0.5, "1px 1px 5px 2px rgb(100,100,100)" }, -}; - -static void -test_transition (gconstpointer data) -{ - ValueTransitionTest *test = &tests[GPOINTER_TO_INT (data)]; - GtkStyleProperty *prop; - GtkCssValue *value1; - GtkCssValue *value2; - GtkCssValue *expected; - GtkCssValue *result; - GtkCssParser *parser; - GBytes *bytes; - - prop = (GtkStyleProperty *)_gtk_css_style_property_lookup_by_id (test->prop); - - bytes = g_bytes_new_static (test->value1, strlen (test->value1)); - parser = gtk_css_parser_new_for_bytes (bytes, NULL, NULL, NULL, NULL, NULL); - value1 = _gtk_style_property_parse_value (prop, parser); - gtk_css_parser_unref (parser); - g_bytes_unref (bytes); - - bytes = g_bytes_new_static (test->value1, strlen (test->value2)); - parser = gtk_css_parser_new_for_bytes (bytes, NULL, NULL, NULL, NULL, NULL); - value2 = _gtk_style_property_parse_value (prop, parser); - gtk_css_parser_unref (parser); - g_bytes_unref (bytes); - - bytes = g_bytes_new_static (test->value1, strlen (test->expected)); - parser = gtk_css_parser_new_for_bytes (bytes, NULL, NULL, NULL, NULL, NULL); - expected = _gtk_style_property_parse_value (prop, parser); - gtk_css_parser_unref (parser); - g_bytes_unref (bytes); - - result = _gtk_css_value_transition (value1, value2, test->prop, test->progress); - g_assert_true (value_is_near (test->prop, result, expected)); - - gtk_css_value_unref (value1); - gtk_css_value_unref (value2); - gtk_css_value_unref (expected); - gtk_css_value_unref (result); -} - -int -main (int argc, char **argv) -{ - GtkStyleProperty *previous; - int j; - - gtk_test_init (&argc, &argv); - - previous = NULL; - j = 0; - for (int i = 0; i < G_N_ELEMENTS (tests); i++) - { - ValueTransitionTest *test = &tests[i]; - GtkStyleProperty *prop; - char *path; - - prop = (GtkStyleProperty *)_gtk_css_style_property_lookup_by_id (test->prop); - if (prop != previous) - { - previous = prop; - j = 0; - } - else - j++; - - path = g_strdup_printf ("/css/value/transition/%s/%d", _gtk_style_property_get_name ((GtkStyleProperty *)prop), j); - g_test_add_data_func (path, GINT_TO_POINTER (i), test_transition); - g_free (path); - } - - return g_test_run (); -} diff --git a/testsuite/css/transition.c b/testsuite/css/transition.c new file mode 100644 index 0000000000..6d180b0b7d --- /dev/null +++ b/testsuite/css/transition.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2021 Red Hat Inc. + * + * Author: + * Matthias Clasen <mclasen@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gtk/gtk.h> +#include "gtk/gtkcssvalueprivate.h" +#include "gtk/gtkcsscolorvalueprivate.h" +#include "gtk/gtkcssnumbervalueprivate.h" +#include "gtk/gtkcssstylepropertyprivate.h" +#include "gtk/gtkcssstaticstyleprivate.h" + +static gboolean +color_is_near (const GdkRGBA *color1, + const GdkRGBA *color2) +{ + if (fabs (color1->red - color2->red) > FLT_EPSILON) + return FALSE; + if (fabs (color1->green - color2->green) > FLT_EPSILON) + return FALSE; + if (fabs (color1->blue- color2->blue) > FLT_EPSILON) + return FALSE; + if (fabs (color1->alpha- color2->alpha) > FLT_EPSILON) + return FALSE; + return TRUE; +} + +static gboolean +value_is_near (int prop, + GtkCssValue *value1, + GtkCssValue *value2) +{ + if (_gtk_css_value_equal (value1, value2)) + return TRUE; + + switch (prop) + { + case GTK_CSS_PROPERTY_COLOR: + { + const GdkRGBA *c1, *c2; + gboolean res; + + c1 = gtk_css_color_value_get_rgba (value1); + c2 = gtk_css_color_value_get_rgba (value2); + + res = color_is_near (c1, c2); + + return res; + } + break; + + case GTK_CSS_PROPERTY_FONT_SIZE: + { + double n1, n2; + + n1 = _gtk_css_number_value_get (value1, 100); + n2 = _gtk_css_number_value_get (value2, 100); + + return fabs (n1 - n2) < FLT_EPSILON; + } + break; + + default: + break; + } + + return FALSE; +} + +static void +assert_css_value (int prop, + GtkCssValue *result, + GtkCssValue *expected) +{ + if (result == expected) + return; + + if (((result == NULL) != (expected == NULL)) || + !value_is_near (prop, result, expected)) + { + char *r = result ? _gtk_css_value_to_string (result) : g_strdup ("(nil)"); + char *e = expected ? _gtk_css_value_to_string (expected) : g_strdup ("(nil)"); + g_print ("Expected %s got %s\n", e, r); + g_free (r); + g_free (e); + + g_assert_not_reached (); + } +} + +/* Tests for css transitions */ + +typedef struct { + int prop; + const char *value1; + const char *value2; + double progress; + const char *value3; +} ValueTransitionTest; + +static ValueTransitionTest tests[] = { + { GTK_CSS_PROPERTY_COLOR, "transparent", "rgb(255,0,0)", 0.25, "rgba(255,0,0,0.25)" }, + { GTK_CSS_PROPERTY_BOX_SHADOW, "none", "2px 2px 10px 4px rgb(200,200,200)", 0.5, "1px 1px 5px 2px rgba(200,200,200,0.5)" }, + { GTK_CSS_PROPERTY_BOX_SHADOW, "2px 2px 10px 4px rgb(200,200,200)", "none", 0.5, "1px 1px 5px 2px rgba(200,200,200,0.5)" }, + { GTK_CSS_PROPERTY_BOX_SHADOW, "2px 2px 10px 4px rgb(200,200,200), 0px 10px 8px 6px rgb(200,100,0)", "none", 0.5, "1px 1px 5px 2px rgba(200,200,200,0.5), 0px 5px 4px 3px rgba(200,100,0,0.5)" }, + { GTK_CSS_PROPERTY_FONT_SIZE, "12px", "16px", 0.25, "13px" }, + { GTK_CSS_PROPERTY_FONT_SIZE, "10px", "10pt", 0.5, "11.66666667px" }, + { GTK_CSS_PROPERTY_FONT_FAMILY, "cantarell", "sans", 0, "cantarell"}, + { GTK_CSS_PROPERTY_FONT_FAMILY, "cantarell", "sans", 1, "sans" }, + { GTK_CSS_PROPERTY_FONT_FAMILY, "cantarell", "sans", 0.5, NULL }, + { GTK_CSS_PROPERTY_BACKGROUND_POSITION, "20px 10px", "40px", 0.5, "30px calc(5px + 25%)" }, + //TODO We don't currently transition border-image-width + //{ GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH, "10px 20px", "0px", 0.5, "5px 10px 0.5px 0.5px" }, + { GTK_CSS_PROPERTY_FILTER, "none", "blur(6px)", 0.5, "blur(3px)" }, + { GTK_CSS_PROPERTY_FILTER, "none", "blur(6px),contrast(0.6)", 0.5, "blur(3px),contrast(0.3)" }, + { GTK_CSS_PROPERTY_FILTER, "contrast(0.6)", "blur(6px)", 0.5, NULL}, +}; + +static GtkCssValue * +value_from_string (GtkStyleProperty *prop, + const char *str) +{ + GBytes *bytes; + GtkCssParser *parser; + GtkCssValue *value; + + bytes = g_bytes_new_static (str, strlen (str)); + parser = gtk_css_parser_new_for_bytes (bytes, NULL, NULL, NULL, NULL, NULL); + value = _gtk_style_property_parse_value (prop, parser); + gtk_css_parser_unref (parser); + g_bytes_unref (bytes); + + return value; +} + +static void +test_transition (gconstpointer data) +{ + ValueTransitionTest *test = &tests[GPOINTER_TO_INT (data)]; + GtkStyleProperty *prop; + GtkCssValue *value1; + GtkCssValue *value2; + GtkCssValue *value3; + GtkCssValue *computed1; + GtkCssValue *computed2; + GtkCssValue *computed3; + GtkCssValue *result; + GtkStyleProvider *provider; + GtkCssStyle *style; + + provider = GTK_STYLE_PROVIDER (gtk_settings_get_default ()); + style = gtk_css_static_style_get_default (); + + prop = (GtkStyleProperty *)_gtk_css_style_property_lookup_by_id (test->prop); + + value1 = value_from_string (prop, test->value1); + g_assert_nonnull (value1); + computed1 = _gtk_css_value_compute (value1, test->prop, provider, style, NULL); + + value2 = value_from_string (prop, test->value2); + g_assert_nonnull (value1); + computed2 = _gtk_css_value_compute (value2, test->prop, provider, style, NULL); + + if (test->value3) + { + value3 = value_from_string (prop, test->value3); + computed3 = _gtk_css_value_compute (value3, test->prop, provider, style, NULL); + } + else + { + value3 = computed3 = NULL; + } + + result = _gtk_css_value_transition (computed1, computed2, test->prop, test->progress); + assert_css_value (test->prop, result, computed3); + + gtk_css_value_unref (value1); + gtk_css_value_unref (value2); + if (value3) + gtk_css_value_unref (value3); + gtk_css_value_unref (computed1); + gtk_css_value_unref (computed2); + if (computed3) + gtk_css_value_unref (computed3); + gtk_css_value_unref (result); +} + +int +main (int argc, char **argv) +{ + GtkStyleProperty *previous; + int j; + + gtk_test_init (&argc, &argv); + + previous = NULL; + j = 0; + for (int i = 0; i < G_N_ELEMENTS (tests); i++) + { + ValueTransitionTest *test = &tests[i]; + GtkStyleProperty *prop; + char *path; + + prop = (GtkStyleProperty *)_gtk_css_style_property_lookup_by_id (test->prop); + if (prop != previous) + { + previous = prop; + j = 0; + } + else + j++; + + path = g_strdup_printf ("/css/value/transition/%s/%d", _gtk_style_property_get_name ((GtkStyleProperty *)prop), j); + g_test_add_data_func (path, GINT_TO_POINTER (i), test_transition); + g_free (path); + } + + return g_test_run (); +} diff --git a/testsuite/reftests/frame-inhibitor.c b/testsuite/reftests/frame-inhibitor.c index 567dc07ae1..9d699c4224 100644 --- a/testsuite/reftests/frame-inhibitor.c +++ b/testsuite/reftests/frame-inhibitor.c @@ -30,6 +30,7 @@ tick_callback_for_1_frame (GtkWidget *widget, gpointer unused) { reftest_uninhibit_snapshot (); + gtk_widget_queue_draw (widget); return G_SOURCE_REMOVE; } |