aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/devdraw/cocoa-screen.m
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2020-01-08 20:07:15 -0500
committerRuss Cox <rsc@swtch.com>2020-01-13 16:46:14 -0500
commit933b98054f40bb224acda134d7bb77a023bcc57f (patch)
tree9d8994836d92c20b52b126970347240c08de8ef6 /src/cmd/devdraw/cocoa-screen.m
parentce27d7babdf2ee09ff6d1f8d4a166c2208995774 (diff)
downloadplan9port-933b98054f40bb224acda134d7bb77a023bcc57f.tar.gz
plan9port-933b98054f40bb224acda134d7bb77a023bcc57f.tar.bz2
plan9port-933b98054f40bb224acda134d7bb77a023bcc57f.zip
devdraw: use consistent mac-* prefix on macOS files
We were using osx- and cocoa- but it's not even OS X anymore.
Diffstat (limited to 'src/cmd/devdraw/cocoa-screen.m')
-rw-r--r--src/cmd/devdraw/cocoa-screen.m1249
1 files changed, 0 insertions, 1249 deletions
diff --git a/src/cmd/devdraw/cocoa-screen.m b/src/cmd/devdraw/cocoa-screen.m
deleted file mode 100644
index 64b2bf4c..00000000
--- a/src/cmd/devdraw/cocoa-screen.m
+++ /dev/null
@@ -1,1249 +0,0 @@
-#define Cursor OSXCursor
-#define Point OSXPoint
-#define Rect OSXRect
-
-#import <Cocoa/Cocoa.h>
-#import <Metal/Metal.h>
-#import <QuartzCore/CAMetalLayer.h>
-
-#undef Cursor
-#undef Point
-#undef Rect
-
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include <memdraw.h>
-#include <keyboard.h>
-#include <cursor.h>
-#include "cocoa-screen.h"
-#include "osx-keycodes.h"
-#include "devdraw.h"
-#include "bigarrow.h"
-#include "glendapng.h"
-
-AUTOFRAMEWORK(Cocoa)
-AUTOFRAMEWORK(Metal)
-AUTOFRAMEWORK(QuartzCore)
-
-#define LOG if(0)NSLog
-
-static void setprocname(const char*);
-static uint keycvt(uint);
-static uint msec(void);
-static Memimage* initimg(void);
-
-void
-usage(void)
-{
- fprint(2, "usage: devdraw (don't run directly)\n");
- threadexitsall("usage");
-}
-
-
-@interface AppDelegate : NSObject<NSApplicationDelegate,NSWindowDelegate>
-+ (void)makewin:(NSValue *)v;
-+ (void)callkicklabel:(NSString *)v;
-+ (void)callsetNeedsDisplayInRect:(NSValue *)v;
-+ (void)callsetcursor:(NSValue *)v;
-@end
-@interface DevDrawView : NSView<NSTextInputClient>
-- (void)clearInput;
-- (void)getmouse:(NSEvent *)e;
-- (void)sendmouse:(NSUInteger)b;
-- (void)resetLastInputRect;
-- (void)enlargeLastInputRect:(NSRect)r;
-@end
-@interface DrawLayer : CAMetalLayer
-@end
-
-static AppDelegate *myApp = NULL;
-static DevDrawView *myContent = NULL;
-static NSWindow *win = NULL;
-static NSCursor *currentCursor = NULL;
-
-static DrawLayer *layer;
-static id<MTLDevice> device;
-static id<MTLCommandQueue> commandQueue;
-static id<MTLTexture> texture;
-
-static Memimage *img = NULL;
-
-static QLock snarfl;
-
-void
-threadmain(int argc, char **argv)
-{
- /*
- * Move the protocol off stdin/stdout so that
- * any inadvertent prints don't screw things up.
- */
- dup(0,3);
- dup(1,4);
- close(0);
- close(1);
- open("/dev/null", OREAD);
- open("/dev/null", OWRITE);
-
- ARGBEGIN{
- case 'D': /* for good ps -a listings */
- break;
- case 'f': /* fall through for backward compatibility */
- case 'g':
- case 'b':
- break;
- default:
- usage();
- }ARGEND
-
- setprocname(argv0);
-
- @autoreleasepool{
- [NSApplication sharedApplication];
- [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
- myApp = [AppDelegate new];
- [NSApp setDelegate:myApp];
- [NSApp run];
- }
-}
-
-
-void
-callservep9p(void *v)
-{
- USED(v);
-
- servep9p();
- [NSApp terminate:myApp];
-}
-
-@implementation AppDelegate
-
-+ (void)makewin:(NSValue *)v
-{
- NSRect r, sr;
- Rectangle wr;
- int set;
- char *s;
- NSArray *allDevices;
-
- const NSWindowStyleMask Winstyle = NSWindowStyleMaskTitled
- | NSWindowStyleMaskClosable
- | NSWindowStyleMaskMiniaturizable
- | NSWindowStyleMaskResizable;
-
- sr = [[NSScreen mainScreen] frame];
- r = [[NSScreen mainScreen] visibleFrame];
-
- s = [v pointerValue];
- LOG(@"makewin(%s)", s);
- if(s && *s){
- if(parsewinsize(s, &wr, &set) < 0)
- sysfatal("%r");
- }else{
- wr = Rect(0, 0, sr.size.width*2/3, sr.size.height*2/3);
- set = 0;
- }
-
- r.origin.x = wr.min.x;
- r.origin.y = sr.size.height-wr.max.y; /* winsize is top-left-based */
- r.size.width = fmin(Dx(wr), r.size.width);
- r.size.height = fmin(Dy(wr), r.size.height);
- r = [NSWindow contentRectForFrameRect:r styleMask:Winstyle];
-
- win = [[NSWindow alloc]
- initWithContentRect:r
- styleMask:Winstyle
- backing:NSBackingStoreBuffered defer:NO];
- [win setTitle:@"devdraw"];
-
- if(!set)
- [win center];
- [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
- [win setContentMinSize:NSMakeSize(64,64)];
- [win setOpaque:YES];
- [win setRestorable:NO];
- [win setAcceptsMouseMovedEvents:YES];
- [win setDelegate:myApp];
-
- myContent = [DevDrawView new];
- [win setContentView:myContent];
- [myContent setWantsLayer:YES];
- [myContent setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay];
-
- device = nil;
- allDevices = MTLCopyAllDevices();
- for(id mtlDevice in allDevices) {
- if ([mtlDevice isLowPower] && ![mtlDevice isRemovable]) {
- device = mtlDevice;
- break;
- }
- }
- if(!device)
- device = MTLCreateSystemDefaultDevice();
-
- commandQueue = [device newCommandQueue];
-
- layer = (DrawLayer *)[myContent layer];
- layer.device = device;
- layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
- layer.framebufferOnly = YES;
- layer.opaque = YES;
-
- // We use a default transparent layer on top of the CAMetalLayer.
- // This seems to make fullscreen applications behave.
- {
- CALayer *stub = [CALayer layer];
- stub.frame = CGRectMake(0, 0, 1, 1);
- [stub setNeedsDisplay];
- [layer addSublayer:stub];
- }
-
- [NSEvent setMouseCoalescingEnabled:NO];
-
- topwin();
-}
-
-+ (void)callkicklabel:(NSString *)s
-{
- LOG(@"callkicklabel(%@)", s);
- [win setTitle:s];
- [[NSApp dockTile] setBadgeLabel:s];
-}
-
-
-+ (void)callsetNeedsDisplayInRect:(NSValue *)v
-{
- NSRect r;
- dispatch_time_t time;
-
- r = [v rectValue];
- LOG(@"callsetNeedsDisplayInRect(%g, %g, %g, %g)", r.origin.x, r.origin.y, r.size.width, r.size.height);
- r = [win convertRectFromBacking:r];
- LOG(@"setNeedsDisplayInRect(%g, %g, %g, %g)", r.origin.x, r.origin.y, r.size.width, r.size.height);
- [layer setNeedsDisplayInRect:r];
-
- time = dispatch_time(DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC);
- dispatch_after(time, dispatch_get_main_queue(), ^(void){
- [layer setNeedsDisplayInRect:r];
- });
-
- [myContent enlargeLastInputRect:r];
-}
-
-typedef struct Cursors Cursors;
-struct Cursors {
- Cursor *c;
- Cursor2 *c2;
-};
-
-+ (void)callsetcursor:(NSValue *)v
-{
- Cursors *cs;
- Cursor *c;
- Cursor2 *c2;
- NSBitmapImageRep *r, *r2;
- NSImage *i;
- NSPoint p;
- uchar *plane[5], *plane2[5];
- uint b;
-
- cs = [v pointerValue];
- c = cs->c;
- if(!c)
- c = &bigarrow;
- c2 = cs->c2;
- if(!c2)
- c2 = &bigarrow2;
-
- r = [[NSBitmapImageRep alloc]
- initWithBitmapDataPlanes:nil
- pixelsWide:16
- pixelsHigh:16
- bitsPerSample:1
- samplesPerPixel:2
- hasAlpha:YES
- isPlanar:YES
- colorSpaceName:NSDeviceWhiteColorSpace
- bytesPerRow:2
- bitsPerPixel:0];
- [r getBitmapDataPlanes:plane];
- for(b=0; b<nelem(c->set); b++){
- plane[0][b] = ~c->set[b] & c->clr[b];
- plane[1][b] = c->set[b] | c->clr[b];
- }
-
- r2 = [[NSBitmapImageRep alloc]
- initWithBitmapDataPlanes:nil
- pixelsWide:32
- pixelsHigh:32
- bitsPerSample:1
- samplesPerPixel:2
- hasAlpha:YES
- isPlanar:YES
- colorSpaceName:NSDeviceWhiteColorSpace
- bytesPerRow:4
- bitsPerPixel:0];
- [r2 getBitmapDataPlanes:plane2];
- for(b=0; b<nelem(c2->set); b++){
- plane2[0][b] = ~c2->set[b] & c2->clr[b];
- plane2[1][b] = c2->set[b] | c2->clr[b];
- }
-
- // For checking out the cursor bitmap image
-/*
- static BOOL saveimg = YES;
- if(saveimg){
- NSData *data = [r representationUsingType: NSBitmapImageFileTypeBMP properties: @{}];
- [data writeToFile: @"/tmp/r.bmp" atomically: NO];
- data = [r2 representationUsingType: NSBitmapImageFileTypeBMP properties: @{}];
- [data writeToFile: @"/tmp/r2.bmp" atomically: NO];
- saveimg = NO;
- }
-*/
-
- i = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)];
- [i addRepresentation:r2];
- [i addRepresentation:r];
-
- p = NSMakePoint(-c->offset.x, -c->offset.y);
- currentCursor = [[NSCursor alloc] initWithImage:i hotSpot:p];
-
- [win invalidateCursorRectsForView:myContent];
-}
-
-- (void)applicationDidFinishLaunching:(id)arg
-{
- NSMenu *m, *sm;
- NSData *d;
- NSImage *i;
-
- LOG(@"applicationDidFinishLaunching");
-
- sm = [NSMenu new];
- [sm addItemWithTitle:@"Toggle Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
- [sm addItemWithTitle:@"Hide" action:@selector(hide:) keyEquivalent:@"h"];
- [sm addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
- m = [NSMenu new];
- [m addItemWithTitle:@"DEVDRAW" action:NULL keyEquivalent:@""];
- [m setSubmenu:sm forItem:[m itemWithTitle:@"DEVDRAW"]];
- [NSApp setMainMenu:m];
-
- d = [[NSData alloc] initWithBytes:glenda_png length:(sizeof glenda_png)];
- i = [[NSImage alloc] initWithData:d];
- [NSApp setApplicationIconImage:i];
- [[NSApp dockTile] display];
-
- proccreate(callservep9p, nil, 0);
-}
-
-- (NSApplicationPresentationOptions)window:(id)arg
- willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions {
- NSApplicationPresentationOptions o;
- o = proposedOptions;
- o &= ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar);
- o |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
- return o;
-}
-
-- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
- return YES;
-}
-
-- (void)windowDidResize:(NSNotification *)notification
-{
- if(![myContent inLiveResize] && img) {
- resizeimg();
- }
-}
-
-- (void)windowDidBecomeKey:(id)arg
-{
- [myContent sendmouse:0];
-}
-
-@end
-
-@implementation DevDrawView
-{
- NSMutableString *_tmpText;
- NSRange _markedRange;
- NSRange _selectedRange;
- NSRect _lastInputRect; // The view is flipped, this is not.
- BOOL _tapping;
- NSUInteger _tapFingers;
- NSUInteger _tapTime;
-}
-
-- (id)init
-{
- LOG(@"View init");
- self = [super init];
- [self setAllowedTouchTypes:NSTouchTypeMaskDirect|NSTouchTypeMaskIndirect];
- _tmpText = [[NSMutableString alloc] initWithCapacity:2];
- _markedRange = NSMakeRange(NSNotFound, 0);
- _selectedRange = NSMakeRange(0, 0);
- return self;
-}
-
-- (CALayer *)makeBackingLayer
-{
- LOG(@"makeBackingLayer");
- return [DrawLayer layer];
-}
-
-- (BOOL)wantsUpdateLayer
-{
- return YES;
-}
-
-- (BOOL)isOpaque
-{
- return YES;
-}
-
-- (BOOL)isFlipped
-{
- return YES;
-}
-
-- (BOOL)acceptsFirstResponder
-{
- return YES;
-}
-
-- (void)mouseMoved:(NSEvent*)e{ [self getmouse:e];}
-- (void)mouseDown:(NSEvent*)e{ [self getmouse:e];}
-- (void)mouseDragged:(NSEvent*)e{ [self getmouse:e];}
-- (void)mouseUp:(NSEvent*)e{ [self getmouse:e];}
-- (void)otherMouseDown:(NSEvent*)e{ [self getmouse:e];}
-- (void)otherMouseDragged:(NSEvent*)e{ [self getmouse:e];}
-- (void)otherMouseUp:(NSEvent*)e{ [self getmouse:e];}
-- (void)rightMouseDown:(NSEvent*)e{ [self getmouse:e];}
-- (void)rightMouseDragged:(NSEvent*)e{ [self getmouse:e];}
-- (void)rightMouseUp:(NSEvent*)e{ [self getmouse:e];}
-
-- (void)scrollWheel:(NSEvent*)e
-{
- NSInteger s;
-
- s = [e scrollingDeltaY];
- if(s > 0)
- [self sendmouse:8];
- else if (s < 0)
- [self sendmouse:16];
-}
-
-- (void)keyDown:(NSEvent*)e
-{
- LOG(@"keyDown to interpret");
-
- [self interpretKeyEvents:[NSArray arrayWithObject:e]];
-
- [self resetLastInputRect];
-}
-
-- (void)flagsChanged:(NSEvent*)e
-{
- static NSEventModifierFlags omod;
- NSEventModifierFlags m;
- uint b;
-
- LOG(@"flagsChanged");
- m = [e modifierFlags];
-
- b = [NSEvent pressedMouseButtons];
- b = (b&~6) | (b&4)>>1 | (b&2)<<1;
- if(b){
- if(m & ~omod & NSEventModifierFlagControl)
- b |= 1;
- if(m & ~omod & NSEventModifierFlagOption)
- b |= 2;
- if(m & ~omod & NSEventModifierFlagCommand)
- b |= 4;
- [self sendmouse:b];
- }else if(m & ~omod & NSEventModifierFlagOption)
- keystroke(Kalt);
-
- omod = m;
-}
-
-- (void)magnifyWithEvent:(NSEvent*)e
-{
- if(fabs([e magnification]) > 0.02)
- [[self window] toggleFullScreen:nil];
-}
-
-- (void)touchesBeganWithEvent:(NSEvent*)e
-{
- _tapping = YES;
- _tapFingers = [e touchesMatchingPhase:NSTouchPhaseTouching inView:nil].count;
- _tapTime = msec();
-}
-- (void)touchesMovedWithEvent:(NSEvent*)e
-{
- _tapping = NO;
-}
-- (void)touchesEndedWithEvent:(NSEvent*)e
-{
- if(_tapping
- && [e touchesMatchingPhase:NSTouchPhaseTouching inView:nil].count == 0
- && msec() - _tapTime < 250){
- switch(_tapFingers){
- case 3:
- [self sendmouse:2];
- [self sendmouse:0];
- break;
- case 4:
- [self sendmouse:2];
- [self sendmouse:1];
- [self sendmouse:0];
- break;
- }
- _tapping = NO;
- }
-}
-- (void)touchesCancelledWithEvent:(NSEvent*)e
-{
- _tapping = NO;
-}
-
-- (void)getmouse:(NSEvent *)e
-{
- NSUInteger b;
- NSEventModifierFlags m;
-
- b = [NSEvent pressedMouseButtons];
- b = b&~6 | (b&4)>>1 | (b&2)<<1;
- b = mouseswap(b);
-
- if(b == 1){
- m = [e modifierFlags];
- if(m & NSEventModifierFlagOption){
- abortcompose();
- b = 2;
- }else
- if(m & NSEventModifierFlagCommand)
- b = 4;
- }
- [self sendmouse:b];
-}
-
-- (void)sendmouse:(NSUInteger)b
-{
- NSPoint p;
-
- p = [self.window convertPointToBacking:
- [self.window mouseLocationOutsideOfEventStream]];
- p.y = Dy(mouserect) - p.y;
- // LOG(@"(%g, %g) <- sendmouse(%d)", p.x, p.y, (uint)b);
- mousetrack(p.x, p.y, b, msec());
- if(b && _lastInputRect.size.width && _lastInputRect.size.height)
- [self resetLastInputRect];
-}
-
-- (void)resetCursorRects {
- [super resetCursorRects];
- [self addCursorRect:self.bounds cursor:currentCursor];
-}
-
-- (void)viewDidEndLiveResize
-{
- [super viewDidEndLiveResize];
- if(img)
- resizeimg();
-}
-
-- (void)viewDidChangeBackingProperties
-{
- [super viewDidChangeBackingProperties];
- if(img)
- resizeimg();
-}
-
-// conforms to protocol NSTextInputClient
-- (BOOL)hasMarkedText
-{
- LOG(@"hasMarkedText");
- return _markedRange.location != NSNotFound;
-}
-- (NSRange)markedRange
-{
- LOG(@"markedRange");
- return _markedRange;
-}
-- (NSRange)selectedRange
-{
- LOG(@"selectedRange");
- return _selectedRange;
-}
-- (void)setMarkedText:(id)string
- selectedRange:(NSRange)sRange
- replacementRange:(NSRange)rRange
-{
- NSString *str;
-
- LOG(@"setMarkedText: %@ (%ld, %ld) (%ld, %ld)", string,
- sRange.location, sRange.length,
- rRange.location, rRange.length);
-
- [self clearInput];
-
- if([string isKindOfClass:[NSAttributedString class]])
- str = [string string];
- else
- str = string;
-
- if(rRange.location == NSNotFound){
- if(_markedRange.location != NSNotFound){
- rRange = _markedRange;
- }else{
- rRange = _selectedRange;
- }
- }
-
- if(str.length == 0){
- [_tmpText deleteCharactersInRange:rRange];
- [self unmarkText];
- }else{
- _markedRange = NSMakeRange(rRange.location, str.length);
- [_tmpText replaceCharactersInRange:rRange withString:str];
- }
- _selectedRange.location = rRange.location + sRange.location;
- _selectedRange.length = sRange.length;
-
- if(_tmpText.length){
- uint i;
- LOG(@"text length %ld", _tmpText.length);
- for(i = 0; i <= _tmpText.length; ++i){
- if(i == _markedRange.location)
- keystroke('[');
- if(_selectedRange.length){
- if(i == _selectedRange.location)
- keystroke('{');
- if(i == NSMaxRange(_selectedRange))
- keystroke('}');
- }
- if(i == NSMaxRange(_markedRange))
- keystroke(']');
- if(i < _tmpText.length)
- keystroke([_tmpText characterAtIndex:i]);
- }
- int l;
- l = 1 + _tmpText.length - NSMaxRange(_selectedRange)
- + (_selectedRange.length > 0);
- LOG(@"move left %d", l);
- for(i = 0; i < l; ++i)
- keystroke(Kleft);
- }
-
- LOG(@"text: \"%@\" (%ld,%ld) (%ld,%ld)", _tmpText,
- _markedRange.location, _markedRange.length,
- _selectedRange.location, _selectedRange.length);
-}
-- (void)unmarkText
-{
- //NSUInteger i;
- NSUInteger len;
-
- LOG(@"unmarkText");
- len = [_tmpText length];
- //for(i = 0; i < len; ++i)
- // keystroke([_tmpText characterAtIndex:i]);
- [_tmpText deleteCharactersInRange:NSMakeRange(0, len)];
- _markedRange = NSMakeRange(NSNotFound, 0);
- _selectedRange = NSMakeRange(0, 0);
-}
-- (NSArray<NSAttributedStringKey> *)validAttributesForMarkedText
-{
- LOG(@"validAttributesForMarkedText");
- return @[];
-}
-- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)r
- actualRange:(NSRangePointer)actualRange
-{
- NSRange sr;
- NSAttributedString *s;
-
- LOG(@"attributedSubstringForProposedRange: (%ld, %ld) (%ld, %ld)",
- r.location, r.length, actualRange->location, actualRange->length);
- sr = NSMakeRange(0, [_tmpText length]);
- sr = NSIntersectionRange(sr, r);
- if(actualRange)
- *actualRange = sr;
- LOG(@"use range: %ld, %ld", sr.location, sr.length);
- s = nil;
- if(sr.length)
- s = [[NSAttributedString alloc]
- initWithString:[_tmpText substringWithRange:sr]];
- LOG(@" return %@", s);
- return s;
-}
-- (void)insertText:(id)s
- replacementRange:(NSRange)r
-{
- NSUInteger i;
- NSUInteger len;
-
- LOG(@"insertText: %@ replacementRange: %ld, %ld", s, r.location, r.length);
-
- [self clearInput];
-
- len = [s length];
- for(i = 0; i < len; ++i)
- keystroke([s characterAtIndex:i]);
- [_tmpText deleteCharactersInRange:NSMakeRange(0, _tmpText.length)];
- _markedRange = NSMakeRange(NSNotFound, 0);
- _selectedRange = NSMakeRange(0, 0);
-}
-- (NSUInteger)characterIndexForPoint:(NSPoint)point
-{
- LOG(@"characterIndexForPoint: %g, %g", point.x, point.y);
- return 0;
-}
-- (NSRect)firstRectForCharacterRange:(NSRange)r
- actualRange:(NSRangePointer)actualRange
-{
- LOG(@"firstRectForCharacterRange: (%ld, %ld) (%ld, %ld)",
- r.location, r.length, actualRange->location, actualRange->length);
- if(actualRange)
- *actualRange = r;
- return [[self window] convertRectToScreen:_lastInputRect];
-}
-- (void)doCommandBySelector:(SEL)s
-{
- NSEvent *e;
- NSEventModifierFlags m;
- uint c, k;
-
- LOG(@"doCommandBySelector (%@)", NSStringFromSelector(s));
-
- e = [NSApp currentEvent];
- c = [[e characters] characterAtIndex:0];
- k = keycvt(c);
- LOG(@"keyDown: character0: 0x%x -> 0x%x", c, k);
- m = [e modifierFlags];
-
- if(m & NSEventModifierFlagCommand){
- if((m & NSEventModifierFlagShift) && 'a' <= k && k <= 'z')
- k += 'A' - 'a';
- if(' '<=k && k<='~')
- k += Kcmd;
- }
- if(k>0)
- keystroke(k);
-}
-
-// Helper for managing input rect approximately
-- (void)resetLastInputRect
-{
- LOG(@"resetLastInputRect");
- _lastInputRect.origin.x = 0.0;
- _lastInputRect.origin.y = 0.0;
- _lastInputRect.size.width = 0.0;
- _lastInputRect.size.height = 0.0;
-}
-
-- (void)enlargeLastInputRect:(NSRect)r
-{
- r.origin.y = [self bounds].size.height - r.origin.y - r.size.height;
- _lastInputRect = NSUnionRect(_lastInputRect, r);
- LOG(@"update last input rect (%g, %g, %g, %g)",
- _lastInputRect.origin.x, _lastInputRect.origin.y,
- _lastInputRect.size.width, _lastInputRect.size.height);
-}
-
-- (void)clearInput
-{
- if(_tmpText.length){
- uint i;
- int l;
- l = 1 + _tmpText.length - NSMaxRange(_selectedRange)
- + (_selectedRange.length > 0);
- LOG(@"move right %d", l);
- for(i = 0; i < l; ++i)
- keystroke(Kright);
- l = _tmpText.length+2+2*(_selectedRange.length > 0);
- LOG(@"backspace %d", l);
- for(uint i = 0; i < l; ++i)
- keystroke(Kbs);
- }
-}
-
-@end
-
-@implementation DrawLayer
-
-- (void)display
-{
- id<MTLCommandBuffer> cbuf;
- id<MTLBlitCommandEncoder> blit;
-
- LOG(@"display");
-
- cbuf = [commandQueue commandBuffer];
-
- LOG(@"display query drawable");
-
-@autoreleasepool{
- id<CAMetalDrawable> drawable;
-
- drawable = [layer nextDrawable];
- if(!drawable){
- LOG(@"display couldn't get drawable");
- [self setNeedsDisplay];
- return;
- }
-
- LOG(@"display got drawable");
-
- blit = [cbuf blitCommandEncoder];
- [blit copyFromTexture:texture
- sourceSlice:0
- sourceLevel:0
- sourceOrigin:MTLOriginMake(0, 0, 0)
- sourceSize:MTLSizeMake(texture.width, texture.height, texture.depth)
- toTexture:drawable.texture
- destinationSlice:0
- destinationLevel:0
- destinationOrigin:MTLOriginMake(0, 0, 0)];
- [blit endEncoding];
-
- [cbuf presentDrawable:drawable];
- drawable = nil;
-}
- [cbuf addCompletedHandler:^(id<MTLCommandBuffer> cmdBuff){
- if(cmdBuff.error){
- NSLog(@"command buffer finished with error: %@",
- cmdBuff.error.localizedDescription);
- }else
- LOG(@"command buffer finishes present drawable");
- }];
- [cbuf commit];
-
- LOG(@"display commit");
-}
-
-@end
-
-static uint
-msec(void)
-{
- return nsec()/1000000;
-}
-
-static uint
-keycvt(uint code)
-{
- switch(code){
- case '\r': return '\n';
- case 127: return '\b';
- case NSUpArrowFunctionKey: return Kup;
- case NSDownArrowFunctionKey: return Kdown;
- case NSLeftArrowFunctionKey: return Kleft;
- case NSRightArrowFunctionKey: return Kright;
- case NSInsertFunctionKey: return Kins;
- case NSDeleteFunctionKey: return Kdel;
- case NSHomeFunctionKey: return Khome;
- case NSEndFunctionKey: return Kend;
- case NSPageUpFunctionKey: return Kpgup;
- case NSPageDownFunctionKey: return Kpgdown;
- case NSF1FunctionKey: return KF|1;
- case NSF2FunctionKey: return KF|2;
- case NSF3FunctionKey: return KF|3;
- case NSF4FunctionKey: return KF|4;
- case NSF5FunctionKey: return KF|5;
- case NSF6FunctionKey: return KF|6;
- case NSF7FunctionKey: return KF|7;
- case NSF8FunctionKey: return KF|8;
- case NSF9FunctionKey: return KF|9;
- case NSF10FunctionKey: return KF|10;
- case NSF11FunctionKey: return KF|11;
- case NSF12FunctionKey: return KF|12;
- case NSBeginFunctionKey:
- case NSPrintScreenFunctionKey:
- case NSScrollLockFunctionKey:
- case NSF13FunctionKey:
- case NSF14FunctionKey:
- case NSF15FunctionKey:
- case NSF16FunctionKey:
- case NSF17FunctionKey:
- case NSF18FunctionKey:
- case NSF19FunctionKey:
- case NSF20FunctionKey:
- case NSF21FunctionKey:
- case NSF22FunctionKey:
- case NSF23FunctionKey:
- case NSF24FunctionKey:
- case NSF25FunctionKey:
- case NSF26FunctionKey:
- case NSF27FunctionKey:
- case NSF28FunctionKey:
- case NSF29FunctionKey:
- case NSF30FunctionKey:
- case NSF31FunctionKey:
- case NSF32FunctionKey:
- case NSF33FunctionKey:
- case NSF34FunctionKey:
- case NSF35FunctionKey:
- case NSPauseFunctionKey:
- case NSSysReqFunctionKey:
- case NSBreakFunctionKey:
- case NSResetFunctionKey:
- case NSStopFunctionKey:
- case NSMenuFunctionKey:
- case NSUserFunctionKey:
- case NSSystemFunctionKey:
- case NSPrintFunctionKey:
- case NSClearLineFunctionKey:
- case NSClearDisplayFunctionKey:
- case NSInsertLineFunctionKey:
- case NSDeleteLineFunctionKey:
- case NSInsertCharFunctionKey:
- case NSDeleteCharFunctionKey:
- case NSPrevFunctionKey:
- case NSNextFunctionKey:
- case NSSelectFunctionKey:
- case NSExecuteFunctionKey:
- case NSUndoFunctionKey:
- case NSRedoFunctionKey:
- case NSFindFunctionKey:
- case NSHelpFunctionKey:
- case NSModeSwitchFunctionKey: return 0;
- default: return code;
- }
-}
-
-Memimage*
-attachscreen(char *label, char *winsize)
-{
- LOG(@"attachscreen(%s, %s)", label, winsize);
- [AppDelegate
- performSelectorOnMainThread:@selector(makewin:)
- withObject:[NSValue valueWithPointer:winsize]
- waitUntilDone:YES];
- kicklabel(label);
- setcursor(nil, nil);
- mouseresized = 0;
- return initimg();
-}
-
-static Memimage*
-initimg(void)
-{
-@autoreleasepool{
- CGFloat scale;
- NSSize size;
- MTLTextureDescriptor *textureDesc;
-
- size = [myContent convertSizeToBacking:[myContent bounds].size];
- mouserect = Rect(0, 0, size.width, size.height);
-
- LOG(@"initimg %.0f %.0f", size.width, size.height);
-
- img = allocmemimage(mouserect, XRGB32);
- if(img == nil)
- panic("allocmemimage: %r");
- if(img->data == nil)
- panic("img->data == nil");
-
- textureDesc = [MTLTextureDescriptor
- texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
- width:size.width
- height:size.height
- mipmapped:NO];
- textureDesc.allowGPUOptimizedContents = YES;
- textureDesc.usage = MTLTextureUsageShaderRead;
- textureDesc.cpuCacheMode = MTLCPUCacheModeWriteCombined;
- texture = [device newTextureWithDescriptor:textureDesc];
-
- scale = [win backingScaleFactor];
- [layer setDrawableSize:size];
- [layer setContentsScale:scale];
-
- // NOTE: This is not really the display DPI.
- // On retina, scale is 2; otherwise it is 1.
- // This formula gives us 220 for retina, 110 otherwise.
- // That's not quite right but it's close to correct.
- // https://en.wikipedia.org/wiki/Retina_display#Models
- displaydpi = scale * 110;
-}
- LOG(@"initimg return");
-
- return img;
-}
-
-void
-_flushmemscreen(Rectangle r)
-{
- LOG(@"_flushmemscreen(%d,%d,%d,%d)", r.min.x, r.min.y, Dx(r), Dy(r));
- if(!rectinrect(r, Rect(0, 0, texture.width, texture.height))){
- LOG(@"Rectangle is out of bounds, return.");
- return;
- }
-
- @autoreleasepool{
- [texture
- replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r))
- mipmapLevel:0
- withBytes:byteaddr(img, Pt(r.min.x, r.min.y))
- bytesPerRow:img->width*sizeof(u32int)];
- [AppDelegate
- performSelectorOnMainThread:@selector(callsetNeedsDisplayInRect:)
- withObject:[NSValue valueWithRect:NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r))]
- waitUntilDone:NO];
- }
-}
-
-void
-setmouse(Point p)
-{
- @autoreleasepool{
- NSPoint q;
-
- LOG(@"setmouse(%d,%d)", p.x, p.y);
- q = [win convertPointFromBacking:NSMakePoint(p.x, p.y)];
- LOG(@"(%g, %g) <- fromBacking", q.x, q.y);
- q = [myContent convertPoint:q toView:nil];
- LOG(@"(%g, %g) <- toWindow", q.x, q.y);
- q = [win convertPointToScreen:q];
- LOG(@"(%g, %g) <- toScreen", q.x, q.y);
- // Quartz has the origin of the "global display
- // coordinate space" at the top left of the primary
- // screen with y increasing downward, while Cocoa has
- // the origin at the bottom left of the primary screen
- // with y increasing upward. We flip the coordinate
- // with a negative sign and shift upward by the height
- // of the primary screen.
- q.y = NSScreen.screens[0].frame.size.height - q.y;
- LOG(@"(%g, %g) <- setmouse", q.x, q.y);
- CGWarpMouseCursorPosition(NSPointToCGPoint(q));
- CGAssociateMouseAndMouseCursorPosition(true);
- }
-}
-
-char*
-getsnarf(void)
-{
- NSPasteboard *pb;
- NSString *s;
-
- @autoreleasepool{
- pb = [NSPasteboard generalPasteboard];
-
- qlock(&snarfl);
- s = [pb stringForType:NSPasteboardTypeString];
- qunlock(&snarfl);
-
- if(s)
- return strdup((char *)[s UTF8String]);
- else
- return nil;
- }
-}
-
-void
-putsnarf(char *s)
-{
- NSArray *t;
- NSPasteboard *pb;
- NSString *str;
-
- if(strlen(s) >= SnarfSize)
- return;
-
- @autoreleasepool{
- t = [NSArray arrayWithObject:NSPasteboardTypeString];
- pb = [NSPasteboard generalPasteboard];
- str = [[NSString alloc] initWithUTF8String:s];
-
- qlock(&snarfl);
- [pb declareTypes:t owner:nil];
- [pb setString:str forType:NSPasteboardTypeString];
- qunlock(&snarfl);
- }
-}
-
-void
-kicklabel(char *label)
-{
- NSString *s;
-
- LOG(@"kicklabel(%s)", label);
- if(label == nil)
- return;
-
- @autoreleasepool{
- s = [[NSString alloc] initWithUTF8String:label];
- [AppDelegate
- performSelectorOnMainThread:@selector(callkicklabel:)
- withObject:s
- waitUntilDone:NO];
- }
-}
-
-void
-setcursor(Cursor *c, Cursor2 *c2)
-{
- Cursors cs;
-
- cs.c = c;
- cs.c2 = c2;
-
- [AppDelegate
- performSelectorOnMainThread:@selector(callsetcursor:)
- withObject:[NSValue valueWithPointer:&cs]
- waitUntilDone:YES];
-}
-
-void
-topwin(void)
-{
- [win
- performSelectorOnMainThread:
- @selector(makeKeyAndOrderFront:)
- withObject:nil
- waitUntilDone:YES];
-
- [NSApp activateIgnoringOtherApps:YES];
-}
-
-void
-resizeimg(void)
-{
- zlock();
- _drawreplacescreenimage(initimg());
-
- mouseresized = 1;
- zunlock();
- [myContent sendmouse:0];
-}
-
-void
-resizewindow(Rectangle r)
-{
- LOG(@"resizewindow %d %d %d %d", r.min.x, r.min.y, Dx(r), Dy(r));
- dispatch_async(dispatch_get_main_queue(), ^(void){
- NSSize s;
-
- s = [myContent convertSizeFromBacking:NSMakeSize(Dx(r), Dy(r))];
- [win setContentSize:s];
- });
-}
-
-static void
-setprocname(const char *s)
-{
- CFStringRef process_name;
-
- process_name = CFStringCreateWithBytes(nil, (uchar*)s, strlen(s), kCFStringEncodingUTF8, false);
-
- // Adapted from Chrome's mac_util.mm.
- // http://src.chromium.org/viewvc/chrome/trunk/src/base/mac/mac_util.mm
- //
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- // Warning: here be dragons! This is SPI reverse-engineered from WebKit's
- // plugin host, and could break at any time (although realistically it's only
- // likely to break in a new major release).
- // When 10.7 is available, check that this still works, and update this
- // comment for 10.8.
-
- // Private CFType used in these LaunchServices calls.
- typedef CFTypeRef PrivateLSASN;
- typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
- typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
- CFStringRef,
- CFStringRef,
- CFDictionaryRef*);
-
- static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
- NULL;
- static LSSetApplicationInformationItemType
- ls_set_application_information_item_func = NULL;
- static CFStringRef ls_display_name_key = NULL;
-
- static bool did_symbol_lookup = false;
- if (!did_symbol_lookup) {
- did_symbol_lookup = true;
- CFBundleRef launch_services_bundle =
- CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
- if (!launch_services_bundle) {
- fprint(2, "Failed to look up LaunchServices bundle\n");
- return;
- }
-
- ls_get_current_application_asn_func =
- (LSGetCurrentApplicationASNType)(
- CFBundleGetFunctionPointerForName(
- launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
- if (!ls_get_current_application_asn_func)
- fprint(2, "Could not find _LSGetCurrentApplicationASN\n");
-
- ls_set_application_information_item_func =
- (LSSetApplicationInformationItemType)(
- CFBundleGetFunctionPointerForName(
- launch_services_bundle,
- CFSTR("_LSSetApplicationInformationItem")));
- if (!ls_set_application_information_item_func)
- fprint(2, "Could not find _LSSetApplicationInformationItem\n");
-
- CFStringRef* key_pointer = (CFStringRef*)(
- CFBundleGetDataPointerForName(launch_services_bundle,
- CFSTR("_kLSDisplayNameKey")));
- ls_display_name_key = key_pointer ? *key_pointer : NULL;
- if (!ls_display_name_key)
- fprint(2, "Could not find _kLSDisplayNameKey\n");
-
- // Internally, this call relies on the Mach ports that are started up by the
- // Carbon Process Manager. In debug builds this usually happens due to how
- // the logging layers are started up; but in release, it isn't started in as
- // much of a defined order. So if the symbols had to be loaded, go ahead
- // and force a call to make sure the manager has been initialized and hence
- // the ports are opened.
- ProcessSerialNumber psn;
- GetCurrentProcess(&psn);
- }
- if (!ls_get_current_application_asn_func ||
- !ls_set_application_information_item_func ||
- !ls_display_name_key) {
- return;
- }
-
- PrivateLSASN asn = ls_get_current_application_asn_func();
- // Constant used by WebKit; what exactly it means is unknown.
- const int magic_session_constant = -2;
- OSErr err =
- ls_set_application_information_item_func(magic_session_constant, asn,
- ls_display_name_key,
- process_name,
- NULL /* optional out param */);
- if(err != noErr)
- fprint(2, "Call to set process name failed\n");
-}