提交 26a7bd70 编写于 作者: C Chinmay Garde

Complete OpenGL setup and input event handling on Mac

上级 d1aa1908
......@@ -255,6 +255,8 @@ if (is_android) {
"mac/platform_view_mac.mm",
"mac/sky_app_delegate.h",
"mac/sky_app_delegate.m",
"mac/sky_application.h",
"mac/sky_application.mm",
"mac/sky_window.h",
"mac/sky_window.mm",
"testing/test_runner.cc",
......
......@@ -29,6 +29,13 @@
<key>NSMainNibFile</key>
<string>sky_mac</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<string>SkyApplication</string>
<!--
Sky Load URL
-->
<key>org.domokit.sky.load_url</key>
<string>https://domokit.github.io/home.dart</string>
</dict>
</plist>
......@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "sky/shell/switches.h"
#include "sky/shell/testing/test_runner.h"
#include "sky/shell/mac/sky_application.h"
namespace sky {
namespace shell {
......@@ -30,8 +31,8 @@ bool FlagsValid() {
void Usage() {
std::cerr << "(For Test Shell) Usage: sky_shell"
<< " --" << switches::kNonInteractive
<< " --" << switches::kPackageRoot << "=PACKAGE_ROOT"
<< " --" << switches::kNonInteractive << " --"
<< switches::kPackageRoot << "=PACKAGE_ROOT"
<< " --" << switches::kSnapshot << "=SNAPSHOT"
<< " [ MAIN_DART ]" << std::endl;
}
......@@ -64,14 +65,26 @@ void Init() {
runner.Start(single_test.Pass());
}
void AttachMessageLoopToMainRunLoop(void) {
// We want to call Run() on the MessageLoopForUI but after NSApplicationMain.
// If called before this point, the call is blocking and will prevent the
// NSApplicationMain invocation.
dispatch_async(dispatch_get_main_queue(), ^() {
base::MessageLoopForUI::current()->Run();
});
}
} // namespace
} // namespace shell
} // namespace sky
int main(int argc, const char * argv[]) {
return PlatformMacMain(argc, argv, ^(){
int main(int argc, const char* argv[]) {
[SkyApplication sharedApplication];
return PlatformMacMain(argc, argv, ^() {
if (!sky::shell::FlagsValid()) {
sky::shell::Usage();
sky::shell::AttachMessageLoopToMainRunLoop();
return NSApplicationMain(argc, argv);
} else {
auto loop = base::MessageLoop::current();
......
......@@ -9,10 +9,11 @@
extern "C" {
#endif
typedef int(^PlatformMacMainCallback)(void);
typedef int (^PlatformMacMainCallback)(void);
int PlatformMacMain(int argc, const char *argv[],
PlatformMacMainCallback callback);
int PlatformMacMain(int argc,
const char* argv[],
PlatformMacMainCallback callback);
#ifdef __cplusplus
}
......
......@@ -35,10 +35,10 @@ static void RedirectIOConnectionsToSyslog() {
ASL_LOG_DESCRIPTOR_WRITE);
#endif
}
int PlatformMacMain(int argc, const char *argv[],
PlatformMacMainCallback callback) {
int PlatformMacMain(int argc,
const char* argv[],
PlatformMacMainCallback callback) {
base::mac::ScopedNSAutoreleasePool pool;
base::AtExitManager exit_manager;
......@@ -59,7 +59,7 @@ int PlatformMacMain(int argc, const char *argv[],
DLOG_ASSERT(result);
scoped_ptr<base::MessageLoopForUI> main_message_loop(
new base::MessageLoopForUI());
new base::MessageLoopForUI());
#if TARGET_OS_IPHONE
// One cannot start the message loop on the platform main thread. Instead,
......@@ -67,9 +67,8 @@ int PlatformMacMain(int argc, const char *argv[],
main_message_loop->Attach();
#endif
auto service_provider_context =
make_scoped_ptr(new sky::shell::ServiceProviderContext(
main_message_loop->task_runner()));
auto service_provider_context = make_scoped_ptr(
new sky::shell::ServiceProviderContext(main_message_loop->task_runner()));
sky::shell::Shell::Init(service_provider_context.Pass());
......
......@@ -11,12 +11,9 @@ PlatformView* PlatformView::Create(const Config& config) {
return new PlatformViewMac(config);
}
PlatformViewMac::PlatformViewMac(const Config& config)
: PlatformView(config) {
}
PlatformViewMac::PlatformViewMac(const Config& config) : PlatformView(config) {}
PlatformViewMac::~PlatformViewMac() {
}
PlatformViewMac::~PlatformViewMac() {}
void PlatformViewMac::SurfaceCreated(gfx::AcceleratedWidget widget) {
DCHECK(window_ == 0);
......
......@@ -4,7 +4,6 @@
#import <Cocoa/Cocoa.h>
@interface SkyAppDelegate : NSObject <NSApplicationDelegate>
@interface SkyAppDelegate : NSObject<NSApplicationDelegate>
@end
......@@ -6,7 +6,7 @@
@interface SkyAppDelegate ()
@property (assign) IBOutlet NSWindow *window;
@property(assign) IBOutlet NSWindow* window;
@end
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef __SKY_SHELL_MAC_SKY_APPLICATION__
#define __SKY_SHELL_MAC_SKY_APPLICATION__
#import <AppKit/AppKit.h>
#include "base/mac/scoped_sending_event.h"
#include "base/message_loop/message_pump_mac.h"
// A specific subclass of NSApplication is necessary on Mac in order to
// interact correctly with the main runloop.
@interface SkyApplication : NSApplication<CrAppProtocol, CrAppControlProtocol>
@end
#endif /* defined(__SKY_SHELL_MAC_SKY_APPLICATION__) */
// Copyright 2015 The Chromium 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 "sky/shell/mac/sky_application.h"
#include "base/auto_reset.h"
#include "base/logging.h"
@implementation SkyApplication {
BOOL handlingSendEvent_;
}
+ (void)initialize {
if (self == [SkyApplication class]) {
NSApplication* app = [SkyApplication sharedApplication];
DCHECK([app conformsToProtocol:@protocol(CrAppControlProtocol)])
<< "Existing NSApp (class " << [[app className] UTF8String]
<< ") does not conform to required protocol.";
DCHECK(base::MessagePumpMac::UsingCrApp())
<< "MessagePumpMac::Create() was called before "
<< "+[SkyApplication initialize]";
}
}
- (void)sendEvent:(NSEvent*)event {
base::AutoReset<BOOL> scoper(&handlingSendEvent_, YES);
[super sendEvent:event];
}
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
handlingSendEvent_ = handlingSendEvent;
}
- (BOOL)isHandlingSendEvent {
return handlingSendEvent_;
}
@end
......@@ -4,7 +4,7 @@
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7702"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<customObject id="-2" userLabel="File's Owner" customClass="SkyApplication">
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
</connections>
......@@ -675,7 +675,7 @@
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<openGLView autoresizesSubviews="NO" useAuxiliaryDepthBufferStencil="NO" allowOffline="YES" translatesAutoresizingMaskIntoConstraints="NO" id="AUD-Hu-um3">
<openGLView autoresizesSubviews="NO" useAuxiliaryDepthBufferStencil="NO" useDoubleBufferingEnabled="YES" allowOffline="YES" translatesAutoresizingMaskIntoConstraints="NO" id="AUD-Hu-um3">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
</openGLView>
</subviews>
......
......@@ -11,22 +11,43 @@
#include "sky/shell/shell.h"
#include "sky/shell/ui_delegate.h"
@interface SkyWindow () <NSWindowDelegate>
@interface SkyWindow ()<NSWindowDelegate>
@property (assign) IBOutlet NSOpenGLView *renderSurface;
@property (getter=isSurfaceSetup) BOOL surfaceSetup;
@property(assign) IBOutlet NSOpenGLView* renderSurface;
@property(getter=isSurfaceSetup) BOOL surfaceSetup;
@end
static inline sky::EventType EventTypeFromNSEventPhase(NSEventPhase phase) {
switch (phase) {
case NSEventPhaseNone:
return sky::EVENT_TYPE_UNKNOWN;
case NSEventPhaseBegan:
return sky::EVENT_TYPE_POINTER_DOWN;
case NSEventPhaseStationary:
// There is no EVENT_TYPE_POINTER_STATIONARY. So we just pass a move type
// with the same coordinates
case NSEventPhaseChanged:
return sky::EVENT_TYPE_POINTER_MOVE;
case NSEventPhaseEnded:
return sky::EVENT_TYPE_POINTER_UP;
case NSEventPhaseCancelled:
return sky::EVENT_TYPE_POINTER_CANCEL;
case NSEventPhaseMayBegin:
return sky::EVENT_TYPE_UNKNOWN;
}
return sky::EVENT_TYPE_UNKNOWN;
}
@implementation SkyWindow {
sky::SkyEnginePtr _sky_engine;
scoped_ptr<sky::shell::ShellView> _shell_view;
}
@synthesize renderSurface=_renderSurface;
@synthesize surfaceSetup=_surfaceSetup;
@synthesize renderSurface = _renderSurface;
@synthesize surfaceSetup = _surfaceSetup;
-(void) awakeFromNib {
- (void)awakeFromNib {
[super awakeFromNib];
self.delegate = self;
......@@ -34,7 +55,7 @@
[self windowDidResize:nil];
}
-(void) setupShell {
- (void)setupShell {
NSAssert(_shell_view == nullptr, @"The shell view must not already be set");
auto shell_view = new sky::shell::ShellView(sky::shell::Shell::Shared());
_shell_view.reset(shell_view);
......@@ -43,11 +64,13 @@
self.platformView->SurfaceCreated(widget);
}
-(NSString *) skyInitialLoadURL {
return @"http://localhost:8080/sky/sdk/example/rendering/simple_autolayout.dart";
- (NSString*)skyInitialLoadURL {
// TODO(csg): There should be a way to specify this in the UI
return [[NSBundle mainBundle]
.infoDictionary objectForKey:@"org.domokit.sky.load_url"];
}
-(void) setupAndLoadDart {
- (void)setupAndLoadDart {
auto interface_request = mojo::GetProxy(&_sky_engine);
self.platformView->ConnectToEngine(interface_request.Pass());
......@@ -55,19 +78,20 @@
_sky_engine->RunFromNetwork(string);
}
-(void) windowDidResize:(NSNotification *)notification {
- (void)windowDidResize:(NSNotification*)notification {
[self setupSurfaceIfNecessary];
// Resize
// sky::ViewportMetricsPtr metrics = sky::ViewportMetrics::New();
// metrics->physical_width = size.width * scale;
// metrics->physical_height = size.height * scale;
// metrics->device_pixel_ratio = scale;
// _sky_engine->OnViewportMetricsChanged(metrics.Pass());
auto metrics = sky::ViewportMetrics::New();
auto size = self.renderSurface.frame.size;
metrics->physical_width = size.width;
metrics->physical_height = size.height;
metrics->device_pixel_ratio = 1.0;
_sky_engine->OnViewportMetricsChanged(metrics.Pass());
}
-(void) setupSurfaceIfNecessary {
- (void)setupSurfaceIfNecessary {
if (self.isSurfaceSetup) {
return;
}
......@@ -86,26 +110,39 @@
#pragma mark - Responder overrides
- (void)dispatchEvent:(NSEvent *)event phase:(NSEventPhase) phase {
NSPoint location = [_renderSurface convertPoint:event.locationInWindow
fromView:nil];
- (void)dispatchEvent:(NSEvent*)event phase:(NSEventPhase)phase {
NSPoint location =
[_renderSurface convertPoint:event.locationInWindow fromView:nil];
location.y = _renderSurface.frame.size.height - location.y;
auto input = sky::InputEvent::New();
input->type = EventTypeFromNSEventPhase(phase);
input->time_stamp =
base::TimeDelta::FromSecondsD(event.timestamp).InMilliseconds();
input->pointer_data = sky::PointerData::New();
input->pointer_data->kind = sky::POINTER_KIND_TOUCH;
input->pointer_data->x = location.x;
input->pointer_data->y = location.y;
_sky_engine->OnInputEvent(input.Pass());
}
- (void)mouseDown:(NSEvent *)event {
- (void)mouseDown:(NSEvent*)event {
[self dispatchEvent:event phase:NSEventPhaseBegan];
}
- (void)mouseDragged:(NSEvent *)event {
- (void)mouseDragged:(NSEvent*)event {
[self dispatchEvent:event phase:NSEventPhaseChanged];
}
- (void)mouseUp:(NSEvent *)event {
- (void)mouseUp:(NSEvent*)event {
[self dispatchEvent:event phase:NSEventPhaseEnded];
}
- (void) dealloc {
- (void)dealloc {
self.platformView->SurfaceDestroyed();
[super dealloc];
}
......
......@@ -92,7 +92,7 @@ component("gl") {
"gl_surface_android.cc",
"gl_surface_egl.cc",
"gl_surface_egl.h",
"gl_surface_mac.cc",
"gl_surface_mac.mm",
"gl_surface_osmesa.cc",
"gl_surface_osmesa.h",
"gl_surface_stub.cc",
......@@ -218,6 +218,7 @@ component("gl") {
"gl_context.h",
"gl_context_ios.h",
"gl_context_ios.mm",
"gl_context_mac.h",
"gl_context_mac.mm",
"gl_context_stub.cc",
"gl_context_stub.h",
......@@ -238,7 +239,8 @@ component("gl") {
"gl_surface.h",
"gl_surface_ios.h",
"gl_surface_ios.mm",
"gl_surface_mac.cc",
"gl_surface_mac.h",
"gl_surface_mac.mm",
"gl_surface_stub.cc",
"gl_surface_stub.h",
"gl_switches.cc",
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef __UI_GL_GL_CONTEXT_MAC_H__
#define __UI_GL_GL_CONTEXT_MAC_H__
#include "base/compiler_specific.h"
#include "ui/gl/gl_context.h"
namespace gfx {
class GLSurface;
class GLContextMac : public GLContextReal {
public:
explicit GLContextMac(GLShareGroup* share_group);
bool Initialize(GLSurface* compatible_surface,
GpuPreference gpu_preference) override;
void Destroy() override;
bool MakeCurrent(GLSurface* surface) override;
void ReleaseCurrent(GLSurface* surface) override;
bool IsCurrent(GLSurface* surface) override;
void* GetHandle() override;
void OnSetSwapInterval(int interval) override;
std::string GetExtensions() override;
bool WasAllocatedUsingRobustnessExtension() override;
bool GetTotalGpuMemory(size_t* bytes) override;
void SetUnbindFboOnMakeCurrent() override;
protected:
~GLContextMac() override;
private:
uintptr_t context_;
DISALLOW_COPY_AND_ASSIGN(GLContextMac);
};
} // namespace gfx
#endif /* defined(__UI_GL_GL_CONTEXT_MAC_H__) */
......@@ -6,16 +6,98 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event.h"
#include "ui/gl/gl_context_cgl.h"
#include "ui/gl/gl_context_mac.h"
#include "ui/gl/gl_context_stub.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
#import <AppKit/AppKit.h>
#import <OpenGL/gl.h>
#define CAST_CONTEXT (reinterpret_cast<NSOpenGLContext*>(context_))
namespace gfx {
class GLShareGroup;
GLContextMac::GLContextMac(GLShareGroup* share_group)
: GLContextReal(share_group),
context_(0) {
// Instead of creating a context here, we steal one from the NSOpenGLView
// that is passed to us in the initialize call.
}
bool GLContextMac::Initialize(GLSurface* compatible_surface,
GpuPreference gpu_preference) {
if (compatible_surface == nullptr) {
return false;
}
auto view = reinterpret_cast<NSOpenGLView *>(compatible_surface->GetHandle());
context_ = reinterpret_cast<uintptr_t>(view.openGLContext);
[CAST_CONTEXT retain];
return CAST_CONTEXT != nullptr;
}
void GLContextMac::Destroy() {
[CAST_CONTEXT release];
context_ = 0;
}
bool GLContextMac::MakeCurrent(GLSurface* surface) {
[CAST_CONTEXT makeCurrentContext];
SetRealGLApi();
if (!InitializeDynamicBindings()) {
return false;
}
if (!surface->OnMakeCurrent(this)) {
return false;
}
return true;
}
void GLContextMac::ReleaseCurrent(GLSurface* surface) {
[NSOpenGLContext clearCurrentContext];
}
bool GLContextMac::IsCurrent(GLSurface* surface) {
return [NSOpenGLContext currentContext] == CAST_CONTEXT;
}
void* GLContextMac::GetHandle() {
return reinterpret_cast<void *>(context_);
}
void GLContextMac::OnSetSwapInterval(int interval) {
}
std::string GLContextMac::GetExtensions() {
return reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
}
bool GLContextMac::WasAllocatedUsingRobustnessExtension() {
return false;
}
bool GLContextMac::GetTotalGpuMemory(size_t* bytes) {
DCHECK(false);
return false;
}
void GLContextMac::SetUnbindFboOnMakeCurrent() {
DCHECK(false);
}
GLContextMac::~GLContextMac() {
Destroy();
}
scoped_refptr<GLContext> GLContext::CreateGLContext(
GLShareGroup* share_group,
GLSurface* compatible_surface,
......@@ -25,11 +107,7 @@ scoped_refptr<GLContext> GLContext::CreateGLContext(
case kGLImplementationDesktopGL:
case kGLImplementationAppleGL: {
scoped_refptr<GLContext> context;
// Note that with virtualization we might still be able to make current
// a different onscreen surface with this context later. But we should
// always be creating the context with an offscreen surface first.
DCHECK(compatible_surface->IsOffscreen());
context = new GLContextCGL(share_group);
context = new GLContextMac(share_group);
if (!context->Initialize(compatible_surface, gpu_preference))
return NULL;
......
......@@ -9,6 +9,11 @@
#include "ui/gl/gl_enums.h"
#include "base/logging.h"
#import <AppKit/AppKit.h>
#import <OpenGL/gl.h>
#define WIDGET_AS_VIEW (reinterpret_cast<NSOpenGLView*>(widget_))
namespace gfx {
GLSurfaceMac::GLSurfaceMac(gfx::AcceleratedWidget widget,
......@@ -22,13 +27,12 @@ GLSurfaceMac::~GLSurfaceMac() {
}
bool GLSurfaceMac::OnMakeCurrent(GLContext* context) {
DCHECK(false);
return false;
return true;
}
bool GLSurfaceMac::SwapBuffers() {
DCHECK(false);
return false;
[[NSOpenGLContext currentContext] flushBuffer];
return true;
}
void GLSurfaceMac::Destroy() {
......@@ -36,13 +40,12 @@ void GLSurfaceMac::Destroy() {
}
bool GLSurfaceMac::IsOffscreen() {
DCHECK(false);
return false;
}
gfx::Size GLSurfaceMac::GetSize() {
DCHECK(false);
return Size(0.0, 0.0);
auto size = WIDGET_AS_VIEW.bounds.size;
return Size(size.width, size.height);
}
void* GLSurfaceMac::GetHandle() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册