WebEvent.mm   [plain text]

/*
* Copyright (C) 2009, 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 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.
*/

// FIXME: Rename this file to WebEventIOS.mm after we upstream the iOS port and remove the PLATFORM(IOS)-guard.

#import "config.h"
#import "WebEvent.h"

#import "KeyEventCocoa.h"
#import <wtf/Assertions.h>

#if PLATFORM(IOS)

#import "WAKAppKitStubs.h"

using WebCore::windowsKeyCodeForKeyCode;
using WebCore::windowsKeyCodeForCharCode;
@implementation WebEvent

@synthesize type = _type;
@synthesize timestamp = _timestamp;
@synthesize wasHandled = _wasHandled;

- (WebEvent *)initWithMouseEventType:(WebEventType)type
timeStamp:(CFTimeInterval)timeStamp
location:(CGPoint)point
{
self = [super init];
if (!self)
return nil;

_type = type;
_timestamp = timeStamp;

_locationInWindow = point;

return self;
}

- (WebEvent *)initWithScrollWheelEventWithTimeStamp:(CFTimeInterval)timeStamp
location:(CGPoint)point
deltaX:(float)deltaX
deltaY:(float)deltaY
{
self = [super init];
if (!self)
return nil;

_type = WebEventScrollWheel;
_timestamp = timeStamp;

_locationInWindow = point;
_deltaX = deltaX;
_deltaY = deltaY;

return self;
}

- (WebEvent *)initWithTouchEventType:(WebEventType)type
timeStamp:(CFTimeInterval)timeStamp
location:(CGPoint)point
modifiers:(WebEventFlags)modifiers
touchCount:(unsigned)touchCount
touchLocations:(NSArray *)touchLocations
touchIdentifiers:(NSArray *)touchIdentifiers
touchPhases:(NSArray *)touchPhases isGesture:(BOOL)isGesture
gestureScale:(float)gestureScale
gestureRotation:(float)gestureRotation
{
self = [super init];
if (!self)
return nil;

_type = type;
_timestamp = timeStamp;
_modifierFlags = modifiers;

// FIXME: <rdar://problem/7185284> TouchEvents may be in more than one window some day.
_locationInWindow = point;
_touchCount = touchCount;
_touchLocations = [touchLocations copy];
_touchIdentifiers = [touchIdentifiers copy];
_touchPhases = [touchPhases copy];
_isGesture = isGesture;
_gestureScale = gestureScale;
_gestureRotation = gestureRotation;

return self;
}

static int windowsKeyCodeForCharCodeIOS(unichar charCode)
{
// iPhone Specific Cases
// <rdar://7709408>: We get 10 ('\n') from UIKit when using the software keyboard
if (charCode == 10)
return 0x0D;

// General Case
return windowsKeyCodeForCharCode(charCode);
}

// FIXME: to be removed when the adoption of the new initializer is complete.
- (WebEvent *)initWithKeyEventType:(WebEventType)type
timeStamp:(CFTimeInterval)timeStamp
characters:(NSString *)characters
charactersIgnoringModifiers:(NSString *)charactersIgnoringModifiers
modifiers:(WebEventFlags)modifiers
isRepeating:(BOOL)repeating
withFlags:(NSUInteger)flags
keyCode:(uint16_t)keyCode
isTabKey:(BOOL)tabKey
characterSet:(WebEventCharacterSet)characterSet
{
UNUSED_PARAM(characterSet);
self = [super init];
if (!self)
return nil;

_type = type;
_timestamp = timeStamp;

_characters = [characters retain];
_charactersIgnoringModifiers = [charactersIgnoringModifiers retain];
_modifierFlags = modifiers;
_keyRepeating = repeating;
_keyboardFlags = flags;
_tabKey = tabKey;

if (keyCode)
_keyCode = windowsKeyCodeForKeyCode(keyCode);

// NOTE: this preserves the original semantics which used the
// characters string for the keyCode. This should be changed in iOS 4.0 to
// allow the client to explicitly specify a keyCode, otherwise default to
// mapping the characters string to a keyCode.
// e.g. add an 'else' before this 'if'.
if ([charactersIgnoringModifiers length] == 1) {
unichar ch = [charactersIgnoringModifiers characterAtIndex:0];
_keyCode = windowsKeyCodeForCharCodeIOS(ch);
}

return self;
}

