- Revision
- 91129
- Author
- [email protected]
- Date
- 2011-07-15 16:49:53 -0700 (Fri, 15 Jul 2011)
Log Message
ALT + DOWN arrow key does not open select
https://bugs.webkit.org/show_bug.cgi?id=14407
<rdar://problem/5319507>
Reviewed by Alexey Proskuryakov.
No test, because eventSender sends events to the WebView, rather than
the popup menu, so the popup isn't closed.
* WebCore.vcproj/WebCore.vcproj:
Add SelectElementWin.cpp to project.
* dom/SelectElement.cpp:
(WebCore::SelectElement::platformHandleKeydownEvent):
Moved ARROW_KEYS_POP_MENU code here. Updated to return whether the
function has handled the key, or whether the caller needs to process it
further.
(WebCore::SelectElement::menuListDefaultEventHandler):
Allow the platform the first chance at handling the keyboard event.
* dom/SelectElement.h:
Declare platformHandleKeydownEvent().
* dom/SelectElementWin.cpp: Added.
(WebCore::SelectElement::platformHandleKeyboardEvent):
Allow (Shift) F4 and (Ctrl/Shift) Alt/AltGr + Up/Down
arrow to show the popup. After the popup is dismissed, call
setSelectedIndex(), and report that we handled the event.
* platform/win/PopupMenuWin.cpp:
Declare HIGH_BIT_MASK_SHORT.
(WebCore::PopupMenuWin::show):
Forward WM_SYSKEYDOWN to the popup's HWND.
(WebCore::PopupMenuWin::wndProc):
Allow the same shortcuts that show the menu to hide it, matching
Firefox.
Modified Paths
Added Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (91128 => 91129)
--- trunk/Source/WebCore/ChangeLog 2011-07-15 23:48:56 UTC (rev 91128)
+++ trunk/Source/WebCore/ChangeLog 2011-07-15 23:49:53 UTC (rev 91129)
@@ -1,3 +1,42 @@
+2011-07-13 Jon Honeycutt <[email protected]>
+
+ ALT + DOWN arrow key does not open select
+
+ https://bugs.webkit.org/show_bug.cgi?id=14407
+ <rdar://problem/5319507>
+
+ Reviewed by Alexey Proskuryakov.
+
+ No test, because eventSender sends events to the WebView, rather than
+ the popup menu, so the popup isn't closed.
+
+ * WebCore.vcproj/WebCore.vcproj:
+ Add SelectElementWin.cpp to project.
+
+ * dom/SelectElement.cpp:
+ (WebCore::SelectElement::platformHandleKeydownEvent):
+ Moved ARROW_KEYS_POP_MENU code here. Updated to return whether the
+ function has handled the key, or whether the caller needs to process it
+ further.
+ (WebCore::SelectElement::menuListDefaultEventHandler):
+ Allow the platform the first chance at handling the keyboard event.
+
+ * dom/SelectElement.h:
+ Declare platformHandleKeydownEvent().
+ * dom/SelectElementWin.cpp: Added.
+ (WebCore::SelectElement::platformHandleKeyboardEvent):
+ Allow (Shift) F4 and (Ctrl/Shift) Alt/AltGr + Up/Down
+ arrow to show the popup. After the popup is dismissed, call
+ setSelectedIndex(), and report that we handled the event.
+
+ * platform/win/PopupMenuWin.cpp:
+ Declare HIGH_BIT_MASK_SHORT.
+ (WebCore::PopupMenuWin::show):
+ Forward WM_SYSKEYDOWN to the popup's HWND.
+ (WebCore::PopupMenuWin::wndProc):
+ Allow the same shortcuts that show the menu to hide it, matching
+ Firefox.
+
2011-07-12 Jon Honeycutt <[email protected]>
Ensure that a single select element's child option elements are
Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (91128 => 91129)
--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2011-07-15 23:48:56 UTC (rev 91128)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2011-07-15 23:49:53 UTC (rev 91129)
@@ -47806,6 +47806,10 @@
>
</File>
<File
+ RelativePath="..\dom\SelectElementWin.cpp"
+ >
+ </File>
+ <File
RelativePath="..\dom\SelectorNodeList.cpp"
>
<FileConfiguration
Modified: trunk/Source/WebCore/dom/SelectElement.cpp (91128 => 91129)
--- trunk/Source/WebCore/dom/SelectElement.cpp 2011-07-15 23:48:56 UTC (rev 91128)
+++ trunk/Source/WebCore/dom/SelectElement.cpp 2011-07-15 23:49:53 UTC (rev 91129)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -557,44 +558,57 @@
element->setNeedsStyleRecalc();
}
+#if !PLATFORM(WIN)
+bool SelectElement::platformHandleKeydownEvent(SelectElementData& data, Element* element, KeyboardEvent* event)
+{
+#if ARROW_KEYS_POP_MENU
+ if (!isSpatialNavigationEnabled(element->document()->frame())) {
+ if (event->keyIdentifier() == "Down" || event->keyIdentifier() == "Up") {
+ element->focus();
+
+ // Calling focus() may cause us to lose our renderer. Return true so that our caller doesn't process the event
+ // further, but don't set the event as handled.
+ if (!element->renderer())
+ return true;
+
+ // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
+ // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
+ saveLastSelection(data, element);
+ if (RenderMenuList* menuList = toRenderMenuList(element->renderer()))
+ menuList->showPopup();
+ event->setDefaultHandled();
+ }
+ return true;
+ }
+#endif
+ return false;
+}
+#endif
+
void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm)
{
if (event->type() == eventNames().keydownEvent) {
if (!element->renderer() || !event->isKeyboardEvent())
return;
- const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier();
- bool handled = false;
+ if (platformHandleKeydownEvent(data, element, static_cast<KeyboardEvent*>(event)))
+ return;
-#if ARROW_KEYS_POP_MENU
- if (!isSpatialNavigationEnabled(element->document()->frame())) {
- if (keyIdentifier == "Down" || keyIdentifier == "Up") {
- element->focus();
-
- if (!element->renderer()) // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event.
- return;
-
- // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
- // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
- saveLastSelection(data, element);
- if (RenderMenuList* menuList = toRenderMenuList(element->renderer()))
- menuList->showPopup();
-
- event->setDefaultHandled();
- }
- return;
- }
-#endif
// When using spatial navigation, we want to be able to navigate away from the select element
// when the user hits any of the arrow keys, instead of changing the selection.
- if (isSpatialNavigationEnabled(element->document()->frame()))
+ if (isSpatialNavigationEnabled(element->document()->frame())) {
if (!data.activeSelectionState())
return;
+ }
+ const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier();
+ bool handled = false;
+
UNUSED_PARAM(htmlForm);
const Vector<Element*>& listItems = data.listItems(element);
int listIndex = optionToListIndex(data, element, selectedIndex(data, element));
+
if (keyIdentifier == "Down" || keyIdentifier == "Right") {
listIndex = nextValidIndex(listItems, listIndex, SkipForwards, 1);
handled = true;
Modified: trunk/Source/WebCore/dom/SelectElement.h (91128 => 91129)
--- trunk/Source/WebCore/dom/SelectElement.h 2011-07-15 23:48:56 UTC (rev 91128)
+++ trunk/Source/WebCore/dom/SelectElement.h 2011-07-15 23:49:53 UTC (rev 91129)
@@ -106,6 +106,7 @@
private:
static void menuListDefaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement*);
+ static bool platformHandleKeydownEvent(SelectElementData&, Element*, KeyboardEvent*);
static void listBoxDefaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement*);
static void setOptionsChangedOnRenderer(SelectElementData&, Element*);
};
Added: trunk/Source/WebCore/dom/SelectElementWin.cpp (0 => 91129)
--- trunk/Source/WebCore/dom/SelectElementWin.cpp (rev 0)
+++ trunk/Source/WebCore/dom/SelectElementWin.cpp 2011-07-15 23:49:53 UTC (rev 91129)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SelectElement.h"
+
+#include "Element.h"
+#include "KeyboardEvent.h"
+#include "RenderMenuList.h"
+
+namespace WebCore {
+
+bool SelectElement::platformHandleKeydownEvent(SelectElementData& data, Element* element, KeyboardEvent* event)
+{
+ // Allow (Shift) F4 and (Ctrl/Shift) Alt/AltGr + Up/Down arrow to pop the menu, matching Firefox.
+ bool eventShowsMenu = (!event->altKey() && !event->ctrlKey() && event->keyIdentifier() == "F4")
+ || ((event->altGraphKey() || event->altKey()) && (event->keyIdentifier() == "Down" || event->keyIdentifier() == "Up"));
+ if (!eventShowsMenu)
+ return false;
+
+ // Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
+ // which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
+ saveLastSelection(data, element);
+ if (RenderMenuList* menuList = toRenderMenuList(element->renderer()))
+ menuList->showPopup();
+
+ int index = selectedIndex(data, element);
+ ASSERT(index >= 0);
+ ASSERT(index < data.listItems(element).size());
+ setSelectedIndex(data, element, index);
+ event->setDefaultHandled();
+ return true;
+}
+
+}
Modified: trunk/Source/WebCore/platform/win/PopupMenuWin.cpp (91128 => 91129)
--- trunk/Source/WebCore/platform/win/PopupMenuWin.cpp 2011-07-15 23:48:56 UTC (rev 91128)
+++ trunk/Source/WebCore/platform/win/PopupMenuWin.cpp 2011-07-15 23:49:53 UTC (rev 91129)
@@ -49,6 +49,8 @@
#define MAKEPOINTS(l) (*((POINTS FAR *)&(l)))
#endif
+#define HIGH_BIT_MASK_SHORT 0x8000
+
using std::min;
namespace WebCore {
@@ -244,6 +246,7 @@
case WM_KEYUP:
case WM_CHAR:
case WM_DEADCHAR:
+ case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
@@ -809,17 +812,46 @@
break;
}
- case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN: {
if (!client())
break;
+ bool altKeyPressed = GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT;
+ bool ctrlKeyPressed = GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT;
+
lResult = 0;
switch (LOWORD(wParam)) {
+ case VK_F4: {
+ if (!altKeyPressed && !ctrlKeyPressed) {
+ int index = focusedIndex();
+ ASSERT(index >= 0);
+ client()->valueChanged(index);
+ hide();
+ }
+ break;
+ }
case VK_DOWN:
+ if (altKeyPressed) {
+ int index = focusedIndex();
+ ASSERT(index >= 0);
+ client()->valueChanged(index);
+ hide();
+ } else
+ down();
+ break;
case VK_RIGHT:
down();
break;
case VK_UP:
+ if (altKeyPressed) {
+ int index = focusedIndex();
+ ASSERT(index >= 0);
+ client()->valueChanged(index);
+ hide();
+ } else
+ up();
+ break;
case VK_LEFT:
up();
break;
@@ -869,6 +901,7 @@
break;
}
break;
+ }
case WM_CHAR: {
if (!client())
break;