REGRESSION (r237738): Command Down Arrow doesn't scroll to the end of a page anymore
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Nov 2018 22:57:44 +0000 (22:57 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Nov 2018 22:57:44 +0000 (22:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191967
<rdar://problem/45976390>

Reviewed by Tim Horton.

Source/WebKit:

Fixes an issue where pressing Command + Down Arrow does not scroll the view to the end of the page.

Following r237738 the value of the enumerations used to identify modifier keys (e.g. Shift) changed
to match the values of the corresponding enumerations in GraphicsServices, which are the
enumerations UIKit uses to computes the modifier flags bitmask when instantiating a WebEvent to
pass to WebKit. Before r237738 WebKit was using enumerations whose values matched the values
of the corresponding UIKit public API UIKeyModifier* enumerations. For non-content editable elements,
WebKit intercepts UIKit events in -_handleKeyUIEvent, synthesizes and dispatches its own WebEvent.
However it was creating WebEvents with a modifier flags bitmask built from the UIKeyModifier* enumerations,
-_modifierFlags, as opposed to a bitmask from the GraphicsServices enumerations, -_gsModifierFlags.
Instead WebKit should call -_gsModifierFlags to compute the GraphicsServices-compatible modifier
flags bitmask when instantiating a WebEvent.

* Platform/spi/ios/UIKitSPI.h: Expose -_gsModifierFlags and remove -_modifierFlags.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _handleKeyUIEvent:]): Remove unnecessary code to update the current modifier state.
This will be done by the WebProcess when it receives the keyboard event.
(-[WKContentView _didHandleKeyEvent:eventWasHandled:]): Do not pass modifier flags changed events
to the scrolling animator as it does not know how to handle these kinds of events and triggers an
assertion failure when it tries to read the input string from the event (calls -charactersIgnoringModifiers).
FlagsChanged WebEvents events do not have an input string just like a FlagsChanged NSEvent that
they model on Mac.
* UIProcess/ios/WKWebEvent.mm:
(-[WKWebEvent initWithEvent:]): Pass the value of -_gsModifierFlags for the modifier flags bitmask
instead of the value of -_modifierFlags.

Tools:

Add more test infrastructure to dispatch key up events.

* WebKitTestRunner/ios/HIDEventGenerator.h:
* WebKitTestRunner/ios/HIDEventGenerator.mm:
(createHIDKeyEvent): Renamed from createHIDKeyDownEvent() and modified to take a boolean as
to whether to create an event for a key down or key up.
(createHIDKeyDownEvent): Deleted; renamed to createHIDKeyEvent().
* WebKitTestRunner/ios/UIScriptControllerIOS.mm:
(WTR::createUIPhysicalKeyboardEvent): Added. Convenience function to create a UIPhysicalKeyboardEvent.
(WTR::UIScriptController::keyDown): Modified to dispatch a key up event in addition to dispatching
a key down event.

LayoutTests:

Add tests to ensure that Command + Down Arrow and Command + Up Arrow scroll to the end of
the page and the top of the page, respectively.

* fast/scrolling/ios/key-command-scroll-to-bottom-expected.html: Added.
* fast/scrolling/ios/key-command-scroll-to-bottom.html: Added.
* fast/scrolling/ios/key-command-scroll-to-top-expected.html: Added.
* fast/scrolling/ios/key-command-scroll-to-top.html: Added.
* resources/ui-helper.js:
(window.UIHelper.keyDown): Pass the modifiers array to EventSender.keyDown() to make
this function work on Mac.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238526 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom-expected.html [new file with mode: 0644]
LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom.html [new file with mode: 0644]
LayoutTests/fast/scrolling/ios/key-command-scroll-to-top-expected.html [new file with mode: 0644]
LayoutTests/fast/scrolling/ios/key-command-scroll-to-top.html [new file with mode: 0644]
LayoutTests/resources/ui-helper.js
Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/ios/UIKitSPI.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WKWebEvent.mm
Tools/ChangeLog
Tools/WebKitTestRunner/ios/HIDEventGenerator.h
Tools/WebKitTestRunner/ios/HIDEventGenerator.mm
Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm

index 2d809b1..8ea68ad 100644 (file)
@@ -1,3 +1,22 @@
+2018-11-26  Daniel Bates  <dabates@apple.com>
+
+        REGRESSION (r237738): Command Down Arrow doesn't scroll to the end of a page anymore
+        https://bugs.webkit.org/show_bug.cgi?id=191967
+        <rdar://problem/45976390>
+
+        Reviewed by Tim Horton.
+
+        Add tests to ensure that Command + Down Arrow and Command + Up Arrow scroll to the end of
+        the page and the top of the page, respectively.
+
+        * fast/scrolling/ios/key-command-scroll-to-bottom-expected.html: Added.
+        * fast/scrolling/ios/key-command-scroll-to-bottom.html: Added.
+        * fast/scrolling/ios/key-command-scroll-to-top-expected.html: Added.
+        * fast/scrolling/ios/key-command-scroll-to-top.html: Added.
+        * resources/ui-helper.js:
+        (window.UIHelper.keyDown): Pass the modifiers array to EventSender.keyDown() to make
+        this function work on Mac.
+
 2018-11-24  Ryosuke Niwa  <rniwa@webkit.org>
 
         SVG use element inside a shadow tree cannot reference an element in the same tree
diff --git a/LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom-expected.html b/LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom-expected.html
new file mode 100644 (file)
index 0000000..00dcc16
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width">
+<style>
+body {
+    margin: 0;
+    padding: 0;
+}
+
+#expected {
+    position: fixed;
+    bottom: 0px;
+    width: 256px;
+    height: 256px;
+    background-color: green;
+}
+</style>
+</head>
+<body>
+<div id="expected"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom.html b/LayoutTests/fast/scrolling/ios/key-command-scroll-to-bottom.html
new file mode 100644 (file)
index 0000000..da2d04a
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width">
+<script src="../../../resources/ui-helper.js"></script>
+<style>
+body {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+//  UIKit hides the scroll indicator after 1 second.
+const ScrollIndicatorFlashHideDelay = 1000; // milliseconds
+
+let secondSquareMaxY;
+
+function done()
+{
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function didEndScroll()
+{
+    window.onscroll = null;
+    // FIXME: Disable flashing of scroll indicator or find a way know when the flash has finished.
+    window.setTimeout(done, ScrollIndicatorFlashHideDelay);
+}
+
+window.onscroll = function (event) {
+
+    if (window.scrollY + window.innerHeight >= secondSquareMaxY)
+        didEndScroll();
+}
+
+function runTest()
+{
+    let secondSquare = document.getElementById("secondSquare");
+    secondSquareMaxY = secondSquare.offsetTop + secondSquare.offsetHeight;
+    if (window.testRunner)
+        UIHelper.keyDown("downArrow", ["metaKey"]);
+}
+</script>
+</head>
+<body onload="runTest()">
+<p id="description">Tests that pressing <key>Command</key> + <key>&#x2193;</key> scrolls to the bottom of the page. This test PASSED if you see a green square. Otherwise, it FAILED.</p>
+<div style="width: 256px; height: 256px; background-color: red"></div>
+<div style="height: 2000px"></div>
+<div id="secondSquare" style="width: 256px; height: 256px; background-color: green"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/scrolling/ios/key-command-scroll-to-top-expected.html b/LayoutTests/fast/scrolling/ios/key-command-scroll-to-top-expected.html
new file mode 100644 (file)
index 0000000..9b2687b
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width">
+<style>
+body {
+    margin: 0;
+    padding: 0;
+}
+
+#expected {
+    width: 256px;
+    height: 256px;
+    background-color: green;
+}
+</style>
+</head>
+<body>
+<p>Tests that pressing <key>Command</key> + <key>&#x2191;</key> scrolls to the bottom of the page. This test PASSED if you see a green square. Otherwise, it FAILED.</p>
+<div id="expected"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/scrolling/ios/key-command-scroll-to-top.html b/LayoutTests/fast/scrolling/ios/key-command-scroll-to-top.html
new file mode 100644 (file)
index 0000000..d36e870
--- /dev/null
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width">
+<script src="../../../resources/ui-helper.js"></script>
+<style>
+body {
+    margin: 0;
+    padding: 0;
+}
+
+.green {
+    background-color: green;
+}
+
+.red {
+    background-color: red;
+}
+
+.hidden {
+    display: none;
+}
+</style>
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+//  UIKit hides the scroll indicator after 1 second.
+const ScrollIndicatorFlashHideDelay = 1000; // milliseconds
+
+function done()
+{
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function swapRedGreenBackground(element)
+{
+    if (element.classList.contains("red")) {
+        element.classList.remove("red");
+        element.classList.add("green");
+    } else if (element.classList.contains("green")) {
+        element.classList.remove("green");
+        element.classList.add("red");
+    }
+}
+
+function didEndScroll()
+{
+    window.onscroll = null;
+    // FIXME: Disable flashing of scroll indicator or find a way know when the flash has finished.
+    window.setTimeout(done, ScrollIndicatorFlashHideDelay);
+}
+
+function handleScroll(event)
+{
+    if (!window.scrollY)
+        didEndScroll();
+}
+
+function runTest()
+{
+    let secondSquare = document.getElementById("secondSquare");
+    secondSquareMaxY = secondSquare.offsetTop + secondSquare.offsetHeight;
+
+    function scrollToTop() {
+        console.assert(window.scrollY + window.innerHeight >= secondSquareMaxY);
+        swapRedGreenBackground(document.getElementById("firstSquare"));
+        swapRedGreenBackground(document.getElementById("secondSquare"));
+        window.onscroll = handleScroll;
+        if (window.testRunner)
+            UIHelper.keyDown("upArrow", ["metaKey"]);
+
+    }
+    window.scrollTo(0, secondSquareMaxY);
+    window.setTimeout(scrollToTop, 0);
+}
+
+window.onload = function ()
+{
+    if (!window.testRunner) {
+        // Show manual instructions.
+        document.getElementById("manual-instructions").classList.remove("hidden");
+        return;
+    }
+    runTest();
+}
+</script>
+</head>
+<body>
+<p id="description">Tests that pressing <key>Command</key> + <key>&#x2191;</key> scrolls to the bottom of the page. This test PASSED if you see a green square. Otherwise, it FAILED.</p>
+<p id="manual-instructions" class="hidden">To run this test by hand, click <button onclick="runTest()">Run test</button> to first scroll to the bottom of the page. Then press <key>Command</key> + <key>&#x2191;</key>.</p>
+<div id="firstSquare" style="width: 256px; height: 256px" class="red"></div>
+<div style="height: 2000px"></div>
+<div id="secondSquare" style="width: 256px; height: 256px" class="green"></div>
+</body>
+</html>
index ed9497f..4a42b9f 100644 (file)
@@ -57,7 +57,7 @@ window.UIHelper = class UIHelper {
     static keyDown(key, modifiers=[])
     {
         if (!this.isWebKit2() || !this.isIOS()) {
-            eventSender.keyDown(key);
+            eventSender.keyDown(key, modifiers);
             return Promise.resolve();
         }
 
index 9ee62ec..4e8d2eb 100644 (file)
@@ -1,3 +1,37 @@
+2018-11-26  Daniel Bates  <dabates@apple.com>
+
+        REGRESSION (r237738): Command Down Arrow doesn't scroll to the end of a page anymore
+        https://bugs.webkit.org/show_bug.cgi?id=191967
+        <rdar://problem/45976390>
+
+        Reviewed by Tim Horton.
+
+        Fixes an issue where pressing Command + Down Arrow does not scroll the view to the end of the page.
+
+        Following r237738 the value of the enumerations used to identify modifier keys (e.g. Shift) changed
+        to match the values of the corresponding enumerations in GraphicsServices, which are the
+        enumerations UIKit uses to computes the modifier flags bitmask when instantiating a WebEvent to
+        pass to WebKit. Before r237738 WebKit was using enumerations whose values matched the values
+        of the corresponding UIKit public API UIKeyModifier* enumerations. For non-content editable elements,
+        WebKit intercepts UIKit events in -_handleKeyUIEvent, synthesizes and dispatches its own WebEvent.
+        However it was creating WebEvents with a modifier flags bitmask built from the UIKeyModifier* enumerations,
+        -_modifierFlags, as opposed to a bitmask from the GraphicsServices enumerations, -_gsModifierFlags.
+        Instead WebKit should call -_gsModifierFlags to compute the GraphicsServices-compatible modifier
+        flags bitmask when instantiating a WebEvent.
+
+        * Platform/spi/ios/UIKitSPI.h: Expose -_gsModifierFlags and remove -_modifierFlags.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _handleKeyUIEvent:]): Remove unnecessary code to update the current modifier state.
+        This will be done by the WebProcess when it receives the keyboard event.
+        (-[WKContentView _didHandleKeyEvent:eventWasHandled:]): Do not pass modifier flags changed events
+        to the scrolling animator as it does not know how to handle these kinds of events and triggers an
+        assertion failure when it tries to read the input string from the event (calls -charactersIgnoringModifiers).
+        FlagsChanged WebEvents events do not have an input string just like a FlagsChanged NSEvent that
+        they model on Mac.
+        * UIProcess/ios/WKWebEvent.mm:
+        (-[WKWebEvent initWithEvent:]): Pass the value of -_gsModifierFlags for the modifier flags bitmask
+        instead of the value of -_modifierFlags.
+
 2018-11-26  Chris Dumez  <cdumez@apple.com>
 
         [PSON] process pre-warming should not be on for everyone
index 27f25c1..143f16c 100644 (file)
@@ -199,7 +199,6 @@ typedef enum {
 - (void *)_hidEvent;
 - (NSString *)_unmodifiedInput;
 - (NSString *)_modifiedInput;
-- (NSInteger)_modifierFlags;
 - (BOOL)_isKeyDown;
 @end
 
@@ -1026,6 +1025,7 @@ typedef NSInteger UICompositingMode;
 - (UIPhysicalKeyboardEvent *)_cloneEvent NS_RETURNS_RETAINED;
 @property (nonatomic, readonly) UIKeyboardInputFlags _inputFlags;
 @property (nonatomic, readonly) CFIndex _keyCode;
+@property (nonatomic, readonly) NSInteger _gsModifierFlags;
 @end
 
 @interface UIColor (IPI)
index a8be12e..3b6a186 100644 (file)
@@ -3842,8 +3842,6 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
 - (void)_handleKeyUIEvent:(::UIEvent *)event
 {
     bool isHardwareKeyboardEvent = !!event._hidEvent;
-    if (isHardwareKeyboardEvent && ((UIPhysicalKeyboardEvent *)event)._inputFlags & kUIKeyboardInputModifierFlagsChanged)
-        _page->updateCurrentModifierState();
 
     // We only want to handle key event from the hardware keyboard when we are
     // first responder and we are not interacting with editable content.
@@ -3879,7 +3877,8 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
 
 - (void)_didHandleKeyEvent:(::WebEvent *)event eventWasHandled:(BOOL)eventWasHandled
 {
-    [_keyboardScrollingAnimator handleKeyEvent:event];
+    if (!(event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged))
+        [_keyboardScrollingAnimator handleKeyEvent:event];
     
     if (auto handler = WTFMove(_keyWebEventHandler)) {
         handler(event, eventWasHandled);
index 941c818..7d81e33 100644 (file)
 {
     uint16_t keyCode;
     UIKeyboardInputFlags inputFlags;
+    NSInteger modifierFlags;
     BOOL isHardwareKeyboardEvent = !!event._hidEvent;
     if (!isHardwareKeyboardEvent) {
         keyCode = 0;
         inputFlags = (UIKeyboardInputFlags)0;
+        modifierFlags = 0;
     } else {
         UIPhysicalKeyboardEvent *keyEvent = (UIPhysicalKeyboardEvent *)event;
         keyCode = keyEvent._keyCode;
         inputFlags = keyEvent._inputFlags;
+        modifierFlags = keyEvent._gsModifierFlags;
         event = [[keyEvent _cloneEvent] autorelease]; // UIKit uses a singleton for hardware keyboard events.
     }
 
-    self = [super initWithKeyEventType:(event._isKeyDown ? WebEventKeyDown : WebEventKeyUp) timeStamp:event.timestamp characters:event._modifiedInput charactersIgnoringModifiers:event._unmodifiedInput modifiers:event._modifierFlags isRepeating:(inputFlags & kUIKeyboardInputRepeat) withFlags:inputFlags keyCode:keyCode isTabKey:[event._modifiedInput isEqualToString:@"\t"] characterSet:WebEventCharacterSetUnicode];
+    self = [super initWithKeyEventType:(event._isKeyDown ? WebEventKeyDown : WebEventKeyUp) timeStamp:event.timestamp characters:event._modifiedInput charactersIgnoringModifiers:event._unmodifiedInput modifiers:modifierFlags isRepeating:(inputFlags & kUIKeyboardInputRepeat) withFlags:inputFlags keyCode:keyCode isTabKey:[event._modifiedInput isEqualToString:@"\t"] characterSet:WebEventCharacterSetUnicode];
     if (!self)
         return nil;
 
index 1af3754..b51e38f 100644 (file)
@@ -1,3 +1,23 @@
+2018-11-26  Daniel Bates  <dabates@apple.com>
+
+        REGRESSION (r237738): Command Down Arrow doesn't scroll to the end of a page anymore
+        https://bugs.webkit.org/show_bug.cgi?id=191967
+        <rdar://problem/45976390>
+
+        Reviewed by Tim Horton.
+
+        Add more test infrastructure to dispatch key up events.
+
+        * WebKitTestRunner/ios/HIDEventGenerator.h:
+        * WebKitTestRunner/ios/HIDEventGenerator.mm:
+        (createHIDKeyEvent): Renamed from createHIDKeyDownEvent() and modified to take a boolean as
+        to whether to create an event for a key down or key up.
+        (createHIDKeyDownEvent): Deleted; renamed to createHIDKeyEvent().
+        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+        (WTR::createUIPhysicalKeyboardEvent): Added. Convenience function to create a UIPhysicalKeyboardEvent.
+        (WTR::UIScriptController::keyDown): Modified to dispatch a key up event in addition to dispatching
+        a key down event.
+
 2018-11-26  Aakash Jain  <aakash_jain@apple.com>
 
         [ews-app] Set Foreign Keys in EWS Django app models
index 16f5daa..475de4b 100644 (file)
@@ -69,7 +69,7 @@ extern NSString* const HIDEventPhaseCanceled;
 
 extern NSUInteger const HIDMaxTouchCount;
 
-RetainPtr<IOHIDEventRef> createHIDKeyDownEvent(NSString *, uint64_t timestamp);
+RetainPtr<IOHIDEventRef> createHIDKeyEvent(NSString *, uint64_t timestamp, bool isKeyDown);
 
 @interface HIDEventGenerator : NSObject
 
index 71612fc..50e7aeb 100644 (file)
@@ -973,9 +973,9 @@ static inline uint32_t hidUsageCodeForCharacter(NSString *key)
     return 0;
 }
 
-RetainPtr<IOHIDEventRef> createHIDKeyDownEvent(NSString *character, uint64_t timestamp)
+RetainPtr<IOHIDEventRef> createHIDKeyEvent(NSString *character, uint64_t timestamp, bool isKeyDown)
 {
-    return adoptCF(IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault, timestamp, kHIDPage_KeyboardOrKeypad, hidUsageCodeForCharacter(character), true /* key down */, kIOHIDEventOptionNone));
+    return adoptCF(IOHIDEventCreateKeyboardEvent(kCFAllocatorDefault, timestamp, kHIDPage_KeyboardOrKeypad, hidUsageCodeForCharacter(character), isKeyDown, kIOHIDEventOptionNone));
 }
 
 - (void)keyPress:(NSString *)character completionBlock:(void (^)(void))completionBlock
index c4b9962..f235d2a 100644 (file)
@@ -400,6 +400,15 @@ static UIKeyModifierFlags parseModifierArray(JSContextRef context, JSValueRef ar
     return modifiers;
 }
 
+static UIPhysicalKeyboardEvent *createUIPhysicalKeyboardEvent(const String& hidInputString, const String& uiEventInputString, UIKeyModifierFlags modifierFlags, bool isKeyDown)
+{
+    auto* keyboardEvent = [getUIPhysicalKeyboardEventClass() _eventWithInput:uiEventInputString inputFlags:(UIKeyboardInputFlags)0];
+    keyboardEvent._modifierFlags = modifierFlags;
+    auto hidEvent = createHIDKeyEvent(hidInputString, keyboardEvent.timestamp, isKeyDown);
+    [keyboardEvent _setHIDEvent:hidEvent.get() keyboard:nullptr];
+    return keyboardEvent;
+}
+
 void UIScriptController::keyDown(JSStringRef character, JSValueRef modifierArray)
 {
     // Character can be either a single Unicode code point or the name of a special key (e.g. "downArrow").
@@ -412,10 +421,16 @@ void UIScriptController::keyDown(JSStringRef character, JSValueRef modifierArray
     // for a special key.
     String inputString = toWTFString(toWK(character));
     String uiEventInputString = inputString.length() > 1 ? emptyString() : inputString;
-    auto *keyboardEvent = [getUIPhysicalKeyboardEventClass() _eventWithInput:uiEventInputString inputFlags:(UIKeyboardInputFlags)0];
-    keyboardEvent._modifierFlags = parseModifierArray(m_context->jsContext(), modifierArray);
-    auto hidEvent = createHIDKeyDownEvent(inputString, keyboardEvent.timestamp);
-    [keyboardEvent _setHIDEvent:hidEvent.get() keyboard:nullptr];
+    auto modifierFlags = parseModifierArray(m_context->jsContext(), modifierArray);
+
+    // Note that UIKit will call -release on the passed UIPhysicalKeyboardEvent.
+
+    // Key down
+    auto* keyboardEvent = createUIPhysicalKeyboardEvent(inputString, uiEventInputString, modifierFlags, true /* isKeyDown */);
+    [[UIApplication sharedApplication] handleKeyUIEvent:keyboardEvent];
+
+    // Key up
+    keyboardEvent = createUIPhysicalKeyboardEvent(inputString, uiEventInputString, modifierFlags, false /* isKeyDown */);
     [[UIApplication sharedApplication] handleKeyUIEvent:keyboardEvent];
 }