Steal ChromeEventProcessingWindow from chrome.

Chromium has done quite a lot of low level works for us, steal them to
ease our lives.
This commit is contained in:
Cheng Zhao 2013-04-12 15:24:36 +08:00
Родитель c27cbaaaf9
Коммит 3391370857
4 изменённых файлов: 142 добавлений и 0 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
.DS_Store
build/
*.xcodeproj
*.swp

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

@ -13,6 +13,8 @@
'browser/atom_browser_main_parts.cc',
'browser/atom_browser_main_parts.h',
'browser/atom_browser_main_parts_mac.mm',
'browser/atom_event_processing_window.h',
'browser/atom_event_processing_window.mm',
'browser/native_window.cc',
'browser/native_window.h',
'browser/native_window_mac.h',

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

@ -0,0 +1,33 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_ATOM_EVENT_PROCESSING_WINDOW_H_
#define ATOM_BROWSER_ATOM_EVENT_PROCESSING_WINDOW_H_
#import <Cocoa/Cocoa.h>
#include "base/memory/scoped_nsobject.h"
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
// Override NSWindow to access unhandled keyboard events (for command
// processing); subclassing NSWindow is the only method to do
// this.
@interface AtomEventProcessingWindow : UnderlayOpenGLHostingWindow {
@private
BOOL redispatchingEvent_;
BOOL eventHandled_;
}
// Sends a key event to |NSApp sendEvent:|, but also makes sure that it's not
// short-circuited to the RWHV. This is used to send keyboard events to the menu
// and the cmd-` handler if a keyboard event comes back unhandled from the
// renderer. The event must be of type |NSKeyDown|, |NSKeyUp|, or
// |NSFlagsChanged|.
// Returns |YES| if |event| has been handled.
- (BOOL)redispatchKeyEvent:(NSEvent*)event;
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
@end
#endif // ATOM_BROWSER_ATOM_EVENT_PROCESSING_WINDOW_H_

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

@ -0,0 +1,106 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "browser/atom_event_processing_window.h"
#include "base/logging.h"
#import "content/public/browser/render_widget_host_view_mac_base.h"
@interface AtomEventProcessingWindow ()
// Duplicate the given key event, but changing the associated window.
- (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event;
@end
@implementation AtomEventProcessingWindow
- (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 = [[event window] convertBaseToScreen:eventLoc];
eventLoc = [self convertScreenToBase:eventLoc];
// 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 // AtomEventProcessingWindow