skia2/tools/sk_app/mac/GLWindowContext_mac.mm
Jim Van Verth 2782b2872b Fix drag events in Mac viewer.
Rather than depend on the Cocoa event system we intercept the events
in our main loop and send them to the appropriate sk_app::Window. A
hashmap that maps from Cocoa windowNumbers to an sk_app::Window is
added to make this possible.

We continue to send the event on through the Cocoa system to catch
system level events -- e.g., window close and drag events. We also
continue to catch key events in an NSView to keep the app from beeping
annoyingly because it thinks it's capturing events outside its focus.
Finally we ensure that move events are always enabled for the window
so that imgui knows that the cursor is over it.

Bug: skia:8737
Change-Id: Id49df51f68942fbf51634d6484291df862074864
Reviewed-on: https://skia-review.googlesource.com/c/191574
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
2019-02-13 19:26:39 +00:00

190 lines
5.7 KiB
Plaintext

/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "../GLWindowContext.h"
#include "WindowContextFactory_mac.h"
#include "gl/GrGLInterface.h"
#include <OpenGL/gl.h>
#include <Cocoa/Cocoa.h>
using sk_app::DisplayParams;
using sk_app::window_context_factory::MacWindowInfo;
using sk_app::GLWindowContext;
namespace {
class GLWindowContext_mac : public GLWindowContext {
public:
GLWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
~GLWindowContext_mac() override;
void onSwapBuffers() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
NSView* fMainView;
NSOpenGLView* fGLView;
NSOpenGLContext* fGLContext;
NSOpenGLPixelFormat* fPixelFormat;
typedef GLWindowContext INHERITED;
};
GLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, const DisplayParams& params)
: INHERITED(params)
, fMainView(info.fMainView) {
// any config code here (particularly for msaa)?
this->initializeContext();
}
GLWindowContext_mac::~GLWindowContext_mac() {
this->destroyContext();
}
sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() {
SkASSERT(nil != fMainView);
// set up pixel format
constexpr int kMaxAttributes = 18;
NSOpenGLPixelFormatAttribute attributes[kMaxAttributes];
int numAttributes = 0;
attributes[numAttributes++] = NSOpenGLPFAAccelerated;
attributes[numAttributes++] = NSOpenGLPFAClosestPolicy;
attributes[numAttributes++] = NSOpenGLPFADoubleBuffer;
attributes[numAttributes++] = NSOpenGLPFAOpenGLProfile;
attributes[numAttributes++] = NSOpenGLProfileVersion3_2Core;
attributes[numAttributes++] = NSOpenGLPFAColorSize;
attributes[numAttributes++] = 24;
attributes[numAttributes++] = NSOpenGLPFAAlphaSize;
attributes[numAttributes++] = 8;
attributes[numAttributes++] = NSOpenGLPFADepthSize;
attributes[numAttributes++] = 0;
attributes[numAttributes++] = NSOpenGLPFAStencilSize;
attributes[numAttributes++] = 8;
if (fDisplayParams.fMSAASampleCount > 1) {
attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
attributes[numAttributes++] = 1;
attributes[numAttributes++] = NSOpenGLPFASamples;
attributes[numAttributes++] = fDisplayParams.fMSAASampleCount;
} else {
attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
attributes[numAttributes++] = 0;
}
attributes[numAttributes++] = 0;
SkASSERT(numAttributes <= kMaxAttributes);
fPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
if (nil == fPixelFormat) {
return nullptr;
}
// create context
fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil];
if (nil == fGLContext) {
[fPixelFormat release];
fPixelFormat = nil;
return nullptr;
}
// create view
NSRect rect = fMainView.bounds;
fGLView = [[NSOpenGLView alloc] initWithFrame:rect];
if (nil == fGLView) {
[fGLContext release];
fGLContext = nil;
[fPixelFormat release];
fPixelFormat = nil;
return nullptr;
}
[fGLView setTranslatesAutoresizingMaskIntoConstraints:NO];
// attach OpenGL view to main view
[fMainView addSubview:fGLView];
NSDictionary *views = NSDictionaryOfVariableBindings(fGLView);
[fMainView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[fGLView]|"
options:0
metrics:nil
views:views]];
[fMainView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[fGLView]|"
options:0
metrics:nil
views:views]];
// make context current
GLint swapInterval = 1;
[fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
[fGLView setOpenGLContext:fGLContext];
[fGLView setPixelFormat:fPixelFormat];
// TODO: support Retina displays
[fGLView setWantsBestResolutionOpenGLSurface:NO];
[fGLContext setView:fGLView];
[fGLContext makeCurrentContext];
glClearStencil(0);
glClearColor(0, 0, 0, 255);
glStencilMask(0xffffffff);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
GLint stencilBits;
[fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
fStencilBits = stencilBits;
GLint sampleCount;
[fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
fSampleCount = sampleCount;
fSampleCount = SkTMax(fSampleCount, 1);
const NSRect viewportRect = [fGLView bounds];
fWidth = viewportRect.size.width;
fHeight = viewportRect.size.height;
glViewport(0, 0, fWidth, fHeight);
return GrGLMakeNativeInterface();
}
void GLWindowContext_mac::onDestroyContext() {
[fGLView removeFromSuperview];
[fGLView release];
fGLView = nil;
[fGLContext release];
fGLContext = nil;
[fPixelFormat release];
fPixelFormat = nil;
}
void GLWindowContext_mac::onSwapBuffers() {
[fGLContext flushBuffer];
}
} // anonymous namespace
namespace sk_app {
namespace window_context_factory {
WindowContext* NewGLForMac(const MacWindowInfo& info, const DisplayParams& params) {
WindowContext* ctx = new GLWindowContext_mac(info, params);
if (!ctx->isValid()) {
delete ctx;
return nullptr;
}
return ctx;
}
} // namespace window_context_factory
} // namespace sk_app