diff --git a/sky/shell/BUILD.gn b/sky/shell/BUILD.gn
index cc865dd8d00..2430fa72363 100644
--- a/sky/shell/BUILD.gn
+++ b/sky/shell/BUILD.gn
@@ -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",
diff --git a/sky/shell/mac/Info.plist b/sky/shell/mac/Info.plist
index 3e73f37a075..9b2e91c647c 100644
--- a/sky/shell/mac/Info.plist
+++ b/sky/shell/mac/Info.plist
@@ -29,6 +29,13 @@
NSMainNibFile
sky_mac
NSPrincipalClass
- NSApplication
+ SkyApplication
+
+
+ org.domokit.sky.load_url
+ https://domokit.github.io/home.dart
+
diff --git a/sky/shell/mac/main_mac.mm b/sky/shell/mac/main_mac.mm
index a6db5790343..ccc80ddb2ca 100644
--- a/sky/shell/mac/main_mac.mm
+++ b/sky/shell/mac/main_mac.mm
@@ -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();
diff --git a/sky/shell/mac/platform_mac.h b/sky/shell/mac/platform_mac.h
index 25a479aa346..6e0cf4b34e1 100644
--- a/sky/shell/mac/platform_mac.h
+++ b/sky/shell/mac/platform_mac.h
@@ -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
}
diff --git a/sky/shell/mac/platform_mac.mm b/sky/shell/mac/platform_mac.mm
index 2ba18ed2c1a..2b6d6e897a5 100644
--- a/sky/shell/mac/platform_mac.mm
+++ b/sky/shell/mac/platform_mac.mm
@@ -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 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());
diff --git a/sky/shell/mac/platform_view_mac.mm b/sky/shell/mac/platform_view_mac.mm
index 459cbad8860..f4bc15b1d19 100644
--- a/sky/shell/mac/platform_view_mac.mm
+++ b/sky/shell/mac/platform_view_mac.mm
@@ -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);
diff --git a/sky/shell/mac/sky_app_delegate.h b/sky/shell/mac/sky_app_delegate.h
index 6326af00ce9..dbe422b2937 100644
--- a/sky/shell/mac/sky_app_delegate.h
+++ b/sky/shell/mac/sky_app_delegate.h
@@ -4,7 +4,6 @@
#import
-@interface SkyAppDelegate : NSObject
+@interface SkyAppDelegate : NSObject
@end
-
diff --git a/sky/shell/mac/sky_app_delegate.m b/sky/shell/mac/sky_app_delegate.m
index 4a527099828..c6ba6c56961 100644
--- a/sky/shell/mac/sky_app_delegate.m
+++ b/sky/shell/mac/sky_app_delegate.m
@@ -6,7 +6,7 @@
@interface SkyAppDelegate ()
-@property (assign) IBOutlet NSWindow *window;
+@property(assign) IBOutlet NSWindow* window;
@end
diff --git a/sky/shell/mac/sky_application.h b/sky/shell/mac/sky_application.h
new file mode 100644
index 00000000000..a74edca41cc
--- /dev/null
+++ b/sky/shell/mac/sky_application.h
@@ -0,0 +1,18 @@
+// 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
+
+#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
+@end
+
+#endif /* defined(__SKY_SHELL_MAC_SKY_APPLICATION__) */
diff --git a/sky/shell/mac/sky_application.mm b/sky/shell/mac/sky_application.mm
new file mode 100644
index 00000000000..51a04c3061e
--- /dev/null
+++ b/sky/shell/mac/sky_application.mm
@@ -0,0 +1,39 @@
+// 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 scoper(&handlingSendEvent_, YES);
+ [super sendEvent:event];
+}
+
+- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
+ handlingSendEvent_ = handlingSendEvent;
+}
+
+- (BOOL)isHandlingSendEvent {
+ return handlingSendEvent_;
+}
+
+@end
diff --git a/sky/shell/mac/sky_mac.xib b/sky/shell/mac/sky_mac.xib
index 8abc72a57b9..0173ec3d28e 100644
--- a/sky/shell/mac/sky_mac.xib
+++ b/sky/shell/mac/sky_mac.xib
@@ -4,7 +4,7 @@
-
+
@@ -675,7 +675,7 @@
-
+
diff --git a/sky/shell/mac/sky_window.mm b/sky/shell/mac/sky_window.mm
index bcad63cb042..f16c8a13cc0 100644
--- a/sky/shell/mac/sky_window.mm
+++ b/sky/shell/mac/sky_window.mm
@@ -11,22 +11,43 @@
#include "sky/shell/shell.h"
#include "sky/shell/ui_delegate.h"
-@interface SkyWindow ()
+@interface SkyWindow ()
-@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 _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];
}
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 43d0765e7a2..3c0a5bb7dc2 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -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",
diff --git a/ui/gl/gl_context_mac.h b/ui/gl/gl_context_mac.h
new file mode 100644
index 00000000000..6577c1f3c63
--- /dev/null
+++ b/ui/gl/gl_context_mac.h
@@ -0,0 +1,43 @@
+// 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__) */
diff --git a/ui/gl/gl_context_mac.mm b/ui/gl/gl_context_mac.mm
index 389b80dd0a8..1b2b301fcaa 100644
--- a/ui/gl/gl_context_mac.mm
+++ b/ui/gl/gl_context_mac.mm
@@ -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
+#import
+
+#define CAST_CONTEXT (reinterpret_cast(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(compatible_surface->GetHandle());
+ context_ = reinterpret_cast(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(context_);
+}
+
+void GLContextMac::OnSetSwapInterval(int interval) {
+}
+
+std::string GLContextMac::GetExtensions() {
+ return reinterpret_cast(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::CreateGLContext(
GLShareGroup* share_group,
GLSurface* compatible_surface,
@@ -25,11 +107,7 @@ scoped_refptr GLContext::CreateGLContext(
case kGLImplementationDesktopGL:
case kGLImplementationAppleGL: {
scoped_refptr 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;
diff --git a/ui/gl/gl_surface_mac.cc b/ui/gl/gl_surface_mac.mm
similarity index 84%
rename from ui/gl/gl_surface_mac.cc
rename to ui/gl/gl_surface_mac.mm
index 0686117cd35..83fcb66bb41 100644
--- a/ui/gl/gl_surface_mac.cc
+++ b/ui/gl/gl_surface_mac.mm
@@ -9,6 +9,11 @@
#include "ui/gl/gl_enums.h"
#include "base/logging.h"
+#import
+#import
+
+#define WIDGET_AS_VIEW (reinterpret_cast(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() {