menu: Port to use css nodes

Use the element name menu for the main node, and use two subnodes
with name arrow and style classes .top and .bottom for the arrows
of scrolling menus.
This commit is contained in:
Matthias Clasen 2015-11-02 20:45:46 -05:00
parent f6ca908e03
commit 0b52b29dfc
2 changed files with 66 additions and 15 deletions

View File

@ -112,6 +112,9 @@
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gtkwindowprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkstylecontextprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "deprecated/gtktearoffmenuitem.h"
@ -878,6 +881,7 @@ gtk_menu_class_init (GtkMenuClass *class)
GTK_SCROLL_PAGE_DOWN);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_MENU_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, "menu");
}
@ -1077,11 +1081,34 @@ gtk_menu_window_event (GtkWidget *window,
return handled;
}
static void
node_style_changed_cb (GtkCssNode *node,
GtkCssStyle *old_style,
GtkCssStyle *new_style,
GtkWidget *widget)
{
GtkBitmask *changes;
static GtkBitmask *affects_size = NULL;
if (G_UNLIKELY (affects_size == NULL))
affects_size = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP);
changes = _gtk_bitmask_new ();
changes = gtk_css_style_add_difference (changes, old_style, new_style);
if (_gtk_bitmask_intersects (changes, affects_size))
gtk_widget_queue_resize (widget);
else
gtk_widget_queue_draw (widget);
_gtk_bitmask_free (changes);
}
static void
gtk_menu_init (GtkMenu *menu)
{
GtkMenuPrivate *priv;
GtkStyleContext *context;
GtkCssNode *widget_node;
priv = gtk_menu_get_instance_private (menu);
@ -1110,10 +1137,26 @@ gtk_menu_init (GtkMenu *menu)
priv->monitor_num = -1;
priv->drag_start_y = -1;
context = gtk_widget_get_style_context (GTK_WIDGET (menu));
gtk_style_context_add_class (context, GTK_STYLE_CLASS_MENU);
_gtk_widget_set_captured_event_handler (GTK_WIDGET (menu), gtk_menu_captured_event);
widget_node = gtk_widget_get_css_node (GTK_WIDGET (menu));
priv->top_arrow = gtk_css_node_new ();
gtk_css_node_set_name (priv->top_arrow, I_("arrow"));
gtk_css_node_add_class (priv->top_arrow, g_quark_from_static_string (GTK_STYLE_CLASS_TOP));
gtk_css_node_set_parent (priv->top_arrow, widget_node);
gtk_css_node_set_visible (priv->top_arrow, FALSE);
gtk_css_node_set_state (priv->top_arrow, gtk_css_node_get_state (widget_node));
g_signal_connect_object (priv->top_arrow, "style-changed", G_CALLBACK (node_style_changed_cb), menu, 0);
g_object_unref (priv->top_arrow);
priv->bottom_arrow = gtk_css_node_new ();
gtk_css_node_set_name (priv->bottom_arrow, I_("arrow"));
gtk_css_node_add_class (priv->bottom_arrow, g_quark_from_static_string (GTK_STYLE_CLASS_BOTTOM));
gtk_css_node_set_parent (priv->bottom_arrow, widget_node);
gtk_css_node_set_visible (priv->bottom_arrow, FALSE);
gtk_css_node_set_state (priv->bottom_arrow, gtk_css_node_get_state (widget_node));
g_signal_connect_object (priv->bottom_arrow, "style-changed", G_CALLBACK (node_style_changed_cb), menu, 0);
g_object_unref (priv->bottom_arrow);
}
static void
@ -3071,14 +3114,9 @@ gtk_menu_draw (GtkWidget *widget,
gtk_widget_get_allocated_width (widget),
gtk_widget_get_allocated_height (widget));
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
if (priv->upper_arrow_visible && !priv->tearoff_active)
{
gtk_style_context_save (context);
gtk_style_context_set_state (context, priv->upper_arrow_state);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
gtk_style_context_save_to_node (context, priv->top_arrow);
gtk_render_background (context, cr,
upper.x, upper.y,
@ -3097,9 +3135,7 @@ gtk_menu_draw (GtkWidget *widget,
if (priv->lower_arrow_visible && !priv->tearoff_active)
{
gtk_style_context_save (context);
gtk_style_context_set_state (context, priv->lower_arrow_state);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
gtk_style_context_save_to_node (context, priv->bottom_arrow);
gtk_render_background (context, cr,
lower.x, lower.y,
@ -3115,8 +3151,6 @@ gtk_menu_draw (GtkWidget *widget,
gtk_style_context_restore (context);
}
gtk_style_context_restore (context);
}
if (gtk_cairo_should_draw_window (cr, priv->bin_window))
@ -3904,6 +3938,7 @@ gtk_menu_handle_scrolling (GtkMenu *menu,
if (arrow_state != priv->upper_arrow_state)
{
priv->upper_arrow_state = arrow_state;
gtk_css_node_set_state (priv->top_arrow, arrow_state);
gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET (menu)),
&rect, FALSE);
@ -3977,6 +4012,7 @@ gtk_menu_handle_scrolling (GtkMenu *menu,
if (arrow_state != priv->lower_arrow_state)
{
priv->lower_arrow_state = arrow_state;
gtk_css_node_set_state (priv->bottom_arrow, arrow_state);
gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET (menu)),
&rect, FALSE);
@ -4704,10 +4740,16 @@ static void
gtk_menu_stop_scrolling (GtkMenu *menu)
{
GtkMenuPrivate *priv = menu->priv;
GtkStateFlags state;
gtk_menu_remove_scroll_timeout (menu);
priv->upper_arrow_prelight = FALSE;
priv->lower_arrow_prelight = FALSE;
state = gtk_css_node_get_state (priv->top_arrow);
gtk_css_node_set_state (priv->top_arrow, state & ~GTK_STATE_FLAG_PRELIGHT);
state = gtk_css_node_get_state (priv->bottom_arrow);
gtk_css_node_set_state (priv->bottom_arrow, state & ~GTK_STATE_FLAG_PRELIGHT);
}
static void
@ -4871,6 +4913,11 @@ gtk_menu_scroll_to (GtkMenu *menu,
y += arrow_border.top;
}
gtk_css_node_set_visible (priv->top_arrow, priv->upper_arrow_visible);
gtk_css_node_set_visible (priv->bottom_arrow, priv->lower_arrow_visible);
gtk_css_node_set_state (priv->top_arrow, priv->upper_arrow_state);
gtk_css_node_set_state (priv->bottom_arrow, priv->lower_arrow_state);
/* Scroll the menu: */
if (gtk_widget_get_realized (widget))
{

View File

@ -26,6 +26,7 @@
#define __GTK_MENU_PRIVATE_H__
#include <gtk/gtkmenu.h>
#include <gtk/gtkcssnodeprivate.h>
G_BEGIN_DECLS
@ -68,6 +69,9 @@ struct _GtkMenuPrivate
GdkWindow *view_window;
GdkWindow *bin_window;
GtkCssNode *top_arrow;
GtkCssNode *bottom_arrow;
gint scroll_offset;
gint saved_scroll_offset;
gint scroll_step;