Index: ios/chrome/browser/ui/contextual_search/window_gesture_observer.mm |
diff --git a/ios/chrome/browser/ui/contextual_search/window_gesture_observer.mm b/ios/chrome/browser/ui/contextual_search/window_gesture_observer.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0ef504e8114087cc42992b25b0d97e3076c5df6c |
--- /dev/null |
+++ b/ios/chrome/browser/ui/contextual_search/window_gesture_observer.mm |
@@ -0,0 +1,61 @@ |
+// 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" |
+ |
+@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(), ^{ |
+ if (_actionPassesSelf) { |
+ [_target performSelector:_action withObject:self]; |
+ } else { |
+ [_target performSelector:_action]; |
+ } |
+ }); |
+ // Only invoke from the first qualifying touch. |
+ break; |
+ } |
+ } |
+ |
+ // Cancels to forward touch to other handlers. |
+ self.state = UIGestureRecognizerStateFailed; |
+ [super touchesBegan:touches withEvent:event]; |
+} |
+ |
+@end |