diff options
Diffstat (limited to 'packages/gtk+/gtk+-2.6.4-1.osso7/gtkcombobox.c.diff')
-rw-r--r-- | packages/gtk+/gtk+-2.6.4-1.osso7/gtkcombobox.c.diff | 950 |
1 files changed, 950 insertions, 0 deletions
diff --git a/packages/gtk+/gtk+-2.6.4-1.osso7/gtkcombobox.c.diff b/packages/gtk+/gtk+-2.6.4-1.osso7/gtkcombobox.c.diff index e69de29bb2..2376beaeaa 100644 --- a/packages/gtk+/gtk+-2.6.4-1.osso7/gtkcombobox.c.diff +++ b/packages/gtk+/gtk+-2.6.4-1.osso7/gtkcombobox.c.diff @@ -0,0 +1,950 @@ +--- gtk+-2.6.4/gtk/gtkcombobox.c 2005-02-25 21:11:08.000000000 +0200 ++++ gtk+-2.6.4/gtk/gtkcombobox.c 2005-04-06 16:19:36.406003808 +0300 +@@ -17,6 +17,10 @@ + * Boston, MA 02111-1307, USA. + */ + ++/* ++ * Modified for Nokia Oyj during 2002-2004. ++ */ ++ + #include <config.h> + #include "gtkalias.h" + #include "gtkcombobox.h" +@@ -39,6 +43,8 @@ + #include "gtktreeselection.h" + #include "gtkvseparator.h" + #include "gtkwindow.h" ++#include "gtkcomboboxentry.h" ++#include "gtktoolbar.h" + + #include <gdk/gdkkeysyms.h> + +@@ -52,6 +58,13 @@ + + #include "gtktreeprivate.h" + ++#define HILDON_MAX_WIDTH 406 ++#define HILDON_MAX_HEIGHT 305 ++#define HILDON_MAX_ITEMS 8 ++/* this is also defined in gtkmenu.c and should be replaced with ++ a style property */ ++#define MENU_SCROLL_ARROW_HEIGHT 20 ++ + /* WELCOME, to THE house of evil code */ + + typedef struct _ComboCellInfo ComboCellInfo; +@@ -119,6 +132,9 @@ + GtkTreeViewRowSeparatorFunc row_separator_func; + gpointer row_separator_data; + GtkDestroyNotify row_separator_destroy; ++ ++ /* Hildon hack: state of our style property */ ++ gboolean autodimmed_button; + }; + + /* While debugging this evil code, I have learned that +@@ -201,6 +217,7 @@ + + #define BONUS_PADDING 4 + #define SCROLL_TIME 100 ++#define HILDON_PADDING 25 + + /* common */ + static void gtk_combo_box_class_init (GtkComboBoxClass *klass); +@@ -273,6 +290,14 @@ + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); ++static gboolean gtk_combo_box_focus_in (GtkWidget *widget, ++ GdkEventFocus *event); ++static gint gtk_combo_box_focus (GtkWidget *widget, ++ GtkDirectionType dir); ++static void gtk_combo_box_child_focus_in (GtkWidget *widget, ++ GdkEventFocus *event); ++static void gtk_combo_box_child_focus_out (GtkWidget *widget, ++ GdkEventFocus *event); + static gboolean gtk_combo_box_expose_event (GtkWidget *widget, + GdkEventExpose *event); + static gboolean gtk_combo_box_scroll_event (GtkWidget *widget, +@@ -285,6 +310,12 @@ + + static void gtk_combo_box_check_appearance (GtkComboBox *combo_box); + ++/* <Hildon addition> */ ++extern void gtk_grab_combo_box_entry_focus (GtkComboBoxEntry *entry_box); ++ ++static void gtk_combo_box_grab_focus (GtkWidget *focus_widget); ++/* </hildon addition> */ ++ + /* listening to the model */ + static void gtk_combo_box_model_row_inserted (GtkTreeModel *model, + GtkTreePath *path, +@@ -424,6 +455,9 @@ + static void gtk_combo_box_start_editing (GtkCellEditable *cell_editable, + GdkEvent *event); + ++static void gtk_combo_box_menu_position_above (GtkMenu *menu, gint *x, ++ gint *y, gboolean *push_in, ++ gpointer user_data); + + GType + gtk_combo_box_get_type (void) +@@ -479,6 +513,25 @@ + return combo_box_type; + } + ++/* Hildon addition: Check if the button needs to be dimmed */ ++static void hildon_check_autodim(GtkComboBox *combo_box) ++{ ++ GtkWidget *widget; ++ GtkTreeModel *model; ++ GtkTreeIter iter; ++ ++ widget = combo_box->priv->button; ++ model = combo_box->priv->model; ++ ++ if (combo_box->priv->autodimmed_button && widget != NULL) ++ { ++ if (model && gtk_tree_model_get_iter_first(model, &iter)) ++ gtk_widget_set_sensitive(widget, TRUE); ++ else ++ gtk_widget_set_sensitive(widget, FALSE); ++ } ++} ++ + /* common */ + static void + gtk_combo_box_class_init (GtkComboBoxClass *klass) +@@ -504,6 +557,11 @@ + widget_class->mnemonic_activate = gtk_combo_box_mnemonic_activate; + widget_class->style_set = gtk_combo_box_style_set; + widget_class->state_changed = gtk_combo_box_state_changed; ++ ++ /* Hildon addition */ ++ widget_class->grab_focus = gtk_combo_box_grab_focus; ++ widget_class->focus_in_event = gtk_combo_box_focus_in; ++ widget_class->focus = gtk_combo_box_focus; + + gtk_object_class = (GtkObjectClass *)klass; + gtk_object_class->destroy = gtk_combo_box_destroy; +@@ -687,6 +745,41 @@ + FALSE, + G_PARAM_READABLE)); + ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_boolean ("hildonlike", ++ _("Size request"), ++ _("Size allocate"), ++ FALSE, ++ G_PARAM_READABLE)); ++ ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_int ("arrow-height", ++ P_("Arrow height for option menu"), ++ P_("Sets arrow height"), ++ 0, ++ G_MAXINT, ++ 28, ++ G_PARAM_READWRITE)); ++ ++ gtk_widget_class_install_style_property (widget_class, ++ g_param_spec_int ("arrow-width", ++ P_("Arrow width for option menu"), ++ P_("Sets arrow width"), ++ 0, ++ G_MAXINT, ++ 26, ++ G_PARAM_READWRITE)); ++ ++ ++ /* Hildon hack: style property for enabling the autodimming hack */ ++ gtk_widget_class_install_style_property ( ++ widget_class, ++ g_param_spec_boolean ("autodimmed_button", ++ _("Autodimmed button"), ++ _("Automatically dims the button if the list is empty"), ++ FALSE, ++ G_PARAM_READABLE)); ++ + g_type_class_add_private (object_class, sizeof (GtkComboBoxPrivate)); + } + +@@ -731,6 +824,11 @@ + combo_box->priv->editing_canceled = FALSE; + combo_box->priv->auto_scroll = FALSE; + combo_box->priv->focus_on_click = TRUE; ++ ++ /* Hildon hack: default value for our style property if it is queried before ++ * the style is set */ ++ combo_box->priv->autodimmed_button = FALSE; ++ GTK_WIDGET_SET_FLAGS ( combo_box, GTK_CAN_FOCUS ); + } + + static void +@@ -911,7 +1009,19 @@ + { + GtkComboBox *combo_box = GTK_COMBO_BOX (widget); + ++ /* Hildon hack: read the state of our style property */ ++ gtk_widget_style_get (GTK_WIDGET(combo_box), ++ "autodimmed_button", &(combo_box->priv->autodimmed_button), NULL); ++ + gtk_combo_box_check_appearance (combo_box); ++ ++ /* Hildon hack: handle the dimmed state of the button in regards whether ++ * the list is empty or not. This has to be done here because ++ * in the callback functions of GtkTreeModel the button widget ++ * may have not yet been set. However, we repeat this stuff in ++ * those functions, because later the button will be set and ++ * we want to update our state. */ ++ hildon_check_autodim(combo_box); + + if (combo_box->priv->tree_view && combo_box->priv->cell_view) + gtk_cell_view_set_background_color (GTK_CELL_VIEW (combo_box->priv->cell_view), +@@ -922,10 +1032,17 @@ + gtk_combo_box_button_toggled (GtkWidget *widget, + gpointer data) + { ++ gboolean hildonlike; + GtkComboBox *combo_box = GTK_COMBO_BOX (data); ++ ++ gtk_widget_style_get (GTK_WIDGET (combo_box), "hildonlike", &hildonlike, NULL); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) + { ++ if (hildonlike) { ++ gtk_combo_box_grab_focus(GTK_WIDGET(combo_box)); ++ } ++ + if (!combo_box->priv->popup_in_progress) + gtk_combo_box_popup (combo_box); + } +@@ -1103,7 +1220,7 @@ + { + gtk_container_remove (GTK_CONTAINER (combo_box->priv->popup_frame), + combo_box->priv->popup_widget); +- g_object_unref (combo_box->priv->popup_widget); ++ g_object_unref (G_OBJECT (combo_box->priv->popup_widget)); + combo_box->priv->popup_widget = NULL; + } + +@@ -1175,7 +1292,7 @@ + popup); + + gtk_widget_show (popup); +- g_object_ref (popup); ++ g_object_ref (G_OBJECT (popup)); + combo_box->priv->popup_widget = popup; + } + } +@@ -1250,9 +1367,13 @@ + GtkRequisition requisition; + GList *children; + gint screen_width; ++ gint screen_height; + gint menu_xpos; + gint menu_ypos; +- gint menu_width; ++ gint menu_width, menu_height; ++ gint counter = 0; ++ gint scroll_offset = 0; ++ gint max_items = 0; + + g_return_if_fail (GTK_IS_COMBO_BOX (user_data)); + +@@ -1261,6 +1382,7 @@ + + gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition); + menu_width = requisition.width; ++ menu_height = requisition.height; + + active = gtk_menu_get_active (GTK_MENU (combo_box->priv->popup_widget)); + gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos); +@@ -1275,6 +1397,11 @@ + } + + children = GTK_MENU_SHELL (combo_box->priv->popup_widget)->children; ++ child = children->data; ++ gtk_widget_get_child_requisition (child, &requisition); ++ max_items = (HILDON_MAX_HEIGHT-2*MENU_SCROLL_ARROW_HEIGHT)/requisition.height; ++ max_items -= 1; ++ + while (children) + { + child = children->data; +@@ -1284,27 +1411,119 @@ + + if (GTK_WIDGET_VISIBLE (child)) + { +- gtk_widget_get_child_requisition (child, &requisition); +- menu_ypos -= requisition.height; ++ if (counter < max_items - 2) ++ menu_ypos -= requisition.height; ++ if (counter > max_items - 3) ++ scroll_offset += requisition.height; + } +- ++ ++ counter++; + children = children->next; + } ++ gtk_widget_get_child_requisition (GTK_WIDGET(menu), &requisition); + ++ if ( requisition.height >= HILDON_MAX_HEIGHT ) ++ menu_ypos -= MENU_SCROLL_ARROW_HEIGHT; ++ + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) + menu_xpos = menu_xpos + widget->allocation.width - menu_width; + ++ { ++ gint menu_xpad, menu_ypad; ++ gtk_widget_style_get (GTK_WIDGET (menu), ++ "horizontal-padding", &menu_xpad, ++ "vertical-padding", &menu_ypad, ++ NULL); ++ menu_xpos -= menu_xpad - 3; ++ menu_ypos -= menu_ypad - 1; ++ } ++ + /* Clamp the position on screen */ + screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget)); ++ screen_height = gdk_screen_get_height (gtk_widget_get_screen (widget)); + + if (menu_xpos < 0) + menu_xpos = 0; + else if ((menu_xpos + menu_width) > screen_width) + menu_xpos -= ((menu_xpos + menu_width) - screen_width); + ++ if (menu_ypos + menu_height > screen_height) ++ { ++ menu_ypos = screen_height - menu_height; ++ } ++ if (menu_ypos < 0) ++ { ++ menu_ypos = 0; ++ } ++ ++ GTK_MENU(combo_box->priv->popup_widget)->scroll_offset = scroll_offset; ++ + *x = menu_xpos; + *y = menu_ypos; + ++ *push_in = FALSE; ++} ++ ++static void ++gtk_combo_box_menu_position_above (GtkMenu *menu, ++ gint *x, ++ gint *y, ++ gboolean *push_in, ++ gpointer user_data) ++{ ++ /* ++ * This function positiones the menu above widgets. ++ * This is a modified version of the position function ++ * gtk_combo_box_position_over. ++ * NB: This is only used when gtkcombobox is in toolbar! ++ */ ++ ++ GtkWidget *child; ++ GtkRequisition requisition; ++ GList *children; ++ gint screen_width; ++ gint menu_xpos; ++ gint menu_ypos; ++ gint gx,gy; ++ gint menu_width; ++ GtkWidget *widget; ++ ++ widget = GTK_WIDGET(user_data); ++ ++ gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition); ++ menu_width = requisition.width; ++ ++ gdk_window_get_position(GDK_WINDOW(widget->window), &gx, &gy); ++ gtk_widget_translate_coordinates (widget, gtk_widget_get_toplevel(widget), ++ gx, gy, &menu_xpos, &menu_ypos); ++ ++ menu_ypos -= GTK_WIDGET(menu)->style->ythickness * 2; ++ menu_ypos -= GTK_WIDGET(widget)->style->ythickness * 2; ++ ++ menu_ypos -= widget->allocation.height; ++ ++ children = GTK_MENU_SHELL (menu)->children; ++ while (children) { ++ child = children->data; ++ if (GTK_WIDGET_VISIBLE (child)){ ++ gtk_widget_get_child_requisition (child, &requisition); ++ menu_ypos -= requisition.height; ++ } ++ children = children->next; ++ } ++ ++ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ++ menu_xpos = menu_xpos + widget->allocation.width - menu_width; ++ ++ screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget)); ++ ++ if (menu_xpos < 0) ++ menu_xpos = 0; ++ else if ((menu_xpos + menu_width) > screen_width) ++ menu_xpos -= ((menu_xpos + menu_width) - screen_width); ++ ++ *x = menu_xpos; ++ *y = menu_ypos; + *push_in = TRUE; + } + +@@ -1318,21 +1537,44 @@ + GtkComboBox *combo_box; + GtkWidget *menu_item; + ++ gboolean hildonlike; ++ + combo_box = GTK_COMBO_BOX (user_data); + +- if (combo_box->priv->wrap_width > 0 || combo_box->priv->cell_view == NULL) +- gtk_combo_box_menu_position_below (menu, x, y, push_in, user_data); +- else ++ gtk_widget_style_get (GTK_WIDGET (combo_box), "hildonlike", &hildonlike, NULL); ++ ++ if (!(combo_box->priv->wrap_width > 0 || combo_box->priv->cell_view == NULL)) + { + /* FIXME handle nested menus better */ + menu_item = gtk_menu_get_active (GTK_MENU (combo_box->priv->popup_widget)); + if (menu_item) + gtk_menu_shell_select_item (GTK_MENU_SHELL (combo_box->priv->popup_widget), + menu_item); ++ } + +- gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data); ++ if (hildonlike) ++ { ++ /* HILDON: we check if combobox is in a toolbar */ ++ gboolean in_toolbar = gtk_widget_get_ancestor(GTK_WIDGET(combo_box), GTK_TYPE_TOOLBAR) != NULL; ++ if (in_toolbar) ++ { ++ /*due to limits in combo's sizes we use position_over here also*/ ++ gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data); ++ return; ++ } + } + ++ if (combo_box->priv->wrap_width > 0 || combo_box->priv->cell_view == NULL) ++/* ++ * Changed because we always want the combo box position to be over ++ * the combo box, unless it's in toolbar. ++ * ++ gtk_combo_box_menu_position_below (menu, x, y, push_in, user_data); ++*/ ++ gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data); ++ else ++ gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data); ++ + } + + static void +@@ -1430,7 +1672,7 @@ + list = cells; + while (list) + { +- g_object_get (list->data, "sensitive", &sensitive, NULL); ++ g_object_get (G_OBJECT (list->data), "sensitive", &sensitive, NULL); + + if (sensitive) + break; +@@ -1469,7 +1711,7 @@ + list = cells; + while (list) + { +- g_object_get (list->data, "sensitive", &sensitive, NULL); ++ g_object_get (G_OBJECT (list->data), "sensitive", &sensitive, NULL); + + if (sensitive) + break; +@@ -1516,8 +1758,8 @@ + if (menu != combo_box->priv->popup_widget && child == children) + { + separator = GTK_WIDGET (child->next->data); +- g_object_set (item, "visible", sensitive, NULL); +- g_object_set (separator, "visible", sensitive, NULL); ++ g_object_set (G_OBJECT (item), "visible", sensitive, NULL); ++ g_object_set (G_OBJECT (separator), "visible", sensitive, NULL); + } + else + gtk_widget_set_sensitive (item, sensitive); +@@ -1543,16 +1785,19 @@ + if (gtk_tree_row_reference_valid (combo_box->priv->active_row)) + { + path = gtk_tree_row_reference_get_path (combo_box->priv->active_row); +- active_item = gtk_tree_path_get_indices (path)[0]; +- gtk_tree_path_free (path); +- +- if (combo_box->priv->add_tearoffs) +- active_item++; ++ if (path) ++ { ++ active_item = gtk_tree_path_get_indices (path)[0]; ++ gtk_tree_path_free (path); ++ ++ if (combo_box->priv->add_tearoffs) ++ active_item++; ++ } + } + + /* FIXME handle nested menus better */ +- gtk_menu_set_active (GTK_MENU (combo_box->priv->popup_widget), active_item); +- ++ gtk_menu_set_active (GTK_MENU (combo_box->priv->popup_widget), active_item); ++ + if (combo_box->priv->wrap_width == 0) + { + width = GTK_WIDGET (combo_box)->allocation.width; +@@ -1684,6 +1929,7 @@ + { + gint padding; + GtkRequisition req; ++ gboolean hildonlike; + + if (combo_box->priv->cell_view) + gtk_widget_style_get (combo_box->priv->cell_view, +@@ -1691,9 +1937,17 @@ + NULL); + else + padding = 0; ++ ++ gtk_widget_style_get (GTK_WIDGET (combo_box), "hildonlike", &hildonlike, ++ NULL); + + /* add some pixels for good measure */ +- padding += BONUS_PADDING; ++ /* Hildon: we need more padding because our theming ++ * Not elegent way to do it anyway ... */ ++ if (hildonlike) ++ padding += HILDON_PADDING; ++ else ++ padding += BONUS_PADDING; + + if (combo_box->priv->cell_view) + gtk_cell_view_get_size_of_row (GTK_CELL_VIEW (combo_box->priv->cell_view), +@@ -1709,6 +1963,7 @@ + { + GtkTreeIter iter; + GtkTreePath *path; ++ gboolean hildonlike; + + if (!combo_box->priv->model || + !gtk_tree_model_get_iter_first (combo_box->priv->model, &iter)) +@@ -1717,6 +1972,7 @@ + combo_box->priv->width = 0; + + path = gtk_tree_path_new_from_indices (0, -1); ++ gtk_widget_style_get (GTK_WIDGET (combo_box), "hildonlike", &hildonlike, NULL); + + do + { +@@ -1727,8 +1983,11 @@ + path, &req); + else + req.width = 0; ++ /* Hildon: we need more padding because our theming ++ * Not elegent way to do it anyway ... */ + +- combo_box->priv->width = MAX (combo_box->priv->width, req.width); ++ combo_box->priv->width = MAX (combo_box->priv->width, ++ req.width + (hildonlike == 1) ? HILDON_PADDING : 0 ); + + gtk_tree_path_next (path); + } +@@ -1744,10 +2003,19 @@ + gint width, height; + gint focus_width, focus_pad; + GtkRequisition bin_req; ++ gboolean hildonlike; ++ gint arrow_width; ++ gint arrow_height; + + GtkComboBox *combo_box = GTK_COMBO_BOX (widget); + + gtk_combo_box_check_appearance (combo_box); ++ ++ /* get hildonlike style property */ ++ gtk_widget_style_get (widget, "hildonlike", ++ &hildonlike, "arrow-width", ++ &arrow_width, "arrow-height", ++ &arrow_height, NULL); + + /* common */ + gtk_widget_size_request (GTK_BIN (widget)->child, &bin_req); +@@ -1829,6 +2097,13 @@ + requisition->height = MAX (requisition->height, button_req.height); + requisition->width += button_req.width; + } ++ ++ requisition->width = MIN (requisition->width, HILDON_MAX_WIDTH); ++ ++ /* HILDON quick fix: height forced to be 28px as specified by Hildon specs. */ ++ if (hildonlike) ++ if (requisition->height > arrow_height) ++ requisition->height = arrow_height; + } + + static void +@@ -1839,17 +2114,32 @@ + gint focus_width, focus_pad; + GtkAllocation child; + GtkRequisition req; ++ GtkRequisition child_req; + gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; ++ gboolean hildonlike; ++ gint arrow_width; ++ gint arrow_height; + + gtk_combo_box_check_appearance (combo_box); + +- widget->allocation = *allocation; +- + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, ++ "hildonlike", &hildonlike, ++ "arrow-width", &arrow_width, ++ "arrow-height", &arrow_height, + NULL); + ++ /* HILDON: set height to fixed value */ ++ if (hildonlike) ++ if (allocation->height > arrow_height) ++ { ++ allocation->y += (allocation->height - arrow_height) / 2; ++ allocation->height = arrow_height; ++ } ++ ++ widget->allocation = *allocation; ++ + if (!combo_box->priv->tree_view) + { + if (combo_box->priv->cell_view) +@@ -1909,7 +2199,16 @@ + child.width = child.x; + child.x = allocation->x + + border_width + xthickness + focus_width + focus_pad; +- child.width -= child.x; ++ child.width -= child.x + xthickness; ++ } ++ ++ if (hildonlike) ++ { ++ gtk_widget_size_request(GTK_BIN(widget)->child, &child_req); ++ child.y += (child.height - child_req.height) / 2; ++ child.height = child_req.height; ++ gtk_widget_hide(combo_box->priv->separator); ++ gtk_widget_hide(combo_box->priv->arrow); + } + + child.width = MAX (1, child.width); +@@ -1928,6 +2227,11 @@ + child.height = allocation->height; + child.width = MAX (1, child.width); + child.height = MAX (1, child.height); ++ ++ /* HILDON quick fix */ ++ if (hildonlike) ++ child.width = arrow_width; ++ + gtk_widget_size_allocate (combo_box->priv->button, &child); + + if (is_rtl) +@@ -1938,6 +2242,13 @@ + child.width = allocation->width - req.width; + child.width = MAX (1, child.width); + child.height = MAX (1, child.height); ++ ++ if (hildonlike) ++ { ++ gtk_widget_size_request(GTK_BIN(widget)->child, &child_req); ++ child.y += (child.height - child_req.height) / 2; ++ child.height = child_req.height; ++ } + gtk_widget_size_allocate (GTK_BIN (widget)->child, &child); + } + } +@@ -1990,6 +2301,11 @@ + GTK_WIDGET (combo_box->priv->cell_view_frame)->style->ythickness); + } + } ++ ++ gtk_widget_size_request(GTK_BIN(widget)->child, &child_req); ++ ++ child.y += (child.height - child_req.height) / 2; ++ child.height = child_req.height; + + child.width = MAX (1, child.width); + child.height = MAX (1, child.height); +@@ -2036,6 +2352,8 @@ + gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (combo_box->priv->cell_view), NULL); + } + ++ ++ + static void + gtk_combo_box_forall (GtkContainer *container, + gboolean include_internals, +@@ -2057,6 +2375,46 @@ + } + + static gboolean ++gtk_combo_box_focus_in (GtkWidget *widget, ++ GdkEventFocus *event) ++{ ++ g_return_val_if_fail( widget, FALSE ); ++ ++ if ( !GTK_CONTAINER( widget )->focus_child ) ++ { ++ gtk_combo_box_grab_focus ( GTK_WIDGET(widget) ); ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++static gint ++gtk_combo_box_focus (GtkWidget *widget, ++ GtkDirectionType dir) ++{ ++ g_return_val_if_fail (widget, FALSE); ++ if (GTK_WIDGET_HAS_FOCUS(widget)||GTK_CONTAINER(widget)->focus_child) ++ return FALSE; ++ ++ gtk_widget_grab_focus (widget); ++ return TRUE; ++} ++ ++static void ++gtk_combo_box_child_focus_in (GtkWidget * widget, ++ GdkEventFocus *event) ++{ ++ gtk_widget_event( widget, (GdkEvent*)event ); ++} ++ ++static void ++gtk_combo_box_child_focus_out (GtkWidget * widget, ++ GdkEventFocus *event) ++{ ++ gtk_widget_event( widget, (GdkEvent*)event ); ++} ++ ++static gboolean + gtk_combo_box_expose_event (GtkWidget *widget, + GdkEventExpose *event) + { +@@ -2357,11 +2715,13 @@ + gboolean add_children) + { + GtkWidget *menu; ++ gboolean hildonlike; ++ ++ gtk_widget_style_get (GTK_WIDGET (combo_box), "hildonlike", &hildonlike, NULL); + + if (combo_box->priv->cell_view) + { + combo_box->priv->button = gtk_toggle_button_new (); +- + g_signal_connect (combo_box->priv->button, "toggled", + G_CALLBACK (gtk_combo_box_button_toggled), combo_box); + g_signal_connect_after (combo_box->priv->button, +@@ -2400,6 +2760,9 @@ + gtk_widget_show_all (combo_box->priv->button); + } + ++ g_signal_connect_swapped (combo_box->priv->button, "focus_in_event", G_CALLBACK (gtk_combo_box_child_focus_in), combo_box); ++ g_signal_connect_swapped (combo_box->priv->button, "focus_out_event", G_CALLBACK (gtk_combo_box_child_focus_out), combo_box); ++ + g_signal_connect (combo_box->priv->button, "button_press_event", + G_CALLBACK (gtk_combo_box_menu_button_press), + combo_box); +@@ -2749,6 +3112,9 @@ + { + GtkComboBox *combo_box = GTK_COMBO_BOX (user_data); + ++ /* Hildon hack: sets the popup button sensitive if we have items in the list */ ++ hildon_check_autodim(combo_box); ++ + gtk_tree_row_reference_inserted (G_OBJECT (user_data), path); + + if (combo_box->priv->tree_view) +@@ -2783,7 +3149,10 @@ + if (combo_box->priv->tree_view) + gtk_combo_box_list_popup_resize (combo_box); + else +- gtk_combo_box_menu_row_deleted (model, path, user_data); ++ gtk_combo_box_menu_row_deleted (model, path, user_data); ++ ++ /* Hildon hack: dim the popup button in case item count reaches 0 */ ++ hildon_check_autodim(combo_box); + } + + static void +@@ -3458,10 +3827,46 @@ + gboolean found; + GtkTreeIter iter; + GtkTreeIter new_iter; ++ gboolean hildonlike; ++ gint index = gtk_combo_box_get_active (combo_box); ++ gint new_index; ++ gint items = 0; + + if (combo_box->priv->model == NULL) + return FALSE; + ++ items = gtk_tree_model_iter_n_children (combo_box->priv->model, NULL); ++ ++ gtk_widget_style_get (GTK_WIDGET (combo_box), "hildonlike", ++ &hildonlike, NULL); ++ ++ /* Hildon select key */ ++ if (hildonlike) ++ { ++ if (event->keyval == GDK_KP_Enter || event->keyval == GDK_Return) ++ { ++ gtk_combo_box_popup (combo_box); ++ return TRUE; ++ } ++ else if (event->keyval == GDK_Left && items != 0) ++ { ++ new_index = (index == 0) ? items - 1 : index - 1; ++ gtk_combo_box_set_active (combo_box, new_index); ++ return TRUE; ++ } ++ else if (event->keyval == GDK_Right && items != 0) ++ { ++ new_index = (index == items - 1) ? 0 : index + 1; ++ gtk_combo_box_set_active (combo_box, new_index); ++ return TRUE; ++ } ++ else if ((event->keyval == GDK_Down || event->keyval == GDK_KP_Down) ++ || (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)) ++ { ++ return FALSE; ++ } ++ } ++ + if ((event->keyval == GDK_Down || event->keyval == GDK_KP_Down) && + state == GDK_MOD1_MASK) + { +@@ -3714,7 +4119,7 @@ + + combo_box = GTK_COMBO_BOX (layout); + +- g_object_ref (cell); ++ g_object_ref (G_OBJECT (cell)); + gtk_object_sink (GTK_OBJECT (cell)); + + info = g_new0 (ComboCellInfo, 1); +@@ -3771,7 +4176,7 @@ + + combo_box = GTK_COMBO_BOX (layout); + +- g_object_ref (cell); ++ g_object_ref (G_OBJECT (cell)); + gtk_object_sink (GTK_OBJECT (cell)); + + info = g_new0 (ComboCellInfo, 1); +@@ -3833,7 +4238,7 @@ + ComboCellInfo *info = (ComboCellInfo *)i->data; + + gtk_combo_box_cell_layout_clear_attributes (layout, info->cell); +- g_object_unref (info->cell); ++ g_object_unref (G_OBJECT (info->cell)); + g_free (info); + i->data = NULL; + } +@@ -3922,7 +4327,7 @@ + + if (GTK_IS_MENU_ITEM (parent) && + gtk_menu_item_get_submenu (GTK_MENU_ITEM (parent))) +- g_object_set (cell, "sensitive", TRUE, NULL); ++ g_object_set (G_OBJECT (cell), "sensitive", TRUE, NULL); + } + + +@@ -4137,7 +4542,7 @@ + GtkWidget * + gtk_combo_box_new (void) + { +- return g_object_new (GTK_TYPE_COMBO_BOX, NULL); ++ return GTK_WIDGET (g_object_new (GTK_TYPE_COMBO_BOX, NULL)); + } + + /** +@@ -4157,7 +4562,9 @@ + + g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); + +- combo_box = g_object_new (GTK_TYPE_COMBO_BOX, "model", model, NULL); ++ combo_box = GTK_COMBO_BOX (g_object_new (GTK_TYPE_COMBO_BOX, ++ "model", model, ++ NULL)); + + return GTK_WIDGET (combo_box); + } +@@ -4512,6 +4919,7 @@ + if (!model) + { + gtk_combo_box_unset_model (combo_box); ++ hildon_check_autodim(combo_box); + return; + } + +@@ -4524,7 +4932,7 @@ + gtk_combo_box_unset_model (combo_box); + + combo_box->priv->model = model; +- g_object_ref (combo_box->priv->model); ++ g_object_ref (G_OBJECT (combo_box->priv->model)); + + combo_box->priv->inserted_id = + g_signal_connect (combo_box->priv->model, "row_inserted", +@@ -4561,6 +4969,8 @@ + if (combo_box->priv->cell_view) + gtk_cell_view_set_model (GTK_CELL_VIEW (combo_box->priv->cell_view), + combo_box->priv->model); ++ ++ hildon_check_autodim(combo_box); + } + + /** +@@ -5140,3 +5550,33 @@ + + return combo->priv->focus_on_click; + } ++/* Hildon addition: ++ * This is added, because we need to be able grab focus for our widget. ++ * Focus grabbing can happen it two ways: If we are using combobox entry ++ * we grab entry widget focus, otherwise togglebutton focus ++ */ ++static void gtk_combo_box_grab_focus (GtkWidget *focus_widget) ++{ ++ GtkComboBox *combo_box; ++ GtkComboBoxEntry *combo_entry; ++ gboolean hildonlike; ++ ++ combo_box = GTK_COMBO_BOX (focus_widget); ++ ++ gtk_widget_style_get (focus_widget, "hildonlike", ++ &hildonlike, NULL); ++ ++ if (hildonlike) ++ { ++ /* Are we in entry mode ? */ ++ if ( GTK_IS_COMBO_BOX_ENTRY(combo_box)) ++ { ++ combo_entry = GTK_COMBO_BOX_ENTRY (combo_box); ++ gtk_grab_combo_box_entry_focus (combo_entry); ++ } ++ else ++ { ++ gtk_widget_grab_focus (combo_box->priv->button); ++ } ++ } ++} |