summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/icon-browser/iconbrowserwin.c22
-rw-r--r--gdk/gdk.c2
-rw-r--r--gdk/x11/gdkdrag-x11.c87
-rw-r--r--gdk/x11/gdkdrop-x11.c51
-rw-r--r--gdk/x11/gdkkeys-x11.c2
-rw-r--r--gsk/vulkan/gskvulkanimage.c2
-rw-r--r--gtk/a11y/gtkatspiaction.c8
-rw-r--r--gtk/gtkcomposetable.c2
-rw-r--r--gtk/gtkcssbordervalue.c2
-rw-r--r--gtk/gtkcssfiltervalue.c84
-rw-r--r--gtk/gtkcssselector.c5
-rw-r--r--gtk/gtkcssshadowvalue.c119
-rw-r--r--gtk/gtkcssshadowvalueprivate.h8
-rw-r--r--gtk/gtkcssstylepropertyimpl.c4
-rw-r--r--gtk/gtkcssvalue.c4
-rw-r--r--gtk/gtkdialog.c50
-rw-r--r--gtk/gtkgrid.c59
-rw-r--r--gtk/gtklistbase.c2
-rw-r--r--gtk/gtkmessagedialog.c2
-rw-r--r--gtk/gtkshow.c2
-rw-r--r--gtk/gtktextbtree.c4
-rw-r--r--gtk/gtktreemodelfilter.c3
-rw-r--r--gtk/gtkwidget.c2
-rw-r--r--gtk/meson.build12
-rw-r--r--gtk/theme/Adwaita/_common.scss8
-rw-r--r--meson.build7
-rw-r--r--modules/media/meson.build2
-rw-r--r--modules/printbackends/meson.build4
-rw-r--r--po/cs.po4
-rw-r--r--testsuite/css/data.test.in4
-rw-r--r--testsuite/css/meson.build13
-rw-r--r--testsuite/css/parser/filter-invalid1.css3
-rw-r--r--testsuite/css/parser/filter-invalid1.errors1
-rw-r--r--testsuite/css/parser/filter-invalid1.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid2.css3
-rw-r--r--testsuite/css/parser/filter-invalid2.errors1
-rw-r--r--testsuite/css/parser/filter-invalid2.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid3.css3
-rw-r--r--testsuite/css/parser/filter-invalid3.errors1
-rw-r--r--testsuite/css/parser/filter-invalid3.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid4.css3
-rw-r--r--testsuite/css/parser/filter-invalid4.errors1
-rw-r--r--testsuite/css/parser/filter-invalid4.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid5.css3
-rw-r--r--testsuite/css/parser/filter-invalid5.errors1
-rw-r--r--testsuite/css/parser/filter-invalid5.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid6.css3
-rw-r--r--testsuite/css/parser/filter-invalid6.errors1
-rw-r--r--testsuite/css/parser/filter-invalid6.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid7.css3
-rw-r--r--testsuite/css/parser/filter-invalid7.errors1
-rw-r--r--testsuite/css/parser/filter-invalid7.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid8.css3
-rw-r--r--testsuite/css/parser/filter-invalid8.errors1
-rw-r--r--testsuite/css/parser/filter-invalid8.ref.css0
-rw-r--r--testsuite/css/parser/filter-invalid9.css3
-rw-r--r--testsuite/css/parser/filter-invalid9.errors1
-rw-r--r--testsuite/css/parser/filter-invalid9.ref.css0
-rw-r--r--testsuite/css/parser/filter.css23
-rw-r--r--testsuite/css/parser/filter.ref.css23
-rw-r--r--testsuite/css/parser/meson.build29
-rw-r--r--testsuite/css/test-css-value.c166
-rw-r--r--testsuite/css/transition.c236
-rw-r--r--testsuite/reftests/frame-inhibitor.c1
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 *
diff --git a/gdk/gdk.c b/gdk/gdk.c
index 953079cdd5..a0938af58a 100644
--- a/gdk/gdk.c
+++ b/gdk/gdk.c
@@ -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 (&GTK_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 = { &GTK_CSS_VALUE_SHADOW, 1, TRUE, 0 };
+static GtkCssValue shadow_none_singleton = { &GTK_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 (&GTK_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 == &GTK_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,
)
diff --git a/po/cs.po b/po/cs.po
index 0e942948e3..53f48eff53 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -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;
}