gfx/skia/trunk/src/views/mac/SkNSView.mm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     2 /*
     3  * Copyright 2011 Google Inc.
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     9 #import "SkNSView.h"
    10 #include "SkCanvas.h"
    11 #include "SkCGUtils.h"
    12 #include "SkEvent.h"
    13 SK_COMPILE_ASSERT(SK_SUPPORT_GPU, not_implemented_for_non_gpu_build);
    14 #include <OpenGL/gl.h>
    16 //#define FORCE_REDRAW
    17 // Can be dropped when we no longer support 10.6.
    18 #define RETINA_API_AVAILABLE (defined(MAC_OS_X_VERSION_10_7) && \
    19                               MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
    20 @implementation SkNSView
    21 @synthesize fWind, fTitle, fOptionsDelegate, fGLContext;
    23 - (id)initWithCoder:(NSCoder*)coder {
    24     if ((self = [super initWithCoder:coder])) {
    25         self = [self initWithDefaults];
    26         [self setUpWindow];
    27     }
    28     return self;
    29 }
    31 - (id)initWithFrame:(NSRect)frameRect {
    32     if ((self = [super initWithFrame:frameRect])) {
    33         self = [self initWithDefaults];
    34         [self setUpWindow];
    35     }
    36     return self;
    37 }
    39 - (id)initWithDefaults {
    40 #if RETINA_API_AVAILABLE
    41     [self setWantsBestResolutionOpenGLSurface:YES];
    42 #endif
    43     fRedrawRequestPending = false;
    44     fWind = NULL;
    45     return self;
    46 }
    48 - (void)setUpWindow {
    49     [[NSNotificationCenter defaultCenter] addObserver:self
    50                                           selector:@selector(backingPropertiesChanged:)
    51                                           name:@"NSWindowDidChangeBackingPropertiesNotification"
    52                                           object:[self window]];
    53     if (NULL != fWind) {
    54         fWind->setVisibleP(true);
    55         NSSize size = self.frame.size;
    56 #if RETINA_API_AVAILABLE
    57         size = [self convertSizeToBacking:self.frame.size];
    58 #endif
    59         fWind->resize((int) size.width, (int) size.height,
    60                       kPMColor_SkColorType);
    61     }
    62 }
    64 -(BOOL) isFlipped {
    65     return YES;
    66 }
    68 - (BOOL)acceptsFirstResponder {
    69     return YES;
    70 }
    72 - (float)scaleFactor {
    73     NSWindow *window = [self window];
    74 #if RETINA_API_AVAILABLE
    75     if (window) {
    76         return [window backingScaleFactor];
    77     }
    78     return [[NSScreen mainScreen] backingScaleFactor];
    79 #else
    80     if (window) {
    81         return [window userSpaceScaleFactor];
    82     }
    83     return [[NSScreen mainScreen] userSpaceScaleFactor];
    84 #endif
    85 }
    87 - (void)backingPropertiesChanged:(NSNotification *)notification {
    88     CGFloat oldBackingScaleFactor = (CGFloat)[
    89         [notification.userInfo objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue
    90     ];
    91     CGFloat newBackingScaleFactor = [self scaleFactor];
    92     if (oldBackingScaleFactor == newBackingScaleFactor) {
    93         return;
    94     }
    96     // TODO: need a better way to force a refresh (that works).
    97     // [fGLContext update] does not appear to update if the point size has not changed,
    98     // even if the backing size has changed.
    99     [self setFrameSize:NSMakeSize(self.frame.size.width + 1, self.frame.size.height + 1)];
   100 }
   102 - (void)resizeSkView:(NSSize)newSize {
   103 #if RETINA_API_AVAILABLE
   104     newSize = [self convertSizeToBacking:newSize];
   105 #endif
   106     if (NULL != fWind &&
   107             (fWind->width()  != newSize.width ||
   108              fWind->height() != newSize.height))
   109     {
   110         fWind->resize((int) newSize.width, (int) newSize.height);
   111         if (NULL != fGLContext) {
   112             glClear(GL_STENCIL_BUFFER_BIT);
   113             [fGLContext update];
   114         }
   115     }
   116 }
   118 - (void) setFrameSize:(NSSize)newSize {
   119     [super setFrameSize:newSize];
   120     [self resizeSkView:newSize];
   121 }
   123 - (void)dealloc {
   124     delete fWind;
   125     self.fGLContext = nil;
   126     self.fTitle = nil;
   127     [super dealloc];
   128 }
   130 ////////////////////////////////////////////////////////////////////////////////
   132 - (void)drawSkia {
   133     fRedrawRequestPending = false;
   134     if (NULL != fWind) {
   135         SkAutoTUnref<SkCanvas> canvas(fWind->createCanvas());
   136         fWind->draw(canvas);
   137 #ifdef FORCE_REDRAW
   138         fWind->inval(NULL);
   139 #endif
   140     }
   141 }
   143 - (void)setSkTitle:(const char *)title {
   144     self.fTitle = [NSString stringWithUTF8String:title];
   145     [[self window] setTitle:self.fTitle];
   146 }
   148 - (BOOL)onHandleEvent:(const SkEvent&)evt {
   149     return false;
   150 }
   152 #include "SkOSMenu.h"
   153 - (void)onAddMenu:(const SkOSMenu*)menu {
   154     [self.fOptionsDelegate view:self didAddMenu:menu];
   155 }
   157 - (void)onUpdateMenu:(const SkOSMenu*)menu {
   158     [self.fOptionsDelegate view:self didUpdateMenu:menu];
   159 }
   161 - (void)postInvalWithRect:(const SkIRect*)r {
   162     if (!fRedrawRequestPending) {
   163         fRedrawRequestPending = true;
   164         [self setNeedsDisplay:YES];
   165         [self performSelector:@selector(drawSkia) withObject:nil afterDelay:0];
   166     }
   167 }
   168 ///////////////////////////////////////////////////////////////////////////////
   170 #include "SkKey.h"
   171 enum {
   172 	SK_MacReturnKey		= 36,
   173 	SK_MacDeleteKey		= 51,
   174 	SK_MacEndKey		= 119,
   175 	SK_MacLeftKey		= 123,
   176 	SK_MacRightKey		= 124,
   177 	SK_MacDownKey		= 125,
   178 	SK_MacUpKey			= 126,
   179     SK_Mac0Key          = 0x52,
   180     SK_Mac1Key          = 0x53,
   181     SK_Mac2Key          = 0x54,
   182     SK_Mac3Key          = 0x55,
   183     SK_Mac4Key          = 0x56,
   184     SK_Mac5Key          = 0x57,
   185     SK_Mac6Key          = 0x58,
   186     SK_Mac7Key          = 0x59,
   187     SK_Mac8Key          = 0x5b,
   188     SK_Mac9Key          = 0x5c
   189 };
   191 static SkKey raw2key(UInt32 raw)
   192 {
   193 	static const struct {
   194 		UInt32  fRaw;
   195 		SkKey   fKey;
   196 	} gKeys[] = {
   197 		{ SK_MacUpKey,		kUp_SkKey		},
   198 		{ SK_MacDownKey,	kDown_SkKey		},
   199 		{ SK_MacLeftKey,	kLeft_SkKey		},
   200 		{ SK_MacRightKey,   kRight_SkKey	},
   201 		{ SK_MacReturnKey,  kOK_SkKey		},
   202 		{ SK_MacDeleteKey,  kBack_SkKey		},
   203 		{ SK_MacEndKey,		kEnd_SkKey		},
   204         { SK_Mac0Key,       k0_SkKey        },
   205         { SK_Mac1Key,       k1_SkKey        },
   206         { SK_Mac2Key,       k2_SkKey        },
   207         { SK_Mac3Key,       k3_SkKey        },
   208         { SK_Mac4Key,       k4_SkKey        },
   209         { SK_Mac5Key,       k5_SkKey        },
   210         { SK_Mac6Key,       k6_SkKey        },
   211         { SK_Mac7Key,       k7_SkKey        },
   212         { SK_Mac8Key,       k8_SkKey        },
   213         { SK_Mac9Key,       k9_SkKey        }
   214 	};
   216 	for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
   217 		if (gKeys[i].fRaw == raw)
   218 			return gKeys[i].fKey;
   219 	return kNONE_SkKey;
   220 }
   222 - (void)keyDown:(NSEvent *)event {
   223     if (NULL == fWind)
   224         return;
   226     SkKey key = raw2key([event keyCode]);
   227     if (kNONE_SkKey != key)
   228         fWind->handleKey(key);
   229     else{
   230         unichar c = [[event characters] characterAtIndex:0];
   231         fWind->handleChar((SkUnichar)c);
   232     }
   233 }
   235 - (void)keyUp:(NSEvent *)event {
   236     if (NULL == fWind)
   237         return;
   239     SkKey key = raw2key([event keyCode]);
   240     if (kNONE_SkKey != key)
   241         fWind->handleKeyUp(key);
   242  // else
   243  //     unichar c = [[event characters] characterAtIndex:0];
   244 }
   246 static const struct {
   247     unsigned    fNSModifierMask;
   248     unsigned    fSkModifierMask;
   249 } gModifierMasks[] = {
   250     { NSAlphaShiftKeyMask,  kShift_SkModifierKey },
   251     { NSShiftKeyMask,       kShift_SkModifierKey },
   252     { NSControlKeyMask,     kControl_SkModifierKey },
   253     { NSAlternateKeyMask,   kOption_SkModifierKey },
   254     { NSCommandKeyMask,     kCommand_SkModifierKey },
   255 };
   257 static unsigned convertNSModifiersToSk(NSUInteger nsModi) {
   258     unsigned skModi = 0;
   259     for (size_t i = 0; i < SK_ARRAY_COUNT(gModifierMasks); ++i) {
   260         if (nsModi & gModifierMasks[i].fNSModifierMask) {
   261             skModi |= gModifierMasks[i].fSkModifierMask;
   262         }
   263     }
   264     return skModi;
   265 }
   267 - (void)mouseDown:(NSEvent *)event {
   268     NSPoint p = [event locationInWindow];
   269     unsigned modi = convertNSModifiersToSk([event modifierFlags]);
   271     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
   272         NSPoint loc = [self convertPoint:p fromView:nil];
   273 #if RETINA_API_AVAILABLE
   274         loc = [self convertPointToBacking:loc]; //y-up
   275         loc.y = -loc.y;
   276 #endif
   277         fWind->handleClick((int) loc.x, (int) loc.y,
   278                            SkView::Click::kDown_State, self, modi);
   279     }
   280 }
   282 - (void)mouseDragged:(NSEvent *)event {
   283     NSPoint p = [event locationInWindow];
   284     unsigned modi = convertNSModifiersToSk([event modifierFlags]);
   286     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
   287         NSPoint loc = [self convertPoint:p fromView:nil];
   288 #if RETINA_API_AVAILABLE
   289         loc = [self convertPointToBacking:loc]; //y-up
   290         loc.y = -loc.y;
   291 #endif
   292         fWind->handleClick((int) loc.x, (int) loc.y,
   293                            SkView::Click::kMoved_State, self, modi);
   294     }
   295 }
   297 - (void)mouseMoved:(NSEvent *)event {
   298     NSPoint p = [event locationInWindow];
   299     unsigned modi = convertNSModifiersToSk([event modifierFlags]);
   301     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
   302         NSPoint loc = [self convertPoint:p fromView:nil];
   303 #if RETINA_API_AVAILABLE
   304         loc = [self convertPointToBacking:loc]; //y-up
   305         loc.y = -loc.y;
   306 #endif
   307         fWind->handleClick((int) loc.x, (int) loc.y,
   308                            SkView::Click::kMoved_State, self, modi);
   309     }
   310 }
   312 - (void)mouseUp:(NSEvent *)event {
   313     NSPoint p = [event locationInWindow];
   314     unsigned modi = convertNSModifiersToSk([event modifierFlags]);
   316     if ([self mouse:p inRect:[self bounds]] && NULL != fWind) {
   317         NSPoint loc = [self convertPoint:p fromView:nil];
   318 #if RETINA_API_AVAILABLE
   319         loc = [self convertPointToBacking:loc]; //y-up
   320         loc.y = -loc.y;
   321 #endif
   322         fWind->handleClick((int) loc.x, (int) loc.y,
   323                            SkView::Click::kUp_State, self, modi);
   324     }
   325 }
   327 ///////////////////////////////////////////////////////////////////////////////
   328 #include <OpenGL/OpenGL.h>
   330 namespace { 
   331 CGLContextObj createGLContext(int msaaSampleCount) {
   332     GLint major, minor;
   333     CGLGetVersion(&major, &minor);
   335     static const CGLPixelFormatAttribute attributes[] = {
   336         kCGLPFAStencilSize, (CGLPixelFormatAttribute) 8,
   337         kCGLPFAAccelerated,
   338         kCGLPFADoubleBuffer,
   339         (CGLPixelFormatAttribute)0
   340     };
   342     CGLPixelFormatObj format;
   343     GLint npix = 0;
   344     if (msaaSampleCount > 0) {
   345         static int kAttributeCount = SK_ARRAY_COUNT(attributes);
   346         CGLPixelFormatAttribute msaaAttributes[kAttributeCount + 5];
   347         memcpy(msaaAttributes, attributes, sizeof(attributes));
   348         SkASSERT(0 == msaaAttributes[kAttributeCount - 1]);
   349         msaaAttributes[kAttributeCount - 1] = kCGLPFASampleBuffers;
   350         msaaAttributes[kAttributeCount + 0] = (CGLPixelFormatAttribute)1;
   351         msaaAttributes[kAttributeCount + 1] = kCGLPFAMultisample;
   352         msaaAttributes[kAttributeCount + 2] = kCGLPFASamples;
   353         msaaAttributes[kAttributeCount + 3] =
   354                                     (CGLPixelFormatAttribute)msaaSampleCount;
   355         msaaAttributes[kAttributeCount + 4] = (CGLPixelFormatAttribute)0;
   356         CGLChoosePixelFormat(msaaAttributes, &format, &npix);
   357     }
   358     if (!npix) {
   359         CGLChoosePixelFormat(attributes, &format, &npix);
   360     }
   361     CGLContextObj ctx;
   362     CGLCreateContext(format, NULL, &ctx);
   363     CGLDestroyPixelFormat(format);
   365     static const GLint interval = 1;
   366     CGLSetParameter(ctx, kCGLCPSwapInterval, &interval);
   367     CGLSetCurrentContext(ctx);
   368     return ctx;
   369 }
   370 }
   372 - (void)viewDidMoveToWindow {
   373     [super viewDidMoveToWindow];
   375     //Attaching view to fGLContext requires that the view to be part of a window,
   376     //and that the NSWindow instance must have a CoreGraphics counterpart (or 
   377     //it must NOT be deferred or should have been on screen at least once)
   378     if ([fGLContext view] != self && nil != self.window) {
   379         [fGLContext setView:self];
   380     }
   381 }
   382 - (bool)attach:(SkOSWindow::SkBackEndTypes)attachType
   383         withMSAASampleCount:(int) sampleCount
   384         andGetInfo:(SkOSWindow::AttachmentInfo*) info {
   385     if (nil == fGLContext) {
   386         CGLContextObj ctx = createGLContext(sampleCount);
   387         fGLContext = [[NSOpenGLContext alloc] initWithCGLContextObj:ctx];
   388         CGLReleaseContext(ctx);
   389         if (NULL == fGLContext) {
   390             return false;
   391         }
   392         [fGLContext setView:self];
   393     }
   395     [fGLContext makeCurrentContext];
   396     CGLPixelFormatObj format = CGLGetPixelFormat((CGLContextObj)[fGLContext CGLContextObj]);
   397     CGLDescribePixelFormat(format, 0, kCGLPFASamples, &info->fSampleCount);
   398     CGLDescribePixelFormat(format, 0, kCGLPFAStencilSize, &info->fStencilBits);
   399     NSSize size = self.bounds.size;
   400 #if RETINA_API_AVAILABLE
   401     size = [self convertSizeToBacking:size];
   402 #endif
   403     glViewport(0, 0, (int) size.width, (int) size.height);
   404     glClearColor(0, 0, 0, 0);
   405     glClearStencil(0);
   406     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   407     return true;
   408 }
   410 - (void)detach {
   411     [fGLContext release];
   412     fGLContext = nil;
   413 }
   415 - (void)present {
   416     if (nil != fGLContext) {
   417         [fGLContext flushBuffer];
   418     }
   419 }
   420 @end

mercurial