[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