Compare commits

...

6 Commits

Author SHA1 Message Date
Benjamin Otte
7f7700d7d9 menu: Only set position in one place 2019-05-29 21:01:50 +02:00
Benjamin Otte
43f4559d17 menu: Simplify function
No need to do complicated math when we can just look at the allocation.
2019-05-29 21:01:50 +02:00
Benjamin Otte
52f5c7830c testgtk: Remove CSS loading
The CSS is not fun.
And it doesn't work.
2019-05-29 21:01:49 +02:00
Benjamin Otte
512778b83a menuitem: Introduce gtk_menu_item_get_menu_shell()
Returns the parent menu shell or NULL.

Replace all calls to gtk_widget_get_parent() with this function.
2019-05-29 21:01:49 +02:00
Benjamin Otte
8c4517cf75 rendernodeparser: Handle empty Cairo nodes
Cairo nodes can contain a NULL surface if they have never been drawn to.
Make this the default Cairo node.
2019-05-29 16:52:13 +02:00
Benjamin Otte
f3e9e3fe82 rendernodeparser: Parse cairo script
Use cairo-script-interpreter to parse the scripts that generate cairo
nodes.

This requires libcairoscriptinterpreter.so to work properly, but if
it isn't found we disable this (unimportant for normal functioning)
code and just emits a parser warning.
The testsuite requires it however or it will fail.

A new test is included that tests all of this.
2019-05-29 16:52:13 +02:00
15 changed files with 264 additions and 170 deletions

View File

@@ -294,6 +294,8 @@
#mesondefine GTK_PRINT_BACKENDS #mesondefine GTK_PRINT_BACKENDS
#mesondefine HAVE_CAIRO_SCRIPT_INTERPRETER
#mesondefine HAVE_HARFBUZZ #mesondefine HAVE_HARFBUZZ
#mesondefine HAVE_PANGOFT #mesondefine HAVE_PANGOFT

View File

@@ -36,6 +36,9 @@
#ifdef CAIRO_HAS_SCRIPT_SURFACE #ifdef CAIRO_HAS_SCRIPT_SURFACE
#include <cairo-script.h> #include <cairo-script.h>
#endif #endif
#ifdef HAVE_CAIRO_SCRIPT_INTERPRETER
#include <cairo-script-interpreter.h>
#endif
typedef struct _Declaration Declaration; typedef struct _Declaration Declaration;
@@ -132,6 +135,131 @@ clear_texture (gpointer inout_texture)
g_clear_object ((GdkTexture **) inout_texture); g_clear_object ((GdkTexture **) inout_texture);
} }
static cairo_surface_t *
csi_hooks_surface_create (void *closure,
cairo_content_t content,
double width,
double height,
long uid)
{
return cairo_surface_create_similar (closure, content, width, height);
}
static const cairo_user_data_key_t csi_hooks_key;
static cairo_t *
csi_hooks_context_create (void *closure,
cairo_surface_t *surface)
{
cairo_t *cr = cairo_create (surface);
cairo_set_user_data (cr,
&csi_hooks_key,
cairo_surface_reference (surface),
(cairo_destroy_func_t) cairo_surface_destroy);
return cr;
}
static void
csi_hooks_context_destroy (void *closure,
void *ptr)
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_get_user_data (ptr, &csi_hooks_key);
cr = cairo_create (closure);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
static gboolean
parse_script (GtkCssParser *parser,
gpointer out_data)
{
#ifdef HAVE_CAIRO_SCRIPT_INTERPRETER
GError *error = NULL;
GBytes *bytes;
GtkCssLocation start_location;
char *url, *scheme;
cairo_script_interpreter_t *csi;
cairo_script_interpreter_hooks_t hooks = {
.surface_create = csi_hooks_surface_create,
.context_create = csi_hooks_context_create,
.context_destroy = csi_hooks_context_destroy,
};
start_location = *gtk_css_parser_get_start_location (parser);
url = gtk_css_parser_consume_url (parser);
if (url == NULL)
return FALSE;
scheme = g_uri_parse_scheme (url);
if (scheme && g_ascii_strcasecmp (scheme, "data") == 0)
{
bytes = gtk_css_data_url_parse (url, NULL, &error);
}
else
{
GFile *file;
file = gtk_css_parser_resolve_url (parser, url);
bytes = g_file_load_bytes (file, NULL, NULL, &error);
g_object_unref (file);
}
g_free (scheme);
g_free (url);
if (bytes == NULL)
{
gtk_css_parser_emit_error (parser,
&start_location,
gtk_css_parser_get_end_location (parser),
error);
g_clear_error (&error);
return FALSE;
}
hooks.closure = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
csi = cairo_script_interpreter_create ();
cairo_script_interpreter_install_hooks (csi, &hooks);
cairo_script_interpreter_feed_string (csi, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
g_bytes_unref (bytes);
if (cairo_surface_status (hooks.closure) != CAIRO_STATUS_SUCCESS)
{
gtk_css_parser_error_value (parser, "Invalid Cairo script: %s", cairo_status_to_string (cairo_surface_status (hooks.closure)));
cairo_script_interpreter_destroy (csi);
return FALSE;
}
if (cairo_script_interpreter_destroy (csi) != CAIRO_STATUS_SUCCESS)
{
gtk_css_parser_error_value (parser, "Invalid Cairo script");
cairo_surface_destroy (hooks.closure);
return FALSE;
}
*(cairo_surface_t **) out_data = hooks.closure;
return TRUE;
#else
gtk_css_parser_warn (parser,
GTK_CSS_PARSER_WARNING_UNIMPLEMENTED,
gtk_css_parser_get_block_location (parser),
gtk_css_parser_get_start_location (parser),
"GTK was compiled with script interpreter support. Using fallback pixel data for Cairo node.");
*(cairo_surface_t **) out_data = NULL;
return TRUE;
#endif
}
static void
clear_surface (gpointer inout_surface)
{
g_clear_pointer ((cairo_surface_t **) inout_surface, cairo_surface_destroy);
}
static gboolean static gboolean
parse_rounded_rect (GtkCssParser *parser, parse_rounded_rect (GtkCssParser *parser,
gpointer out_rect) gpointer out_rect)
@@ -930,35 +1058,40 @@ parse_cairo_node (GtkCssParser *parser)
{ {
graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50); graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50);
GdkTexture *pixels = NULL; GdkTexture *pixels = NULL;
cairo_surface_t *surface = NULL;
const Declaration declarations[] = { const Declaration declarations[] = {
{ "bounds", parse_rect, NULL, &bounds }, { "bounds", parse_rect, NULL, &bounds },
{ "pixels", parse_texture, clear_texture, &pixels } { "pixels", parse_texture, clear_texture, &pixels },
{ "script", parse_script, clear_surface, &surface }
}; };
GskRenderNode *node; GskRenderNode *node;
cairo_t *cr;
parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
node = gsk_cairo_node_new (&bounds); node = gsk_cairo_node_new (&bounds);
cr = gsk_cairo_node_get_draw_context (node); if (surface != NULL)
if (pixels != NULL)
{ {
cairo_surface_t *surface; cairo_t *cr = gsk_cairo_node_get_draw_context (node);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
else if (pixels != NULL)
{
cairo_t *cr = gsk_cairo_node_get_draw_context (node);
surface = gdk_texture_download_surface (pixels); surface = gdk_texture_download_surface (pixels);
cairo_set_source_surface (cr, surface, 0, 0); cairo_set_source_surface (cr, surface, 0, 0);
cairo_paint (cr); cairo_paint (cr);
cairo_surface_destroy (surface); cairo_destroy (cr);
} }
else else
{ {
gdk_cairo_set_source_rgba (cr, &GDK_RGBA ("FF00CC")); /* do nothing */
cairo_paint (cr);
} }
cairo_destroy (cr);
g_clear_object (&pixels); g_clear_object (&pixels);
g_clear_pointer (&surface, cairo_surface_destroy);
return node; return node;
} }
@@ -2246,36 +2379,39 @@ render_node_print (Printer *p,
start_node (p, "cairo"); start_node (p, "cairo");
append_rect_param (p, "bounds", &node->bounds); append_rect_param (p, "bounds", &node->bounds);
array = g_byte_array_new (); if (surface != NULL)
cairo_surface_write_to_png_stream (surface, cairo_write_array, array); {
b64 = g_base64_encode (array->data, array->len); array = g_byte_array_new ();
cairo_surface_write_to_png_stream (surface, cairo_write_array, array);
b64 = g_base64_encode (array->data, array->len);
_indent (p); _indent (p);
g_string_append_printf (p->str, "pixels: url(\"data:image/png;base64,%s\");\n", b64); g_string_append_printf (p->str, "pixels: url(\"data:image/png;base64,%s\");\n", b64);
g_free (b64); g_free (b64);
g_byte_array_free (array, TRUE); g_byte_array_free (array, TRUE);
#ifdef CAIRO_HAS_SCRIPT_SURFACE #ifdef CAIRO_HAS_SCRIPT_SURFACE
if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_RECORDING) if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_RECORDING)
{
cairo_device_t *script;
array = g_byte_array_new ();
script = cairo_script_create_for_stream (cairo_write_array, array);
if (cairo_script_from_recording_surface (script, surface) == CAIRO_STATUS_SUCCESS)
{ {
b64 = g_base64_encode (array->data, array->len); cairo_device_t *script;
_indent (p);
g_string_append_printf (p->str, "script: url(\"data:;base64,%s\");\n", b64);
g_free (b64);
}
cairo_device_destroy (script); array = g_byte_array_new ();
g_byte_array_free (array, TRUE); script = cairo_script_create_for_stream (cairo_write_array, array);
}
if (cairo_script_from_recording_surface (script, surface) == CAIRO_STATUS_SUCCESS)
{
b64 = g_base64_encode (array->data, array->len);
_indent (p);
g_string_append_printf (p->str, "script: url(\"data:;base64,%s\");\n", b64);
g_free (b64);
}
cairo_device_destroy (script);
g_byte_array_free (array, TRUE);
}
#endif #endif
}
end_node (p); end_node (p);
} }

