Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/exp/shiny: OSX Appkit deprecations on OSX 10.12 (Sierra) #17413

Closed
joeblew99 opened this issue Oct 12, 2016 · 6 comments
Closed

x/exp/shiny: OSX Appkit deprecations on OSX 10.12 (Sierra) #17413

joeblew99 opened this issue Oct 12, 2016 · 6 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@joeblew99
Copy link

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.7.1 darwin/amd64

What operating system and processor architecture are you using (go env)?


GOARCH="amd64"
GOBIN="/Users/apple/workspace/go/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/apple/workspace/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/wp/ff6sz9qs6g71jnm12nj2kbyw0000gp/T/go-build687574504=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"

What did you do?

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

go get -u golang.org/x/exp/shiny

What did you expect to see?

no errors...

What did you see instead?


x-MacBook-Pro:textedit apple$ pwd
/Users/apple/workspace/go/src/golang.org/x/exp/shiny/example/textedit
x-MacBook-Pro:textedit apple$ go run main.go
# golang.org/x/exp/shiny/driver/gldriver
../../driver/gldriver/cocoa.m:110:23: warning: 'NSScrollWheel' is deprecated: first deprecated in macOS 10.12 [-Wdeprecated-declarations]
/System/Library/Frameworks/AppKit.framework/Headers/NSEvent.h:81:26: note: 'NSScrollWheel' has been explicitly marked deprecated here
../../driver/gldriver/cocoa.m:164:30: warning: 'NSKeyDown' is deprecated: first deprecated in macOS 10.12 [-Wdeprecated-declarations]
/System/Library/Frameworks/AppKit.framework/Headers/NSEvent.h:73:26: note: 'NSKeyDown' has been explicitly marked deprecated here
../../driver/gldriver/cocoa.m:253:15: warning: 'NSTitledWindowMask' is deprecated: first deprecated in macOS 10.12 [-Wdeprecated-declarations]
/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:953:32: note: 'NSTitledWindowMask' has been explicitly marked deprecated here
../../driver/gldriver/cocoa.m:256:23: warning: 'NSResizableWindowMask' is deprecated: first deprecated in macOS 10.12 [-Wdeprecated-declarations]
/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:956:32: note: 'NSResizableWindowMask' has been explicitly marked deprecated here
../../driver/gldriver/cocoa.m:257:23: warning: 'NSMiniaturizableWindowMask' is deprecated: first deprecated in macOS 10.12 [-Wdeprecated-declarations]
/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:955:32: note: 'NSMiniaturizableWindowMask' has been explicitly marked deprecated here
../../driver/gldriver/cocoa.m:258:23: warning: 'NSClosableWindowMask' is deprecated: first deprecated in macOS 10.12 [-Wdeprecated-declarations]
/System/Library/Frameworks/AppKit.framework/Headers/NSWindow.h:954:32: note: 'NSClosableWindowMask' has been explicitly marked deprecated here
x-MacBook-Pro:textedit apple$ 

@joeblew99
Copy link
Author

joeblew99 commented Oct 12, 2016

@nigeltao
i fixed the errors.

Let me know how i can contribute to this repo.

Also the widgets are coming along ok !

@joeblew99 joeblew99 changed the title x/shiny: OSX Appkit deprecations on OSX 10.12 (Sierra) x/exp/shiny: OSX Appkit deprecations on OSX 10.12 (Sierra) Oct 12, 2016
@quentinmit quentinmit added this to the Unreleased milestone Oct 12, 2016
@quentinmit quentinmit added the NeedsFix The path to resolution is known, but the work has not been done. label Oct 12, 2016
@quentinmit
Copy link
Contributor

@joeblew99 Take a look at https://golang.org/doc/contribute.html to learn how to use Gerrit to contribute code.

@joeblew99
Copy link
Author

mhhh. Cant i just sign the CLA and send a PR :) ?

@nigeltao
Copy link
Contributor

We use Gerrit for all code review (and CLA enforcement), not PRs. Sorry.

@joeblew99
Copy link
Author

Just too busy on the current commercial project right now to do this.

