+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 */
+
+ combo->current_button = 0;
+
+ /* Check to see if we released inside the button */
+ if (child && is_within (child, combo->button))
+ {
+ 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);
+ return;
+ }
+ }
+
+ 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);
+ }
+}
+
+static void
+find_child_window (GtkContainer *container,
+ GdkEventButton *event)
+{
+ gtk_container_foreach (container, find_child_foreach, event);
+}
+
+static gint
+gtk_combo_list_enter (GtkWidget *widget,
+ GdkEventCrossing *event,
+ GtkCombo *combo)
+{
+ 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 = gdk_event_new (GDK_BUTTON_PRESS);
+ gint x, y;
+ GdkModifierType mask;
+
+ gtk_grab_remove (combo->popwin);
+
+ /* Transfer the grab over to the list by synthesizing
+ * a button press event
+ */
+ gdk_window_get_pointer (combo->list->window, &x, &y, &mask);
+
+ 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;
+
+ 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;
+}
+