2015-11-17 19:20:13 +01:00
|
|
|
// Copyright 2015 The Chromium Embedded Framework 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 "libcef/browser/native/browser_platform_delegate_native_mac.h"
|
|
|
|
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
#import <CoreServices/CoreServices.h>
|
|
|
|
|
2020-09-22 21:54:02 +02:00
|
|
|
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
|
2015-11-17 19:20:13 +01:00
|
|
|
#include "libcef/browser/context.h"
|
|
|
|
#include "libcef/browser/native/file_dialog_runner_mac.h"
|
|
|
|
#include "libcef/browser/native/javascript_dialog_runner_mac.h"
|
|
|
|
#include "libcef/browser/native/menu_runner_mac.h"
|
|
|
|
#include "libcef/browser/thread_util.h"
|
|
|
|
|
|
|
|
#include "base/mac/scoped_nsautorelease_pool.h"
|
2016-05-25 01:35:43 +02:00
|
|
|
#include "base/memory/ptr_util.h"
|
2015-11-17 19:20:13 +01:00
|
|
|
#include "base/threading/thread_restrictions.h"
|
2020-01-23 22:58:01 +01:00
|
|
|
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
|
2015-11-17 19:20:13 +01:00
|
|
|
#include "content/public/browser/native_web_keyboard_event.h"
|
|
|
|
#include "content/public/browser/render_widget_host_view.h"
|
|
|
|
#include "content/public/browser/web_contents.h"
|
2020-03-04 01:29:39 +01:00
|
|
|
#include "third_party/blink/public/common/input/web_input_event.h"
|
|
|
|
#include "third_party/blink/public/common/input/web_mouse_event.h"
|
|
|
|
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
|
2017-05-17 11:29:28 +02:00
|
|
|
#import "ui/base/cocoa/cocoa_base_utils.h"
|
|
|
|
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
|
2020-01-23 22:58:01 +01:00
|
|
|
#include "ui/events/base_event_utils.h"
|
2015-11-17 19:20:13 +01:00
|
|
|
#include "ui/events/keycodes/keyboard_codes_posix.h"
|
|
|
|
#include "ui/gfx/geometry/rect.h"
|
|
|
|
|
|
|
|
// Wrapper NSView for the native view. Necessary to destroy the browser when
|
|
|
|
// the view is deleted.
|
|
|
|
@interface CefBrowserHostView : NSView {
|
|
|
|
@private
|
2020-09-25 03:40:47 +02:00
|
|
|
CefBrowserHostBase* browser_; // weak
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2020-09-25 03:40:47 +02:00
|
|
|
@property(nonatomic, assign) CefBrowserHostBase* browser;
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation CefBrowserHostView
|
|
|
|
|
|
|
|
@synthesize browser = browser_;
|
|
|
|
|
2017-05-17 11:29:28 +02:00
|
|
|
- (void)dealloc {
|
2015-11-17 19:20:13 +01:00
|
|
|
if (browser_) {
|
|
|
|
// Force the browser to be destroyed and release the reference added in
|
|
|
|
// PlatformCreateWindow().
|
2020-09-25 03:40:47 +02:00
|
|
|
static_cast<AlloyBrowserHostImpl*>(browser_)->WindowDestroyed();
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
// Receives notifications from the browser window. Will delete itself when done.
|
2019-04-23 19:17:56 +02:00
|
|
|
@interface CefWindowDelegate : NSObject <NSWindowDelegate> {
|
2015-11-17 19:20:13 +01:00
|
|
|
@private
|
2020-09-25 03:40:47 +02:00
|
|
|
CefBrowserHostBase* browser_; // weak
|
2015-11-17 19:20:13 +01:00
|
|
|
NSWindow* window_;
|
|
|
|
}
|
2020-09-25 03:40:47 +02:00
|
|
|
- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostBase*)browser;
|
2015-11-17 19:20:13 +01:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation CefWindowDelegate
|
|
|
|
|
2020-09-25 03:40:47 +02:00
|
|
|
- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostBase*)browser {
|
2015-11-17 19:20:13 +01:00
|
|
|
if (self = [super init]) {
|
|
|
|
window_ = window;
|
|
|
|
browser_ = browser;
|
|
|
|
|
|
|
|
[window_ setDelegate:self];
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)windowShouldClose:(id)window {
|
2016-01-19 21:09:01 +01:00
|
|
|
if (browser_ && !browser_->TryCloseBrowser()) {
|
2015-11-17 19:20:13 +01:00
|
|
|
// Cancel the close.
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean ourselves up after clearing the stack of anything that might have the
|
|
|
|
// window on it.
|
|
|
|
[self performSelectorOnMainThread:@selector(cleanup:)
|
|
|
|
withObject:window
|
|
|
|
waitUntilDone:NO];
|
|
|
|
|
|
|
|
// Allow the close.
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)cleanup:(id)window {
|
2018-09-06 13:46:32 +02:00
|
|
|
[window_ setDelegate:nil];
|
2015-11-17 19:20:13 +01:00
|
|
|
[self release];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
NSTimeInterval currentEventTimestamp() {
|
|
|
|
NSEvent* currentEvent = [NSApp currentEvent];
|
|
|
|
if (currentEvent)
|
|
|
|
return [currentEvent timestamp];
|
|
|
|
else {
|
|
|
|
// FIXME(API): In case there is no current event, the timestamp could be
|
|
|
|
// obtained by getting the time since the application started. This involves
|
|
|
|
// taking some more static functions from Chromium code.
|
|
|
|
// Another option is to have the timestamp as a field in CefEvent structures
|
|
|
|
// and let the client provide it.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSUInteger NativeModifiers(int cef_modifiers) {
|
|
|
|
NSUInteger native_modifiers = 0;
|
|
|
|
if (cef_modifiers & EVENTFLAG_SHIFT_DOWN)
|
|
|
|
native_modifiers |= NSShiftKeyMask;
|
|
|
|
if (cef_modifiers & EVENTFLAG_CONTROL_DOWN)
|
|
|
|
native_modifiers |= NSControlKeyMask;
|
|
|
|
if (cef_modifiers & EVENTFLAG_ALT_DOWN)
|
|
|
|
native_modifiers |= NSAlternateKeyMask;
|
|
|
|
if (cef_modifiers & EVENTFLAG_COMMAND_DOWN)
|
|
|
|
native_modifiers |= NSCommandKeyMask;
|
|
|
|
if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON)
|
|
|
|
native_modifiers |= NSAlphaShiftKeyMask;
|
|
|
|
if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON)
|
|
|
|
native_modifiers |= NSNumericPadKeyMask;
|
|
|
|
|
|
|
|
return native_modifiers;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
CefBrowserPlatformDelegateNativeMac::CefBrowserPlatformDelegateNativeMac(
|
2017-04-20 21:28:17 +02:00
|
|
|
const CefWindowInfo& window_info,
|
|
|
|
SkColor background_color)
|
2020-07-04 20:21:34 +02:00
|
|
|
: CefBrowserPlatformDelegateNative(window_info, background_color),
|
2017-05-17 11:29:28 +02:00
|
|
|
host_window_created_(false) {}
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
void CefBrowserPlatformDelegateNativeMac::BrowserDestroyed(
|
2020-09-25 03:40:47 +02:00
|
|
|
CefBrowserHostBase* browser) {
|
2020-07-04 20:21:34 +02:00
|
|
|
CefBrowserPlatformDelegateNative::BrowserDestroyed(browser);
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
if (host_window_created_) {
|
|
|
|
// Release the reference added in CreateHostWindow().
|
|
|
|
browser->Release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CefBrowserPlatformDelegateNativeMac::CreateHostWindow() {
|
|
|
|
base::mac::ScopedNSAutoreleasePool autorelease_pool;
|
|
|
|
|
|
|
|
NSWindow* newWnd = nil;
|
|
|
|
|
2019-04-23 19:17:56 +02:00
|
|
|
NSView* parentView =
|
|
|
|
CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.parent_view);
|
2015-11-17 19:20:13 +01:00
|
|
|
NSRect contentRect = {{window_info_.x, window_info_.y},
|
|
|
|
{window_info_.width, window_info_.height}};
|
|
|
|
if (parentView == nil) {
|
|
|
|
// Create a new window.
|
|
|
|
NSRect screen_rect = [[NSScreen mainScreen] visibleFrame];
|
2017-05-17 11:29:28 +02:00
|
|
|
NSRect window_rect = {
|
|
|
|
{window_info_.x, screen_rect.size.height - window_info_.y},
|
|
|
|
{window_info_.width, window_info_.height}};
|
2015-11-17 19:20:13 +01:00
|
|
|
if (window_rect.size.width == 0)
|
|
|
|
window_rect.size.width = 750;
|
|
|
|
if (window_rect.size.height == 0)
|
|
|
|
window_rect.size.height = 750;
|
|
|
|
|
|
|
|
contentRect.origin.x = 0;
|
|
|
|
contentRect.origin.y = 0;
|
|
|
|
contentRect.size.width = window_rect.size.width;
|
|
|
|
contentRect.size.height = window_rect.size.height;
|
|
|
|
|
|
|
|
newWnd = [[UnderlayOpenGLHostingWindow alloc]
|
2017-05-17 11:29:28 +02:00
|
|
|
initWithContentRect:window_rect
|
|
|
|
styleMask:(NSTitledWindowMask | NSClosableWindowMask |
|
|
|
|
NSMiniaturizableWindowMask |
|
|
|
|
NSResizableWindowMask |
|
|
|
|
NSUnifiedTitleAndToolbarWindowMask)
|
|
|
|
backing:NSBackingStoreBuffered
|
|
|
|
defer:NO];
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
// Create the delegate for control and browser window events.
|
|
|
|
[[CefWindowDelegate alloc] initWithWindow:newWnd andBrowser:browser_];
|
|
|
|
|
|
|
|
parentView = [newWnd contentView];
|
|
|
|
window_info_.parent_view = parentView;
|
|
|
|
|
2016-06-09 20:48:38 +02:00
|
|
|
// Make the content view for the window have a layer. This will make all
|
|
|
|
// sub-views have layers. This is necessary to ensure correct layer
|
|
|
|
// ordering of all child views and their layers.
|
|
|
|
[parentView setWantsLayer:YES];
|
|
|
|
}
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
host_window_created_ = true;
|
|
|
|
|
|
|
|
// Add a reference that will be released in BrowserDestroyed().
|
|
|
|
browser_->AddRef();
|
|
|
|
|
|
|
|
// Create the browser view.
|
|
|
|
CefBrowserHostView* browser_view =
|
|
|
|
[[CefBrowserHostView alloc] initWithFrame:contentRect];
|
|
|
|
browser_view.browser = browser_;
|
|
|
|
[parentView addSubview:browser_view];
|
|
|
|
[browser_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
|
|
|
[browser_view setNeedsDisplay:YES];
|
|
|
|
[browser_view release];
|
|
|
|
|
|
|
|
// Parent the TabContents to the browser view.
|
|
|
|
const NSRect bounds = [browser_view bounds];
|
2020-07-08 19:23:29 +02:00
|
|
|
NSView* native_view = web_contents_->GetNativeView().GetNativeNSView();
|
2015-11-17 19:20:13 +01:00
|
|
|
[browser_view addSubview:native_view];
|
|
|
|
[native_view setFrame:bounds];
|
|
|
|
[native_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
|
|
|
[native_view setNeedsDisplay:YES];
|
|
|
|
|
|
|
|
window_info_.view = browser_view;
|
|
|
|
|
|
|
|
if (newWnd != nil && !window_info_.hidden) {
|
|
|
|
// Show the window.
|
2017-05-17 11:29:28 +02:00
|
|
|
[newWnd makeKeyAndOrderFront:nil];
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefBrowserPlatformDelegateNativeMac::CloseHostWindow() {
|
2019-04-23 19:17:56 +02:00
|
|
|
NSView* nsview = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.view);
|
|
|
|
if (nsview != nil) {
|
|
|
|
[[nsview window] performSelectorOnMainThread:@selector(performClose:)
|
|
|
|
withObject:nil
|
|
|
|
waitUntilDone:NO];
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-17 11:29:28 +02:00
|
|
|
CefWindowHandle CefBrowserPlatformDelegateNativeMac::GetHostWindowHandle()
|
|
|
|
const {
|
2015-11-17 19:20:13 +01:00
|
|
|
if (windowless_handler_)
|
|
|
|
return windowless_handler_->GetParentWindowHandle();
|
|
|
|
return window_info_.view;
|
|
|
|
}
|
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
void CefBrowserPlatformDelegateNativeMac::SendKeyEvent(
|
|
|
|
const CefKeyEvent& event) {
|
|
|
|
auto view = GetHostView();
|
|
|
|
if (!view)
|
|
|
|
return;
|
|
|
|
|
|
|
|
content::NativeWebKeyboardEvent web_event = TranslateWebKeyEvent(event);
|
|
|
|
view->ForwardKeyboardEvent(web_event, ui::LatencyInfo());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefBrowserPlatformDelegateNativeMac::SendMouseClickEvent(
|
|
|
|
const CefMouseEvent& event,
|
|
|
|
CefBrowserHost::MouseButtonType type,
|
|
|
|
bool mouseUp,
|
|
|
|
int clickCount) {
|
|
|
|
auto view = GetHostView();
|
|
|
|
if (!view)
|
|
|
|
return;
|
|
|
|
|
|
|
|
blink::WebMouseEvent web_event =
|
|
|
|
TranslateWebClickEvent(event, type, mouseUp, clickCount);
|
|
|
|
view->RouteOrProcessMouseEvent(web_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefBrowserPlatformDelegateNativeMac::SendMouseMoveEvent(
|
|
|
|
const CefMouseEvent& event,
|
|
|
|
bool mouseLeave) {
|
|
|
|
auto view = GetHostView();
|
|
|
|
if (!view)
|
|
|
|
return;
|
|
|
|
|
|
|
|
blink::WebMouseEvent web_event = TranslateWebMoveEvent(event, mouseLeave);
|
|
|
|
view->RouteOrProcessMouseEvent(web_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefBrowserPlatformDelegateNativeMac::SendMouseWheelEvent(
|
|
|
|
const CefMouseEvent& event,
|
|
|
|
int deltaX,
|
|
|
|
int deltaY) {
|
|
|
|
auto view = GetHostView();
|
|
|
|
if (!view)
|
|
|
|
return;
|
|
|
|
|
|
|
|
blink::WebMouseWheelEvent web_event =
|
|
|
|
TranslateWebWheelEvent(event, deltaX, deltaY);
|
|
|
|
view->RouteOrProcessMouseEvent(web_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefBrowserPlatformDelegateNativeMac::SendTouchEvent(
|
|
|
|
const CefTouchEvent& event) {
|
|
|
|
NOTIMPLEMENTED();
|
|
|
|
}
|
|
|
|
|
2015-11-17 19:20:13 +01:00
|
|
|
void CefBrowserPlatformDelegateNativeMac::SendFocusEvent(bool setFocus) {
|
2020-01-23 22:58:01 +01:00
|
|
|
auto view = GetHostView();
|
2015-11-17 19:20:13 +01:00
|
|
|
if (view) {
|
|
|
|
view->SetActive(setFocus);
|
|
|
|
|
|
|
|
if (setFocus) {
|
|
|
|
// Give keyboard focus to the native view.
|
2020-07-08 19:23:29 +02:00
|
|
|
NSView* view = web_contents_->GetContentNativeView().GetNativeNSView();
|
2015-11-17 19:20:13 +01:00
|
|
|
DCHECK([view canBecomeKeyView]);
|
|
|
|
[[view window] makeFirstResponder:view];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Point CefBrowserPlatformDelegateNativeMac::GetScreenPoint(
|
|
|
|
const gfx::Point& view) const {
|
|
|
|
if (windowless_handler_)
|
|
|
|
return windowless_handler_->GetParentScreenPoint(view);
|
|
|
|
|
2019-04-23 19:17:56 +02:00
|
|
|
NSView* nsview = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.parent_view);
|
2015-11-17 19:20:13 +01:00
|
|
|
if (nsview) {
|
|
|
|
NSRect bounds = [nsview bounds];
|
|
|
|
NSPoint view_pt = {view.x(), bounds.size.height - view.y()};
|
|
|
|
NSPoint window_pt = [nsview convertPoint:view_pt toView:nil];
|
2016-04-27 22:38:52 +02:00
|
|
|
NSPoint screen_pt =
|
|
|
|
ui::ConvertPointFromWindowToScreen([nsview window], window_pt);
|
2015-11-17 19:20:13 +01:00
|
|
|
return gfx::Point(screen_pt.x, screen_pt.y);
|
|
|
|
}
|
|
|
|
return gfx::Point();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CefBrowserPlatformDelegateNativeMac::ViewText(const std::string& text) {
|
|
|
|
// TODO(cef): Implement this functionality.
|
|
|
|
NOTIMPLEMENTED();
|
|
|
|
}
|
|
|
|
|
2018-11-03 02:15:09 +01:00
|
|
|
bool CefBrowserPlatformDelegateNativeMac::HandleKeyboardEvent(
|
2015-11-17 19:20:13 +01:00
|
|
|
const content::NativeWebKeyboardEvent& event) {
|
|
|
|
// Give the top level menu equivalents a chance to handle the event.
|
|
|
|
if ([event.os_event type] == NSKeyDown)
|
2018-11-03 02:15:09 +01:00
|
|
|
return [[NSApp mainMenu] performKeyEquivalent:event.os_event];
|
|
|
|
return false;
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2019-04-24 04:50:25 +02:00
|
|
|
// static
|
|
|
|
void CefBrowserPlatformDelegate::HandleExternalProtocol(const GURL& url) {}
|
2015-11-17 19:20:13 +01:00
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
CefEventHandle CefBrowserPlatformDelegateNativeMac::GetEventHandle(
|
|
|
|
const content::NativeWebKeyboardEvent& event) const {
|
|
|
|
return event.os_event;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<CefFileDialogRunner>
|
|
|
|
CefBrowserPlatformDelegateNativeMac::CreateFileDialogRunner() {
|
|
|
|
return base::WrapUnique(new CefFileDialogRunnerMac);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<CefJavaScriptDialogRunner>
|
|
|
|
CefBrowserPlatformDelegateNativeMac::CreateJavaScriptDialogRunner() {
|
|
|
|
return base::WrapUnique(new CefJavaScriptDialogRunnerMac);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<CefMenuRunner>
|
|
|
|
CefBrowserPlatformDelegateNativeMac::CreateMenuRunner() {
|
|
|
|
return base::WrapUnique(new CefMenuRunnerMac);
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Point CefBrowserPlatformDelegateNativeMac::GetDialogPosition(
|
|
|
|
const gfx::Size& size) {
|
|
|
|
// Dialogs are always re-positioned by the constrained window sheet controller
|
|
|
|
// so nothing interesting to return yet.
|
|
|
|
return gfx::Point();
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::Size CefBrowserPlatformDelegateNativeMac::GetMaximumDialogSize() {
|
2020-07-08 19:23:29 +02:00
|
|
|
if (!web_contents_)
|
|
|
|
return gfx::Size();
|
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
// The dialog should try to fit within the overlay for the web contents.
|
|
|
|
// Note that, for things like print preview, this is just a suggested maximum.
|
2020-07-08 19:23:29 +02:00
|
|
|
return web_contents_->GetContainerBounds().size();
|
2020-01-23 22:58:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
content::NativeWebKeyboardEvent
|
|
|
|
CefBrowserPlatformDelegateNativeMac::TranslateWebKeyEvent(
|
2015-11-17 19:20:13 +01:00
|
|
|
const CefKeyEvent& key_event) const {
|
2020-06-09 19:48:00 +02:00
|
|
|
content::NativeWebKeyboardEvent result(
|
|
|
|
blink::WebInputEvent::Type::kUndefined,
|
|
|
|
blink::WebInputEvent::Modifiers::kNoModifiers, ui::EventTimeForNow());
|
2020-01-23 22:58:01 +01:00
|
|
|
|
2015-11-17 19:20:13 +01:00
|
|
|
// Use a synthetic NSEvent in order to obtain the windowsKeyCode member from
|
|
|
|
// the NativeWebKeyboardEvent constructor. This is the only member which can
|
|
|
|
// not be easily translated (without hardcoding keyCodes)
|
|
|
|
// Determining whether a modifier key is left or right seems to be done
|
|
|
|
// through the key code as well.
|
|
|
|
NSEventType event_type;
|
|
|
|
if (key_event.character == 0 && key_event.unmodified_character == 0) {
|
|
|
|
// Check if both character and unmodified_characther are empty to determine
|
|
|
|
// if this was a NSFlagsChanged event.
|
|
|
|
// A dead key will have an empty character, but a non-empty unmodified
|
|
|
|
// character
|
|
|
|
event_type = NSFlagsChanged;
|
|
|
|
} else {
|
|
|
|
switch (key_event.type) {
|
|
|
|
case KEYEVENT_RAWKEYDOWN:
|
|
|
|
case KEYEVENT_KEYDOWN:
|
|
|
|
case KEYEVENT_CHAR:
|
|
|
|
event_type = NSKeyDown;
|
|
|
|
break;
|
|
|
|
case KEYEVENT_KEYUP:
|
|
|
|
event_type = NSKeyUp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-17 11:29:28 +02:00
|
|
|
NSString* charactersIgnoringModifiers =
|
|
|
|
[[[NSString alloc] initWithCharacters:&key_event.unmodified_character
|
|
|
|
length:1] autorelease];
|
|
|
|
NSString* characters =
|
2019-04-23 19:17:56 +02:00
|
|
|
[[[NSString alloc] initWithCharacters:&key_event.character
|
|
|
|
length:1] autorelease];
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
NSEvent* synthetic_event =
|
2017-05-17 11:29:28 +02:00
|
|
|
[NSEvent keyEventWithType:event_type
|
|
|
|
location:NSMakePoint(0, 0)
|
|
|
|
modifierFlags:NativeModifiers(key_event.modifiers)
|
|
|
|
timestamp:currentEventTimestamp()
|
|
|
|
windowNumber:0
|
|
|
|
context:nil
|
|
|
|
characters:characters
|
|
|
|
charactersIgnoringModifiers:charactersIgnoringModifiers
|
|
|
|
isARepeat:NO
|
|
|
|
keyCode:key_event.native_key_code];
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
result = content::NativeWebKeyboardEvent(synthetic_event);
|
|
|
|
if (key_event.type == KEYEVENT_CHAR)
|
2020-06-09 19:48:00 +02:00
|
|
|
result.SetType(blink::WebInputEvent::Type::kChar);
|
2015-11-17 19:20:13 +01:00
|
|
|
|
2017-04-20 21:28:17 +02:00
|
|
|
result.is_system_key = key_event.is_system_key;
|
2020-01-23 22:58:01 +01:00
|
|
|
|
|
|
|
return result;
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
blink::WebMouseEvent
|
|
|
|
CefBrowserPlatformDelegateNativeMac::TranslateWebClickEvent(
|
2015-11-17 19:20:13 +01:00
|
|
|
const CefMouseEvent& mouse_event,
|
|
|
|
CefBrowserHost::MouseButtonType type,
|
2017-05-17 11:29:28 +02:00
|
|
|
bool mouseUp,
|
|
|
|
int clickCount) const {
|
2020-01-23 22:58:01 +01:00
|
|
|
blink::WebMouseEvent result;
|
|
|
|
TranslateWebMouseEvent(result, mouse_event);
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
switch (type) {
|
2017-05-17 11:29:28 +02:00
|
|
|
case MBT_LEFT:
|
2020-06-09 19:48:00 +02:00
|
|
|
result.SetType(mouseUp ? blink::WebInputEvent::Type::kMouseUp
|
|
|
|
: blink::WebInputEvent::Type::kMouseDown);
|
2017-05-17 11:29:28 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kLeft;
|
|
|
|
break;
|
|
|
|
case MBT_MIDDLE:
|
2020-06-09 19:48:00 +02:00
|
|
|
result.SetType(mouseUp ? blink::WebInputEvent::Type::kMouseUp
|
|
|
|
: blink::WebInputEvent::Type::kMouseDown);
|
2017-05-17 11:29:28 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kMiddle;
|
|
|
|
break;
|
|
|
|
case MBT_RIGHT:
|
2020-06-09 19:48:00 +02:00
|
|
|
result.SetType(mouseUp ? blink::WebInputEvent::Type::kMouseUp
|
|
|
|
: blink::WebInputEvent::Type::kMouseDown);
|
2017-05-17 11:29:28 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kRight;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NOTREACHED();
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 21:28:17 +02:00
|
|
|
result.click_count = clickCount;
|
2020-01-23 22:58:01 +01:00
|
|
|
|
|
|
|
return result;
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
blink::WebMouseEvent CefBrowserPlatformDelegateNativeMac::TranslateWebMoveEvent(
|
2015-11-17 19:20:13 +01:00
|
|
|
const CefMouseEvent& mouse_event,
|
|
|
|
bool mouseLeave) const {
|
2020-01-23 22:58:01 +01:00
|
|
|
blink::WebMouseEvent result;
|
|
|
|
TranslateWebMouseEvent(result, mouse_event);
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
if (!mouseLeave) {
|
2020-06-09 19:48:00 +02:00
|
|
|
result.SetType(blink::WebInputEvent::Type::kMouseMove);
|
2015-11-17 19:20:13 +01:00
|
|
|
if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kLeft;
|
2015-11-17 19:20:13 +01:00
|
|
|
else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kMiddle;
|
2015-11-17 19:20:13 +01:00
|
|
|
else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kRight;
|
2015-11-17 19:20:13 +01:00
|
|
|
else
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kNoButton;
|
2015-11-17 19:20:13 +01:00
|
|
|
} else {
|
2020-06-09 19:48:00 +02:00
|
|
|
result.SetType(blink::WebInputEvent::Type::kMouseLeave);
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kNoButton;
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2017-04-20 21:28:17 +02:00
|
|
|
result.click_count = 0;
|
2020-01-23 22:58:01 +01:00
|
|
|
|
|
|
|
return result;
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
blink::WebMouseWheelEvent
|
|
|
|
CefBrowserPlatformDelegateNativeMac::TranslateWebWheelEvent(
|
2015-11-17 19:20:13 +01:00
|
|
|
const CefMouseEvent& mouse_event,
|
2017-05-17 11:29:28 +02:00
|
|
|
int deltaX,
|
|
|
|
int deltaY) const {
|
2020-01-23 22:58:01 +01:00
|
|
|
blink::WebMouseWheelEvent result;
|
|
|
|
TranslateWebMouseEvent(result, mouse_event);
|
2015-11-17 19:20:13 +01:00
|
|
|
|
2020-06-09 19:48:00 +02:00
|
|
|
result.SetType(blink::WebInputEvent::Type::kMouseWheel);
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
static const double scrollbarPixelsPerCocoaTick = 40.0;
|
2017-09-13 18:47:43 +02:00
|
|
|
result.delta_x = deltaX;
|
2017-04-20 21:28:17 +02:00
|
|
|
result.delta_y = deltaY;
|
|
|
|
result.wheel_ticks_x = deltaX / scrollbarPixelsPerCocoaTick;
|
|
|
|
result.wheel_ticks_y = deltaY / scrollbarPixelsPerCocoaTick;
|
2020-03-30 22:13:42 +02:00
|
|
|
result.delta_units = ui::ScrollGranularity::kScrollByPrecisePixel;
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kLeft;
|
2015-11-17 19:20:13 +01:00
|
|
|
else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kMiddle;
|
2015-11-17 19:20:13 +01:00
|
|
|
else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kRight;
|
2015-11-17 19:20:13 +01:00
|
|
|
else
|
2017-04-20 21:28:17 +02:00
|
|
|
result.button = blink::WebMouseEvent::Button::kNoButton;
|
2015-11-17 19:20:13 +01:00
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
return result;
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
void CefBrowserPlatformDelegateNativeMac::TranslateWebMouseEvent(
|
2015-11-17 19:20:13 +01:00
|
|
|
blink::WebMouseEvent& result,
|
|
|
|
const CefMouseEvent& mouse_event) const {
|
|
|
|
// position
|
2017-04-20 21:28:17 +02:00
|
|
|
result.SetPositionInWidget(mouse_event.x, mouse_event.y);
|
2015-11-17 19:20:13 +01:00
|
|
|
|
2017-04-20 21:28:17 +02:00
|
|
|
const gfx::Point& screen_pt =
|
|
|
|
GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y));
|
|
|
|
result.SetPositionInScreen(screen_pt.x(), screen_pt.y());
|
2015-11-17 19:20:13 +01:00
|
|
|
|
|
|
|
// modifiers
|
2017-05-17 11:29:28 +02:00
|
|
|
result.SetModifiers(result.GetModifiers() |
|
2020-01-23 22:58:01 +01:00
|
|
|
TranslateWebEventModifiers(mouse_event.modifiers));
|
2015-11-17 19:20:13 +01:00
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
// timestamp
|
2018-05-17 10:58:21 +02:00
|
|
|
result.SetTimeStamp(base::TimeTicks() +
|
|
|
|
base::TimeDelta::FromSeconds(currentEventTimestamp()));
|
2018-02-22 18:09:28 +01:00
|
|
|
|
|
|
|
result.pointer_type = blink::WebPointerProperties::PointerType::kMouse;
|
2015-11-17 19:20:13 +01:00
|
|
|
}
|
2019-07-17 20:47:27 +02:00
|
|
|
|
2020-01-23 22:58:01 +01:00
|
|
|
content::RenderWidgetHostViewMac*
|
|
|
|
CefBrowserPlatformDelegateNativeMac::GetHostView() const {
|
2020-07-08 19:23:29 +02:00
|
|
|
if (!web_contents_)
|
|
|
|
return nullptr;
|
2020-01-23 22:58:01 +01:00
|
|
|
return static_cast<content::RenderWidgetHostViewMac*>(
|
2020-07-08 19:23:29 +02:00
|
|
|
web_contents_->GetRenderWidgetHostView());
|
2019-07-17 20:47:27 +02:00
|
|
|
}
|