106 lines
		
	
	
	
		
			3.7 KiB
			
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
	
		
			3.7 KiB
			
		
	
	
	
		
			Text
		
	
	
	
	
	
// Copyright (c) 2013 GitHub, Inc.
 | 
						|
// Use of this source code is governed by the MIT license that can be
 | 
						|
// found in the LICENSE file.
 | 
						|
 | 
						|
#import "atom/browser/ui/cocoa/event_processing_window.h"
 | 
						|
 | 
						|
#include "base/logging.h"
 | 
						|
#import "content/public/browser/render_widget_host_view_mac_base.h"
 | 
						|
 | 
						|
@interface EventProcessingWindow ()
 | 
						|
// Duplicate the given key event, but changing the associated window.
 | 
						|
- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event;
 | 
						|
@end
 | 
						|
 | 
						|
@implementation EventProcessingWindow
 | 
						|
 | 
						|
- (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];
 | 
						|
  eventLoc = [self convertRectFromScreen:
 | 
						|
    [[event window] convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)]].origin;
 | 
						|
 | 
						|
  // 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;
 | 
						|
}
 | 
						|
 | 
						|
@end  // EventProcessingWindow
 |