[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-10851-g50815da
mrobinson at webkit.org
mrobinson at webkit.org
Wed Dec 22 17:51:03 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit 79be008e34beffe7c6a1caf5e97dbc09d85a2cd6
Author: mrobinson at webkit.org <mrobinson at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Wed Dec 1 16:46:39 2010 +0000
2010-12-01 Martin Robinson <mrobinson at igalia.com>
Reviewed by Xan Lopez.
[Gtk] Open menulists should support typeahead find
https://bugs.webkit.org/show_bug.cgi?id=27443
Added a GTK+-specific layout test to track typeahead find state.
* platform/gtk/fast/forms/menulist-typeahead-find-expected.txt: Added.
* platform/gtk/fast/forms/menulist-typeahead-find.html: Added.
2010-12-01 Apelete Seketeli <apelete at seketeli.org> and Martin Robinson <mrobinson at igalia.com>
Reviewed by Xan Lopez.
[Gtk] Open menulists should support typeahead find
https://bugs.webkit.org/show_bug.cgi?id=27443
Added typeahead find support for open GTK+ menulists.
Test: platform/gtk/fast/forms/menulist-typeahead-find.html
* platform/gtk/PopupMenuGtk.cpp:
(WebCore::PopupMenuGtk::PopupMenuGtk): Initialize new members.
(WebCore::PopupMenuGtk::show): Track currently selected menu item
via a signal handler.
(WebCore::PopupMenuGtk::typeAheadFind): Added.
(WebCore::PopupMenuGtk::menuUnmapped): Reset typeahead find state
when menu is unmapped.
(WebCore::PopupMenuGtk::resetTypeAheadFindState): Added.
(WebCore::PopupMenuGtk::selectItemCallback): Added.
(WebCore::PopupMenuGtk::keyPressEventCallback): Added.
* platform/gtk/PopupMenuGtk.h: Added new members to track typeahead
find state.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73025 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index b398498..cc92616 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,5 +1,17 @@
2010-12-01 Martin Robinson <mrobinson at igalia.com>
+ Reviewed by Xan Lopez.
+
+ [Gtk] Open menulists should support typeahead find
+ https://bugs.webkit.org/show_bug.cgi?id=27443
+
+ Added a GTK+-specific layout test to track typeahead find state.
+
+ * platform/gtk/fast/forms/menulist-typeahead-find-expected.txt: Added.
+ * platform/gtk/fast/forms/menulist-typeahead-find.html: Added.
+
+2010-12-01 Martin Robinson <mrobinson at igalia.com>
+
Skip failing tests for text height on GTK
https://bugs.webkit.org/show_bug.cgi?id=50314
diff --git a/LayoutTests/platform/gtk/fast/forms/menulist-typeahead-find-expected.txt b/LayoutTests/platform/gtk/fast/forms/menulist-typeahead-find-expected.txt
new file mode 100644
index 0000000..d8996fa
--- /dev/null
+++ b/LayoutTests/platform/gtk/fast/forms/menulist-typeahead-find-expected.txt
@@ -0,0 +1,11 @@
+
+
+Cannot run interactively.
+Expected Apple: was Apple
+Expected Carrot: was Carrot
+Expected Cauliflower: was Cauliflower
+Expected Corn: was Corn
+Expected Carrot: was Carrot
+Expected Apple: was Apple
+Expected Cauliflower: was Cauliflower
+Expected Star fruit: was Star fruit
diff --git a/LayoutTests/platform/gtk/fast/forms/menulist-typeahead-find.html b/LayoutTests/platform/gtk/fast/forms/menulist-typeahead-find.html
new file mode 100644
index 0000000..0623723
--- /dev/null
+++ b/LayoutTests/platform/gtk/fast/forms/menulist-typeahead-find.html
@@ -0,0 +1,55 @@
+<p>
+<select id="menulist">
+ <option>Apple</option>
+ <option>Banana</option>
+ <option>Carrot</option>
+ <option>Cauliflower</option>
+ <option>Corn</option>
+ <option>Star fish</option>
+ <option>Star fruit</option>
+</select>
+</p>
+<div id="result">Cannot run interactively.</div>
+
+<script>
+var result = document.getElementById('result');
+var menulist = document.getElementById('menulist');
+
+function testTypeAheadFind(keys, expectedMenuListText)
+{
+ if (!window.eventSender)
+ return;
+
+ eventSender.mouseMoveTo(menulist.offsetLeft + (menulist.offsetWidth / 2), menulist.offsetTop + (menulist.offsetHeight / 2));
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+
+ for (var i = 0; i < keys.length; i++)
+ eventSender.keyDown(keys[i]);
+ eventSender.keyDown('\n');
+
+ result.innerHTML += "<br/>" + "Expected " + expectedMenuListText + ": ";
+ result.innerHTML += "was " + menulist.value;
+}
+
+if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+
+testTypeAheadFind(['a'], "Apple");
+testTypeAheadFind(['c'], "Carrot");
+
+// This tests that iterating via pressing the same key works.
+testTypeAheadFind(['c', 'c'], "Cauliflower");
+testTypeAheadFind(['c', 'c', 'c'], "Corn");
+
+// This tests that this also wraps around properly.
+testTypeAheadFind(['c', 'c', 'c', 'c'], "Carrot");
+
+// This tests that typing larger segments of words works.
+testTypeAheadFind(['a', 'p', 'p'], "Apple");
+testTypeAheadFind(['c', 'a', 'u'], "Cauliflower");
+
+// This tests that a sequence with a space works.
+testTypeAheadFind(['S', 't', 'a', 'r', ' ', 'f', 'r'], "Star fruit");
+
+</script>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 3715545..28b3c12 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,27 @@
+2010-12-01 Apelete Seketeli <apelete at seketeli.org> and Martin Robinson <mrobinson at igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ [Gtk] Open menulists should support typeahead find
+ https://bugs.webkit.org/show_bug.cgi?id=27443
+
+ Added typeahead find support for open GTK+ menulists.
+
+ Test: platform/gtk/fast/forms/menulist-typeahead-find.html
+
+ * platform/gtk/PopupMenuGtk.cpp:
+ (WebCore::PopupMenuGtk::PopupMenuGtk): Initialize new members.
+ (WebCore::PopupMenuGtk::show): Track currently selected menu item
+ via a signal handler.
+ (WebCore::PopupMenuGtk::typeAheadFind): Added.
+ (WebCore::PopupMenuGtk::menuUnmapped): Reset typeahead find state
+ when menu is unmapped.
+ (WebCore::PopupMenuGtk::resetTypeAheadFindState): Added.
+ (WebCore::PopupMenuGtk::selectItemCallback): Added.
+ (WebCore::PopupMenuGtk::keyPressEventCallback): Added.
+ * platform/gtk/PopupMenuGtk.h: Added new members to track typeahead
+ find state.
+
2010-12-01 Nikolas Zimmermann <nzimmermann at rim.com>
Reviewed by Xan Lopez.
diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp
index 07ca912..49dd24e 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.cpp
+++ b/WebCore/platform/gtk/PopupMenuGtk.cpp
@@ -5,6 +5,7 @@
* Copyright (C) 2006 Michael Emmel mike.emmel at gmail.com
* Copyright (C) 2008 Collabora Ltd.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2010 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,16 +28,22 @@
#include "PopupMenuGtk.h"
#include "FrameView.h"
+#include "GOwnPtr.h"
#include "GtkVersioning.h"
#include "HostWindow.h"
#include "PlatformString.h"
-#include <wtf/text/CString.h>
+#include <gdk/gdk.h>
#include <gtk/gtk.h>
+#include <wtf/text/CString.h>
namespace WebCore {
+static const uint32_t gSearchTimeoutMs = 1000;
+
PopupMenuGtk::PopupMenuGtk(PopupMenuClient* client)
: m_popupClient(client)
+ , m_previousKeyEventCharacter(0)
+ , m_currentlySelectedMenuItem(0)
{
}
@@ -54,7 +61,8 @@ void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index)
if (!m_popup) {
m_popup = GTK_MENU(gtk_menu_new());
- g_signal_connect(m_popup.get(), "unmap", G_CALLBACK(menuUnmapped), this);
+ g_signal_connect(m_popup.get(), "unmap", G_CALLBACK(PopupMenuGtk::menuUnmapped), this);
+ g_signal_connect(m_popup.get(), "key-press-event", G_CALLBACK(PopupMenuGtk::keyPressEventCallback), this);
} else
gtk_container_foreach(GTK_CONTAINER(m_popup.get()), reinterpret_cast<GtkCallback>(menuRemoveItem), this);
@@ -76,7 +84,8 @@ void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index)
item = gtk_menu_item_new_with_label(client()->itemText(i).utf8().data());
m_indexMap.add(item, i);
- g_signal_connect(item, "activate", G_CALLBACK(menuItemActivated), this);
+ g_signal_connect(item, "activate", G_CALLBACK(PopupMenuGtk::menuItemActivated), this);
+ g_signal_connect(item, "select", G_CALLBACK(PopupMenuGtk::selectItemCallback), this);
// FIXME: Apply the PopupMenuStyle from client()->itemStyle(i)
gtk_widget_set_sensitive(item, client()->itemIsEnabled(i));
@@ -141,6 +150,76 @@ void PopupMenuGtk::disconnectClient()
m_popupClient = 0;
}
+bool PopupMenuGtk::typeAheadFind(GdkEventKey* event)
+{
+ // If we were given a non-printable character just skip it.
+ gunichar unicodeCharacter = gdk_keyval_to_unicode(event->keyval);
+ if (!unicodeCharacter) {
+ resetTypeAheadFindState();
+ return false;
+ }
+
+ glong charactersWritten;
+ GOwnPtr<gunichar2> utf16String(g_ucs4_to_utf16(&unicodeCharacter, 1, 0, &charactersWritten, 0));
+ if (!utf16String) {
+ resetTypeAheadFindState();
+ return false;
+ }
+
+ // If the character is the same as the last character, the user is probably trying to
+ // cycle through the menulist entries. This matches the WebCore behavior for collapsed
+ // menulists.
+ bool repeatingCharacter = unicodeCharacter != m_previousKeyEventCharacter;
+ if (event->time - m_previousKeyEventTimestamp > gSearchTimeoutMs)
+ m_currentSearchString = String(static_cast<UChar*>(utf16String.get()), charactersWritten);
+ else if (repeatingCharacter)
+ m_currentSearchString.append(String(static_cast<UChar*>(utf16String.get()), charactersWritten));
+
+ m_previousKeyEventTimestamp = event->time;
+ m_previousKeyEventCharacter = unicodeCharacter;
+
+ // Like the Chromium port, we case fold before searching, because
+ // strncmp does not handle non-ASCII characters.
+ GOwnPtr<gchar> searchStringWithCaseFolded(g_utf8_casefold(m_currentSearchString.utf8().data(), -1));
+ size_t prefixLength = strlen(searchStringWithCaseFolded.get());
+
+ GList* children = gtk_container_get_children(GTK_CONTAINER(m_popup.get()));
+ if (!children)
+ return true;
+
+ // If a menu item has already been selected, start searching from the current
+ // item down the list. This will make multiple key presses of the same character
+ // advance the selection. GList* currentChild = children;
+ if (m_currentlySelectedMenuItem) {
+ currentChild = g_list_find(children, m_currentlySelectedMenuItem);
+ if (!currentChild) {
+ m_currentlySelectedMenuItem = 0;
+ currentChild = children;
+ }
+
+ // Repeating characters should iterate.
+ if (repeatingCharacter) {
+ if (GList* nextChild = g_list_next(currentChild))
+ currentChild = nextChild;
+ }
+ }
+
+ GList* firstChild = currentChild;
+ do {
+ currentChild = g_list_next(currentChild);
+ if (!currentChild)
+ currentChild = children;
+
+ GOwnPtr<gchar> itemText(g_utf8_casefold(gtk_menu_item_get_label(GTK_MENU_ITEM(currentChild->data)), -1));
+ if (!strncmp(searchStringWithCaseFolded.get(), itemText.get(), prefixLength)) {
+ gtk_menu_shell_select_item(GTK_MENU_SHELL(m_popup.get()), GTK_WIDGET(currentChild->data));
+ return true;
+ }
+ } while (currentChild != firstChild);
+
+ return true;
+}
+
void PopupMenuGtk::menuItemActivated(GtkMenuItem* item, PopupMenuGtk* that)
{
ASSERT(that->client());
@@ -151,6 +230,7 @@ void PopupMenuGtk::menuItemActivated(GtkMenuItem* item, PopupMenuGtk* that)
void PopupMenuGtk::menuUnmapped(GtkWidget*, PopupMenuGtk* that)
{
ASSERT(that->client());
+ that->resetTypeAheadFindState();
that->client()->popupDidHide();
}
@@ -161,11 +241,29 @@ void PopupMenuGtk::menuPositionFunction(GtkMenu*, gint* x, gint* y, gboolean* pu
*pushIn = true;
}
+void PopupMenuGtk::resetTypeAheadFindState()
+{
+ m_currentlySelectedMenuItem = 0;
+ m_previousKeyEventCharacter = 0;
+ m_currentSearchString = "";
+}
+
void PopupMenuGtk::menuRemoveItem(GtkWidget* widget, PopupMenuGtk* that)
{
ASSERT(that->m_popup);
gtk_container_remove(GTK_CONTAINER(that->m_popup.get()), widget);
}
+int PopupMenuGtk::selectItemCallback(GtkMenuItem* item, PopupMenuGtk* that)
+{
+ that->m_currentlySelectedMenuItem = GTK_WIDGET(item);
+ return FALSE;
+}
+
+int PopupMenuGtk::keyPressEventCallback(GtkWidget* widget, GdkEventKey* event, PopupMenuGtk* that)
+{
+ return that->typeAheadFind(event);
+}
+
}
diff --git a/WebCore/platform/gtk/PopupMenuGtk.h b/WebCore/platform/gtk/PopupMenuGtk.h
index 8848e06..e47fda6 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.h
+++ b/WebCore/platform/gtk/PopupMenuGtk.h
@@ -24,11 +24,12 @@
#include "IntRect.h"
#include "PopupMenu.h"
#include "PopupMenuClient.h"
-#include <glib.h>
#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+typedef struct _GdkEventKey GdkEventKey;
+
namespace WebCore {
class FrameView;
@@ -43,19 +44,27 @@ public:
virtual void hide();
virtual void updateFromElement();
virtual void disconnectClient();
+ bool typeAheadFind(GdkEventKey*);
private:
PopupMenuClient* client() const { return m_popupClient; }
+ void resetTypeAheadFindState();
static void menuItemActivated(GtkMenuItem* item, PopupMenuGtk*);
static void menuUnmapped(GtkWidget*, PopupMenuGtk*);
static void menuPositionFunction(GtkMenu*, gint*, gint*, gboolean*, PopupMenuGtk*);
static void menuRemoveItem(GtkWidget*, PopupMenuGtk*);
+ static int selectItemCallback(GtkMenuItem*, PopupMenuGtk*);
+ static int keyPressEventCallback(GtkWidget*, GdkEventKey*, PopupMenuGtk*);
PopupMenuClient* m_popupClient;
IntPoint m_menuPosition;
PlatformRefPtr<GtkMenu> m_popup;
HashMap<GtkWidget*, int> m_indexMap;
+ String m_currentSearchString;
+ uint32_t m_previousKeyEventTimestamp;
+ unsigned int m_previousKeyEventCharacter;
+ GtkWidget* m_currentlySelectedMenuItem;
};
}
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list