Bug 863841 - Implement recognition of double-tap gestures with smartMagnifyWithEvent (Mountain Lion and up), and magnifyWithEvent (Lion). r=smichaud, r=masayuki

On 10.6 SDK, it was necessary to change nsCocoaWindow.mm/h in order to make it call magnifyWithEvent for double-tap gestures properly.
This commit is contained in:
Brandon Waterloo 2013-04-29 11:24:26 -04:00
Родитель cc9163b762
Коммит 2bd5581bfd
5 изменённых файлов: 95 добавлений и 17 удалений

Просмотреть файл

@ -79,7 +79,7 @@
* MozTapGesture - Generated when the user executes a two finger
* tap gesture on the input device. Client coordinates contain the
* center point of the tap.
* (XXX Not implemented on Mac)
* (XXX On OS X, only Lion (10.7) and up)
*
* MozPressTapGesture - Generated when the user executes a press
* and tap two finger gesture (first finger down, second finger down,

Просмотреть файл

@ -338,9 +338,13 @@ typedef NSInteger NSEventGestureAxis;
- (void)swipeWithEvent:(NSEvent *)anEvent;
- (void)beginGestureWithEvent:(NSEvent *)anEvent;
- (void)magnifyWithEvent:(NSEvent *)anEvent;
- (void)smartMagnifyWithEvent:(NSEvent *)anEvent;
- (void)rotateWithEvent:(NSEvent *)anEvent;
- (void)endGestureWithEvent:(NSEvent *)anEvent;
// Helper function for Lion smart magnify events
+ (BOOL)isLionSmartMagnifyEvent:(NSEvent*)anEvent;
// Support for fluid swipe tracking.
#ifdef __LP64__
- (void)maybeTrackScrollEventAsSwipe:(NSEvent *)anEvent

Просмотреть файл

@ -3148,14 +3148,15 @@ NSEvent* gLastDragMouseDownEvent = nil;
}
/*
* XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
* rotateWithEvent, and endGestureWithEvent methods are part of a
* PRIVATE interface exported by nsResponder and reverse-engineering
* was necessary to obtain the methods' prototypes. Thus, Apple may
* change the interface in the future without notice.
* In OS X Mountain Lion and above, smart zoom gestures are implemented in
* smartMagnifyWithEvent. In OS X Lion, they are implemented in
* magnifyWithEvent. See inline comments for more info.
*
* The prototypes were obtained from the following link:
* http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html
* The prototypes swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
* smartMagnifyWithEvent, rotateWithEvent, and endGestureWithEvent were
* obtained from the following links:
* https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html
* https://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKit.html
*/
- (void)swipeWithEvent:(NSEvent *)anEvent
@ -3209,6 +3210,15 @@ NSEvent* gLastDragMouseDownEvent = nil;
if (!anEvent || !mGeckoChild)
return;
/*
* In OS X 10.7.* (Lion), smart zoom events come through magnifyWithEvent,
* instead of smartMagnifyWithEvent. See bug 863841.
*/
if ([ChildView isLionSmartMagnifyEvent: anEvent]) {
[self smartMagnifyWithEvent: anEvent];
return;
}
nsAutoRetainCocoaObject kungFuDeathGrip(self);
float deltaZ = [anEvent deltaZ];
@ -3243,6 +3253,31 @@ NSEvent* gLastDragMouseDownEvent = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)smartMagnifyWithEvent:(NSEvent *)anEvent
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!anEvent || !mGeckoChild) {
return;
}
nsAutoRetainCocoaObject kungFuDeathGrip(self);
// Setup the "double tap" event.
nsSimpleGestureEvent geckoEvent(true, NS_SIMPLE_GESTURE_TAP,
mGeckoChild, 0, 0.0);
[self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent];
geckoEvent.clickCount = 1;
// Send the event.
mGeckoChild->DispatchWindowEvent(geckoEvent);
// Clear the gesture state
mGestureState = eGestureState_None;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)rotateWithEvent:(NSEvent *)anEvent
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
@ -3348,6 +3383,22 @@ NSEvent* gLastDragMouseDownEvent = nil;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
+ (BOOL)isLionSmartMagnifyEvent:(NSEvent*)anEvent
{
/*
* On Lion, smart zoom events have type NSEventTypeGesture, subtype 0x16,
* whereas pinch zoom events have type NSEventTypeMagnify. So, use that to
* discriminate between the two. Smart zoom gestures do not call
* beginGestureWithEvent or endGestureWithEvent, so mGestureState is not
* changed. Documentation couldn't be found for the meaning of the subtype
* 0x16, but it will probably never change. See bug 863841.
*/
return nsCocoaFeatures::OnLionOrLater() &&
!nsCocoaFeatures::OnMountainLionOrLater() &&
[anEvent type] == NSEventTypeGesture &&
[anEvent subtype] == 0x16;
}
#ifdef __LP64__
- (bool)sendSwipeEvent:(NSEvent*)aEvent
withKind:(PRUint32)aMsg

Просмотреть файл

@ -95,6 +95,8 @@ typedef struct _nsCocoaWindowList {
- (void)updateTrackingArea;
- (NSView*)trackingAreaView;
- (ChildView*)mainChildView;
@end
@interface NSWindow (Undocumented)
@ -190,7 +192,6 @@ typedef struct _nsCocoaWindowList {
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync;
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect;
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
- (ChildView*)mainChildView;
@end
class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa

Просмотреть файл

@ -2585,6 +2585,20 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
return [contentView superview] ? [contentView superview] : contentView;
}
- (ChildView*)mainChildView
{
NSView *contentView = [self contentView];
// A PopupWindow's contentView is a ChildView object.
if ([contentView isKindOfClass:[ChildView class]]) {
return (ChildView*)contentView;
}
NSView* lastView = [[contentView subviews] lastObject];
if ([lastView isKindOfClass:[ChildView class]]) {
return (ChildView*)lastView;
}
return nil;
}
- (void)removeTrackingArea
{
if (mTrackingArea) {
@ -2694,6 +2708,22 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
return retval;
}
// If we were built on OS X 10.6 or with the 10.6 SDK and are running on Lion,
// the OS (specifically -[NSWindow sendEvent:]) won't send NSEventTypeGesture
// events to -[ChildView magnifyWithEvent:] as it should. The following code
// gets around this. See bug 863841.
#if !defined( MAC_OS_X_VERSION_10_7 ) || \
( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 )
- (void)sendEvent:(NSEvent *)anEvent
{
if ([ChildView isLionSmartMagnifyEvent: anEvent]) {
[[self mainChildView] magnifyWithEvent:anEvent];
return;
}
[super sendEvent:anEvent];
}
#endif
@end
@interface TitlebarMouseHandlingView : NSView<EventRedirection>
@ -3015,14 +3045,6 @@ static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
mTitlebarView = nil;
}
- (ChildView*)mainChildView
{
NSView* view = [[[self contentView] subviews] lastObject];
if (view && [view isKindOfClass:[ChildView class]])
return (ChildView*)view;
return nil;
}
// Returning YES here makes the setShowsToolbarButton method work even though
// the window doesn't contain an NSToolbar.
- (BOOL)_hasToolbar