[gtk+] menu: Port to use css nodes



commit 0b52b29dfc05cb042617f14dd2afb85fd4a038a7
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Nov 2 20:45:46 2015 -0500

    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.

 gtk/gtkmenu.c        |   77 ++++++++++++++++++++++++++++++++++++++++----------
 gtk/gtkmenuprivate.h |    4 ++
 2 files changed, 66 insertions(+), 15 deletions(-)
---
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 61f8541..0409b54 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -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");
 }
 
 
@@ -1078,10 +1082,33 @@ gtk_menu_window_event (GtkWidget *window,
 }
 
 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))
     {
diff --git a/gtk/gtkmenuprivate.h b/gtk/gtkmenuprivate.h
index f1a40d8..927747b 100644
--- a/gtk/gtkmenuprivate.h
+++ b/gtk/gtkmenuprivate.h
@@ -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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]