- (WebEvent *)initWithKeyEventType:(WebEventType)type
timeStamp:(CFTimeInterval)timeStamp
characters:(NSString *)characters
charactersIgnoringModifiers:(NSString *)charactersIgnoringModifiers
modifiers:(WebEventFlags)modifiers
isRepeating:(BOOL)repeating
withFlags:(NSUInteger)flags
withInputManagerHint:(NSString *)hint
keyCode:(uint16_t)keyCode
isTabKey:(BOOL)tabKey
{
self = [super init];
if (!self)
return nil;

_type = type;
_timestamp = timeStamp;

_characters = [characters retain];
_charactersIgnoringModifiers = [charactersIgnoringModifiers retain];
_modifierFlags = modifiers;
_keyRepeating = repeating;
_keyboardFlags = flags;
_inputManagerHint = [hint retain];
_tabKey = tabKey;

if (keyCode)
_keyCode = windowsKeyCodeForKeyCode(keyCode);

// NOTE: this preserves the original semantics which used the
// characters string for the keyCode. This should be changed in iOS 4.0 to
// allow the client to explicitly specify a keyCode, otherwise default to
// mapping the characters string to a keyCode.
// e.g. add an 'else' before this 'if'.
if ([charactersIgnoringModifiers length] == 1) {
unichar ch = [charactersIgnoringModifiers characterAtIndex:0];
_keyCode = windowsKeyCodeForCharCodeIOS(ch);
}

return self;
}

- (void)dealloc
{
[_characters release];
[_charactersIgnoringModifiers release];
[_inputManagerHint release];

[_touchLocations release];
[_touchIdentifiers release];
[_touchPhases release];

[super dealloc];
}

- (NSString *)_typeDescription
{
switch (_type) {
case WebEventMouseDown:
return @"WebEventMouseDown";
case WebEventMouseUp:
return @"WebEventMouseUp";
case WebEventMouseMoved:
return @"WebEventMouseMoved";
case WebEventScrollWheel:
return @"WebEventScrollWheel";
case WebEventKeyDown:
return @"WebEventKeyDown";
case WebEventKeyUp:
return @"WebEventKeyUp";
case WebEventTouchBegin:
return @"WebEventTouchBegin";
case WebEventTouchChange:
return @"WebEventTouchChange";
case WebEventTouchEnd:
return @"WebEventTouchEnd";
case WebEventTouchCancel:
return @"WebEventTouchCancel";
default:
ASSERT_NOT_REACHED();
}
return @"Unknown";
}

- (NSString *)_modiferFlagsDescription
{
switch (_modifierFlags) {
case WebEventMouseDown:
return @"WebEventMouseDown";
case WebEventMouseUp:
return @"WebEventMouseUp";
case WebEventMouseMoved:
return @"WebEventMouseMoved";
case WebEventScrollWheel:
return @"WebEventScrollWheel";
case WebEventKeyDown:
return @"WebEventKeyDown";
case WebEventKeyUp:
return @"WebEventKeyUp";
case WebEventTouchBegin:
return @"WebEventTouchBegin";
case WebEventTouchChange:
return @"WebEventTouchChange";
case WebEventTouchEnd:
return @"WebEventTouchEnd";
case WebEventTouchCancel:
return @"WebEventTouchCancel";
default:
ASSERT_NOT_REACHED();
}
return @"Unknown";
}

- (NSString *)_touchLocationsDescription:(NSArray *)locations
{
BOOL shouldAddComma = NO;
NSMutableString *description = [NSMutableString string];
for (NSValue *value in locations) {
CGPoint point = [value pointValue];
[description appendFormat:@"%@(%f, %f)", (shouldAddComma ? @", " : @""), point.x, point.y];
shouldAddComma = YES;
}
return description;
}

- (NSString *)_touchIdentifiersDescription
{
BOOL shouldAddComma = NO;
NSMutableString *description = [NSMutableString string];
for (NSNumber *identifier in _touchIdentifiers) {
[description appendFormat:@"%@%u", (shouldAddComma ? @", " : @""), [identifier unsignedIntValue]];
shouldAddComma = YES;
}
return description;
}

- (NSString *)_touchPhaseDescription:(WebEventTouchPhaseType)phase
{
switch (phase) {
case WebEventTouchPhaseBegan:
return @"WebEventTouchPhaseBegan";
case WebEventTouchPhaseMoved:
return @"WebEventTouchPhaseMoved";
case WebEventTouchPhaseStationary:
return @"WebEventTouchPhaseStationary";
case WebEventTouchPhaseEnded:
return @"WebEventTouchPhaseEnded";
case WebEventTouchPhaseCancelled:
return @"WebEventTouchPhaseCancelled";
default:
ASSERT_NOT_REACHED();
}
return @"Unknown";
}

