blob: 9a89c05732f20c69af9ae1302bd77e6d21fb0a53 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ios/chrome/browser/ui/contextual_search/window_gesture_observer.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@implementation WindowGestureObserver {
NSObject* _target;
SEL _action;
BOOL _actionPassesSelf;
}
@synthesize viewToExclude = _viewToExclude;
@synthesize touchedView = _touchedView;
- (instancetype)initWithTarget:(id)target action:(SEL)action {
if ((self = [super initWithTarget:target action:action])) {
_target = static_cast<NSObject*>(target);
_action = action;
NSMethodSignature* signature = [_target methodSignatureForSelector:action];
_actionPassesSelf = [signature numberOfArguments] == 3;
[self removeTarget:target action:action];
self.cancelsTouchesInView = NO;
}
return self;
}
- (void)setViewToExclude:(UIView*)viewToExclude {
_viewToExclude = viewToExclude;
for (UIGestureRecognizer* recognizer in [viewToExclude gestureRecognizers]) {
[self requireGestureRecognizerToFail:recognizer];
}
}
- (void)addTarget:(id)target action:(SEL)action {
// No-op.
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
_touchedView = nil;
for (UITouch* touch in touches) {
if (![[touch view] isDescendantOfView:_viewToExclude]) {
_touchedView = [touch view];
dispatch_async(dispatch_get_main_queue(), ^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if (_actionPassesSelf) {
[_target performSelector:_action withObject:self];
} else {
[_target performSelector:_action];
}
#pragma clang diagnostic pop
});
// Only invoke from the first qualifying touch.
break;
}
}
// Cancels to forward touch to other handlers.
self.state = UIGestureRecognizerStateFailed;
[super touchesBegan:touches withEvent:event];
}
@end