Instead, i inline the the fix:
golang.org/x/exp/shiny/driver/gldriver/cocoa.m

You can easily drop this in and see the differences with git yourself..


// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin
// +build 386 amd64
// +build !ios

#include "_cgo_export.h"
#include <pthread.h>
#include <stdio.h>

#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#import <OpenGL/gl3.h>

void makeCurrentContext(uintptr_t context) {
    NSOpenGLContext* ctx = (NSOpenGLContext*)context;
    [ctx makeCurrentContext];
}

void flushContext(uintptr_t context) {
    NSOpenGLContext* ctx = (NSOpenGLContext*)context;
    [ctx flushBuffer];
}

uint64 threadID() {
    uint64 id;
    if (pthread_threadid_np(pthread_self(), &id)) {
        abort();
    }
    return id;
}

@interface ScreenGLView : NSOpenGLView<NSWindowDelegate>
{
}
@end

@implementation ScreenGLView
- (void)prepareOpenGL {
    [self setWantsBestResolutionOpenGLSurface:YES];
    GLint swapInt = 1;
    NSOpenGLContext *ctx = [self openGLContext];
    [ctx setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];

    // Using attribute arrays in OpenGL 3.3 requires the use of a VBA.
    // But VBAs don't exist in ES 2. So we bind a default one.
    GLuint vba;
    glGenVertexArrays(1, &vba);
    glBindVertexArray(vba);

    preparedOpenGL((GoUintptr)self, (GoUintptr)ctx, (GoUintptr)vba);
}

- (void)callSetGeom {
    // Calculate screen PPI.
    //
    // Note that the backingScaleFactor converts from logical
    // pixels to actual pixels, but both of these units vary
    // independently from real world size. E.g.
    //
    // 13" Retina Macbook Pro, 2560x1600, 227ppi, backingScaleFactor=2, scale=3.15
    // 15" Retina Macbook Pro, 2880x1800, 220ppi, backingScaleFactor=2, scale=3.06
    // 27" iMac,               2560x1440, 109ppi, backingScaleFactor=1, scale=1.51
    // 27" Retina iMac,        5120x2880, 218ppi, backingScaleFactor=2, scale=3.03
    NSScreen *screen = self.window.screen;
    double screenPixW = [screen frame].size.width * [screen backingScaleFactor];

    CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] valueForKey:@"NSScreenNumber"] intValue];
    CGSize screenSizeMM = CGDisplayScreenSize(display); // in millimeters
    float ppi = 25.4 * screenPixW / screenSizeMM.width;
    float pixelsPerPt = ppi/72.0;

    // The width and height reported to the geom package are the
    // bounds of the OpenGL view. Several steps are necessary.
    // First, [self bounds] gives us the number of logical pixels
    // in the view. Multiplying this by the backingScaleFactor
    // gives us the number of actual pixels.
    NSRect r = [self bounds];
    int w = r.size.width * [screen backingScaleFactor];
    int h = r.size.height * [screen backingScaleFactor];

    setGeom((GoUintptr)self, pixelsPerPt, w, h);
}

- (void)reshape {
    [super reshape];
    [self callSetGeom];
}

- (void)drawRect:(NSRect)theRect {
    // Called during resize. Do an extra draw if we are visible.
    // This gets rid of flicker when resizing.
    drawgl((GoUintptr)self);
}

- (void)mouseEventNS:(NSEvent *)theEvent {
    NSPoint p = [theEvent locationInWindow];
    double h = self.frame.size.height;

    // Both h and p are measured in Cocoa pixels, which are a fraction of
    // physical pixels, so we multiply by backingScaleFactor.
    double scale = [self.window.screen backingScaleFactor];

    double x = p.x * scale;
    double y = (h - p.y) * scale - 1; // flip origin from bottom-left to top-left.

    double dx, dy;
    if (theEvent.type == NSEventTypeScrollWheel) {
        dx = theEvent.scrollingDeltaX;
        dy = theEvent.scrollingDeltaY;
    }

    mouseEvent((GoUintptr)self, x, y, dx, dy, theEvent.type, theEvent.buttonNumber, theEvent.modifierFlags);
}

