| 
									
										
										
										
											2014-10-31 11:17:05 -07:00
										 |  |  | // Copyright (c) 2013 GitHub, Inc. | 
					
						
							| 
									
										
										
										
											2014-04-25 17:49:37 +08:00
										 |  |  | // Use of this source code is governed by the MIT license that can be | 
					
						
							| 
									
										
										
										
											2013-04-12 15:24:36 +08:00
										 |  |  | // found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-16 08:30:26 +08:00
										 |  |  | #import "atom/browser/ui/cocoa/event_processing_window.h" | 
					
						
							| 
									
										
										
										
											2013-04-12 15:24:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "base/logging.h" | 
					
						
							|  |  |  | #import "content/public/browser/render_widget_host_view_mac_base.h" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 10:09:36 +08:00
										 |  |  | @interface EventProcessingWindow () | 
					
						
							| 
									
										
										
										
											2013-04-12 15:24:36 +08:00
										 |  |  | // Duplicate the given key event, but changing the associated window. | 
					
						
							|  |  |  | - (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event; | 
					
						
							|  |  |  | @end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 10:09:36 +08:00
										 |  |  | @implementation EventProcessingWindow | 
					
						
							| 
									
										
										
										
											2013-04-12 15:24:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | - (BOOL)redispatchKeyEvent:(NSEvent*)event { | 
					
						
							|  |  |  |   DCHECK(event); | 
					
						
							|  |  |  |   NSEventType eventType = [event type]; | 
					
						
							|  |  |  |   if (eventType != NSKeyDown && | 
					
						
							|  |  |  |       eventType != NSKeyUp && | 
					
						
							|  |  |  |       eventType != NSFlagsChanged) { | 
					
						
							|  |  |  |     NOTREACHED(); | 
					
						
							|  |  |  |     return YES;  // Pretend it's been handled in an effort to limit damage. | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Ordinarily, the event's window should be this window. However, when | 
					
						
							|  |  |  |   // switching between normal and fullscreen mode, we switch out the window, and | 
					
						
							|  |  |  |   // the event's window might be the previous window (or even an earlier one if | 
					
						
							|  |  |  |   // the renderer is running slowly and several mode switches occur). In this | 
					
						
							|  |  |  |   // rare case, we synthesize a new key event so that its associate window | 
					
						
							|  |  |  |   // (number) is our own. | 
					
						
							|  |  |  |   if ([event window] != self) | 
					
						
							|  |  |  |     event = [self keyEventForWindow:self fromKeyEvent:event]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Redispatch the event. | 
					
						
							|  |  |  |   eventHandled_ = YES; | 
					
						
							|  |  |  |   redispatchingEvent_ = YES; | 
					
						
							|  |  |  |   [NSApp sendEvent:event]; | 
					
						
							|  |  |  |   redispatchingEvent_ = NO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // If the event was not handled by [NSApp sendEvent:], the sendEvent: | 
					
						
							|  |  |  |   // method below will be called, and because |redispatchingEvent_| is YES, | 
					
						
							|  |  |  |   // |eventHandled_| will be set to NO. | 
					
						
							|  |  |  |   return eventHandled_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - (void)sendEvent:(NSEvent*)event { | 
					
						
							|  |  |  |   if (!redispatchingEvent_) | 
					
						
							|  |  |  |     [super sendEvent:event]; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     eventHandled_ = NO; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event { | 
					
						
							|  |  |  |   NSEventType eventType = [event type]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Convert the event's location from the original window's coordinates into | 
					
						
							|  |  |  |   // our own. | 
					
						
							|  |  |  |   NSPoint eventLoc = [event locationInWindow]; | 
					
						
							| 
									
										
										
										
											2014-10-25 11:06:39 +08:00
										 |  |  |   eventLoc = [self convertRectFromScreen: | 
					
						
							|  |  |  |     [[event window] convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)]].origin; | 
					
						
							| 
									
										
										
										
											2013-04-12 15:24:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Various things *only* apply to key down/up. | 
					
						
							|  |  |  |   BOOL eventIsARepeat = NO; | 
					
						
							|  |  |  |   NSString* eventCharacters = nil; | 
					
						
							|  |  |  |   NSString* eventUnmodCharacters = nil; | 
					
						
							|  |  |  |   if (eventType == NSKeyDown || eventType == NSKeyUp) { | 
					
						
							|  |  |  |     eventIsARepeat = [event isARepeat]; | 
					
						
							|  |  |  |     eventCharacters = [event characters]; | 
					
						
							|  |  |  |     eventUnmodCharacters = [event charactersIgnoringModifiers]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // This synthesis may be slightly imperfect: we provide nil for the context, | 
					
						
							|  |  |  |   // since I (viettrungluu) am sceptical that putting in the original context | 
					
						
							|  |  |  |   // (if one is given) is valid. | 
					
						
							|  |  |  |   return [NSEvent keyEventWithType:eventType | 
					
						
							|  |  |  |                           location:eventLoc | 
					
						
							|  |  |  |                      modifierFlags:[event modifierFlags] | 
					
						
							|  |  |  |                          timestamp:[event timestamp] | 
					
						
							|  |  |  |                       windowNumber:[window windowNumber] | 
					
						
							|  |  |  |                            context:nil | 
					
						
							|  |  |  |                         characters:eventCharacters | 
					
						
							|  |  |  |        charactersIgnoringModifiers:eventUnmodCharacters | 
					
						
							|  |  |  |                          isARepeat:eventIsARepeat | 
					
						
							|  |  |  |                            keyCode:[event keyCode]]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - (BOOL)performKeyEquivalent:(NSEvent*)event { | 
					
						
							|  |  |  |   if (redispatchingEvent_) | 
					
						
							|  |  |  |     return NO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Give the web site a chance to handle the event. If it doesn't want to | 
					
						
							|  |  |  |   // handle it, it will call us back with one of the |handle*| methods above. | 
					
						
							|  |  |  |   NSResponder* r = [self firstResponder]; | 
					
						
							|  |  |  |   if ([r conformsToProtocol:@protocol(RenderWidgetHostViewMacBase)]) | 
					
						
							|  |  |  |     return [r performKeyEquivalent:event]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ([super performKeyEquivalent:event]) | 
					
						
							|  |  |  |     return YES; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return NO; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 10:09:36 +08:00
										 |  |  | @end  // EventProcessingWindow |