X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcombo.c;h=35734d70f1affa99d6019319d35b7d2213a23f4d;hb=b295f552ee5e236cf3bb0777b078fc14c80a06d2;hp=fc0f267b0187f31a07ae89f7f3d059b77d579e6b;hpb=9595c55184932c11e60e840f10f63d73748e3237;p=~andy%2Fgtk diff --git a/gtk/gtkcombo.c b/gtk/gtkcombo.c index fc0f267b0..35734d70f 100644 --- a/gtk/gtkcombo.c +++ b/gtk/gtkcombo.c @@ -2,28 +2,34 @@ * Copyright 1997 Paolo Molaro * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* - * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +/* Do NOT, I repeat, NOT, copy any of the code in this file. + * The code here relies on all sorts of internal details of GTK+ + */ + +#undef GTK_DISABLE_DEPRECATED + #include #include "gtkarrow.h" @@ -35,78 +41,146 @@ #include "gtklistitem.h" #include "gtkscrolledwindow.h" #include "gtkmain.h" -#include "gtksignal.h" #include "gtkwindow.h" #include "gdk/gdkkeysyms.h" #include "gtkcombo.h" #include "gtkframe.h" +#include "gtkintl.h" const gchar *gtk_combo_string_key = "gtk-combo-string-value"; #define COMBO_LIST_MAX_HEIGHT (400) #define EMPTY_LIST_HEIGHT (15) -static void gtk_combo_class_init (GtkComboClass *klass); -static void gtk_combo_init (GtkCombo *combo); -static void gtk_combo_destroy (GtkObject *combo); -static GtkListItem *gtk_combo_find (GtkCombo *combo); -static gchar * gtk_combo_func (GtkListItem *li); -static gint gtk_combo_focus_idle (GtkCombo *combo); -static gint gtk_combo_entry_focus_out (GtkEntry *entry, - GdkEventFocus *event, - GtkCombo *combo); -static void gtk_combo_get_pos (GtkCombo *combo, - gint *x, - gint *y, - gint *height, - gint *width); -static void gtk_combo_popup_list (GtkCombo *combo); -static void gtk_combo_activate (GtkWidget *widget, - GtkCombo *combo); -static void gtk_combo_popup_button_press (GtkWidget *button, +enum { + PROP_0, + PROP_ENABLE_ARROW_KEYS, + PROP_ENABLE_ARROWS_ALWAYS, + PROP_CASE_SENSITIVE, + PROP_ALLOW_EMPTY, + PROP_VALUE_IN_LIST +}; + +static void gtk_combo_class_init (GtkComboClass *klass); +static void gtk_combo_init (GtkCombo *combo); +static void gtk_combo_realize (GtkWidget *widget); +static void gtk_combo_unrealize (GtkWidget *widget); +static void gtk_combo_destroy (GtkObject *combo); +static GtkListItem *gtk_combo_find (GtkCombo *combo); +static gchar * gtk_combo_func (GtkListItem *li); +static gint gtk_combo_focus_idle (GtkCombo *combo); +static gint gtk_combo_entry_focus_out (GtkEntry *entry, + GdkEventFocus *event, + GtkCombo *combo); +static void gtk_combo_get_pos (GtkCombo *combo, + gint *x, + gint *y, + gint *height, + gint *width); +static void gtk_combo_popup_list (GtkCombo *combo); +static void gtk_combo_popdown_list (GtkCombo *combo); + +static void gtk_combo_activate (GtkWidget *widget, + GtkCombo *combo); +static gboolean gtk_combo_popup_button_press (GtkWidget *button, GdkEventButton *event, GtkCombo *combo); -static void gtk_combo_popup_button_leave (GtkWidget *button, +static gboolean gtk_combo_popup_button_leave (GtkWidget *button, GdkEventCrossing *event, GtkCombo *combo); -static void gtk_combo_update_entry (GtkList *list, - GtkCombo *combo); -static void gtk_combo_update_list (GtkEntry *entry, - GtkCombo *combo); -static gint gtk_combo_button_press (GtkWidget *widget, - GdkEvent *event, - GtkCombo *combo); -static gint gtk_combo_button_release (GtkWidget *widget, - GdkEvent *event, - GtkCombo *combo); -static gint gtk_combo_list_enter (GtkWidget *widget, - GdkEventCrossing *event, - GtkCombo *combo); -static gint gtk_combo_list_key_press (GtkWidget *widget, - GdkEventKey *event, - GtkCombo *combo); -static gint gtk_combo_entry_key_press (GtkEntry *widget, - GdkEventKey *event, - GtkCombo *combo); -static void gtk_combo_item_destroy (GtkObject *object); -static void gtk_combo_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - +static void gtk_combo_update_entry (GtkCombo *combo); +static void gtk_combo_update_list (GtkEntry *entry, + GtkCombo *combo); +static gint gtk_combo_button_press (GtkWidget *widget, + GdkEvent *event, + GtkCombo *combo); +static void gtk_combo_button_event_after (GtkWidget *widget, + GdkEvent *event, + GtkCombo *combo); +static gint gtk_combo_list_enter (GtkWidget *widget, + GdkEventCrossing *event, + GtkCombo *combo); +static gint gtk_combo_list_key_press (GtkWidget *widget, + GdkEventKey *event, + GtkCombo *combo); +static gint gtk_combo_entry_key_press (GtkEntry *widget, + GdkEventKey *event, + GtkCombo *combo); +static gint gtk_combo_window_key_press (GtkWidget *window, + GdkEventKey *event, + GtkCombo *combo); +static void gtk_combo_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_combo_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_combo_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); static GtkHBoxClass *parent_class = NULL; static void gtk_combo_class_init (GtkComboClass * klass) { + GObjectClass *gobject_class; GtkObjectClass *oclass; GtkWidgetClass *widget_class; - parent_class = gtk_type_class (GTK_TYPE_HBOX); + gobject_class = (GObjectClass *) klass; oclass = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gtk_combo_set_property; + gobject_class->get_property = gtk_combo_get_property; + + g_object_class_install_property (gobject_class, + PROP_ENABLE_ARROW_KEYS, + g_param_spec_boolean ("enable_arrow_keys", + _("Enable arrow keys"), + _("Whether the arrow keys move through the list of items"), + TRUE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_ENABLE_ARROWS_ALWAYS, + g_param_spec_boolean ("enable_arrows_always", + _("Always enable arrows"), + _("Obsolete property, ignored"), + TRUE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_CASE_SENSITIVE, + g_param_spec_boolean ("case_sensitive", + _("Case sensitive"), + _("Whether list item matching is case sensitive"), + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, + PROP_ALLOW_EMPTY, + g_param_spec_boolean ("allow_empty", + _("Allow empty"), + _("Whether an empty value may be entered in this field"), + TRUE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, + PROP_VALUE_IN_LIST, + g_param_spec_boolean ("value_in_list", + _("Value in list"), + _("Whether entered values must already be present in the list"), + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + oclass->destroy = gtk_combo_destroy; widget_class->size_allocate = gtk_combo_size_allocate; + widget_class->realize = gtk_combo_realize; + widget_class->unrealize = gtk_combo_unrealize; } static void @@ -117,7 +191,7 @@ gtk_combo_destroy (GtkObject *object) if (combo->popwin) { gtk_widget_destroy (combo->popwin); - gtk_widget_unref (combo->popwin); + g_object_unref (combo->popwin); combo->popwin = NULL; } @@ -128,112 +202,159 @@ static int gtk_combo_entry_key_press (GtkEntry * entry, GdkEventKey * event, GtkCombo * combo) { GList *li; + guint state = event->state & gtk_accelerator_get_default_mod_mask (); /* completion */ - if ((event->keyval == GDK_Tab) && (event->state & GDK_MOD1_MASK)) + if ((event->keyval == GDK_Tab || event->keyval == GDK_KP_Tab) && + state == GDK_MOD1_MASK) { - GCompletion * cmpl; - gchar* prefix; - gchar* nprefix = NULL; - gint pos; + GtkEditable *editable = GTK_EDITABLE (entry); + GCompletion * cmpl; + gchar* prefix; + gchar* nprefix = NULL; + gint pos; - if ( !GTK_LIST (combo->list)->children ) - return FALSE; + if ( !GTK_LIST (combo->list)->children ) + return FALSE; - gtk_signal_emit_stop_by_name (GTK_OBJECT (entry), "key_press_event"); + cmpl = g_completion_new ((GCompletionFunc)gtk_combo_func); + g_completion_add_items (cmpl, GTK_LIST (combo->list)->children); - cmpl = g_completion_new ((GCompletionFunc)gtk_combo_func); - g_completion_add_items (cmpl, GTK_LIST (combo->list)->children); + pos = gtk_editable_get_position (editable); + prefix = gtk_editable_get_chars (editable, 0, pos); - pos = GTK_EDITABLE (entry)->current_pos; - prefix = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, pos); + g_completion_complete (cmpl, prefix, &nprefix); - g_completion_complete(cmpl, prefix, &nprefix); + if (nprefix && strlen (nprefix) > strlen (prefix)) + { + gtk_editable_insert_text (editable, nprefix + pos, + strlen (nprefix) - strlen (prefix), &pos); + gtk_editable_set_position (editable, pos); + } - if (nprefix && strlen (nprefix) > strlen (prefix)) - { - gtk_editable_insert_text (GTK_EDITABLE (entry), nprefix + pos, - strlen (nprefix) - strlen (prefix), &pos); - GTK_EDITABLE (entry)->current_pos = pos; - } + if (nprefix) + g_free (nprefix); + g_free (prefix); + g_completion_free (cmpl); - if (nprefix) - g_free (nprefix); - g_free (prefix); - g_completion_free (cmpl); + return TRUE; + } - return TRUE; - } + if ((event->keyval == GDK_Down || event->keyval == GDK_KP_Down) && + state == GDK_MOD1_MASK) + { + gtk_combo_activate (NULL, combo); + return TRUE; + } if (!combo->use_arrows || !GTK_LIST (combo->list)->children) return FALSE; + gtk_combo_update_list (GTK_ENTRY (combo->entry), combo); li = g_list_find (GTK_LIST (combo->list)->children, gtk_combo_find (combo)); - if ((event->keyval == GDK_Up) - || (event->keyval == GDK_KP_Up) - || ((event->state & GDK_MOD1_MASK) && ((event->keyval == 'p') || (event->keyval == 'P')))) + if (((event->keyval == GDK_Up || event->keyval == GDK_KP_Up) && state == 0) || + ((event->keyval == 'p' || event->keyval == 'P') && state == GDK_MOD1_MASK)) { - if (li) + if (!li) + li = g_list_last (GTK_LIST (combo->list)->children); + else li = li->prev; - if (!li && combo->use_arrows_always) - { - li = g_list_last (GTK_LIST (combo->list)->children); - } + if (li) { gtk_list_select_child (GTK_LIST (combo->list), GTK_WIDGET (li->data)); - gtk_signal_emit_stop_by_name (GTK_OBJECT (entry), "key_press_event"); - return TRUE; + gtk_combo_update_entry (combo); } + + return TRUE; } - else if ((event->keyval == GDK_Down) - || (event->keyval == GDK_KP_Down) - || ((event->state & GDK_MOD1_MASK) && ((event->keyval == 'n') || (event->keyval == 'N')))) + if (((event->keyval == GDK_Down || event->keyval == GDK_KP_Down) && state == 0) || + ((event->keyval == 'n' || event->keyval == 'N') && state == GDK_MOD1_MASK)) { - if (li) + if (!li) + li = GTK_LIST (combo->list)->children; + else if (li) li = li->next; - if (!li && combo->use_arrows_always) - { - li = GTK_LIST (combo->list)->children; - } if (li) { gtk_list_select_child (GTK_LIST (combo->list), GTK_WIDGET (li->data)); - gtk_signal_emit_stop_by_name (GTK_OBJECT (entry), "key_press_event"); - return TRUE; + gtk_combo_update_entry (combo); } + + return TRUE; + } + return FALSE; +} + +static int +gtk_combo_window_key_press (GtkWidget *window, + GdkEventKey *event, + GtkCombo *combo) +{ + guint state = event->state & gtk_accelerator_get_default_mod_mask (); + + if ((event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) && + state == 0) + { + gtk_combo_popdown_list (combo); + gtk_combo_update_entry (combo); + + return TRUE; + } + else if ((event->keyval == GDK_Up || event->keyval == GDK_KP_Up) && + state == GDK_MOD1_MASK) + { + gtk_combo_popdown_list (combo); + + return TRUE; + } + else if ((event->keyval == GDK_space || event->keyval == GDK_KP_Space) && + state == 0) + { + gtk_combo_update_entry (combo); } + return FALSE; } static GtkListItem * gtk_combo_find (GtkCombo * combo) { - gchar *text; + const gchar *text; + GtkListItem *found = NULL; gchar *ltext; + gchar *compare_text; GList *clist; - int (*string_compare) (const char *, const char *); + text = gtk_entry_get_text (GTK_ENTRY (combo->entry)); if (combo->case_sensitive) - string_compare = strcmp; + compare_text = (gchar *)text; else - string_compare = g_strcasecmp; - - text = gtk_entry_get_text (GTK_ENTRY (combo->entry)); - clist = GTK_LIST (combo->list)->children; - - while (clist && clist->data) + compare_text = g_utf8_casefold (text, -1); + + for (clist = GTK_LIST (combo->list)->children; + !found && clist; + clist = clist->next) { ltext = gtk_combo_func (GTK_LIST_ITEM (clist->data)); if (!ltext) continue; - if (!(*string_compare) (ltext, text)) - return (GtkListItem *) clist->data; - clist = clist->next; + + if (!combo->case_sensitive) + ltext = g_utf8_casefold (ltext, -1); + + if (strcmp (ltext, compare_text) == 0) + found = clist->data; + + if (!combo->case_sensitive) + g_free (ltext); } - return NULL; + if (!combo->case_sensitive) + g_free (compare_text); + + return found; } static gchar * @@ -242,13 +363,13 @@ gtk_combo_func (GtkListItem * li) GtkWidget *label; gchar *ltext = NULL; - ltext = (gchar *) gtk_object_get_data (GTK_OBJECT (li), gtk_combo_string_key); + ltext = g_object_get_data (G_OBJECT (li), gtk_combo_string_key); if (!ltext) { label = GTK_BIN (li)->child; if (!label || !GTK_IS_LABEL (label)) return NULL; - gtk_label_get (GTK_LABEL (label), <ext); + ltext = (gchar *) gtk_label_get_text (GTK_LABEL (label)); } return ltext; } @@ -271,6 +392,8 @@ gtk_combo_entry_focus_out (GtkEntry * entry, GdkEventFocus * event, GtkCombo * c if (combo->value_in_list && !gtk_combo_find (combo)) { + GSource *focus_idle; + /* gdk_beep(); *//* this can be annoying */ if (combo->ok_if_empty && !strcmp (gtk_entry_get_text (entry), "")) return FALSE; @@ -281,10 +404,15 @@ gtk_combo_entry_focus_out (GtkEntry * entry, GdkEventFocus * event, GtkCombo * c /* this is needed because if we call gtk_widget_grab_focus() it isn't guaranteed it's the *last* call before the main-loop, so the focus can be lost anyway... - the signal_emit_stop doesn't seem to work either... + the signal_stop_emission doesn't seem to work either... */ - gtk_idle_add ((GtkFunction) gtk_combo_focus_idle, combo); - /*gtk_signal_emit_stop_by_name (GTK_OBJECT (entry), "focus_out_event"); */ + focus_idle = g_idle_source_new (); + g_source_set_closure (focus_idle, + g_cclosure_new_object (G_CALLBACK (gtk_combo_focus_idle), + G_OBJECT (combo))); + g_source_attach (focus_idle, NULL); + + /*g_signal_stop_emission_by_name (entry, "focus_out_event"); */ return TRUE; } return FALSE; @@ -307,16 +435,19 @@ gtk_combo_get_pos (GtkCombo * combo, gint * x, gint * y, gint * height, gint * w gint work_height; gint old_height; gint old_width; + gint scrollbar_spacing; - widget = GTK_WIDGET(combo); + widget = GTK_WIDGET (combo); popup = GTK_SCROLLED_WINDOW (combo->popup); popwin = GTK_BIN (combo->popwin); - + + scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (popup); + gdk_window_get_origin (combo->entry->window, x, y); real_height = MIN (combo->entry->requisition.height, combo->entry->allocation.height); *y += real_height; - avail_height = gdk_screen_height () - *y; + avail_height = gdk_screen_get_height (gtk_widget_get_screen (widget)) - *y; gtk_widget_size_request (combo->list, &list_requisition); min_height = MIN (list_requisition.height, @@ -325,17 +456,17 @@ gtk_combo_get_pos (GtkCombo * combo, gint * x, gint * y, gint * height, gint * w list_requisition.height += EMPTY_LIST_HEIGHT; alloc_width = (widget->allocation.width - - 2 * popwin->child->style->klass->xthickness - + 2 * popwin->child->style->xthickness - 2 * GTK_CONTAINER (popwin->child)->border_width - 2 * GTK_CONTAINER (combo->popup)->border_width - 2 * GTK_CONTAINER (GTK_BIN (popup)->child)->border_width - - 2 * GTK_BIN (popup)->child->style->klass->xthickness); + 2 * GTK_BIN (popup)->child->style->xthickness); - work_height = (2 * popwin->child->style->klass->ythickness + + work_height = (2 * popwin->child->style->ythickness + 2 * GTK_CONTAINER (popwin->child)->border_width + 2 * GTK_CONTAINER (combo->popup)->border_width + 2 * GTK_CONTAINER (GTK_BIN (popup)->child)->border_width + - 2 * GTK_BIN (popup)->child->style->klass->xthickness); + 2 * GTK_BIN (popup)->child->style->ythickness); do { @@ -345,21 +476,26 @@ gtk_combo_get_pos (GtkCombo * combo, gint * x, gint * y, gint * height, gint * w if (!show_hscroll && alloc_width < list_requisition.width) { - work_height += (popup->hscrollbar->requisition.height + - GTK_SCROLLED_WINDOW_GET_CLASS (combo->popup)->scrollbar_spacing); + GtkRequisition requisition; + + gtk_widget_size_request (popup->hscrollbar, &requisition); + work_height += (requisition.height + scrollbar_spacing); + show_hscroll = TRUE; } if (!show_vscroll && work_height + list_requisition.height > avail_height) { + GtkRequisition requisition; + if (work_height + min_height > avail_height && *y - real_height > avail_height) { *y -= (work_height + list_requisition.height + real_height); break; } - alloc_width -= (popup->vscrollbar->requisition.width + - GTK_SCROLLED_WINDOW_GET_CLASS (combo->popup)->scrollbar_spacing); + gtk_widget_size_request (popup->hscrollbar, &requisition); + alloc_width -= (requisition.width + scrollbar_spacing); show_vscroll = TRUE; } } while (old_width != alloc_width || old_height != work_height); @@ -377,6 +513,7 @@ gtk_combo_get_pos (GtkCombo * combo, gint * x, gint * y, gint * height, gint * w static void gtk_combo_popup_list (GtkCombo * combo) { + GtkList *list; gint height, width, x, y; gint old_width, old_height; @@ -392,70 +529,149 @@ gtk_combo_popup_list (GtkCombo * combo) gtk_widget_hide (GTK_SCROLLED_WINDOW (combo->popup)->vscrollbar); } - gtk_widget_set_uposition (combo->popwin, x, y); - gtk_widget_set_usize (combo->popwin, width, height); - gtk_widget_realize (combo->popwin); - gdk_window_resize (combo->popwin->window, width, height); + gtk_combo_update_list (GTK_ENTRY (combo->entry), combo); + + /* We need to make sure some child of combo->popwin + * is focused to disable GtkWindow's automatic + * "focus-the-first-item" code. If there is no selected + * child, we focus the list itself with some hackery. + */ + list = GTK_LIST (combo->list); + + if (list->selection) + { + gtk_widget_grab_focus (list->selection->data); + } + else + { + GTK_WIDGET_SET_FLAGS (list, GTK_CAN_FOCUS); + gtk_widget_grab_focus (combo->list); + GTK_LIST (combo->list)->last_focus_child = NULL; + GTK_WIDGET_UNSET_FLAGS (list, GTK_CAN_FOCUS); + } + + gtk_window_move (GTK_WINDOW (combo->popwin), x, y); + gtk_widget_set_size_request (combo->popwin, width, height); gtk_widget_show (combo->popwin); gtk_widget_grab_focus (combo->popwin); } +static void +gtk_combo_popdown_list (GtkCombo *combo) +{ + combo->current_button = 0; + + if (GTK_BUTTON (combo->button)->in_button) + { + GTK_BUTTON (combo->button)->in_button = FALSE; + gtk_button_released (GTK_BUTTON (combo->button)); + } + + if (GTK_WIDGET_HAS_GRAB (combo->popwin)) + { + gtk_grab_remove (combo->popwin); + gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (combo)), + gtk_get_current_event_time ()); + gdk_display_keyboard_ungrab (gtk_widget_get_display (GTK_WIDGET (combo)), + gtk_get_current_event_time ()); + } + + gtk_widget_hide (combo->popwin); +} + +static gboolean +popup_grab_on_window (GdkWindow *window, + guint32 activate_time) +{ + if ((gdk_pointer_grab (window, TRUE, + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK, + NULL, NULL, activate_time) == 0)) + { + if (gdk_keyboard_grab (window, TRUE, + activate_time) == 0) + return TRUE; + else + { + gdk_display_pointer_ungrab (gdk_drawable_get_display (window), + activate_time); + return FALSE; + } + } + + return FALSE; +} + static void gtk_combo_activate (GtkWidget *widget, GtkCombo *combo) { + if (!combo->button->window || + !popup_grab_on_window (combo->button->window, + gtk_get_current_event_time ())) + return; + gtk_combo_popup_list (combo); + + /* This must succeed since we already have the grab */ + popup_grab_on_window (combo->popwin->window, + gtk_get_current_event_time ()); if (!GTK_WIDGET_HAS_FOCUS (combo->entry)) gtk_widget_grab_focus (combo->entry); gtk_grab_add (combo->popwin); - gdk_pointer_grab (combo->popwin->window, TRUE, - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK, - NULL, NULL, GDK_CURRENT_TIME); } -static void +static gboolean gtk_combo_popup_button_press (GtkWidget *button, GdkEventButton *event, GtkCombo *combo) { if (!GTK_WIDGET_HAS_FOCUS (combo->entry)) gtk_widget_grab_focus (combo->entry); - if (!combo->current_button && (event->button == 1)) - gtk_combo_popup_list (combo); + + if (event->button != 1) + return FALSE; + + if (!popup_grab_on_window (combo->button->window, + gtk_get_current_event_time ())) + return FALSE; combo->current_button = event->button; - - GTK_LIST (combo->list)->drag_selection = TRUE; - gdk_pointer_grab (combo->list->window, TRUE, - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON1_MOTION_MASK | - GDK_BUTTON_RELEASE_MASK, - NULL, NULL, event->time); - gtk_grab_add (combo->list); + + gtk_combo_popup_list (combo); + + /* This must succeed since we already have the grab */ + popup_grab_on_window (combo->popwin->window, + gtk_get_current_event_time ()); + + gtk_button_pressed (GTK_BUTTON (button)); + + gtk_grab_add (combo->popwin); + + return TRUE; } -static void +static gboolean gtk_combo_popup_button_leave (GtkWidget *button, GdkEventCrossing *event, GtkCombo *combo) { - if (combo->current_button) - gtk_signal_emit_stop_by_name (GTK_OBJECT (button), "leave_notify_event"); + /* The idea here is that we want to keep the button down if the + * popup is popped up. + */ + return combo->current_button != 0; } - static void -gtk_combo_update_entry (GtkList * list, GtkCombo * combo) +gtk_combo_update_entry (GtkCombo * combo) { + GtkList *list = GTK_LIST (combo->list); char *text; - gtk_grab_remove (GTK_WIDGET (combo)); - gtk_signal_handler_block (GTK_OBJECT (list), combo->list_change_id); + g_signal_handler_block (list, combo->list_change_id); if (list->selection) { text = gtk_combo_func (GTK_LIST_ITEM (list->selection->data)); @@ -463,7 +679,15 @@ gtk_combo_update_entry (GtkList * list, GtkCombo * combo) text = ""; gtk_entry_set_text (GTK_ENTRY (combo->entry), text); } - gtk_signal_handler_unblock (GTK_OBJECT (list), combo->list_change_id); + g_signal_handler_unblock (list, combo->list_change_id); +} + +static void +gtk_combo_selection_changed (GtkList *list, + GtkCombo *combo) +{ + if (!GTK_WIDGET_VISIBLE (combo->popwin)) + gtk_combo_update_entry (combo); } static void @@ -475,13 +699,13 @@ gtk_combo_update_list (GtkEntry * entry, GtkCombo * combo) gtk_grab_remove (GTK_WIDGET (combo)); - gtk_signal_handler_block (GTK_OBJECT (entry), combo->entry_change_id); + g_signal_handler_block (entry, combo->entry_change_id); if (slist && slist->data) gtk_list_unselect_child (list, GTK_WIDGET (slist->data)); li = gtk_combo_find (combo); if (li) gtk_list_select_child (list, GTK_WIDGET (li)); - gtk_signal_handler_unblock (GTK_OBJECT (entry), combo->entry_change_id); + g_signal_handler_unblock (entry, combo->entry_change_id); } static gint @@ -508,46 +732,38 @@ gtk_combo_button_press (GtkWidget * widget, GdkEvent * event, GtkCombo * combo) } } - gtk_widget_hide (combo->popwin); - gtk_grab_remove (combo->popwin); - gdk_pointer_ungrab (event->button.time); + gtk_combo_popdown_list (combo); return TRUE; } -static gint -gtk_combo_button_release (GtkWidget * widget, GdkEvent * event, GtkCombo * combo) +static gboolean +is_within (GtkWidget *widget, + GtkWidget *ancestor) +{ + return widget == ancestor || gtk_widget_is_ancestor (widget, ancestor); +} + +static void +gtk_combo_button_event_after (GtkWidget *widget, + GdkEvent *event, + GtkCombo *combo) { GtkWidget *child; + if (event->type != GDK_BUTTON_RELEASE) + return; + + child = gtk_get_event_widget ((GdkEvent*) event); + if ((combo->current_button != 0) && (event->button.button == 1)) { /* This was the initial button press */ - GdkEventCrossing tmp_event; - combo->current_button = 0; - if (widget != combo->button) - gtk_widget_event (combo->button, event); - - /* Un-pre-hightlight */ - - tmp_event.type = GDK_LEAVE_NOTIFY; - tmp_event.window = combo->button->window; - tmp_event.send_event = TRUE; - tmp_event.subwindow = NULL; - tmp_event.detail = GDK_NOTIFY_ANCESTOR; - - gtk_widget_event (combo->button, (GdkEvent *)&tmp_event); - /* Check to see if we released inside the button */ - child = gtk_get_event_widget ((GdkEvent*) event); - - while (child && child != (combo->button)) - child = child->parent; - - if (child == combo->button) + if (child && is_within (child, combo->button)) { gtk_grab_add (combo->popwin); gdk_pointer_grab (combo->popwin->window, TRUE, @@ -555,23 +771,38 @@ gtk_combo_button_release (GtkWidget * widget, GdkEvent * event, GtkCombo * combo GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, NULL, NULL, GDK_CURRENT_TIME); - return FALSE; + return; } } - else - { - /* The user has clicked inside the popwin and released */ - if (GTK_WIDGET_HAS_GRAB (combo->popwin)) - { - gtk_grab_remove (combo->popwin); - gdk_pointer_ungrab (event->button.time); - } + if (is_within (child, combo->list)) + gtk_combo_update_entry (combo); + + gtk_combo_popdown_list (combo); + +} + +static void +find_child_foreach (GtkWidget *widget, + gpointer data) +{ + GdkEventButton *event = data; + + if (!event->window) + { + if (event->x >= widget->allocation.x && + event->x < widget->allocation.x + widget->allocation.width && + event->y >= widget->allocation.y && + event->y < widget->allocation.y + widget->allocation.height) + event->window = g_object_ref (widget->window); } - - gtk_widget_hide (combo->popwin); +} - return TRUE; +static void +find_child_window (GtkContainer *container, + GdkEventButton *event) +{ + gtk_container_foreach (container, find_child_foreach, event); } static gint @@ -582,12 +813,12 @@ gtk_combo_list_enter (GtkWidget *widget, GtkWidget *event_widget; event_widget = gtk_get_event_widget ((GdkEvent*) event); - + if ((event_widget == combo->list) && (combo->current_button != 0) && (!GTK_WIDGET_HAS_GRAB (combo->list))) { - GdkEvent tmp_event; + GdkEvent *tmp_event = gdk_event_new (GDK_BUTTON_PRESS); gint x, y; GdkModifierType mask; @@ -598,19 +829,31 @@ gtk_combo_list_enter (GtkWidget *widget, */ gdk_window_get_pointer (combo->list->window, &x, &y, &mask); - tmp_event.button.type = GDK_BUTTON_PRESS; - tmp_event.button.window = combo->list->window; - tmp_event.button.send_event = TRUE; - tmp_event.button.time = GDK_CURRENT_TIME; /* bad */ - tmp_event.button.x = x; - tmp_event.button.y = y; + tmp_event->button.send_event = TRUE; + tmp_event->button.time = GDK_CURRENT_TIME; /* bad */ + tmp_event->button.x = x; + tmp_event->button.y = y; /* We leave all the XInput fields unfilled here, in the expectation * that GtkList doesn't care. */ - tmp_event.button.button = combo->current_button; - tmp_event.button.state = mask; + tmp_event->button.button = combo->current_button; + tmp_event->button.state = mask; - gtk_widget_event (combo->list, &tmp_event); + find_child_window (GTK_CONTAINER (combo->list), &tmp_event->button); + if (!tmp_event->button.window) + { + GtkWidget *child; + + if (GTK_LIST (combo->list)->children) + child = GTK_LIST (combo->list)->children->data; + else + child = combo->list; + + tmp_event->button.window = g_object_ref (child->window); + } + + gtk_widget_event (combo->list, tmp_event); + gdk_event_free (tmp_event); } return FALSE; @@ -619,41 +862,41 @@ gtk_combo_list_enter (GtkWidget *widget, static int gtk_combo_list_key_press (GtkWidget * widget, GdkEventKey * event, GtkCombo * combo) { - if (event->keyval == GDK_Escape) + guint state = event->state & gtk_accelerator_get_default_mod_mask (); + + if (event->keyval == GDK_Escape && state == 0) { - if (GTK_WIDGET_HAS_GRAB (combo->popwin)) - { - gtk_grab_remove (combo->popwin); - gdk_pointer_ungrab (GDK_CURRENT_TIME); - } - else if (GTK_WIDGET_HAS_GRAB (combo->list)) + if (GTK_WIDGET_HAS_GRAB (combo->list)) gtk_list_end_drag_selection (GTK_LIST (combo->list)); - gtk_widget_hide (combo->popwin); - if (GTK_WIDGET_HAS_GRAB (combo->button)) - { - combo->current_button = 0; - GTK_BUTTON (combo->button)->in_button = FALSE; - gtk_button_released (GTK_BUTTON (combo->button)); - gtk_grab_remove (combo->button); - } + + gtk_combo_popdown_list (combo); + return TRUE; } return FALSE; } +static void +combo_event_box_realize (GtkWidget *widget) +{ + GdkCursor *cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), + GDK_TOP_LEFT_ARROW); + gdk_window_set_cursor (widget->window, cursor); + gdk_cursor_unref (cursor); +} + static void gtk_combo_init (GtkCombo * combo) { GtkWidget *arrow; GtkWidget *frame; GtkWidget *event_box; - GdkCursor *cursor; - combo->case_sensitive = 0; - combo->value_in_list = 0; - combo->ok_if_empty = 1; - combo->use_arrows = 1; - combo->use_arrows_always = 0; + combo->case_sensitive = FALSE; + combo->value_in_list = FALSE; + combo->ok_if_empty = TRUE; + combo->use_arrows = TRUE; + combo->use_arrows_always = FALSE; combo->entry = gtk_entry_new (); combo->button = gtk_button_new (); combo->current_button = 0; @@ -665,37 +908,36 @@ gtk_combo_init (GtkCombo * combo) GTK_WIDGET_UNSET_FLAGS (combo->button, GTK_CAN_FOCUS); gtk_widget_show (combo->entry); gtk_widget_show (combo->button); - combo->entry_change_id = gtk_signal_connect (GTK_OBJECT (combo->entry), "changed", - (GtkSignalFunc) gtk_combo_update_list, combo); - gtk_signal_connect (GTK_OBJECT (combo->entry), "key_press_event", - (GtkSignalFunc) gtk_combo_entry_key_press, combo); - gtk_signal_connect_after (GTK_OBJECT (combo->entry), "focus_out_event", - (GtkSignalFunc) gtk_combo_entry_focus_out, combo); - combo->activate_id = gtk_signal_connect (GTK_OBJECT (combo->entry), "activate", - (GtkSignalFunc) gtk_combo_activate, combo); - gtk_signal_connect_after (GTK_OBJECT (combo->button), "button_press_event", - (GtkSignalFunc) gtk_combo_popup_button_press, combo); - /*gtk_signal_connect_after (GTK_OBJECT (combo->button), "button_release_event", - (GtkSignalFunc) gtk_combo_button_release, combo);*/ - gtk_signal_connect (GTK_OBJECT (combo->button), "leave_notify_event", - (GtkSignalFunc) gtk_combo_popup_button_leave, combo); - /*gtk_signal_connect(GTK_OBJECT(combo->button), "clicked", - (GtkSignalFunc)prelight_bug, combo); */ + combo->entry_change_id = g_signal_connect (combo->entry, "changed", + G_CALLBACK (gtk_combo_update_list), + combo); + g_signal_connect (combo->entry, "key_press_event", + G_CALLBACK (gtk_combo_entry_key_press), combo); + g_signal_connect_after (combo->entry, "focus_out_event", + G_CALLBACK (gtk_combo_entry_focus_out), combo); + combo->activate_id = g_signal_connect (combo->entry, "activate", + G_CALLBACK (gtk_combo_activate), + combo); + g_signal_connect (combo->button, "button_press_event", + G_CALLBACK (gtk_combo_popup_button_press), combo); + g_signal_connect (combo->button, "leave_notify_event", + G_CALLBACK (gtk_combo_popup_button_leave), combo); combo->popwin = gtk_window_new (GTK_WINDOW_POPUP); - gtk_widget_ref (combo->popwin); - gtk_window_set_policy (GTK_WINDOW (combo->popwin), 1, 1, 0); + g_object_ref (combo->popwin); + gtk_window_set_resizable (GTK_WINDOW (combo->popwin), FALSE); + + g_signal_connect (combo->popwin, "key_press_event", + G_CALLBACK (gtk_combo_window_key_press), combo); gtk_widget_set_events (combo->popwin, GDK_KEY_PRESS_MASK); event_box = gtk_event_box_new (); gtk_container_add (GTK_CONTAINER (combo->popwin), event_box); + g_signal_connect (event_box, "realize", + G_CALLBACK (combo_event_box_realize), NULL); gtk_widget_show (event_box); - gtk_widget_realize (event_box); - cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW); - gdk_window_set_cursor (event_box->window, cursor); - gdk_cursor_destroy (cursor); frame = gtk_frame_new (NULL); gtk_container_add (GTK_CONTAINER (event_box), frame); @@ -716,7 +958,7 @@ gtk_combo_init (GtkCombo * combo) */ gtk_widget_set_events (combo->list, GDK_ENTER_NOTIFY_MASK); - gtk_list_set_selection_mode(GTK_LIST(combo->list), GTK_SELECTION_BROWSE); + gtk_list_set_selection_mode (GTK_LIST(combo->list), GTK_SELECTION_BROWSE); gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (combo->popup), combo->list); gtk_container_set_focus_vadjustment (GTK_CONTAINER (combo->list), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (combo->popup))); @@ -724,88 +966,144 @@ gtk_combo_init (GtkCombo * combo) gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (combo->popup))); gtk_widget_show (combo->list); - combo->list_change_id = gtk_signal_connect (GTK_OBJECT (combo->list), "selection_changed", - (GtkSignalFunc) gtk_combo_update_entry, combo); - gtk_signal_connect (GTK_OBJECT (combo->popwin), "key_press_event", - (GtkSignalFunc) gtk_combo_list_key_press, combo); - gtk_signal_connect (GTK_OBJECT (combo->popwin), "button_press_event", - GTK_SIGNAL_FUNC (gtk_combo_button_press), combo); - - gtk_signal_connect_after (GTK_OBJECT (combo->list), "button_release_event", - GTK_SIGNAL_FUNC (gtk_combo_button_release), combo); - /* We connect here on the button, because we'll have a grab on it - * when the event occurs. But we are actually interested in enters - * for the combo->list. - */ - gtk_signal_connect (GTK_OBJECT (combo->button), "enter_notify_event", - GTK_SIGNAL_FUNC (gtk_combo_list_enter), combo); + combo->list_change_id = g_signal_connect (combo->list, "selection_changed", + G_CALLBACK (gtk_combo_selection_changed), combo); + + g_signal_connect (combo->popwin, "key_press_event", + G_CALLBACK (gtk_combo_list_key_press), combo); + g_signal_connect (combo->popwin, "button_press_event", + G_CALLBACK (gtk_combo_button_press), combo); + + g_signal_connect (combo->popwin, "event_after", + G_CALLBACK (gtk_combo_button_event_after), combo); + g_signal_connect (combo->list, "event_after", + G_CALLBACK (gtk_combo_button_event_after), combo); + + g_signal_connect (combo->list, "enter_notify_event", + G_CALLBACK (gtk_combo_list_enter), combo); +} + +static void +gtk_combo_realize (GtkWidget *widget) +{ + GtkCombo *combo = GTK_COMBO (widget); + + gtk_window_set_screen (GTK_WINDOW (combo->popwin), + gtk_widget_get_screen (widget)); + + GTK_WIDGET_CLASS( parent_class )->realize (widget); } -GtkType +static void +gtk_combo_unrealize (GtkWidget *widget) +{ + GtkCombo *combo = GTK_COMBO (widget); + + gtk_combo_popdown_list (combo); + gtk_widget_unrealize (combo->popwin); + + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + +GType gtk_combo_get_type (void) { - static GtkType combo_type = 0; + static GType combo_type = 0; if (!combo_type) { - static const GtkTypeInfo combo_info = + static const GTypeInfo combo_info = { - "GtkCombo", - sizeof (GtkCombo), sizeof (GtkComboClass), - (GtkClassInitFunc) gtk_combo_class_init, - (GtkObjectInitFunc) gtk_combo_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_combo_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkCombo), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_combo_init, }; - combo_type = gtk_type_unique (GTK_TYPE_HBOX, &combo_info); + + combo_type = g_type_register_static (GTK_TYPE_HBOX, "GtkCombo", + &combo_info, 0); } + return combo_type; } GtkWidget* gtk_combo_new (void) { - return GTK_WIDGET (gtk_type_new (GTK_TYPE_COMBO)); + return g_object_new (GTK_TYPE_COMBO, NULL); } void -gtk_combo_set_value_in_list (GtkCombo * combo, gint val, gint ok_if_empty) +gtk_combo_set_value_in_list (GtkCombo * combo, gboolean val, gboolean ok_if_empty) { - g_return_if_fail (combo != NULL); g_return_if_fail (GTK_IS_COMBO (combo)); + val = val != FALSE; + ok_if_empty = ok_if_empty != FALSE; - combo->value_in_list = val; - combo->ok_if_empty = ok_if_empty; + g_object_freeze_notify (G_OBJECT (combo)); + if (combo->value_in_list != val) + { + combo->value_in_list = val; + g_object_notify (G_OBJECT (combo), "value_in_list"); + } + if (combo->ok_if_empty != ok_if_empty) + { + combo->ok_if_empty = ok_if_empty; + g_object_notify (G_OBJECT (combo), "allow_empty"); + } + g_object_thaw_notify (G_OBJECT (combo)); } void -gtk_combo_set_case_sensitive (GtkCombo * combo, gint val) +gtk_combo_set_case_sensitive (GtkCombo * combo, gboolean val) { - g_return_if_fail (combo != NULL); g_return_if_fail (GTK_IS_COMBO (combo)); + val = val != FALSE; + if (combo->case_sensitive != val) + { combo->case_sensitive = val; + g_object_notify (G_OBJECT (combo), "case_sensitive"); + } } void -gtk_combo_set_use_arrows (GtkCombo * combo, gint val) +gtk_combo_set_use_arrows (GtkCombo * combo, gboolean val) { - g_return_if_fail (combo != NULL); g_return_if_fail (GTK_IS_COMBO (combo)); + val = val != FALSE; + if (combo->use_arrows != val) + { combo->use_arrows = val; + g_object_notify (G_OBJECT (combo), "enable_arrow_keys"); + } } void -gtk_combo_set_use_arrows_always (GtkCombo * combo, gint val) +gtk_combo_set_use_arrows_always (GtkCombo * combo, gboolean val) { - g_return_if_fail (combo != NULL); g_return_if_fail (GTK_IS_COMBO (combo)); + val = val != FALSE; + if (combo->use_arrows_always != val) + { + g_object_freeze_notify (G_OBJECT (combo)); combo->use_arrows_always = val; - combo->use_arrows = 1; + g_object_notify (G_OBJECT (combo), "enable_arrows_always"); + + if (combo->use_arrows != TRUE) + { + combo->use_arrows = TRUE; + g_object_notify (G_OBJECT (combo), "enable_arrow_keys"); + } + g_object_thaw_notify (G_OBJECT (combo)); + } } void @@ -814,10 +1112,11 @@ gtk_combo_set_popdown_strings (GtkCombo * combo, GList * strings) GList *list; GtkWidget *li; - g_return_if_fail (combo != NULL); g_return_if_fail (GTK_IS_COMBO (combo)); g_return_if_fail (strings != NULL); + gtk_combo_popdown_list (combo); + gtk_list_clear_items (GTK_LIST (combo->list), 0, -1); list = strings; while (list) @@ -829,49 +1128,14 @@ gtk_combo_set_popdown_strings (GtkCombo * combo, GList * strings) } } -static void -gtk_combo_item_destroy (GtkObject * object) -{ - gchar *key; - - key = gtk_object_get_data (object, gtk_combo_string_key); - if (key) - { - gtk_object_remove_data (object, gtk_combo_string_key); - g_free (key); - } -} - void gtk_combo_set_item_string (GtkCombo * combo, GtkItem * item, const gchar * item_value) { - gchar *val; - gint connected = 0; - - g_return_if_fail (combo != NULL); g_return_if_fail (GTK_IS_COMBO (combo)); g_return_if_fail (item != NULL); - val = gtk_object_get_data (GTK_OBJECT (item), gtk_combo_string_key); - if (val) - { - g_free (val); - connected = 1; - } - if (item_value) - { - val = g_strdup(item_value); - gtk_object_set_data (GTK_OBJECT (item), gtk_combo_string_key, val); - if (!connected) - gtk_signal_connect (GTK_OBJECT (item), "destroy", - (GtkSignalFunc) gtk_combo_item_destroy, val); - } - else - { - gtk_object_set_data (GTK_OBJECT (item), gtk_combo_string_key, NULL); - if (connected) - gtk_signal_disconnect_by_data(GTK_OBJECT (item), val); - } + g_object_set_data_full (G_OBJECT (item), gtk_combo_string_key, + g_strdup (item_value), g_free); } static void @@ -880,7 +1144,6 @@ gtk_combo_size_allocate (GtkWidget *widget, { GtkCombo *combo; - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_COMBO (widget)); g_return_if_fail (allocation != NULL); @@ -904,11 +1167,74 @@ gtk_combo_size_allocate (GtkWidget *widget, void gtk_combo_disable_activate (GtkCombo* combo) { - g_return_if_fail (combo != NULL); g_return_if_fail (GTK_IS_COMBO (combo)); if ( combo->activate_id ) { - gtk_signal_disconnect(GTK_OBJECT(combo->entry), combo->activate_id); + g_signal_handler_disconnect (combo->entry, combo->activate_id); combo->activate_id = 0; } } + +static void +gtk_combo_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkCombo *combo = GTK_COMBO (object); + + switch (prop_id) + { + case PROP_ENABLE_ARROW_KEYS: + gtk_combo_set_use_arrows (combo, g_value_get_boolean (value)); + break; + case PROP_ENABLE_ARROWS_ALWAYS: + gtk_combo_set_use_arrows_always (combo, g_value_get_boolean (value)); + break; + case PROP_CASE_SENSITIVE: + gtk_combo_set_case_sensitive (combo, g_value_get_boolean (value)); + break; + case PROP_ALLOW_EMPTY: + combo->ok_if_empty = g_value_get_boolean (value); + break; + case PROP_VALUE_IN_LIST: + combo->value_in_list = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +gtk_combo_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkCombo *combo = GTK_COMBO (object); + + switch (prop_id) + { + case PROP_ENABLE_ARROW_KEYS: + g_value_set_boolean (value, combo->use_arrows); + break; + case PROP_ENABLE_ARROWS_ALWAYS: + g_value_set_boolean (value, combo->use_arrows_always); + break; + case PROP_CASE_SENSITIVE: + g_value_set_boolean (value, combo->case_sensitive); + break; + case PROP_ALLOW_EMPTY: + g_value_set_boolean (value, combo->ok_if_empty); + break; + case PROP_VALUE_IN_LIST: + g_value_set_boolean (value, combo->value_in_list); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +}