/* | |
* Copyright (C) 2004, 2006, 2007, 2010 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 COMPUTER, INC. ``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 COMPUTER, INC. OR | |
* 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. | |
*/ | |
#import "config.h" | |
#import "PlatformKeyboardEvent.h" | |
#if PLATFORM(MAC) | |
#import "KeyEventCocoa.h" | |
#import "Logging.h" | |
#import <Carbon/Carbon.h> | |
using namespace WTF; | |
namespace WebCore { | |
static bool isKeypadEvent(NSEvent* event) | |
{ | |
// Check that this is the type of event that has a keyCode. | |
switch ([event type]) { | |
case NSKeyDown: | |
case NSKeyUp: | |
case NSFlagsChanged: | |
break; | |
default: | |
return false; | |
} | |
if ([event modifierFlags] & NSNumericPadKeyMask) | |
return true; | |
switch ([event keyCode]) { | |
case 71: // Clear | |
case 81: // = | |
case 75: // / | |
case 67: // * | |
case 78: // - | |
case 69: // + | |
case 76: // Enter | |
case 65: // . | |
case 82: // 0 | |
case 83: // 1 | |
case 84: // 2 | |
case 85: // 3 | |
case 86: // 4 | |
case 87: // 5 | |
case 88: // 6 | |
case 89: // 7 | |
case 91: // 8 | |
case 92: // 9 | |
return true; | |
} | |
return false; | |
} | |
static inline bool isKeyUpEvent(NSEvent *event) | |
{ | |
if ([event type] != NSFlagsChanged) | |
return [event type] == NSKeyUp; | |
// FIXME: This logic fails if the user presses both Shift keys at once, for example: | |
// we treat releasing one of them as keyDown. | |
switch ([event keyCode]) { | |
case 54: // Right Command | |
case 55: // Left Command | |
return ([event modifierFlags] & NSCommandKeyMask) == 0; | |
case 57: // Capslock | |
return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0; | |
case 56: // Left Shift | |
case 60: // Right Shift | |
return ([event modifierFlags] & NSShiftKeyMask) == 0; | |
case 58: // Left Alt | |
case 61: // Right Alt | |
return ([event modifierFlags] & NSAlternateKeyMask) == 0; | |
case 59: // Left Ctrl | |
case 62: // Right Ctrl | |
return ([event modifierFlags] & NSControlKeyMask) == 0; | |
case 63: // Function | |
return ([event modifierFlags] & NSFunctionKeyMask) == 0; | |
} | |
return false; | |
} | |
static inline String textFromEvent(NSEvent* event) | |
{ | |
if ([event type] == NSFlagsChanged) | |
return ""; | |
return [event characters]; | |
} | |
static inline String unmodifiedTextFromEvent(NSEvent* event) | |
{ | |
if ([event type] == NSFlagsChanged) | |
return ""; | |
return [event charactersIgnoringModifiers]; | |
} | |
static String keyIdentifierForKeyEvent(NSEvent* event) | |
{ | |
if ([event type] == NSFlagsChanged) | |
switch ([event keyCode]) { | |
case 54: // Right Command | |
case 55: // Left Command | |
return "Meta"; | |
case 57: // Capslock | |
return "CapsLock"; | |
case 56: // Left Shift | |
case 60: // Right Shift | |
return "Shift"; | |
case 58: // Left Alt | |
case 61: // Right Alt | |
return "Alt"; | |
case 59: // Left Ctrl | |
case 62: // Right Ctrl | |
return "Control"; | |
default: | |
ASSERT_NOT_REACHED(); | |
return ""; | |
} | |
NSString *s = [event charactersIgnoringModifiers]; | |
if ([s length] != 1) { | |
LOG(Events, "received an unexpected number of characters in key event: %u", [s length]); | |
return "Unidentified"; | |
} | |
return keyIdentifierForCharCode([s characterAtIndex:0]); | |
} | |
static int windowsKeyCodeForKeyEvent(NSEvent *event) | |
{ | |
int code = windowsKeyCodeForKeyCode([event keyCode]); | |
if (code) | |
return code; | |
NSString* s = [event charactersIgnoringModifiers]; | |
if ([s length] != 1) | |
return 0; | |
return windowsKeyCodeForCharCode([s characterAtIndex:0]); | |
} | |
PlatformKeyboardEvent::PlatformKeyboardEvent(NSEvent *event) | |
: m_type(isKeyUpEvent(event) ? PlatformKeyboardEvent::KeyUp : PlatformKeyboardEvent::KeyDown) | |
, m_text(textFromEvent(event)) | |
, m_unmodifiedText(unmodifiedTextFromEvent(event)) | |
, m_keyIdentifier(keyIdentifierForKeyEvent(event)) | |
, m_autoRepeat(([event type] != NSFlagsChanged) && [event isARepeat]) | |
, m_windowsVirtualKeyCode(windowsKeyCodeForKeyEvent(event)) | |
, m_nativeVirtualKeyCode([event keyCode]) | |
, m_isKeypad(isKeypadEvent(event)) | |
, m_shiftKey([event modifierFlags] & NSShiftKeyMask) | |
, m_ctrlKey([event modifierFlags] & NSControlKeyMask) | |
, m_altKey([event modifierFlags] & NSAlternateKeyMask) | |
, m_metaKey([event modifierFlags] & NSCommandKeyMask) | |
, m_macEvent(event) | |
{ | |
// Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter. | |
if (m_windowsVirtualKeyCode == '\r') { | |
m_text = "\r"; | |
m_unmodifiedText = "\r"; | |
} | |
// The adjustments below are only needed in backward compatibility mode, but we cannot tell what mode we are in from here. | |
// Turn 0x7F into 8, because backspace needs to always be 8. | |
if (m_text == "\x7F") | |
m_text = "\x8"; | |
if (m_unmodifiedText == "\x7F") | |
m_unmodifiedText = "\x8"; | |
// Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab. | |
if (m_windowsVirtualKeyCode == 9) { | |
m_text = "\x9"; | |
m_unmodifiedText = "\x9"; | |
} | |
} | |
void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode) | |
{ | |
// Can only change type from KeyDown to RawKeyDown or Char, as we lack information for other conversions. | |
ASSERT(m_type == KeyDown); | |
ASSERT(type == RawKeyDown || type == Char); | |
m_type = type; | |
if (backwardCompatibilityMode) | |
return; | |
if (type == RawKeyDown) { | |
m_text = String(); | |
m_unmodifiedText = String(); | |
} else { | |
m_keyIdentifier = String(); | |
m_windowsVirtualKeyCode = 0; | |
if (m_text.length() == 1 && (m_text[0U] >= 0xF700 && m_text[0U] <= 0xF7FF)) { | |
// According to NSEvents.h, OpenStep reserves the range 0xF700-0xF8FF for function keys. However, some actual private use characters | |
// happen to be in this range, e.g. the Apple logo (Option+Shift+K). | |
// 0xF7FF is an arbitrary cut-off. | |
m_text = String(); | |
m_unmodifiedText = String(); | |
} | |
} | |
} | |
bool PlatformKeyboardEvent::currentCapsLockState() | |
{ | |
return GetCurrentKeyModifiers() & alphaLock; | |
} | |
void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) | |
{ | |
UInt32 currentModifiers = GetCurrentKeyModifiers(); | |
shiftKey = currentModifiers & ::shiftKey; | |
ctrlKey = currentModifiers & ::controlKey; | |
altKey = currentModifiers & ::optionKey; | |
metaKey = currentModifiers & ::cmdKey; | |
} | |
} | |
#endif // PLATFORM(MAC) |