- (NSString *)_touchPhasesDescription
{
BOOL shouldAddComma = NO;
NSMutableString *description = [NSMutableString string];
for (NSNumber *phase in _touchPhases) {
[description appendFormat:@"%@%@", (shouldAddComma ? @", " : @""), [self _touchPhaseDescription:static_cast<WebEventTouchPhaseType>([phase unsignedIntValue])]];
shouldAddComma = YES;
}
return description;
}

- (NSString *)_eventDescription
{
switch (_type) {
case WebEventMouseDown:
case WebEventMouseUp:
case WebEventMouseMoved:
return [NSString stringWithFormat:@"location: (%f, %f)", _locationInWindow.x, _locationInWindow.y];
case WebEventScrollWheel:
return [NSString stringWithFormat:@"location: (%f, %f) deltaX: %f deltaY: %f", _locationInWindow.x, _locationInWindow.y, _deltaX, _deltaY];
case WebEventKeyDown:
case WebEventKeyUp:
return [NSString stringWithFormat:@"chars: %@ charsNoModifiers: %@ flags: %d repeating: %d keyboardFlags: %lu keyCode %d, isTab: %d", _characters, _charactersIgnoringModifiers, _modifierFlags, _keyRepeating, static_cast<unsigned long>(_keyboardFlags), _keyCode, _tabKey];
case WebEventTouchBegin:
case WebEventTouchChange:
case WebEventTouchEnd:
case WebEventTouchCancel:
return [NSString stringWithFormat:@"location: (%f, %f) count: %d locations: %@ identifiers: %@ phases: %@ isGesture: %d scale: %f rotation: %f", _locationInWindow.x, _locationInWindow.y, _touchCount, [self _touchLocationsDescription:_touchLocations], [self _touchIdentifiersDescription], [self _touchPhasesDescription], (_isGesture ? 1 : 0), _gestureScale, _gestureRotation];
default:
ASSERT_NOT_REACHED();
}
return @"Unknown";
}

- (NSString *)description
{
return [NSString stringWithFormat:@"%@ type: %@ - %@", [super description], [self _typeDescription], [self _eventDescription]];
}

- (CGPoint)locationInWindow
{
ASSERT_WITH_MESSAGE(_type == WebEventMouseDown || _type == WebEventMouseUp || _type == WebEventMouseMoved || _type == WebEventScrollWheel
// FIXME: <rdar://problem/7185284> TouchEvents may be in more than one window some day.
|| _type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel
, "WebEventType: %d", _type);
return _locationInWindow;
}

- (NSString *)characters
{
ASSERT(_type == WebEventKeyDown || _type == WebEventKeyUp);
return [[_characters retain] autorelease];
}

- (NSString *)charactersIgnoringModifiers
{
ASSERT(_type == WebEventKeyDown || _type == WebEventKeyUp);
return [[_charactersIgnoringModifiers retain] autorelease];
}

- (NSString *)inputManagerHint
{
return [[_inputManagerHint retain] autorelease];
}

- (WebEventFlags)modifierFlags
{
return _modifierFlags;
}

- (BOOL)isKeyRepeating
{
ASSERT(_type == WebEventKeyDown || _type == WebEventKeyUp);
return _keyRepeating;
}

- (NSUInteger)keyboardFlags
{
ASSERT(_type == WebEventKeyDown || _type == WebEventKeyUp);
return _keyboardFlags;
}

- (uint16_t)keyCode
{
ASSERT(_type == WebEventKeyDown || _type == WebEventKeyUp);
return _keyCode;
}

- (BOOL)isTabKey
{
ASSERT(_type == WebEventKeyDown || _type == WebEventKeyUp);
return _tabKey;
}

- (float)deltaX
{
ASSERT(_type == WebEventScrollWheel);
return _deltaX;
}

- (float)deltaY
{
ASSERT(_type == WebEventScrollWheel);
return _deltaY;
}

// Touch
- (unsigned)touchCount
{
ASSERT(_type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel);
return _touchCount;
}

- (NSArray *)touchLocations
{
ASSERT(_type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel);
return _touchLocations;
}

- (NSArray *)touchIdentifiers
{
ASSERT(_type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel);
return _touchIdentifiers;
}

- (NSArray *)touchPhases
{
ASSERT(_type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel);
return _touchPhases;
}

// Gesture
- (BOOL)isGesture
{
ASSERT(_type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel);
return _isGesture;
}

- (float)gestureScale
{
ASSERT(_type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel);
return _gestureScale;
}

- (float)gestureRotation
{
ASSERT(_type == WebEventTouchBegin || _type == WebEventTouchChange || _type == WebEventTouchEnd || _type == WebEventTouchCancel);
return _gestureRotation;
}

@end

#endif // PLATFORM(IOS)