--- 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 #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 @@ -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); +/* */ +extern void gtk_grab_combo_box_entry_focus (GtkComboBoxEntry *entry_box); + +static void gtk_combo_box_grab_focus (GtkWidget *focus_widget); +/* */ + /* 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); + } + } +}