18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This file is part of the popup menu implementation for <select> elements in WebCore. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Collabora Ltd. 7db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 8f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch * Copyright (C) 2010 Igalia S.L. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version. 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful, 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details. 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB. If not, write to 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 28db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block#include "PopupMenuGtk.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameView.h" 31f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "GOwnPtr.h" 32545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include "GtkVersioning.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HostWindow.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PlatformString.h" 35f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <gdk/gdk.h> 36d06194330da2bb8da887d2e1adeacb3a5c1504b2Steve Block#include <gtk/gtk.h> 37f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <wtf/text/CString.h> 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 41f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic const uint32_t gSearchTimeoutMs = 1000; 42f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 43db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve BlockPopupMenuGtk::PopupMenuGtk(PopupMenuClient* client) 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : m_popupClient(client) 45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_previousKeyEventCharacter(0) 46f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch , m_currentlySelectedMenuItem(0) 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 50db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve BlockPopupMenuGtk::~PopupMenuGtk() 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (m_popup) { 53d0825bca7fe65beaee391d30da42e937db621564Steve Block g_signal_handlers_disconnect_matched(m_popup.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); 545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian hide(); 555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 58db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index) 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(client()); 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_popup) { 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_popup = GTK_MENU(gtk_menu_new()); 64f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch g_signal_connect(m_popup.get(), "unmap", G_CALLBACK(PopupMenuGtk::menuUnmapped), this); 65f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch g_signal_connect(m_popup.get(), "key-press-event", G_CALLBACK(PopupMenuGtk::keyPressEventCallback), this); 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } else 67d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_container_foreach(GTK_CONTAINER(m_popup.get()), reinterpret_cast<GtkCallback>(menuRemoveItem), this); 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 69f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int x = 0; 70f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch int y = 0; 71f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(view->hostWindow()->platformPageClient())); 72f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (window) 73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch gdk_window_get_origin(window, &x, &y); 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_menuPosition = view->contentsToWindow(rect.location()); 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_menuPosition = IntPoint(m_menuPosition.x() + x, m_menuPosition.y() + y + rect.height()); 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_indexMap.clear(); 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const int size = client()->listSize(); 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < size; ++i) { 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GtkWidget* item; 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (client()->itemIsSeparator(i)) 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project item = gtk_separator_menu_item_new(); 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project item = gtk_menu_item_new_with_label(client()->itemText(i).utf8().data()); 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_indexMap.add(item, i); 87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch g_signal_connect(item, "activate", G_CALLBACK(PopupMenuGtk::menuItemActivated), this); 88f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch g_signal_connect(item, "select", G_CALLBACK(PopupMenuGtk::selectItemCallback), this); 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // FIXME: Apply the PopupMenuStyle from client()->itemStyle(i) 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project gtk_widget_set_sensitive(item, client()->itemIsEnabled(i)); 92d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_menu_shell_append(GTK_MENU_SHELL(m_popup.get()), item); 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project gtk_widget_show(item); 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 96d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_menu_set_active(m_popup.get(), index); 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The size calls are directly copied from gtkcombobox.c which is LGPL 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GtkRequisition requisition; 101d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_widget_set_size_request(GTK_WIDGET(m_popup.get()), -1, -1); 10268513a70bcd92384395513322f1b801e7bf9c729Steve Block#ifdef GTK_API_VERSION_2 103d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_widget_size_request(GTK_WIDGET(m_popup.get()), &requisition); 10468513a70bcd92384395513322f1b801e7bf9c729Steve Block#else 105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch gtk_widget_get_preferred_size(GTK_WIDGET(m_popup.get()), &requisition, 0); 10668513a70bcd92384395513322f1b801e7bf9c729Steve Block#endif 10768513a70bcd92384395513322f1b801e7bf9c729Steve Block 108d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_widget_set_size_request(GTK_WIDGET(m_popup.get()), std::max(rect.width(), requisition.width), -1); 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen GList* children = gtk_container_get_children(GTK_CONTAINER(m_popup.get())); 11106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen GList* p = children; 11228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if (size) { 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < size; i++) { 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (i > index) 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 11706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen GtkWidget* item = reinterpret_cast<GtkWidget*>(p->data); 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GtkRequisition itemRequisition; 11968513a70bcd92384395513322f1b801e7bf9c729Steve Block#ifdef GTK_API_VERSION_2 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project gtk_widget_get_child_requisition(item, &itemRequisition); 12168513a70bcd92384395513322f1b801e7bf9c729Steve Block#else 122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch gtk_widget_get_preferred_size(item, &itemRequisition, 0); 12368513a70bcd92384395513322f1b801e7bf9c729Steve Block#endif 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_menuPosition.setY(m_menuPosition.y() - itemRequisition.height); 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 12606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen p = g_list_next(p); 12728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu } 12828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu } else { 12928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu // Center vertically the empty popup in the combo box area 13028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu m_menuPosition.setY(m_menuPosition.y() - rect.height() / 2); 13128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu } 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 13306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen g_list_free(children); 134d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_menu_popup(m_popup.get(), 0, 0, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, 0, gtk_get_current_event_time()); 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 137db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::hide() 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(m_popup); 140d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_menu_popdown(m_popup.get()); 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 143db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::updateFromElement() 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project client()->setTextFromItem(client()->selectedIndex()); 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 148db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::disconnectClient() 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 150db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block m_popupClient = 0; 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 153f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochbool PopupMenuGtk::typeAheadFind(GdkEventKey* event) 154f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 155f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // If we were given a non-printable character just skip it. 156f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch gunichar unicodeCharacter = gdk_keyval_to_unicode(event->keyval); 157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!unicodeCharacter) { 158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch resetTypeAheadFindState(); 159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch glong charactersWritten; 163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GOwnPtr<gunichar2> utf16String(g_ucs4_to_utf16(&unicodeCharacter, 1, 0, &charactersWritten, 0)); 164f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!utf16String) { 165f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch resetTypeAheadFindState(); 166f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 167f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 169f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // If the character is the same as the last character, the user is probably trying to 170f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // cycle through the menulist entries. This matches the WebCore behavior for collapsed 171f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // menulists. 172f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch bool repeatingCharacter = unicodeCharacter != m_previousKeyEventCharacter; 173f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (event->time - m_previousKeyEventTimestamp > gSearchTimeoutMs) 174f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_currentSearchString = String(static_cast<UChar*>(utf16String.get()), charactersWritten); 175f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else if (repeatingCharacter) 176f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_currentSearchString.append(String(static_cast<UChar*>(utf16String.get()), charactersWritten)); 177f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 178f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_previousKeyEventTimestamp = event->time; 179f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_previousKeyEventCharacter = unicodeCharacter; 180f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 181f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Like the Chromium port, we case fold before searching, because 182f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // strncmp does not handle non-ASCII characters. 183f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GOwnPtr<gchar> searchStringWithCaseFolded(g_utf8_casefold(m_currentSearchString.utf8().data(), -1)); 184f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_t prefixLength = strlen(searchStringWithCaseFolded.get()); 185f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 186f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GList* children = gtk_container_get_children(GTK_CONTAINER(m_popup.get())); 187f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!children) 188f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 189f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 190f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // If a menu item has already been selected, start searching from the current 191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // item down the list. This will make multiple key presses of the same character 192f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // advance the selection. 193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GList* currentChild = children; 194f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_currentlySelectedMenuItem) { 195f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch currentChild = g_list_find(children, m_currentlySelectedMenuItem); 196f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!currentChild) { 197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_currentlySelectedMenuItem = 0; 198f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch currentChild = children; 199f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 200f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Repeating characters should iterate. 202f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (repeatingCharacter) { 203f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (GList* nextChild = g_list_next(currentChild)) 204f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch currentChild = nextChild; 205f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 206f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 207f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 208f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GList* firstChild = currentChild; 209f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch do { 210f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch currentChild = g_list_next(currentChild); 211f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!currentChild) 212f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch currentChild = children; 213f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 214f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GOwnPtr<gchar> itemText(g_utf8_casefold(gtk_menu_item_get_label(GTK_MENU_ITEM(currentChild->data)), -1)); 215f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!strncmp(searchStringWithCaseFolded.get(), itemText.get(), prefixLength)) { 216f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch gtk_menu_shell_select_item(GTK_MENU_SHELL(m_popup.get()), GTK_WIDGET(currentChild->data)); 217f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 218f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 219f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } while (currentChild != firstChild); 220f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 221f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 222f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 223f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 224db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::menuItemActivated(GtkMenuItem* item, PopupMenuGtk* that) 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(that->client()); 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(that->m_indexMap.contains(GTK_WIDGET(item))); 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project that->client()->valueChanged(that->m_indexMap.get(GTK_WIDGET(item))); 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 231db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::menuUnmapped(GtkWidget*, PopupMenuGtk* that) 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(that->client()); 234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch that->resetTypeAheadFindState(); 235231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block that->client()->popupDidHide(); 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 238db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::menuPositionFunction(GtkMenu*, gint* x, gint* y, gboolean* pushIn, PopupMenuGtk* that) 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *x = that->m_menuPosition.x(); 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *y = that->m_menuPosition.y(); 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *pushIn = true; 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 245f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid PopupMenuGtk::resetTypeAheadFindState() 246f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 247f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_currentlySelectedMenuItem = 0; 248f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_previousKeyEventCharacter = 0; 249f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch m_currentSearchString = ""; 250f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 252db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid PopupMenuGtk::menuRemoveItem(GtkWidget* widget, PopupMenuGtk* that) 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(that->m_popup); 255d0825bca7fe65beaee391d30da42e937db621564Steve Block gtk_container_remove(GTK_CONTAINER(that->m_popup.get()), widget); 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 258f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint PopupMenuGtk::selectItemCallback(GtkMenuItem* item, PopupMenuGtk* that) 259f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 260f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch that->m_currentlySelectedMenuItem = GTK_WIDGET(item); 261f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return FALSE; 262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 263f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 264f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint PopupMenuGtk::keyPressEventCallback(GtkWidget* widget, GdkEventKey* event, PopupMenuGtk* that) 265f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return that->typeAheadFind(event); 267f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 268f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 271