View File

@@ -156,6 +156,7 @@ gsk_deps = [
graphene_dep, graphene_dep,
pango_dep, pango_dep,
cairo_dep, cairo_dep,
cairo_csi_dep,
pixbuf_dep, pixbuf_dep,
libgdk_dep, libgdk_dep,
] ]

View File

@@ -62,6 +62,8 @@ typedef enum
* deprecated and will be removed in a future version * deprecated and will be removed in a future version
* @GTK_CSS_PARSER_WARNING_SYNTAX: A syntax construct was used * @GTK_CSS_PARSER_WARNING_SYNTAX: A syntax construct was used
* that should be avoided * that should be avoided
* @GTK_CSS_PARSER_WARNING_UNIMPLEMENTED: A feature is not
* implemented
* *
* Warnings that can occur while parsing CSS. * Warnings that can occur while parsing CSS.
* *

View File

@@ -1814,6 +1814,7 @@ gtk_menu_update_scroll_offset (GtkMenu *menu,
gpointer user_data) gpointer user_data)
{ {
GtkBorder arrows_border; GtkBorder arrows_border;
int offset;
g_return_if_fail (GTK_IS_MENU (menu)); g_return_if_fail (GTK_IS_MENU (menu));
@@ -1821,8 +1822,8 @@ gtk_menu_update_scroll_offset (GtkMenu *menu,
return; return;
get_arrows_border (menu, &arrows_border); get_arrows_border (menu, &arrows_border);
menu->priv->scroll_offset = arrows_border.top + (final_rect->y - flipped_rect->y); offset = arrows_border.top + (final_rect->y - flipped_rect->y);
gtk_menu_scroll_to (menu, menu->priv->scroll_offset); gtk_menu_scroll_to (menu, offset);
} }
/** /**
@@ -3521,30 +3522,19 @@ compute_child_offset (GtkMenu *menu,
gint *height) gint *height)
{ {
GtkMenuPrivate *priv = menu->priv; GtkMenuPrivate *priv = menu->priv;
gint item_top_attach; GtkAllocation allocation;
gint child_offset = 0;
gint i;
get_effective_child_attach (menu_item, &item_top_attach); gtk_widget_get_allocation (menu_item, &allocation);
if (allocation.width > 0)
{
if (offset)
*offset = allocation.y + priv->scroll_offset;
if (height)
*height = allocation.height;
return TRUE;
}
/* there is a possibility that we get called before _size_request, return FALSE;
* so check the height table for safety.
*/
if (!priv->heights || priv->heights_length < gtk_menu_get_n_rows (menu))
return FALSE;
/* when we have a row with only invisible children, its height will
* be zero, so there's no need to check WIDGET_VISIBLE here
*/
for (i = 0; i < item_top_attach; i++)
child_offset += priv->heights[i];
if (offset)
*offset = child_offset;
if (height)
*height = priv->heights[item_top_attach];
return TRUE;
} }
static void static void

View File

