753 lines
19 KiB
Plaintext
753 lines
19 KiB
Plaintext
|
// Copyright (c) 2012 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.
|
||
|
|
||
|
#import <Cocoa/Cocoa.h>
|
||
|
#include <OpenGL/gl.h>
|
||
|
|
||
|
#include "cefclient/osrtest_mac.h"
|
||
|
#include "include/cef_browser.h"
|
||
|
#include "cefclient/osrenderer.h"
|
||
|
#include "cefclient/client_popup_handler.h"
|
||
|
#include "cefclient/resource_util.h"
|
||
|
#include "cefclient/util.h"
|
||
|
|
||
|
// The client OpenGL view.
|
||
|
@interface ClientOpenGLView : NSOpenGLView {
|
||
|
@public
|
||
|
NSTrackingArea* tracking_area_;
|
||
|
CefRefPtr<CefBrowser> browser_;
|
||
|
ClientOSRenderer* renderer_;
|
||
|
NSPoint last_mouse_pos_;
|
||
|
NSPoint cur_mouse_pos_;
|
||
|
bool rotating_;
|
||
|
}
|
||
|
|
||
|
- (id)initWithFrame:(NSRect)frame andTransparency:(bool)transparency;
|
||
|
- (NSPoint)getClickPointForEvent:(NSEvent*)event;
|
||
|
- (void)getKeyInfo:(CefKeyInfo&)info forEvent:(NSEvent*)event;
|
||
|
- (int)getModifiersForEvent:(NSEvent*)event;
|
||
|
- (BOOL)isKeyUpEvent:(NSEvent*)event;
|
||
|
- (BOOL)isKeyPadEvent:(NSEvent*)event;
|
||
|
@end
|
||
|
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
// Handler for off-screen rendering windows.
|
||
|
class ClientOSRHandler : public CefClient,
|
||
|
public CefLifeSpanHandler,
|
||
|
public CefLoadHandler,
|
||
|
public CefRequestHandler,
|
||
|
public CefDisplayHandler,
|
||
|
public CefRenderHandler {
|
||
|
public:
|
||
|
explicit ClientOSRHandler(ClientOpenGLView* view)
|
||
|
: view_(view) {
|
||
|
}
|
||
|
~ClientOSRHandler() {
|
||
|
}
|
||
|
|
||
|
void Disconnect() {
|
||
|
view_ = nil;
|
||
|
}
|
||
|
|
||
|
// CefClient methods
|
||
|
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
|
||
|
return this;
|
||
|
}
|
||
|
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
|
||
|
return this;
|
||
|
}
|
||
|
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE {
|
||
|
return this;
|
||
|
}
|
||
|
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
|
||
|
return this;
|
||
|
}
|
||
|
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE {
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
// CefLifeSpanHandler methods
|
||
|
|
||
|
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
|
||
|
const CefPopupFeatures& popupFeatures,
|
||
|
CefWindowInfo& windowInfo,
|
||
|
const CefString& url,
|
||
|
CefRefPtr<CefClient>& client,
|
||
|
CefBrowserSettings& settings) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
windowInfo.m_bWindowRenderingDisabled = TRUE;
|
||
|
client = new ClientPopupHandler(view_->browser_);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
// Set the view size to match the window size.
|
||
|
const NSRect bounds = [view_ bounds];
|
||
|
browser->SetSize(PET_VIEW, bounds.size.width, bounds.size.height);
|
||
|
|
||
|
view_->browser_ = browser;
|
||
|
}
|
||
|
|
||
|
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE {
|
||
|
if (view_)
|
||
|
view_->browser_ = NULL;
|
||
|
}
|
||
|
|
||
|
// CefLoadHandler methods
|
||
|
|
||
|
virtual void OnLoadStart(CefRefPtr<CefBrowser> browser,
|
||
|
CefRefPtr<CefFrame> frame) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!browser->IsPopup() && frame->IsMain()) {
|
||
|
// We've just started loading a page
|
||
|
SetLoading(true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||
|
CefRefPtr<CefFrame> frame,
|
||
|
int httpStatusCode) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!browser->IsPopup() && frame->IsMain()) {
|
||
|
// We've just finished loading a page
|
||
|
SetLoading(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// CefRequestHandler methods
|
||
|
|
||
|
virtual bool OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
|
||
|
CefRefPtr<CefRequest> request,
|
||
|
CefString& redirectUrl,
|
||
|
CefRefPtr<CefStreamReader>& resourceStream,
|
||
|
CefRefPtr<CefResponse> response,
|
||
|
int loadFlags) OVERRIDE {
|
||
|
REQUIRE_IO_THREAD();
|
||
|
|
||
|
std::string url = request->GetURL();
|
||
|
if (url == "http://tests/osrtest") {
|
||
|
// Show the osrtest HTML contents
|
||
|
resourceStream = GetBinaryResourceReader("osrtest.html");
|
||
|
response->SetMimeType("text/html");
|
||
|
response->SetStatus(200);
|
||
|
} else if (url == "http://tests/transparency") {
|
||
|
// Show the osrtest HTML contents
|
||
|
resourceStream = GetBinaryResourceReader("transparency.html");
|
||
|
response->SetMimeType("text/html");
|
||
|
response->SetStatus(200);
|
||
|
} else if (strstr(url.c_str(), "/logoball.png") != NULL) {
|
||
|
// Load the "logoball.png" image resource.
|
||
|
resourceStream = GetBinaryResourceReader("logoball.png");
|
||
|
response->SetMimeType("image/png");
|
||
|
response->SetStatus(200);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// CefDisplayHandler methods
|
||
|
|
||
|
virtual void OnNavStateChange(CefRefPtr<CefBrowser> browser,
|
||
|
bool canGoBack,
|
||
|
bool canGoForward) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
}
|
||
|
|
||
|
virtual void OnAddressChange(CefRefPtr<CefBrowser> browser,
|
||
|
CefRefPtr<CefFrame> frame,
|
||
|
const CefString& url) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
}
|
||
|
|
||
|
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
|
||
|
const CefString& title) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!view_)
|
||
|
return;
|
||
|
|
||
|
// Set the frame window title bar
|
||
|
NSWindow* window = [view_ window];
|
||
|
std::string titleStr(title);
|
||
|
NSString* str = [NSString stringWithUTF8String:titleStr.c_str()];
|
||
|
[window setTitle:str];
|
||
|
}
|
||
|
|
||
|
// CefRenderHandler methods
|
||
|
|
||
|
virtual bool GetViewRect(CefRefPtr<CefBrowser> browser,
|
||
|
CefRect& rect) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!view_)
|
||
|
return false;
|
||
|
|
||
|
// The simulated screen and view rectangle are the same. This is necessary
|
||
|
// for popup menus to be located and sized inside the view.
|
||
|
const NSRect bounds = [view_ bounds];
|
||
|
rect.x = rect.y = 0;
|
||
|
rect.width = bounds.size.width;
|
||
|
rect.height = bounds.size.height;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual bool GetScreenRect(CefRefPtr<CefBrowser> browser,
|
||
|
CefRect& rect) OVERRIDE {
|
||
|
return GetViewRect(browser, rect);
|
||
|
}
|
||
|
|
||
|
virtual bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||
|
int viewX,
|
||
|
int viewY,
|
||
|
int& screenX,
|
||
|
int& screenY) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!view_)
|
||
|
return false;
|
||
|
|
||
|
// Convert the point from view coordinates to actual screen coordinates.
|
||
|
NSRect bounds = [view_ bounds];
|
||
|
NSPoint view_pt = {viewX, bounds.size.height - viewY};
|
||
|
NSPoint window_pt = [view_ convertPoint:view_pt toView:nil];
|
||
|
NSPoint screen_pt = [[view_ window] convertBaseToScreen:window_pt];
|
||
|
screenX = screen_pt.x;
|
||
|
screenY = screen_pt.y;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
virtual void OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||
|
bool show) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!view_)
|
||
|
return;
|
||
|
|
||
|
view_->renderer_->OnPopupShow(browser, show);
|
||
|
}
|
||
|
|
||
|
virtual void OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||
|
const CefRect& rect) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!view_)
|
||
|
return;
|
||
|
|
||
|
view_->renderer_->OnPopupSize(browser, rect);
|
||
|
}
|
||
|
|
||
|
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
|
||
|
PaintElementType type,
|
||
|
const RectList& dirtyRects,
|
||
|
const void* buffer) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
|
||
|
if (!view_)
|
||
|
return;
|
||
|
|
||
|
[[view_ openGLContext] makeCurrentContext];
|
||
|
|
||
|
view_->renderer_->OnPaint(browser, type, dirtyRects, buffer);
|
||
|
|
||
|
// Notify the view to redraw the invalidated regions.
|
||
|
{
|
||
|
RectList::const_iterator i = dirtyRects.begin();
|
||
|
for (; i != dirtyRects.end(); ++i) {
|
||
|
NSRect rect = {{i->x, i->y}, {i->width, i->height}};
|
||
|
[view_ setNeedsDisplayInRect:rect];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||
|
CefCursorHandle cursor) OVERRIDE {
|
||
|
REQUIRE_UI_THREAD();
|
||
|
[cursor set];
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void SetLoading(bool isLoading) {
|
||
|
}
|
||
|
|
||
|
ClientOpenGLView* view_;
|
||
|
|
||
|
// Include the default reference counting implementation.
|
||
|
IMPLEMENT_REFCOUNTING(ClientOSRPlugin);
|
||
|
};
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
|
||
|
@implementation ClientOpenGLView
|
||
|
|
||
|
- (id)initWithFrame:(NSRect)frame andTransparency:(bool)transparency {
|
||
|
NSOpenGLPixelFormat * pixelFormat =
|
||
|
[[NSOpenGLPixelFormat alloc]
|
||
|
initWithAttributes:(NSOpenGLPixelFormatAttribute[]) {
|
||
|
NSOpenGLPFAWindow,
|
||
|
NSOpenGLPFADoubleBuffer,
|
||
|
NSOpenGLPFADepthSize,
|
||
|
32,
|
||
|
0}];
|
||
|
[pixelFormat autorelease];
|
||
|
|
||
|
self = [super initWithFrame:frame pixelFormat:pixelFormat];
|
||
|
if (self) {
|
||
|
renderer_ = new ClientOSRenderer(transparency);
|
||
|
rotating_ = false;
|
||
|
|
||
|
tracking_area_ =
|
||
|
[[NSTrackingArea alloc] initWithRect:frame
|
||
|
options:NSTrackingMouseMoved |
|
||
|
NSTrackingActiveInActiveApp |
|
||
|
NSTrackingInVisibleRect
|
||
|
owner:self
|
||
|
userInfo:nil];
|
||
|
[self addTrackingArea:tracking_area_];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (void)dealloc {
|
||
|
if (browser_) {
|
||
|
static_cast<ClientOSRHandler*>(browser_->GetClient().get())->Disconnect();
|
||
|
browser_->CloseBrowser();
|
||
|
browser_ = NULL;
|
||
|
}
|
||
|
if (renderer_)
|
||
|
delete renderer_;
|
||
|
|
||
|
[super dealloc];
|
||
|
}
|
||
|
|
||
|
- (void)drawRect: (NSRect)bounds {
|
||
|
NSOpenGLContext* context = [self openGLContext];
|
||
|
[context makeCurrentContext];
|
||
|
|
||
|
renderer_->Render();
|
||
|
|
||
|
[context flushBuffer];
|
||
|
}
|
||
|
|
||
|
- (void)setFrame:(NSRect)frameRect {
|
||
|
[super setFrame:frameRect];
|
||
|
|
||
|
int width = frameRect.size.width;
|
||
|
int height = frameRect.size.height;
|
||
|
|
||
|
[[self openGLContext] makeCurrentContext];
|
||
|
|
||
|
renderer_->SetSize(width, height);
|
||
|
|
||
|
if (browser_)
|
||
|
browser_->SetSize(PET_VIEW, width, height);
|
||
|
}
|
||
|
|
||
|
- (void)mouseDown:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
int clickCount = [event clickCount];
|
||
|
|
||
|
browser_->SendMouseClickEvent(point.x, point.y, MBT_LEFT, false, clickCount);
|
||
|
}
|
||
|
|
||
|
- (void)rightMouseDown:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
|
||
|
if ([event modifierFlags] & NSShiftKeyMask) {
|
||
|
// Start rotation effect.
|
||
|
last_mouse_pos_ = cur_mouse_pos_ = point;
|
||
|
rotating_ = true;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int clickCount = [event clickCount];
|
||
|
|
||
|
browser_->SendMouseClickEvent(point.x, point.y, MBT_RIGHT, false, clickCount);
|
||
|
}
|
||
|
|
||
|
- (void)otherMouseDown:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
int clickCount = [event clickCount];
|
||
|
|
||
|
browser_->SendMouseClickEvent(point.x, point.y, MBT_MIDDLE, false,
|
||
|
clickCount);
|
||
|
}
|
||
|
|
||
|
- (void)mouseUp:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
int clickCount = [event clickCount];
|
||
|
|
||
|
browser_->SendMouseClickEvent(point.x, point.y, MBT_LEFT, true, clickCount);
|
||
|
}
|
||
|
|
||
|
- (void)rightMouseUp:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
if (rotating_) {
|
||
|
// End rotation effect.
|
||
|
renderer_->SetSpin(0, 0);
|
||
|
rotating_ = false;
|
||
|
[self setNeedsDisplay:YES];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
int clickCount = [event clickCount];
|
||
|
|
||
|
browser_->SendMouseClickEvent(point.x, point.y, MBT_RIGHT, true, clickCount);
|
||
|
}
|
||
|
|
||
|
- (void)otherMouseUp:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
int clickCount = [event clickCount];
|
||
|
|
||
|
browser_->SendMouseClickEvent(point.x, point.y, MBT_MIDDLE, true, clickCount);
|
||
|
}
|
||
|
|
||
|
- (void)mouseMoved:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
|
||
|
if (rotating_) {
|
||
|
// Apply rotation effect.
|
||
|
cur_mouse_pos_ = point;
|
||
|
renderer_->IncrementSpin((cur_mouse_pos_.x - last_mouse_pos_.x),
|
||
|
(cur_mouse_pos_.y - last_mouse_pos_.y));
|
||
|
last_mouse_pos_ = cur_mouse_pos_;
|
||
|
[self setNeedsDisplay:YES];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
browser_->SendMouseMoveEvent(point.x, point.y, false);
|
||
|
}
|
||
|
|
||
|
- (void)mouseDragged:(NSEvent *)event {
|
||
|
[self mouseMoved:event];
|
||
|
}
|
||
|
|
||
|
- (void)rightMouseDragged:(NSEvent *)event {
|
||
|
[self mouseMoved:event];
|
||
|
}
|
||
|
|
||
|
- (void)otherMouseDragged:(NSEvent *)event {
|
||
|
[self mouseMoved:event];
|
||
|
}
|
||
|
|
||
|
- (void)mouseEntered:(NSEvent *)event {
|
||
|
[self mouseMoved:event];
|
||
|
}
|
||
|
|
||
|
- (void)mouseExited:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
|
||
|
browser_->SendMouseMoveEvent(point.x, point.y, true);
|
||
|
}
|
||
|
|
||
|
- (void)keyDown:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
CefKeyInfo keyInfo;
|
||
|
[self getKeyInfo:keyInfo forEvent:event];
|
||
|
int modifiers = [self getModifiersForEvent:event];
|
||
|
|
||
|
browser_->SendKeyEvent(KT_KEYDOWN, keyInfo, modifiers);
|
||
|
|
||
|
if ([event modifierFlags] & (NSNumericPadKeyMask | NSFunctionKeyMask)) {
|
||
|
// Don't send a Char event for non-char keys like arrows, function keys and
|
||
|
// clear.
|
||
|
switch (keyInfo.keyCode) {
|
||
|
case 81: // =
|
||
|
case 75: // /
|
||
|
case 67: // *
|
||
|
case 78: // -
|
||
|
case 69: // +
|
||
|
case 76: // Enter
|
||
|
case 65: // .
|
||
|
case 82: // 0
|
||
|
case 83: // 1
|
||
|
case 84: // 2
|
||
|
case 85: // 3
|
||
|
case 86: // 4
|
||
|
case 87: // 5
|
||
|
case 88: // 6
|
||
|
case 89: // 7
|
||
|
case 91: // 8
|
||
|
case 92: // 9
|
||
|
break;
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
browser_->SendKeyEvent(KT_CHAR, keyInfo, modifiers);
|
||
|
}
|
||
|
|
||
|
- (void)keyUp:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
CefKeyInfo keyInfo;
|
||
|
[self getKeyInfo:keyInfo forEvent:event];
|
||
|
int modifiers = [self getModifiersForEvent:event];
|
||
|
|
||
|
browser_->SendKeyEvent(KT_KEYUP, keyInfo, modifiers);
|
||
|
}
|
||
|
|
||
|
- (void)flagsChanged:(NSEvent *)event {
|
||
|
if ([self isKeyUpEvent:event])
|
||
|
[self keyUp:event];
|
||
|
else
|
||
|
[self keyDown:event];
|
||
|
}
|
||
|
|
||
|
- (void)scrollWheel:(NSEvent *)event {
|
||
|
if (!browser_)
|
||
|
return;
|
||
|
|
||
|
CGEventRef cgEvent = [event CGEvent];
|
||
|
ASSERT(cgEvent);
|
||
|
|
||
|
NSPoint point = [self getClickPointForEvent:event];
|
||
|
int deltaX =
|
||
|
CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
|
||
|
int deltaY =
|
||
|
CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
|
||
|
|
||
|
browser_->SendMouseWheelEvent(point.x, point.y, deltaX, deltaY);
|
||
|
}
|
||
|
|
||
|
- (BOOL)canBecomeKeyView {
|
||
|
return (browser_ != NULL);
|
||
|
}
|
||
|
|
||
|
- (BOOL)acceptsFirstResponder {
|
||
|
return (browser_ != NULL);
|
||
|
}
|
||
|
|
||
|
- (BOOL)becomeFirstResponder {
|
||
|
if (browser_) {
|
||
|
browser_->SendFocusEvent(true);
|
||
|
return [super becomeFirstResponder];
|
||
|
}
|
||
|
|
||
|
return NO;
|
||
|
}
|
||
|
|
||
|
- (BOOL)resignFirstResponder {
|
||
|
if (browser_) {
|
||
|
browser_->SendFocusEvent(false);
|
||
|
return [super resignFirstResponder];
|
||
|
}
|
||
|
|
||
|
return NO;
|
||
|
}
|
||
|
|
||
|
- (void)undo:(id)sender {
|
||
|
if (browser_)
|
||
|
browser_->GetFocusedFrame()->Undo();
|
||
|
}
|
||
|
|
||
|
- (void)redo:(id)sender {
|
||
|
if (browser_)
|
||
|
browser_->GetFocusedFrame()->Redo();
|
||
|
}
|
||
|
|
||
|
- (void)cut:(id)sender {
|
||
|
if (browser_)
|
||
|
browser_->GetFocusedFrame()->Cut();
|
||
|
}
|
||
|
|
||
|
- (void)copy:(id)sender {
|
||
|
if (browser_)
|
||
|
browser_->GetFocusedFrame()->Copy();
|
||
|
}
|
||
|
|
||
|
- (void)paste:(id)sender {
|
||
|
if (browser_)
|
||
|
browser_->GetFocusedFrame()->Paste();
|
||
|
}
|
||
|
|
||
|
- (void)delete:(id)sender {
|
||
|
if (browser_)
|
||
|
browser_->GetFocusedFrame()->Delete();
|
||
|
}
|
||
|
|
||
|
- (void)selectAll:(id)sender {
|
||
|
if (browser_)
|
||
|
browser_->GetFocusedFrame()->SelectAll();
|
||
|
}
|
||
|
|
||
|
- (NSPoint)getClickPointForEvent:(NSEvent*)event {
|
||
|
NSPoint windowLocal = [event locationInWindow];
|
||
|
NSPoint contentLocal = [self convertPoint:windowLocal fromView:nil];
|
||
|
int x = contentLocal.x;
|
||
|
int y = [self frame].size.height - contentLocal.y; // Flip y.
|
||
|
|
||
|
return {x,y};
|
||
|
}
|
||
|
|
||
|
- (void)getKeyInfo:(CefKeyInfo&)info forEvent:(NSEvent*)event {
|
||
|
if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
|
||
|
NSString* s = [event characters];
|
||
|
if ([s length] > 0)
|
||
|
info.character = [s characterAtIndex:0];
|
||
|
|
||
|
s = [event charactersIgnoringModifiers];
|
||
|
if ([s length] > 0)
|
||
|
info.characterNoModifiers = [s characterAtIndex:0];
|
||
|
}
|
||
|
|
||
|
info.keyCode = [event keyCode];
|
||
|
}
|
||
|
|
||
|
- (int)getModifiersForEvent:(NSEvent*)event {
|
||
|
int modifiers = 0;
|
||
|
|
||
|
if ([event modifierFlags] & NSControlKeyMask)
|
||
|
modifiers |= KEY_CTRL;
|
||
|
if ([event modifierFlags] & NSShiftKeyMask)
|
||
|
modifiers |= KEY_SHIFT;
|
||
|
if ([event modifierFlags] & NSAlternateKeyMask)
|
||
|
modifiers |= KEY_ALT;
|
||
|
if ([event modifierFlags] & NSCommandKeyMask)
|
||
|
modifiers |= KEY_META;
|
||
|
if ([self isKeyPadEvent:event])
|
||
|
modifiers |= KEY_KEYPAD;
|
||
|
|
||
|
return modifiers;
|
||
|
}
|
||
|
|
||
|
- (BOOL)isKeyUpEvent:(NSEvent*)event {
|
||
|
if ([event type] != NSFlagsChanged)
|
||
|
return [event type] == NSKeyUp;
|
||
|
|
||
|
// FIXME: This logic fails if the user presses both Shift keys at once, for
|
||
|
// example: we treat releasing one of them as keyDown.
|
||
|
switch ([event keyCode]) {
|
||
|
case 54: // Right Command
|
||
|
case 55: // Left Command
|
||
|
return ([event modifierFlags] & NSCommandKeyMask) == 0;
|
||
|
|
||
|
case 57: // Capslock
|
||
|
return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
|
||
|
|
||
|
case 56: // Left Shift
|
||
|
case 60: // Right Shift
|
||
|
return ([event modifierFlags] & NSShiftKeyMask) == 0;
|
||
|
|
||
|
case 58: // Left Alt
|
||
|
case 61: // Right Alt
|
||
|
return ([event modifierFlags] & NSAlternateKeyMask) == 0;
|
||
|
|
||
|
case 59: // Left Ctrl
|
||
|
case 62: // Right Ctrl
|
||
|
return ([event modifierFlags] & NSControlKeyMask) == 0;
|
||
|
|
||
|
case 63: // Function
|
||
|
return ([event modifierFlags] & NSFunctionKeyMask) == 0;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
- (BOOL)isKeyPadEvent:(NSEvent*)event {
|
||
|
if ([event modifierFlags] & NSNumericPadKeyMask)
|
||
|
return true;
|
||
|
|
||
|
switch ([event keyCode]) {
|
||
|
case 71: // Clear
|
||
|
case 81: // =
|
||
|
case 75: // /
|
||
|
case 67: // *
|
||
|
case 78: // -
|
||
|
case 69: // +
|
||
|
case 76: // Enter
|
||
|
case 65: // .
|
||
|
case 82: // 0
|
||
|
case 83: // 1
|
||
|
case 84: // 2
|
||
|
case 85: // 3
|
||
|
case 86: // 4
|
||
|
case 87: // 5
|
||
|
case 88: // 6
|
||
|
case 89: // 7
|
||
|
case 91: // 8
|
||
|
case 92: // 9
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
|
||
|
namespace osrtest {
|
||
|
|
||
|
void RunTest(bool transparent) {
|
||
|
NSRect screen_rect = [[NSScreen mainScreen] visibleFrame];
|
||
|
NSRect window_rect = {{0, screen_rect.size.height}, {700, 700}};
|
||
|
NSWindow* newWnd = [[NSWindow alloc]
|
||
|
initWithContentRect:window_rect
|
||
|
styleMask:(NSTitledWindowMask |
|
||
|
NSClosableWindowMask |
|
||
|
NSMiniaturizableWindowMask |
|
||
|
NSResizableWindowMask |
|
||
|
NSUnifiedTitleAndToolbarWindowMask)
|
||
|
backing:NSBackingStoreBuffered
|
||
|
defer:NO];
|
||
|
ASSERT(newWnd);
|
||
|
|
||
|
ClientOpenGLView* view = [[ClientOpenGLView alloc] initWithFrame:window_rect
|
||
|
andTransparency:transparent];
|
||
|
[view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
||
|
|
||
|
[newWnd setContentView:view];
|
||
|
[view release];
|
||
|
|
||
|
CefWindowInfo info;
|
||
|
CefBrowserSettings settings;
|
||
|
|
||
|
// Initialize the window info as off-screen.
|
||
|
info.SetAsOffScreen(view);
|
||
|
info.SetTransparentPainting(transparent);
|
||
|
|
||
|
// Creat the browser window.
|
||
|
CefBrowser::CreateBrowser(info, new ClientOSRHandler(view),
|
||
|
"http://tests/osrtest", settings);
|
||
|
|
||
|
[newWnd makeKeyAndOrderFront: nil];
|
||
|
}
|
||
|
|
||
|
} // namespace osrtest
|
||
|
|