- (void)mouseMoved:(NSEvent *)theEvent        { [self mouseEventNS:theEvent]; }
- (void)mouseDown:(NSEvent *)theEvent         { [self mouseEventNS:theEvent]; }
- (void)mouseUp:(NSEvent *)theEvent           { [self mouseEventNS:theEvent]; }
- (void)mouseDragged:(NSEvent *)theEvent      { [self mouseEventNS:theEvent]; }
- (void)rightMouseDown:(NSEvent *)theEvent    { [self mouseEventNS:theEvent]; }
- (void)rightMouseUp:(NSEvent *)theEvent      { [self mouseEventNS:theEvent]; }
- (void)rightMouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; }
- (void)otherMouseDown:(NSEvent *)theEvent    { [self mouseEventNS:theEvent]; }
- (void)otherMouseUp:(NSEvent *)theEvent      { [self mouseEventNS:theEvent]; }
- (void)otherMouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; }
- (void)scrollWheel:(NSEvent *)theEvent       { [self mouseEventNS:theEvent]; }

// raw modifier key presses
- (void)flagsChanged:(NSEvent *)theEvent {
    flagEvent((GoUintptr)self, theEvent.modifierFlags);
}

// overrides special handling of escape and tab
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent {
    [self key:theEvent];
    return YES;
}

- (void)keyDown:(NSEvent *)theEvent { [self key:theEvent]; }
- (void)keyUp:(NSEvent *)theEvent   { [self key:theEvent]; }

- (void)key:(NSEvent *)theEvent {
    NSRange range = [theEvent.characters rangeOfComposedCharacterSequenceAtIndex:0];

    uint8_t buf[4] = {0, 0, 0, 0};
    if (![theEvent.characters getBytes:buf
            maxLength:4
            usedLength:nil
            encoding:NSUTF32LittleEndianStringEncoding
            options:NSStringEncodingConversionAllowLossy
            range:range
            remainingRange:nil]) {
        NSLog(@"failed to read key event %@", theEvent);
        return;
    }

    uint32_t rune = (uint32_t)buf[0]<<0 | (uint32_t)buf[1]<<8 | (uint32_t)buf[2]<<16 | (uint32_t)buf[3]<<24;

    uint8_t direction;
    if ([theEvent isARepeat]) {
        direction = 0;
    } else if (theEvent.type == NSEventTypeKeyDown) {
        direction = 1;
    } else {
        direction = 2;
    }
    keyEvent((GoUintptr)self, (int32_t)rune, direction, theEvent.keyCode, theEvent.modifierFlags);
}

- (void)windowDidChangeScreenProfile:(NSNotification *)notification {
    [self callSetGeom];
}

// TODO: catch windowDidMiniaturize?

- (void)windowDidExpose:(NSNotification *)notification {
    lifecycleVisible((GoUintptr)self, true);
}

- (void)windowDidBecomeKey:(NSNotification *)notification {
    lifecycleFocused((GoUintptr)self, true);
}

- (void)windowDidResignKey:(NSNotification *)notification {
    lifecycleFocused((GoUintptr)self, false);
    if ([NSApp isHidden]) {
        lifecycleVisible((GoUintptr)self, false);
    }
}

- (void)windowWillClose:(NSNotification *)notification {
    // TODO: is this right? Closing a window via the top-left red button
    // seems to return early without ever calling windowClosing.
    if (self.window.nextResponder == NULL) {
        return; // already called close
    }

    windowClosing((GoUintptr)self);
    [self.window.nextResponder release];
    self.window.nextResponder = NULL;
}
@end

@interface AppDelegate : NSObject<NSApplicationDelegate>
{
}
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    driverStarted();
    [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    lifecycleDeadAll();
}

- (void)applicationWillHide:(NSNotification *)aNotification {
    lifecycleHideAll();
}
@end