@@ -262,6 +262,12 @@ gtk_menu_item_actionable_interface_init (GtkActionableInterface *iface)
iface->get_action_target_value = gtk_menu_item_get_action_target_value; iface->get_action_target_value = gtk_menu_item_get_action_target_value;
} }
static GtkMenuShell *
gtk_menu_item_get_menu_shell (GtkMenuItem *item)
{
return GTK_MENU_SHELL (gtk_widget_get_ancestor (GTK_WIDGET (item), GTK_TYPE_MENU_SHELL));
}
static void static void
gtk_menu_item_size_allocate (GtkWidget *widget, gtk_menu_item_size_allocate (GtkWidget *widget,
int width, int width,
@@ -273,13 +279,13 @@ gtk_menu_item_size_allocate (GtkWidget *widget,
GtkAllocation child_allocation; GtkAllocation child_allocation;
GtkTextDirection direction; GtkTextDirection direction;
GtkWidget *child; GtkWidget *child;
GtkWidget *parent; GtkMenuShell *shell;
g_return_if_fail (GTK_IS_MENU_ITEM (widget)); g_return_if_fail (GTK_IS_MENU_ITEM (widget));
direction = gtk_widget_get_direction (widget); direction = gtk_widget_get_direction (widget);
parent = gtk_widget_get_parent (widget); shell = gtk_menu_item_get_menu_shell (menu_item);
child = gtk_bin_get_child (GTK_BIN (widget)); child = gtk_bin_get_child (GTK_BIN (widget));
if (child) if (child)
@@ -290,7 +296,7 @@ gtk_menu_item_size_allocate (GtkWidget *widget,
child_allocation.x += priv->toggle_size; child_allocation.x += priv->toggle_size;
child_allocation.width -= priv->toggle_size; child_allocation.width -= priv->toggle_size;
if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator) if ((priv->submenu && !GTK_IS_MENU_BAR (shell)) || priv->reserve_indicator)
{ {
GtkAllocation arrow_alloc; GtkAllocation arrow_alloc;
@@ -359,13 +365,13 @@ gtk_menu_item_real_get_width (GtkWidget *widget,
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget); GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
GtkMenuItemPrivate *priv = menu_item->priv; GtkMenuItemPrivate *priv = menu_item->priv;
GtkWidget *child; GtkWidget *child;
GtkWidget *parent; GtkMenuShell *shell;
guint accel_width; guint accel_width;
gint min_width, nat_width; gint min_width, nat_width;
min_width = nat_width = 0; min_width = nat_width = 0;
parent = gtk_widget_get_parent (widget); shell = gtk_menu_item_get_menu_shell (menu_item);
child = gtk_bin_get_child (GTK_BIN (widget)); child = gtk_bin_get_child (GTK_BIN (widget));
if (child != NULL && gtk_widget_get_visible (child)) if (child != NULL && gtk_widget_get_visible (child))
@@ -375,7 +381,7 @@ gtk_menu_item_real_get_width (GtkWidget *widget,
gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1,
&child_min, &child_nat, NULL, NULL); &child_min, &child_nat, NULL, NULL);
if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator) if ((priv->submenu && !GTK_IS_MENU_BAR (shell)) || priv->reserve_indicator)
{ {
gint arrow_size; gint arrow_size;
@@ -412,7 +418,7 @@ gtk_menu_item_real_get_height (GtkWidget *widget,
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget); GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
GtkMenuItemPrivate *priv = menu_item->priv; GtkMenuItemPrivate *priv = menu_item->priv;
GtkWidget *child; GtkWidget *child;
GtkWidget *parent; GtkMenuShell *shell;
guint accel_width; guint accel_width;
gint min_height, nat_height; gint min_height, nat_height;
gint avail_size = 0; gint avail_size = 0;
@@ -422,7 +428,7 @@ gtk_menu_item_real_get_height (GtkWidget *widget,
if (for_size != -1) if (for_size != -1)
avail_size = for_size; avail_size = for_size;
parent = gtk_widget_get_parent (widget); shell = gtk_menu_item_get_menu_shell (menu_item);
child = gtk_bin_get_child (GTK_BIN (widget)); child = gtk_bin_get_child (GTK_BIN (widget));
if (child != NULL && gtk_widget_get_visible (child)) if (child != NULL && gtk_widget_get_visible (child))
@@ -430,7 +436,7 @@ gtk_menu_item_real_get_height (GtkWidget *widget,
gint child_min, child_nat; gint child_min, child_nat;
gint arrow_size = 0; gint arrow_size = 0;
if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator) if ((priv->submenu && !GTK_IS_MENU_BAR (shell)) || priv->reserve_indicator)
gtk_widget_measure (priv->arrow_widget, gtk_widget_measure (priv->arrow_widget,
GTK_ORIENTATION_VERTICAL, GTK_ORIENTATION_VERTICAL,
-1, -1,
@@ -871,7 +877,7 @@ gtk_menu_item_buildable_custom_finished (GtkBuildable *buildable,
GtkMenuShell *menu_shell; GtkMenuShell *menu_shell;
GtkWidget *attach; GtkWidget *attach;
menu_shell = GTK_MENU_SHELL (gtk_widget_get_parent (GTK_WIDGET (buildable))); menu_shell = gtk_menu_item_get_menu_shell (GTK_MENU_ITEM (buildable));
if (menu_shell) if (menu_shell)
{ {
while (GTK_IS_MENU (menu_shell) && while (GTK_IS_MENU (menu_shell) &&
@@ -938,7 +944,7 @@ update_arrow_widget (GtkMenuItem *menu_item)
gboolean should_have_arrow; gboolean should_have_arrow;
should_have_arrow = priv->reserve_indicator || should_have_arrow = priv->reserve_indicator ||
(priv->submenu && !GTK_IS_MENU_BAR (gtk_widget_get_parent (widget))); (priv->submenu && !GTK_IS_MENU_BAR (gtk_menu_item_get_menu_shell (menu_item)));
if (should_have_arrow) if (should_have_arrow)
{ {
@@ -993,9 +999,7 @@ gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
} }
update_arrow_widget (menu_item); update_arrow_widget (menu_item);
gtk_widget_queue_resize (widget);
if (gtk_widget_get_parent (widget))
gtk_widget_queue_resize (widget);
g_object_notify_by_pspec (G_OBJECT (menu_item), menu_item_props[PROP_SUBMENU]); g_object_notify_by_pspec (G_OBJECT (menu_item), menu_item_props[PROP_SUBMENU]);
} }
@@ -1113,7 +1117,7 @@ gtk_menu_item_enter (GtkEventController *controller,
gpointer user_data) gpointer user_data)
{ {
GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data); GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data);
GtkWidget *menu_shell; GtkMenuShell *menu_shell;
GdkEvent *event; GdkEvent *event;
gboolean is_focus, contains_focus; gboolean is_focus, contains_focus;
@@ -1128,17 +1132,17 @@ gtk_menu_item_enter (GtkEventController *controller,
gdk_event_get_source_device ((GdkEvent*) event)) gdk_event_get_source_device ((GdkEvent*) event))
return; return;
menu_shell = gtk_widget_get_parent (GTK_WIDGET (menu_item)); menu_shell = gtk_menu_item_get_menu_shell (menu_item);
g_object_get (controller, g_object_get (controller,
"is-pointer-focus", &is_focus, "is-pointer-focus", &is_focus,
"contains-pointer-focus", &contains_focus, "contains-pointer-focus", &contains_focus,
NULL); NULL);
if (GTK_IS_MENU_SHELL (menu_shell) && if (menu_shell != NULL &&
GTK_MENU_SHELL (menu_shell)->priv->active && menu_shell->priv->active &&
(is_focus || contains_focus)) (is_focus || contains_focus))
gtk_menu_shell_select_item (GTK_MENU_SHELL (menu_shell), GTK_WIDGET (menu_item)); gtk_menu_shell_select_item (menu_shell, GTK_WIDGET (menu_item));
} }
static void static void
@@ -1148,7 +1152,7 @@ gtk_menu_item_leave (GtkEventController *controller,
gpointer user_data) gpointer user_data)
{ {
GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data); GtkMenuItem *menu_item = GTK_MENU_ITEM (user_data);
GtkWidget *menu_shell = gtk_widget_get_parent (GTK_WIDGET (menu_item)); GtkMenuShell *menu_shell = gtk_menu_item_get_menu_shell (menu_item);
gboolean is_focus, contains_focus; gboolean is_focus, contains_focus;
g_object_get (controller, g_object_get (controller,
@@ -1156,10 +1160,10 @@ gtk_menu_item_leave (GtkEventController *controller,
"contains-pointer-focus", &contains_focus, "contains-pointer-focus", &contains_focus,
NULL); NULL);
if (GTK_IS_MENU_SHELL (menu_shell) && if (menu_shell &&
!menu_item->priv->submenu && !menu_item->priv->submenu &&
!(is_focus || contains_focus)) !(is_focus || contains_focus))
gtk_menu_shell_deselect (GTK_MENU_SHELL (menu_shell)); gtk_menu_shell_deselect (menu_shell);
} }
static void static void
@@ -1205,19 +1209,18 @@ static gboolean
gtk_menu_item_mnemonic_activate (GtkWidget *widget, gtk_menu_item_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling) gboolean group_cycling)
{ {
GtkWidget *parent; GtkMenuShell *menu_shell;
menu_shell = gtk_menu_item_get_menu_shell (GTK_MENU_ITEM (widget));
parent = gtk_widget_get_parent (widget); if (menu_shell)
_gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE);
if (GTK_IS_MENU_SHELL (parent))
_gtk_menu_shell_set_keyboard_mode (GTK_MENU_SHELL (parent), TRUE);
if (group_cycling && if (group_cycling &&
parent && menu_shell &&
GTK_IS_MENU_SHELL (parent) && menu_shell->priv->active)
GTK_MENU_SHELL (parent)->priv->active)
{ {
gtk_menu_shell_select_item (GTK_MENU_SHELL (parent), widget); gtk_menu_shell_select_item (menu_shell, widget);
} }
else else
g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0); g_signal_emit (widget, menu_item_signals[ACTIVATE_ITEM], 0);
@@ -1239,16 +1242,14 @@ static void
gtk_real_menu_item_activate_item (GtkMenuItem *menu_item) gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
{ {
GtkMenuItemPrivate *priv = menu_item->priv; GtkMenuItemPrivate *priv = menu_item->priv;
GtkWidget *parent; GtkMenuShell *menu_shell;
GtkWidget *widget; GtkWidget *widget;
widget = GTK_WIDGET (menu_item); widget = GTK_WIDGET (menu_item);
parent = gtk_widget_get_parent (widget); menu_shell = gtk_menu_item_get_menu_shell (menu_item);
if (parent && GTK_IS_MENU_SHELL (parent)) if (menu_shell)
{ {
GtkMenuShell *menu_shell = GTK_MENU_SHELL (parent);
if (priv->submenu == NULL) if (priv->submenu == NULL)
gtk_menu_shell_activate_item (menu_shell, widget, TRUE); gtk_menu_shell_activate_item (menu_shell, widget, TRUE);
else else
@@ -1327,8 +1328,8 @@ popped_up_cb (GtkMenu *menu,
gboolean flipped_y, gboolean flipped_y,
GtkMenuItem *menu_item) GtkMenuItem *menu_item)
{ {
GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (menu_item)); GtkMenuShell *menu_shell = gtk_menu_item_get_menu_shell (menu_item);
GtkMenu *parent_menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL; GtkMenu *parent_menu = GTK_IS_MENU (menu_shell) ? GTK_MENU (menu_shell) : NULL;
if (parent_menu && GTK_IS_MENU_ITEM (parent_menu->priv->parent_menu_item)) if (parent_menu && GTK_IS_MENU_ITEM (parent_menu->priv->parent_menu_item))
menu_item->priv->submenu_direction = GTK_MENU_ITEM (parent_menu->priv->parent_menu_item)->priv->submenu_direction; menu_item->priv->submenu_direction = GTK_MENU_ITEM (parent_menu->priv->parent_menu_item)->priv->submenu_direction;
@@ -1367,17 +1368,17 @@ gtk_menu_item_real_popup_submenu (GtkWidget *widget,
GtkBorder menu_padding; GtkBorder menu_padding;
gint horizontal_offset; gint horizontal_offset;
gint vertical_offset; gint vertical_offset;
GtkWidget *parent; GtkMenuShell *menu_shell;
GtkMenu *parent_menu; GtkMenu *parent_menu;
parent = gtk_widget_get_parent (widget); menu_shell = gtk_menu_item_get_menu_shell (menu_item);
parent_menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL; parent_menu = GTK_IS_MENU (menu_shell) ? GTK_MENU (menu_shell) : NULL;
if (gtk_widget_is_sensitive (priv->submenu) && parent) if (gtk_widget_is_sensitive (priv->submenu) && menu_shell)
{ {
gboolean take_focus; gboolean take_focus;
take_focus = gtk_menu_shell_get_take_focus (GTK_MENU_SHELL (parent)); take_focus = gtk_menu_shell_get_take_focus (menu_shell);
gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (priv->submenu), take_focus); gtk_menu_shell_set_take_focus (GTK_MENU_SHELL (priv->submenu), take_focus);
if (remember_exact_time) if (remember_exact_time)
@@ -1434,7 +1435,7 @@ gtk_menu_item_real_popup_submenu (GtkWidget *widget,
horizontal_offset = 0; horizontal_offset = 0;
vertical_offset = 0; vertical_offset = 0;
context = gtk_widget_get_style_context (parent); context = gtk_widget_get_style_context (GTK_WIDGET (menu_shell));
gtk_style_context_get_padding (context, &parent_padding); gtk_style_context_get_padding (context, &parent_padding);
context = gtk_widget_get_style_context (priv->submenu); context = gtk_widget_get_style_context (priv->submenu);
gtk_style_context_get_padding (context, &menu_padding); gtk_style_context_get_padding (context, &menu_padding);
@@ -1501,11 +1502,11 @@ gtk_menu_item_popup_timeout (gpointer data)
PopupInfo *info = data; PopupInfo *info = data;
GtkMenuItem *menu_item = info->menu_item; GtkMenuItem *menu_item = info->menu_item;
GtkMenuItemPrivate *priv = menu_item->priv; GtkMenuItemPrivate *priv = menu_item->priv;
GtkWidget *parent; GtkMenuShell *menu_shell;
parent = gtk_widget_get_parent (GTK_WIDGET (menu_item)); menu_shell = gtk_menu_item_get_menu_shell (menu_item);
if (GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->priv->active) if (menu_shell && menu_shell->priv->active)
gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), info->trigger_event, TRUE); gtk_menu_item_real_popup_submenu (GTK_WIDGET (menu_item), info->trigger_event, TRUE);
priv->timer = 0; priv->timer = 0;
@@ -1519,11 +1520,11 @@ gtk_menu_item_popup_timeout (gpointer data)
static gint static gint
get_popup_delay (GtkWidget *widget) get_popup_delay (GtkWidget *widget)
{ {
GtkWidget *parent; GtkMenuShell *menu_shell;
parent = gtk_widget_get_parent (widget); menu_shell = gtk_menu_item_get_menu_shell (GTK_MENU_ITEM (widget));
if (GTK_IS_MENU_SHELL (parent)) if (menu_shell)
return _gtk_menu_shell_get_popup_delay (GTK_MENU_SHELL (parent)); return _gtk_menu_shell_get_popup_delay (menu_shell);
else else
return MENU_POPUP_DELAY; return MENU_POPUP_DELAY;
} }
@@ -1590,13 +1591,13 @@ static gboolean
gtk_menu_item_can_activate_accel (GtkWidget *widget, gtk_menu_item_can_activate_accel (GtkWidget *widget,
guint signal_id) guint signal_id)
{ {
GtkWidget *parent; GtkMenuShell *menu_shell;
parent = gtk_widget_get_parent (widget); menu_shell = gtk_menu_item_get_menu_shell (GTK_MENU_ITEM (widget));
/* Chain to the parent GtkMenu for further checks */ /* Chain to the parent GtkMenu for further checks */
return (gtk_widget_is_sensitive (widget) && gtk_widget_get_visible (widget) && return (gtk_widget_is_sensitive (widget) && gtk_widget_get_visible (widget) &&
parent && gtk_widget_can_activate_accel (parent, signal_id)); menu_shell && gtk_widget_can_activate_accel (GTK_WIDGET (menu_shell), signal_id));
} }
static void static void
@@ -1627,10 +1628,10 @@ gtk_menu_item_parent_cb (GObject *object,
{ {
GtkMenuItem *menu_item = GTK_MENU_ITEM (object); GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
GtkMenu *menu; GtkMenu *menu;
GtkWidget *parent; GtkMenuShell *menu_shell;
parent = gtk_widget_get_parent (GTK_WIDGET (object)); menu_shell = gtk_menu_item_get_menu_shell (menu_item);
menu = GTK_IS_MENU (parent) ? GTK_MENU (parent) : NULL; menu = GTK_IS_MENU (menu_shell) ? GTK_MENU (menu_shell) : NULL;
if (menu) if (menu)
_gtk_menu_item_refresh_accel_path (menu_item, _gtk_menu_item_refresh_accel_path (menu_item,
@@ -1731,8 +1732,8 @@ gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
const gchar *accel_path) const gchar *accel_path)
{ {
GtkMenuItemPrivate *priv = menu_item->priv; GtkMenuItemPrivate *priv = menu_item->priv;
GtkWidget *parent;
GtkWidget *widget; GtkWidget *widget;
GtkMenuShell *menu_shell;
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item)); g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
g_return_if_fail (accel_path == NULL || g_return_if_fail (accel_path == NULL ||
@@ -1747,10 +1748,10 @@ gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
gtk_widget_set_accel_path (widget, NULL, NULL); gtk_widget_set_accel_path (widget, NULL, NULL);
/* install accelerators associated with new path */ /* install accelerators associated with new path */
parent = gtk_widget_get_parent (widget); menu_shell = gtk_menu_item_get_menu_shell (menu_item);
if (GTK_IS_MENU (parent)) if (GTK_IS_MENU (menu_shell))
{ {
GtkMenu *menu = GTK_MENU (parent); GtkMenu *menu = GTK_MENU (menu_shell);
if (menu->priv->accel_group) if (menu->priv->accel_group)
_gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget), _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),

View File

@@ -461,11 +461,14 @@ if cc.get_id() == 'msvc'
endif endif
endif endif
cairo_csi_dep = cc.find_library('cairo-script-interpreter')
if not harfbuzz_dep.found() if not harfbuzz_dep.found()
harfbuzz_dep = dependency('harfbuzz', version: '>= 0.9', required: false, harfbuzz_dep = dependency('harfbuzz', version: '>= 0.9', required: false,
fallback: ['harfbuzz', 'libharfbuzz_dep']) fallback: ['harfbuzz', 'libharfbuzz_dep'])
endif endif
cdata.set('HAVE_CAIRO_SCRIPT_INTERPRETER', cairo_csi_dep.found())
cdata.set('HAVE_HARFBUZZ', harfbuzz_dep.found()) cdata.set('HAVE_HARFBUZZ', harfbuzz_dep.found())
cdata.set('HAVE_PANGOFT', pangoft_dep.found()) cdata.set('HAVE_PANGOFT', pangoft_dep.found())

View File

@@ -6597,7 +6597,7 @@ usage (void)
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
GtkCssProvider *provider, *memory_provider; GtkCssProvider *memory_provider;
GdkDisplay *display; GdkDisplay *display;
GtkBindingSet *binding_set; GtkBindingSet *binding_set;
int i; int i;
@@ -6615,24 +6615,8 @@ main (int argc, char *argv[])
gtk_init (); gtk_init ();
provider = gtk_css_provider_new ();
/* Check to see if we are being run from the correct
* directory.
*/
if (file_exists ("testgtk.css"))
gtk_css_provider_load_from_path (provider, "testgtk.css");
else if (file_exists ("tests/testgtk.css"))
gtk_css_provider_load_from_path (provider, "tests/testgtk.css");
else
g_warning ("Couldn't find file \"testgtk.css\".");
display = gdk_display_get_default (); display = gdk_display_get_default ();
gtk_style_context_add_provider_for_display (display, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK | gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
GDK_CONTROL_MASK | GDK_CONTROL_MASK |
GDK_MOD1_MASK | GDK_MOD1_MASK |

View File

@@ -1,21 +0,0 @@
/* testgtk2.css sets all the buttons in the main window to blue by default */
@import url("testgtk2.css");
* {
font-family: Sans;
font-size: 12px;
}
label:selected {
background-color: gray;
}
label:hover {
background-color: mix (#a0a0a0, rgb (75%, 200, 0%), 0.9);
}
/* override testgtk2, introduce the green color in the button list */
#main_window scrolledwindow button:hover {
background-color: rgb (0%, 75%, 0);
}

View File

@@ -1,10 +0,0 @@
/* this file gets included from testgtk.css */
#main_window button {
font-family: Monospace;
font-size: 10px;
}
#main_window button:hover {
background-color: rgba(0%, 0%, 75%, 0.1);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 B

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,7 @@
transform {
transform: scale(0.5);
child: cairo {
bounds: 0 0 100 100;
script: url("data:;base64,JSFDYWlyb1NjcmlwdAo8PCAvY29udGVudCAvL0NPTE9SX0FMUEhBIC93aWR0aCA1MCAvaGVpZ2h0IDUwID4+IHN1cmZhY2UgY29udGV4dAoxIDAgMC44IHJnYiBzZXQtc291cmNlCnBhaW50CnBvcAo=");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

View File

@@ -23,6 +23,7 @@ compare_render_tests = [
'clip-coordinates-3d', 'clip-coordinates-3d',
'clipped_rounded_clip', 'clipped_rounded_clip',
'color-blur0', 'color-blur0',
'color-matrix-identity',
'cross-fade-in-opacity', 'cross-fade-in-opacity',
'empty-blend', 'empty-blend',
'empty-blur', 'empty-blur',
@@ -50,9 +51,9 @@ compare_render_tests = [
'outset_shadow_offset_y', 'outset_shadow_offset_y',
'outset_shadow_rounded_top', 'outset_shadow_rounded_top',
'outset_shadow_simple', 'outset_shadow_simple',
'scaled-cairo',
'shadow-in-opacity', 'shadow-in-opacity',
'texture-url', 'texture-url',
'color-matrix-identity',
] ]
renderers = [ renderers = [

View File

@@ -1,5 +1,3 @@
cairo { cairo {
bounds: 0 0 50 50; bounds: 0 0 50 50;
pixels: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAABmJLR0QA/wD/AP+gvaeTAAAATklEQVRYhe3OMQHAIADAMJh/aXgCA3t6wZEoyNxjjfd8twP/tAqtQqvQKrQKrUKr0Cq0Cq1Cq9AqtAqtQqvQKrQKrUKr0Cq0Cq1Cq9AqDsEHAi9RKkB7AAAAAElFTkSuQmCC");
script: url("data:;base64,JSFDYWlyb1NjcmlwdAo8PCAvY29udGVudCAvL0NPTE9SX0FMUEhBIC93aWR0aCA1MCAvaGVpZ2h0IDUwID4+IHN1cmZhY2UgY29udGV4dAoxIDAgMC44IHJnYiBzZXQtc291cmNlCnBhaW50CnBvcAo=");
} }