[gimp/gimp-2-10] app: add GTK+ patch allowing controlling combo-box popup style



commit aa7fc3f08d81be9007e31afb461cb9d938f1b5c0
Author: Ell <ell_se yahoo com>
Date:   Wed Mar 27 18:07:04 2019 -0400

    app: add GTK+ patch allowing controlling combo-box popup style
    
    Add a GTK+ patch providing a "popup-style" combo-box style
    property, allowing to manually control the combo-box popup-style.
    Use the LIST style for all combo-boxes in our system-wide gtkrc
    file; this only has effect if GTK+ was built with the above patch.

 build/patches/gtk+-2.24-gimp-issue-2828-0002.patch | 766 +++++++++++++++++++++
 etc/gtkrc                                          |  13 +
 2 files changed, 779 insertions(+)
---
diff --git a/build/patches/gtk+-2.24-gimp-issue-2828-0002.patch 
b/build/patches/gtk+-2.24-gimp-issue-2828-0002.patch
new file mode 100644
index 0000000000..77ffffb0d1
--- /dev/null
+++ b/build/patches/gtk+-2.24-gimp-issue-2828-0002.patch
@@ -0,0 +1,766 @@
+From c5fbac1046016fd8e618197cf7f670589795faeb Mon Sep 17 00:00:00 2001
+From: Ell <ell_se yahoo com>
+Date: Wed, 30 Jan 2019 18:02:42 -0500
+Subject: [PATCH 2/2] ComboBox: add "popup-style" style property
+
+Add a "popup-style" style property to GtkComboBox, which can be
+used to control the combo box's popup style independently of its
+appearance.  This is in contrast to "appears-as-list", which
+controls both the popup-style, and the appearance.
+
+"popup-style" is of enum type GtkComboBoxPopupStyle, and can be one
+of:
+
+  - GTK_COMBO_BOX_POPUP_AUTO (default): use the menu style if
+    "appears-as-list" is FALSE, and the list style if
+    "appears-as-list" is TRUE.
+
+  - GTK_COMBO_BOX_POPUP_MENU: use the menu style.
+
+  - GTK_COMBO_BOX_POPUP_LIST: use the list style.
+---
+ gtk/gtkcombobox.c | 489 +++++++++++++++++++++++++++-------------------
+ gtk/gtkcombobox.h |   7 +
+ 2 files changed, 298 insertions(+), 198 deletions(-)
+
+diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c
+index bd5c0d0a23..8cd8a2a519 100644
+--- a/gtk/gtkcombobox.c
++++ b/gtk/gtkcombobox.c
+@@ -160,6 +160,7 @@ struct _GtkComboBoxPrivate
+   guint focus_on_click : 1;
+   guint button_sensitivity : 2;
+   guint has_entry : 1;
++  guint appears_as_list : 1;
+ 
+   GtkTreeViewRowSeparatorFunc row_separator_func;
+   gpointer                    row_separator_data;
+@@ -335,6 +336,9 @@ static gboolean gtk_combo_box_scroll_event         (GtkWidget        *widget,
+ static void     gtk_combo_box_set_active_internal  (GtkComboBox      *combo_box,
+                                                   GtkTreePath      *path);
+ 
++static GtkComboBoxPopupStyle
++                gtk_combo_box_get_popup_style      (GtkComboBox      *combo_box,
++                                                    gboolean          appears_as_list);
+ static void     gtk_combo_box_check_appearance     (GtkComboBox      *combo_box);
+ static gchar *  gtk_combo_box_real_get_active_text (GtkComboBox      *combo_box);
+ static void     gtk_combo_box_real_move_active     (GtkComboBox      *combo_box,
+@@ -342,6 +346,11 @@ static void     gtk_combo_box_real_move_active     (GtkComboBox      *combo_box,
+ static void     gtk_combo_box_real_popup           (GtkComboBox      *combo_box);
+ static gboolean gtk_combo_box_real_popdown         (GtkComboBox      *combo_box);
+ 
++static void     gtk_combo_box_button_setup         (GtkComboBox      *combo_box,
++                                                    GCallback         button_press);
++static void     gtk_combo_box_button_destroy       (GtkComboBox      *combo_box,
++                                                    GCallback         button_press);
++
+ /* listening to the model */
+ static void     gtk_combo_box_model_row_inserted   (GtkTreeModel     *model,
+                                                   GtkTreePath      *path,
+@@ -976,6 +985,21 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
+                                                               GTK_SHADOW_NONE,
+                                                               GTK_PARAM_READABLE));
+ 
++  /**
++   * GtkComboBox:popup-style:
++   *
++   * The combo box popup style.
++   *
++   * Since: 2.24
++   */
++  gtk_widget_class_install_style_property (widget_class,
++                                         g_param_spec_enum ("popup-style",
++                                                            P_("Popup style"),
++                                                            P_("The combo box popup style"),
++                                                              GTK_TYPE_COMBO_BOX_POPUP_STYLE,
++                                                              GTK_COMBO_BOX_POPUP_AUTO,
++                                                              GTK_PARAM_READABLE));
++
+   g_type_class_add_private (object_class, sizeof (GtkComboBoxPrivate));
+ }
+ 
+@@ -1215,7 +1239,7 @@ gtk_combo_box_state_changed (GtkWidget    *widget,
+ 
+   if (gtk_widget_get_realized (widget))
+     {
+-      if (priv->tree_view && priv->cell_view)
++      if (priv->cell_view_frame && priv->cell_view)
+       gtk_cell_view_set_background_color (GTK_CELL_VIEW (priv->cell_view), 
+                                           &widget->style->base[gtk_widget_get_state (widget)]);
+     }
+@@ -1233,7 +1257,7 @@ gtk_combo_box_button_state_changed (GtkWidget    *widget,
+ 
+   if (gtk_widget_get_realized (widget))
+     {
+-      if (!priv->tree_view && priv->cell_view)
++      if (!priv->cell_view_frame && priv->cell_view)
+       {
+         if ((gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE) !=
+             (gtk_widget_get_state (priv->cell_view) == GTK_STATE_INSENSITIVE))
+@@ -1247,41 +1271,78 @@ gtk_combo_box_button_state_changed (GtkWidget    *widget,
+   gtk_widget_queue_draw (widget);
+ }
+ 
+-static void
+-gtk_combo_box_check_appearance (GtkComboBox *combo_box)
++static GtkComboBoxPopupStyle
++gtk_combo_box_get_popup_style (GtkComboBox *combo_box,
++                               gboolean     appears_as_list)
+ {
+   GtkComboBoxPrivate *priv = combo_box->priv;
+-  gboolean appears_as_list;
++  GtkComboBoxPopupStyle popup_style;
+ 
+   /* if wrap_width > 0, then we are in grid-mode and forced to use
+    * unix style
+    */
+   if (priv->wrap_width)
+-    appears_as_list = FALSE;
+-  else
+-    gtk_widget_style_get (GTK_WIDGET (combo_box),
+-                        "appears-as-list", &appears_as_list,
+-                        NULL);
++    return GTK_COMBO_BOX_POPUP_MENU;
+ 
+-  if (appears_as_list)
+-    {
+-      /* Destroy all the menu mode widgets, if they exist. */
+-      if (GTK_IS_MENU (priv->popup_widget))
+-      gtk_combo_box_menu_destroy (combo_box);
++  gtk_widget_style_get (GTK_WIDGET (combo_box),
++                        "popup-style", &popup_style,
++                        NULL);
+ 
+-      /* Create the list mode widgets, if they don't already exist. */
+-      if (!GTK_IS_TREE_VIEW (priv->tree_view))
+-      gtk_combo_box_list_setup (combo_box);
++  if (popup_style == GTK_COMBO_BOX_POPUP_AUTO)
++    {
++      if (appears_as_list)
++        popup_style = GTK_COMBO_BOX_POPUP_LIST;
++      else
++        popup_style = GTK_COMBO_BOX_POPUP_MENU;
+     }
+-  else
++
++  return popup_style;
++}
++
++static void
++gtk_combo_box_check_appearance (GtkComboBox *combo_box)
++{
++  GtkComboBoxPrivate *priv = combo_box->priv;
++  gboolean appears_as_list;
++
++  gtk_widget_style_get (GTK_WIDGET (combo_box),
++                        "appears-as-list", &appears_as_list,
++                        NULL);
++
++  switch (gtk_combo_box_get_popup_style (combo_box, appears_as_list))
+     {
++    case GTK_COMBO_BOX_POPUP_AUTO:
++      g_return_if_reached ();
++
++    case GTK_COMBO_BOX_POPUP_MENU:
+       /* Destroy all the list mode widgets, if they exist. */
+       if (GTK_IS_TREE_VIEW (priv->tree_view))
+-      gtk_combo_box_list_destroy (combo_box);
++        gtk_combo_box_list_destroy (combo_box);
++      else if (appears_as_list != priv->appears_as_list &&
++               GTK_IS_MENU (priv->popup_widget))
++        gtk_combo_box_menu_destroy (combo_box);
+ 
+       /* Create the menu mode widgets, if they don't already exist. */
+-      if (!GTK_IS_MENU (priv->popup_widget))
+-      gtk_combo_box_menu_setup (combo_box, TRUE);
++      if (!GTK_IS_MENU (priv->popup_widget) ||
++          appears_as_list != priv->appears_as_list)
++        gtk_combo_box_menu_setup (combo_box, TRUE);
++
++      break;
++
++    case GTK_COMBO_BOX_POPUP_LIST:
++      /* Destroy all the menu mode widgets, if they exist. */
++      if (GTK_IS_MENU (priv->popup_widget))
++        gtk_combo_box_menu_destroy (combo_box);
++      else if (appears_as_list != priv->appears_as_list &&
++               GTK_IS_TREE_VIEW (priv->tree_view))
++        gtk_combo_box_list_destroy (combo_box);
++
++      /* Create the list mode widgets, if they don't already exist. */
++      if (!GTK_IS_TREE_VIEW (priv->tree_view) ||
++          appears_as_list != priv->appears_as_list)
++        gtk_combo_box_list_setup (combo_box);
++
++      break;
+     }
+ 
+   gtk_widget_style_get (GTK_WIDGET (combo_box),
+@@ -1298,7 +1359,7 @@ gtk_combo_box_style_set (GtkWidget *widget,
+ 
+   gtk_combo_box_check_appearance (combo_box);
+ 
+-  if (priv->tree_view && priv->cell_view)
++  if (priv->appears_as_list && priv->cell_view)
+     gtk_cell_view_set_background_color (GTK_CELL_VIEW (priv->cell_view), 
+                                       &widget->style->base[gtk_widget_get_state (widget)]);
+ 
+@@ -1355,7 +1416,7 @@ gtk_combo_box_add (GtkContainer *container,
+       /* since the cell_view was unparented, it's gone now */
+       priv->cell_view = NULL;
+ 
+-      if (!priv->tree_view && priv->separator)
++      if (!priv->appears_as_list && priv->separator)
+         {
+         gtk_container_remove (GTK_CONTAINER (priv->separator->parent),
+                               priv->separator);
+@@ -1392,7 +1453,7 @@ gtk_combo_box_remove (GtkContainer *container,
+   GtkComboBox *combo_box = GTK_COMBO_BOX (container);
+   GtkComboBoxPrivate *priv = combo_box->priv;
+   GtkTreePath *path;
+-  gboolean appears_as_list;
++  gboolean uses_list;
+ 
+   if (priv->has_entry)
+     {
+@@ -1420,11 +1481,11 @@ gtk_combo_box_remove (GtkContainer *container,
+   gtk_widget_queue_resize (GTK_WIDGET (container));
+ 
+   if (!priv->tree_view)
+-    appears_as_list = FALSE;
++    uses_list = FALSE;
+   else
+-    appears_as_list = TRUE;
++    uses_list = TRUE;
+   
+-  if (appears_as_list)
++  if (uses_list)
+     gtk_combo_box_list_destroy (combo_box);
+   else if (GTK_IS_MENU (priv->popup_widget))
+     {
+@@ -1446,7 +1507,7 @@ gtk_combo_box_remove (GtkContainer *container,
+     }
+ 
+ 
+-  if (appears_as_list)
++  if (uses_list)
+     gtk_combo_box_list_setup (combo_box); 
+   else
+     gtk_combo_box_menu_setup (combo_box, TRUE);
+@@ -2286,7 +2347,7 @@ gtk_combo_box_size_request (GtkWidget      *widget,
+ 
+   gtk_widget_set_size_request (priv->arrow, arrow_size, arrow_size);
+ 
+-  if (!priv->tree_view)
++  if (!priv->appears_as_list)
+     {
+       /* menu mode */
+ 
+@@ -2381,6 +2442,34 @@ gtk_combo_box_size_request (GtkWidget      *widget,
+                                                                               \
+   gtk_widget_size_allocate (combo_box->priv->button, &child);
+ 
++#define GTK_COMBO_BOX_SIZE_ALLOCATE_POPUP_WINDOW                                \
++  if (priv->popup_window && gtk_widget_get_visible (priv->popup_window))        \
++    {                                                                           \
++      if (priv->tree_view)                                                      \
++        {                                                                       \
++          gint x, y, width, height;                                             \
++          gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);     \
++          gtk_window_move (GTK_WINDOW (priv->popup_window), x, y);              \
++          gtk_widget_set_size_request (priv->popup_window, width, height);      \
++        }                                                                       \
++      else if (priv->cell_view_frame)                                           \
++        {                                                                       \
++          gint width;                                                           \
++          GtkRequisition requisition;                                           \
++                                                                                \
++          /* Warning here, without the check in the position func */            \
++          gtk_menu_reposition (GTK_MENU (priv->popup_widget));                  \
++          if (priv->wrap_width == 0)                                            \
++            {                                                                   \
++              width = GTK_WIDGET (combo_box)->allocation.width;                 \
++              gtk_widget_set_size_request (priv->popup_widget, -1, -1);         \
++              gtk_widget_size_request (priv->popup_widget, &requisition);       \
++              gtk_widget_set_size_request (priv->popup_widget,                  \
++                MAX (width, requisition.width), -1);                            \
++           }                                                                    \
++        }                                                                       \
++    }
++
+ static void
+ gtk_combo_box_size_allocate (GtkWidget     *widget,
+                              GtkAllocation *allocation)
+@@ -2411,7 +2500,7 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
+       shadow_height = 0;
+     }
+ 
+-  if (!priv->tree_view)
++  if (!priv->appears_as_list)
+     {
+       if (priv->cell_view)
+         {
+@@ -2478,22 +2567,7 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
+               child.width -= child.x;
+             }
+ 
+-          if (gtk_widget_get_visible (priv->popup_widget))
+-            {
+-              gint width;
+-              GtkRequisition requisition;
+-
+-              /* Warning here, without the check in the position func */
+-              gtk_menu_reposition (GTK_MENU (priv->popup_widget));
+-              if (priv->wrap_width == 0)
+-                {
+-                  width = GTK_WIDGET (combo_box)->allocation.width;
+-                  gtk_widget_set_size_request (priv->popup_widget, -1, -1);
+-                  gtk_widget_size_request (priv->popup_widget, &requisition);
+-                  gtk_widget_set_size_request (priv->popup_widget,
+-                    MAX (width, requisition.width), -1);
+-               }
+-            }
++          GTK_COMBO_BOX_SIZE_ALLOCATE_POPUP_WINDOW
+ 
+         child.width = MAX (1, child.width);
+         child.height = MAX (1, child.height);
+@@ -2509,6 +2583,9 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
+             child.x = allocation->x + shadow_width;
+           child.y = allocation->y + shadow_height;
+           child.width = allocation->width - req.width - 2 * shadow_width;
++
++          GTK_COMBO_BOX_SIZE_ALLOCATE_POPUP_WINDOW
++
+         child.width = MAX (1, child.width);
+         child.height = MAX (1, child.height);
+           gtk_widget_size_allocate (GTK_BIN (widget)->child, &child);
+@@ -2565,14 +2642,7 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
+           child.height -= delta_y * 2;
+         }
+ 
+-      if (gtk_widget_get_visible (priv->popup_window))
+-        {
+-          gint x, y, width, height;
+-          gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);
+-          gtk_window_move (GTK_WINDOW (priv->popup_window), x, y);
+-          gtk_widget_set_size_request (priv->popup_window, width, height);
+-        }
+-
++      GTK_COMBO_BOX_SIZE_ALLOCATE_POPUP_WINDOW
+       
+       child.width = MAX (1, child.width);
+       child.height = MAX (1, child.height);
+@@ -2581,7 +2651,8 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
+     }
+ }
+ 
+-#undef GTK_COMBO_BOX_ALLOCATE_BUTTON
++#undef GTK_COMBO_BOX_SIZE_ALLOCATE_BUTTON
++#undef GTK_COMBO_BOX_SIZE_ALLOCATE_POPUP_WINDOW
+ 
+ static void
+ gtk_combo_box_unset_model (GtkComboBox *combo_box)
+@@ -2685,7 +2756,7 @@ gtk_combo_box_expose_event (GtkWidget      *widget,
+   gtk_container_propagate_expose (GTK_CONTAINER (widget),
+                                 priv->button, event);
+ 
+-  if (priv->tree_view && priv->cell_view_frame)
++  if (priv->appears_as_list && priv->cell_view_frame)
+     {
+       gtk_container_propagate_expose (GTK_CONTAINER (widget),
+                                     priv->cell_view_frame, event);
+@@ -2930,6 +3001,149 @@ gtk_combo_box_scroll_event (GtkWidget          *widget,
+   return TRUE;
+ }
+ 
++static void
++gtk_combo_box_button_setup (GtkComboBox *combo_box,
++                            GCallback    button_press)
++{
++  GtkComboBoxPrivate *priv = combo_box->priv;
++  gboolean appears_as_list;
++
++  priv->button = gtk_toggle_button_new ();
++  gtk_widget_set_parent (priv->button,
++                         GTK_BIN (combo_box)->child->parent);
++
++  g_signal_connect (priv->button, "toggled",
++                    G_CALLBACK (gtk_combo_box_button_toggled), combo_box);
++  g_signal_connect (priv->button, "button-press-event",
++                    button_press, combo_box);
++
++  gtk_widget_style_get (GTK_WIDGET (combo_box),
++                        "appears-as-list", &appears_as_list,
++                        NULL);
++  priv->appears_as_list = appears_as_list;
++
++  if (!appears_as_list)
++    {
++      gtk_button_set_focus_on_click (GTK_BUTTON (priv->button),
++                                     priv->focus_on_click);
++
++      if (priv->cell_view)
++        {
++          priv->box = gtk_hbox_new (FALSE, 0);
++          gtk_container_add (GTK_CONTAINER (priv->button), priv->box);
++
++          priv->separator = gtk_vseparator_new ();
++          gtk_container_add (GTK_CONTAINER (priv->box), priv->separator);
++
++          priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
++          gtk_container_add (GTK_CONTAINER (priv->box), priv->arrow);
++        }
++      else
++        {
++          priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
++          gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
++        }
++
++      g_signal_connect (priv->button, "state-changed",
++            G_CALLBACK (gtk_combo_box_button_state_changed), 
++            combo_box);
++    }
++  else
++    {
++      GtkStyle *style;
++      GtkWidget *widget = GTK_WIDGET (combo_box);
++
++      priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
++      gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
++      priv->separator = NULL;
++
++      if (priv->cell_view)
++        {
++          style = gtk_widget_get_style (widget);
++          gtk_cell_view_set_background_color (GTK_CELL_VIEW (priv->cell_view),
++                                              &style->base[gtk_widget_get_state (widget)]);
++
++          priv->box = gtk_event_box_new ();
++          gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->box), 
++                                            FALSE);
++
++          if (priv->has_frame)
++            {
++              priv->cell_view_frame = gtk_frame_new (NULL);
++              gtk_frame_set_shadow_type (GTK_FRAME (priv->cell_view_frame),
++                                         GTK_SHADOW_IN);
++            }
++          else 
++            {
++              combo_box->priv->cell_view_frame = gtk_event_box_new ();
++              gtk_event_box_set_visible_window (GTK_EVENT_BOX (combo_box->priv->cell_view_frame), 
++                                                FALSE);
++            }
++          
++          gtk_widget_set_parent (priv->cell_view_frame,
++                                 GTK_BIN (combo_box)->child->parent);
++          gtk_container_add (GTK_CONTAINER (priv->cell_view_frame), priv->box);
++          gtk_widget_show_all (priv->cell_view_frame);
++
++          g_signal_connect (priv->box, "button-press-event",
++                            button_press, combo_box);
++        }
++    }
++
++  gtk_widget_show_all (priv->button);
++}
++
++static void
++gtk_combo_box_button_destroy (GtkComboBox *combo_box,
++                              GCallback    button_press)
++{
++  GtkComboBoxPrivate *priv = combo_box->priv;
++
++  g_signal_handlers_disconnect_by_func (priv->button,
++                                        gtk_combo_box_button_toggled,
++                                        combo_box);
++  g_signal_handlers_disconnect_by_func (priv->button,
++                                        button_press,
++                                        combo_box);
++
++  if (!priv->appears_as_list)
++    {
++      g_signal_handlers_disconnect_by_func (priv->button,
++                                            gtk_combo_box_button_state_changed,
++                                            combo_box);
++    }
++  else
++    {
++      if (priv->box)
++        g_signal_handlers_disconnect_matched (priv->box,
++                G_SIGNAL_MATCH_DATA,
++                0, 0, NULL,
++                button_press,
++                NULL);
++
++      if (priv->cell_view)
++        {
++          g_object_set (priv->cell_view,
++                        "background-set", FALSE,
++                        NULL);
++        }
++
++      if (priv->cell_view_frame)
++        {
++          gtk_widget_unparent (priv->cell_view_frame);
++          priv->cell_view_frame = NULL;
++        }
++    }
++
++  /* unparent will remove our latest ref */
++  gtk_widget_unparent (priv->button);
++  
++  priv->box = NULL;
++  priv->button = NULL;
++  priv->arrow = NULL;
++  priv->separator = NULL;
++}
++
+ /*
+  * menu style
+  */
+@@ -2974,50 +3188,8 @@ gtk_combo_box_menu_setup (GtkComboBox *combo_box,
+   GtkComboBoxPrivate *priv = combo_box->priv;
+   GtkWidget *menu;
+ 
+-  if (priv->cell_view)
+-    {
+-      priv->button = gtk_toggle_button_new ();
+-      gtk_button_set_focus_on_click (GTK_BUTTON (priv->button),
+-                                   priv->focus_on_click);
+-
+-      g_signal_connect (priv->button, "toggled",
+-                        G_CALLBACK (gtk_combo_box_button_toggled), combo_box);
+-      gtk_widget_set_parent (priv->button,
+-                             GTK_BIN (combo_box)->child->parent);
+-
+-      priv->box = gtk_hbox_new (FALSE, 0);
+-      gtk_container_add (GTK_CONTAINER (priv->button), priv->box);
+-
+-      priv->separator = gtk_vseparator_new ();
+-      gtk_container_add (GTK_CONTAINER (priv->box), priv->separator);
+-
+-      priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+-      gtk_container_add (GTK_CONTAINER (priv->box), priv->arrow);
+-
+-      gtk_widget_show_all (priv->button);
+-    }
+-  else
+-    {
+-      priv->button = gtk_toggle_button_new ();
+-      gtk_button_set_focus_on_click (GTK_BUTTON (priv->button),
+-                                   priv->focus_on_click);
+-
+-      g_signal_connect (priv->button, "toggled",
+-                        G_CALLBACK (gtk_combo_box_button_toggled), combo_box);
+-      gtk_widget_set_parent (priv->button,
+-                             GTK_BIN (combo_box)->child->parent);
+-
+-      priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+-      gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
+-      gtk_widget_show_all (priv->button);
+-    }
+-
+-  g_signal_connect (priv->button, "button-press-event",
+-                    G_CALLBACK (gtk_combo_box_menu_button_press),
+-                    combo_box);
+-  g_signal_connect (priv->button, "state-changed",
+-                  G_CALLBACK (gtk_combo_box_button_state_changed), 
+-                  combo_box);
++  gtk_combo_box_button_setup (combo_box,
++                              G_CALLBACK (gtk_combo_box_menu_button_press));
+ 
+   /* create our funky menu */
+   menu = gtk_menu_new ();
+@@ -3174,28 +3346,14 @@ gtk_combo_box_menu_destroy (GtkComboBox *combo_box)
+ {
+   GtkComboBoxPrivate *priv = combo_box->priv;
+ 
+-  g_signal_handlers_disconnect_by_func (priv->button,
+-                                        gtk_combo_box_button_toggled,
+-                                        combo_box);
+-  g_signal_handlers_disconnect_by_func (priv->button,
+-                                        gtk_combo_box_menu_button_press,
+-                                        combo_box);
+-  g_signal_handlers_disconnect_by_func (priv->button,
+-                                        gtk_combo_box_button_state_changed,
+-                                        combo_box);
+   g_signal_handlers_disconnect_by_data (priv->popup_widget, combo_box);
+ 
+-  /* unparent will remove our latest ref */
+-  gtk_widget_unparent (priv->button);
+-  
+-  priv->box = NULL;
+-  priv->button = NULL;
+-  priv->arrow = NULL;
+-  priv->separator = NULL;
+-
+   g_object_unref (priv->column);
+   priv->column = NULL;
+ 
++  gtk_combo_box_button_destroy (combo_box,
++                                G_CALLBACK (gtk_combo_box_menu_button_press));
++
+   /* changing the popup window will unref the menu and the children */
+ }
+ 
+@@ -3329,12 +3487,20 @@ gtk_combo_box_menu_button_press (GtkWidget      *widget,
+   if (GTK_IS_MENU (priv->popup_widget) &&
+       event->type == GDK_BUTTON_PRESS && event->button == 1)
+     {
++      GtkWidget *ewidget = gtk_get_event_widget ((GdkEvent *)event);
++
++      if ((ewidget != priv->button && ewidget != priv->box) ||
++          gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)))
++        return FALSE;
++
+       if (priv->focus_on_click && 
+         !gtk_widget_has_focus (priv->button))
+       gtk_widget_grab_focus (priv->button);
+ 
+       gtk_combo_box_menu_popup (combo_box, event->button, event->time);
+ 
++      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button), TRUE);
++
+       return TRUE;
+     }
+ 
+@@ -3398,8 +3564,7 @@ gtk_combo_box_update_sensitivity (GtkComboBox *combo_box)
+   gtk_widget_set_sensitive (combo_box->priv->button, sensitive);
+ 
+   /* In list-mode, we also need to update sensitivity of the event box */
+-  if (GTK_IS_TREE_VIEW (combo_box->priv->tree_view)
+-      && combo_box->priv->cell_view)
++  if (combo_box->priv->appears_as_list && combo_box->priv->cell_view)
+     gtk_widget_set_sensitive (combo_box->priv->box, sensitive);
+ }
+ 
+@@ -3837,54 +4002,9 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
+ {
+   GtkComboBoxPrivate *priv = combo_box->priv;
+   GtkTreeSelection *sel;
+-  GtkStyle *style;
+-  GtkWidget *widget = GTK_WIDGET (combo_box);
+-
+-  priv->button = gtk_toggle_button_new ();
+-  gtk_widget_set_parent (priv->button,
+-                         GTK_BIN (combo_box)->child->parent);
+-  g_signal_connect (priv->button, "button-press-event",
+-                    G_CALLBACK (gtk_combo_box_list_button_pressed), combo_box);
+-  g_signal_connect (priv->button, "toggled",
+-                    G_CALLBACK (gtk_combo_box_button_toggled), combo_box);
+ 
+-  priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+-  gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
+-  priv->separator = NULL;
+-  gtk_widget_show_all (priv->button);
+-
+-  if (priv->cell_view)
+-    {
+-      style = gtk_widget_get_style (widget);
+-      gtk_cell_view_set_background_color (GTK_CELL_VIEW (priv->cell_view),
+-                                          &style->base[gtk_widget_get_state (widget)]);
+-
+-      priv->box = gtk_event_box_new ();
+-      gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->box), 
+-                                      FALSE);
+-
+-      if (priv->has_frame)
+-      {
+-        priv->cell_view_frame = gtk_frame_new (NULL);
+-        gtk_frame_set_shadow_type (GTK_FRAME (priv->cell_view_frame),
+-                                   GTK_SHADOW_IN);
+-      }
+-      else 
+-      {
+-        combo_box->priv->cell_view_frame = gtk_event_box_new ();
+-        gtk_event_box_set_visible_window (GTK_EVENT_BOX (combo_box->priv->cell_view_frame), 
+-                                          FALSE);
+-      }
+-      
+-      gtk_widget_set_parent (priv->cell_view_frame,
+-                           GTK_BIN (combo_box)->child->parent);
+-      gtk_container_add (GTK_CONTAINER (priv->cell_view_frame), priv->box);
+-      gtk_widget_show_all (priv->cell_view_frame);
+-
+-      g_signal_connect (priv->box, "button-press-event",
+-                      G_CALLBACK (gtk_combo_box_list_button_pressed), 
+-                      combo_box);
+-    }
++  gtk_combo_box_button_setup (combo_box,
++                              G_CALLBACK (gtk_combo_box_list_button_pressed));
+ 
+   priv->tree_view = gtk_tree_view_new ();
+   sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
+@@ -3955,38 +4075,10 @@ gtk_combo_box_list_destroy (GtkComboBox *combo_box)
+ 
+   /* disconnect signals */
+   g_signal_handlers_disconnect_by_data (priv->tree_view, combo_box);
+-  g_signal_handlers_disconnect_by_func (priv->button,
+-                                        gtk_combo_box_list_button_pressed,
+-                                        combo_box);
+   g_signal_handlers_disconnect_by_data (priv->popup_window, combo_box);
+-  
+-  if (priv->box)
+-    g_signal_handlers_disconnect_matched (priv->box,
+-                                        G_SIGNAL_MATCH_DATA,
+-                                        0, 0, NULL,
+-                                        gtk_combo_box_list_button_pressed,
+-                                        NULL);
+ 
+-  /* destroy things (unparent will kill the latest ref from us)
+-   * last unref on button will destroy the arrow
+-   */
+-  gtk_widget_unparent (priv->button);
+-  priv->button = NULL;
+-  priv->arrow = NULL;
+-
+-  if (priv->cell_view)
+-    {
+-      g_object_set (priv->cell_view,
+-                    "background-set", FALSE,
+-                    NULL);
+-    }
+-
+-  if (priv->cell_view_frame)
+-    {
+-      gtk_widget_unparent (priv->cell_view_frame);
+-      priv->cell_view_frame = NULL;
+-      priv->box = NULL;
+-    }
++  gtk_combo_box_button_destroy (combo_box,
++                                G_CALLBACK (gtk_combo_box_list_button_pressed));
+ 
+   if (priv->scroll_timer)
+     {
+@@ -4025,7 +4117,8 @@ gtk_combo_box_list_button_pressed (GtkWidget      *widget,
+   if (ewidget == priv->popup_window)
+     return TRUE;
+ 
+-  if ((ewidget != priv->button && ewidget != priv->box) ||
++  if (event->type != GDK_BUTTON_PRESS || event->button != 1 ||
++      (ewidget != priv->button && ewidget != priv->box) ||
+       gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button)))
+     return FALSE;
+ 
+diff --git a/gtk/gtkcombobox.h b/gtk/gtkcombobox.h
+index 56dd9e6dee..0c394977ab 100644
+--- a/gtk/gtkcombobox.h
++++ b/gtk/gtkcombobox.h
+@@ -37,6 +37,13 @@ G_BEGIN_DECLS
+ #define GTK_IS_COMBO_BOX_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), GTK_TYPE_COMBO_BOX))
+ #define GTK_COMBO_BOX_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), GTK_TYPE_COMBO_BOX, 
GtkComboBoxClass))
+ 
++typedef enum
++{
++  GTK_COMBO_BOX_POPUP_AUTO,
++  GTK_COMBO_BOX_POPUP_MENU,
++  GTK_COMBO_BOX_POPUP_LIST
++} GtkComboBoxPopupStyle;
++
+ typedef struct _GtkComboBox        GtkComboBox;
+ typedef struct _GtkComboBoxClass   GtkComboBoxClass;
+ typedef struct _GtkComboBoxPrivate GtkComboBoxPrivate;
+-- 
+2.19.1
+
diff --git a/etc/gtkrc b/etc/gtkrc
index f4efa07c7e..6df187aaef 100644
--- a/etc/gtkrc
+++ b/etc/gtkrc
@@ -22,3 +22,16 @@ style "gimp-large-preview"
 }
 
 # class "GimpPreview" style "gimp-large-preview"
+
+#
+# Change the combo-box popup style:
+#
+# This only has effect if GTK is built with the patches
+# in the GIMP source-tree's build/patches/ directory.
+#
+style "combo-box-popup-style"
+{
+  GtkComboBox::popup-style = GTK_COMBO_BOX_POPUP_LIST
+}
+
+class "GtkComboBox" style "combo-box-popup-style"


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