uintptr_t doNewWindow(int width, int height) {
    NSScreen *screen = [NSScreen mainScreen];
    double w = (double)width / [screen backingScaleFactor];
    double h = (double)height / [screen backingScaleFactor];
    __block ScreenGLView* view = NULL;

    dispatch_sync(dispatch_get_main_queue(), ^{
        id menuBar = [NSMenu new];
        id menuItem = [NSMenuItem new];
        [menuBar addItem:menuItem];
        [NSApp setMainMenu:menuBar];

        id menu = [NSMenu new];
        NSString* name = [[NSProcessInfo processInfo] processName];

        id hideMenuItem = [[NSMenuItem alloc] initWithTitle:@"Hide"
            action:@selector(hide:) keyEquivalent:@"h"];
        [menu addItem:hideMenuItem];

        id quitMenuItem = [[NSMenuItem alloc] initWithTitle:@"Quit"
            action:@selector(terminate:) keyEquivalent:@"q"];
        [menu addItem:quitMenuItem];
        [menuItem setSubmenu:menu];

        NSRect rect = NSMakeRect(0, 0, w, h);

        NSWindow* window = [[NSWindow alloc] initWithContentRect:rect
                styleMask:NSWindowStyleMaskTitled
                backing:NSBackingStoreBuffered
                defer:NO];
        window.styleMask |= NSWindowStyleMaskResizable;
        window.styleMask |= NSWindowStyleMaskMiniaturizable ;
        window.styleMask |= NSWindowStyleMaskClosable;
        window.title = name;
        window.displaysWhenScreenProfileChanges = YES;
        [window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
        [window setAcceptsMouseMovedEvents:YES];

        NSOpenGLPixelFormatAttribute attr[] = {
            NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
            NSOpenGLPFAColorSize,     24,
            NSOpenGLPFAAlphaSize,     8,
            NSOpenGLPFADepthSize,     16,
            NSOpenGLPFAAccelerated,
            NSOpenGLPFADoubleBuffer,
            NSOpenGLPFAAllowOfflineRenderers,
            0
        };
        id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
        view = [[ScreenGLView alloc] initWithFrame:rect pixelFormat:pixFormat];
        [window setContentView:view];
        [window setDelegate:view];
        [window makeFirstResponder:view];
    });

    return (uintptr_t)view;
}

void doShowWindow(uintptr_t viewID) {
    ScreenGLView* view = (ScreenGLView*)viewID;
    dispatch_async(dispatch_get_main_queue(), ^{
        [view.window makeKeyAndOrderFront:view.window];
    });
}

void doCloseWindow(uintptr_t viewID) {
    ScreenGLView* view = (ScreenGLView*)viewID;
    dispatch_sync(dispatch_get_main_queue(), ^{
        [view.window performClose:view];
    });
}

void startDriver() {
    [NSAutoreleasePool new];
    [NSApplication sharedApplication];
    [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
    AppDelegate* delegate = [[AppDelegate alloc] init];
    [NSApp setDelegate:delegate];
    [NSApp run];
}

void stopDriver() {
    dispatch_async(dispatch_get_main_queue(), ^{
        [NSApp terminate:nil];
    });
}


@gopherbot
Copy link

CL https://golang.org/cl/31539 mentions this issue.

gopherbot pushed a commit to golang/exp that referenced this issue Oct 20, 2016
…ted since OSX 10.12

Reason for revert: constants not available on older OS X releases

Original issue's description:
> shiny/driver: repace style mask and event constants deprecated since OSX 10.12
> 
> Fixes golang/go#17413.
> 
> Change-Id: I4cc8a980fc1d6a45ceef48b282baa7a94663ae10
> Reviewed-on: https://go-review.googlesource.com/31539
> Reviewed-by: David Crawshaw <crawshaw@golang.org>
> 

Change-Id: I35bd4301ebf63689d6b7bb49a29b9ef85657ba1e
Reviewed-on: https://go-review.googlesource.com/31613
Reviewed-by: David Crawshaw <crawshaw@golang.org>
@crawshaw crawshaw reopened this Oct 20, 2016
@gopherbot
Copy link

CL https://golang.org/cl/31543 mentions this issue.

@golang golang locked and limited conversation to collaborators Oct 21, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

5 participants