зеркало из https://github.com/electron/electron.git
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:
Родитель
c27cbaaaf9
Коммит
3391370857
|
@ -1,3 +1,4 @@
|
|||
.DS_Store
|
||||
build/
|
||||
*.xcodeproj
|
||||
*.swp
|
||||
|
|
2
atom.gyp
2
atom.gyp
|
@ -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
|
Загрузка…
Ссылка в новой задаче