+extern bool           g_blockEventsOnDrag;
+extern bool           g_blockEventsOnScroll;
+extern wxCursor       g_globalCursor;
+extern wxWindowGTK   *g_delayedFocus;
+
+static bool       g_hasDoubleClicked = FALSE;
+
+//-----------------------------------------------------------------------------
+// idle callback for SetFirstItem
+//-----------------------------------------------------------------------------
+
+struct wxlistbox_idle_struct
+{
+    wxListBox   *m_listbox;
+    int          m_item;
+    gint         m_tag;
+};
+
+extern "C" gint wxlistbox_idle_callback( gpointer gdata )
+{
+    wxlistbox_idle_struct* data = (wxlistbox_idle_struct*) gdata;
+    gdk_threads_enter();
+
+    gtk_idle_remove( data->m_tag );
+
+    // check that the items haven't been deleted from the listbox since we had
+    // installed this callback
+    wxListBox *lbox = data->m_listbox;
+    if ( data->m_item < lbox->GetCount() )
+    {
+        lbox->SetFirstItem( data->m_item );
+    }
+
+    delete data;
+
+    gdk_threads_leave();
+
+    return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// "button_release_event"
+//-----------------------------------------------------------------------------
+
+/* we would normally emit a wxEVT_COMMAND_LISTBOX_DOUBLECLICKED event once
+   a GDK_2BUTTON_PRESS occurs, but this has the particular problem of the
+   listbox keeping the focus until it receives a GDK_BUTTON_RELEASE event.
+   this can lead to race conditions so that we emit the dclick event
+   after the GDK_BUTTON_RELEASE event after the GDK_2BUTTON_PRESS event */
+
+static gint
+gtk_listbox_button_release_callback( GtkWidget * WXUNUSED(widget),
+                                     GdkEventButton * WXUNUSED(gdk_event),
+                                     wxListBox *listbox )
+{
+    if (g_isIdle) wxapp_install_idle_handler();
+
+    if (g_blockEventsOnDrag) return FALSE;
+    if (g_blockEventsOnScroll) return FALSE;
+
+    if (!listbox->m_hasVMT) return FALSE;
+
+    if (!g_hasDoubleClicked) return FALSE;
+
+    wxCommandEvent event( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, listbox->GetId() );
+    event.SetEventObject( listbox );
+
+    wxArrayInt aSelections;
+    int n, count = listbox->GetSelections(aSelections);
+    if ( count > 0 )
+    {
+        n = aSelections[0];
+        if ( listbox->HasClientObjectData() )
+            event.SetClientObject( listbox->GetClientObject(n) );
+        else if ( listbox->HasClientUntypedData() )
+            event.SetClientData( listbox->GetClientData(n) );
+        event.SetString( listbox->GetString(n) );
+    }
+    else
+    {
+        n = -1;
+    }
+
+    event.m_commandInt = n;
+
+    listbox->GetEventHandler()->ProcessEvent( event );
+
+    return FALSE;
+}