#define Rect RectC#import <Cocoa/Cocoa.h>#import <Metal/Metal.h>#import <QuartzCore/CAMetalLayer.h>#undef Rect #undef nil#define Point Point9#include "u.h"#include "lib.h"#include "kern/dat.h"#include "kern/fns.h"#include "error.h"#include "user.h"#include <draw.h>#include <memdraw.h>#include "screen.h"#include "keyboard.h" #ifndef DEBUG#define DEBUG 0#endif#define LOG(fmt, ...) if(DEBUG)NSLog((@"%s:%d %s " fmt), __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) Memimage *gscreen; @interface DrawLayer : CAMetalLayer@property id<MTLTexture> texture;@end @interface DrawtermView : NSView<NSTextInputClient>- (void)reshape;- (void)clearMods;- (void)clearInput;- (void)mouseevent:(NSEvent *)e;- (void)resetLastInputRect;- (void)enlargeLastInputRect:(NSRect)r;@end @interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>@end static AppDelegate *myApp;static DrawtermView *myview;static NSCursor *currentCursor; static ulong pal[256]; static int readybit;static Rendez rend; static intisready(void*a){ return readybit;} voidguimain(void){ LOG(); @autoreleasepool{ [NSApplication sharedApplication]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; myApp = [AppDelegate new]; [NSApp setDelegate:myApp]; [NSApp run]; }} voidscreeninit(void){ memimageinit(); NSSize s = [myview convertSizeToBacking:myview.frame.size]; screensize(Rect(0, 0, s.width, s.height), ARGB32); gscreen->clipr = Rect(0, 0, s.width, s.height); LOG(@"%g %g", s.width, s.height); terminit(); readybit = 1; wakeup(&rend);} voidscreensize(Rectangle r, ulong chan){ Memimage *i; if((i = allocmemimage(r, chan)) == nil) return; if(gscreen != nil) freememimage(gscreen);@autoreleasepool{ DrawLayer *layer = (DrawLayer *)myview.layer; MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm width:Dx(r) height:Dy(r) mipmapped:NO]; textureDesc.allowGPUOptimizedContents = YES; textureDesc.usage = MTLTextureUsageShaderRead; textureDesc.cpuCacheMode = MTLCPUCacheModeWriteCombined; layer.texture = [layer.device newTextureWithDescriptor:textureDesc]; CGFloat scale = myview.window.backingScaleFactor; [layer setDrawableSize:NSMakeSize(Dx(r), Dy(r))]; [layer setContentsScale:scale];} gscreen = i; gscreen->clipr = ZR;} Memdata*attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen){ LOG(); *r = gscreen->clipr; *chan = gscreen->chan; *depth = gscreen->depth; *width = gscreen->width; *softscreen = 1; gscreen->data->ref++; return gscreen->data;} char *clipread(void){ @autoreleasepool{ NSPasteboard *pb = [NSPasteboard generalPasteboard]; NSString *s = [pb stringForType:NSPasteboardTypeString]; if(s) return strdup([s UTF8String]); } return nil;} intclipwrite(char *buf){ @autoreleasepool{ NSString *s = [[NSString alloc] initWithUTF8String:buf]; NSPasteboard *pb = [NSPasteboard generalPasteboard]; [pb clearContents]; [pb writeObjects:@[s]]; } return strlen(buf);} voidflushmemscreen(Rectangle r){ LOG(@"<- %d %d %d %d", r.min.x, r.min.y, Dx(r), Dy(r)); if(rectclip(&r, gscreen->clipr) == 0) return; LOG(@"-> %d %d %d %d", r.min.x, r.min.y, Dx(r), Dy(r)); @autoreleasepool{ [((DrawLayer *)myview.layer).texture replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r)) mipmapLevel:0 withBytes:byteaddr(gscreen, Pt(r.min.x, r.min.y)) bytesPerRow:gscreen->width * 4]; NSRect sr = [[myview window] convertRectFromBacking:NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r))]; dispatch_async(dispatch_get_main_queue(), ^(void){@autoreleasepool{ LOG(@"setNeedsDisplayInRect %g %g %g %g", sr.origin.x, sr.origin.y, sr.size.width, sr.size.height); [myview setNeedsDisplayInRect:sr]; [myview enlargeLastInputRect:sr]; }}); // ReplaceRegion is somehow asynchronous since 10.14.5. We wait sometime to request a update again. dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 8 * NSEC_PER_MSEC); dispatch_after(time, dispatch_get_main_queue(), ^(void){@autoreleasepool{ LOG(@"setNeedsDisplayInRect %g %g %g %g again", sr.origin.x, sr.origin.y, sr.size.width, sr.size.height); [myview setNeedsDisplayInRect:sr]; }}); time = dispatch_time(DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC); dispatch_after(time, dispatch_get_main_queue(), ^(void){@autoreleasepool{ LOG(@"setNeedsDisplayInRect %g %g %g %g again", sr.origin.x, sr.origin.y, sr.size.width, sr.size.height); [myview setNeedsDisplayInRect:sr]; }}); }} voidgetcolor(ulong i, ulong *r, ulong *g, ulong *b){ ulong v; v = pal[i]; *r = (v>>16)&0xFF; *g = (v>>8)&0xFF; *b = v&0xFF;} voidsetcolor(ulong i, ulong r, ulong g, ulong b){ pal[i] = ((r&0xFF)<<16) & ((g&0xFF)<<8) & (b&0xFF);} voidsetcursor(void){ static unsigned char data[64], data2[256]; unsigned char *planes[2] = {&data[0], &data[32]}; unsigned char *planes2[2] = {&data2[0], &data2[128]}; unsigned int i, x, y, a; unsigned char pu, pb, pl, pr, pc; // upper, bottom, left, right, center unsigned char pul, pur, pbl, pbr; unsigned char ful, fur, fbl, fbr; lock(&cursor.lk); for(i = 0; i < 32; i++){ data[i] = ~cursor.set[i] & cursor.clr[i]; data[i+32] = cursor.set[i] | cursor.clr[i]; } for(a=0; a<2; a++){ for(y=0; y<16; y++){ for(x=0; x<2; x++){ pc = planes[a][x+2*y]; pu = y==0 ? pc : planes[a][x+2*(y-1)]; pb = y==15 ? pc : planes[a][x+2*(y+1)]; pl = (pc>>1) | (x==0 ? pc&0x80 : (planes[a][x-1+2*y]&1)<<7); pr = (pc<<1) | (x==1 ? pc&1 : (planes[a][x+1+2*y]&0x80)>>7); ful = ~(pl^pu) & (pl^pb) & (pu^pr); pul = (ful & pu) | (~ful & pc); fur = ~(pu^pr) & (pu^pl) & (pr^pb); pur = (fur & pr) | (~fur & pc); fbl = ~(pb^pl) & (pb^pr) & (pl^pu); pbl = (fbl & pl) | (~fbl & pc); fbr = ~(pr^pb) & (pr^pu) & (pb^pl); pbr = (fbr & pb) | (~fbr & pc); planes2[a][2*x+4*2*y] = (pul&0x80) | ((pul&0x40)>>1) | ((pul&0x20)>>2) | ((pul&0x10)>>3) | ((pur&0x80)>>1) | ((pur&0x40)>>2) | ((pur&0x20)>>3) | ((pur&0x10)>>4); planes2[a][2*x+1+4*2*y] = ((pul&0x8)<<4) | ((pul&0x4)<<3) | ((pul&0x2)<<2) | ((pul&0x1)<<1) | ((pur&0x8)<<3) | ((pur&0x4)<<2) | ((pur&0x2)<<1) | (pur&0x1); planes2[a][2*x+4*(2*y+1)] = (pbl&0x80) | ((pbl&0x40)>>1) | ((pbl&0x20)>>2) | ((pbl&0x10)>>3) | ((pbr&0x80)>>1) | ((pbr&0x40)>>2) | ((pbr&0x20)>>3) | ((pbr&0x10)>>4); planes2[a][2*x+1+4*(2*y+1)] = ((pbl&0x8)<<4) | ((pbl&0x4)<<3) | ((pbl&0x2)<<2) | ((pbl&0x1)<<1) | ((pbr&0x8)<<3) | ((pbr&0x4)<<2) | ((pbr&0x2)<<1) | (pbr&0x1); } } } NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:planes pixelsWide:16 pixelsHigh:16 bitsPerSample:1 samplesPerPixel:2 hasAlpha:YES isPlanar:YES colorSpaceName:NSDeviceWhiteColorSpace bitmapFormat:0 bytesPerRow:2 bitsPerPixel:0]; NSBitmapImageRep *rep2 = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:planes2 pixelsWide:32 pixelsHigh:32 bitsPerSample:1 samplesPerPixel:2 hasAlpha:YES isPlanar:YES colorSpaceName:NSDeviceWhiteColorSpace bitmapFormat:0 bytesPerRow:4 bitsPerPixel:0]; NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)]; [img addRepresentation:rep2]; [img addRepresentation:rep]; currentCursor = [[NSCursor alloc] initWithImage:img hotSpot:NSMakePoint(-cursor.offset.x, -cursor.offset.y)]; unlock(&cursor.lk); dispatch_async(dispatch_get_main_queue(), ^(void){ [[myview window] invalidateCursorRectsForView:myview]; });} voidmouseset(Point p){ dispatch_async(dispatch_get_main_queue(), ^(void){@autoreleasepool{ NSPoint s; if([[myview window] isKeyWindow]){ s = NSMakePoint(p.x, p.y); LOG(@"-> pixel %g %g", s.x, s.y); s = [[myview window] convertPointFromBacking:s]; LOG(@"-> point %g %g", s.x, s.y); s = [myview convertPoint:s toView:nil]; LOG(@"-> window %g %g", s.x, s.y); s = [[myview window] convertPointToScreen: s]; LOG(@"(%g, %g) <- toScreen", s.x, s.y); s.y = NSScreen.screens[0].frame.size.height - s.y; LOG(@"(%g, %g) <- setmouse", s.x, s.y); CGWarpMouseCursorPosition(s); CGAssociateMouseAndMouseCursorPosition(true); } }});} @implementation AppDelegate{ NSWindow *_window;} static voidmainproc(void *aux){ cpubody();} - (void) applicationDidFinishLaunching:(NSNotification *)aNotification{ LOG(@"BEGIN"); NSMenu *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"]; NSMenu *m = [NSMenu new]; [m addItemWithTitle:@"DEVDRAW" action:NULL keyEquivalent:@""]; [m setSubmenu:sm forItem:[m itemWithTitle:@"DEVDRAW"]]; [NSApp setMainMenu:m]; const NSWindowStyleMask Winstyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; NSRect r = [[NSScreen mainScreen] visibleFrame]; r.size.width = r.size.width*3/4; r.size.height = r.size.height*3/4; r = [NSWindow contentRectForFrameRect:r styleMask:Winstyle]; _window = [[NSWindow alloc] initWithContentRect:r styleMask:Winstyle backing:NSBackingStoreBuffered defer:NO]; [_window setTitle:@"drawterm"]; [_window center]; [_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; [_window setContentMinSize:NSMakeSize(64,64)]; [_window setOpaque:YES]; [_window setRestorable:NO]; [_window setAcceptsMouseMovedEvents:YES]; [_window setDelegate:self]; myview = [DrawtermView new]; [_window setContentView:myview]; [NSEvent setMouseCoalescingEnabled:NO]; setcursor(); [_window makeKeyAndOrderFront:self]; [NSApp activateIgnoringOtherApps:YES]; LOG(@"launch mainproc"); kproc("mainproc", mainproc, 0); ksleep(&rend, isready, 0);} - (NSApplicationPresentationOptions) window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions{ NSApplicationPresentationOptions o; o = proposedOptions; o &= ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar); o |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; return o;} - (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication{ return YES;} - (void) windowDidBecomeKey:(id)arg{ NSPoint p; p = [_window convertPointToBacking:[_window mouseLocationOutsideOfEventStream]]; absmousetrack(p.x, [myview convertSizeToBacking:myview.frame.size].height - p.y, 0, ticks());} - (void) windowDidResignKey:(id)arg{ [myview clearMods];} @end @implementation DrawtermView{ NSMutableString *_tmpText; NSRange _markedRange; NSRange _selectedRange; NSRect _lastInputRect; // The view is flipped, this is not. BOOL _tapping; NSUInteger _tapFingers; NSUInteger _tapTime; BOOL _breakcompose; NSEventModifierFlags _mods;} - (id) initWithFrame:(NSRect)fr{ LOG(@"BEGIN"); self = [super initWithFrame:fr]; [self setWantsLayer:YES]; [self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay]; [self setAllowedTouchTypes:NSTouchTypeMaskDirect|NSTouchTypeMaskIndirect]; _tmpText = [[NSMutableString alloc] initWithCapacity:2]; _markedRange = NSMakeRange(NSNotFound, 0); _selectedRange = NSMakeRange(0, 0); _breakcompose = NO; _mods = 0; LOG(@"END"); return self;} - (CALayer *) makeBackingLayer{ return [DrawLayer layer];} - (BOOL)wantsUpdateLayer{ return YES;} - (BOOL)isOpaque{ return YES;} - (BOOL)isFlipped{ return YES;} static uintevkey(uint v){ switch(v){ 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 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 NSInsertFunctionKey: return Kins; case NSDeleteFunctionKey: return Kdel; case NSHomeFunctionKey: return Khome; case NSEndFunctionKey: return Kend; case NSPageUpFunctionKey: return Kpgup; case NSPageDownFunctionKey: return Kpgdown; case NSScrollLockFunctionKey: return Kscroll; case NSBeginFunctionKey: 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 NSPrintScreenFunctionKey: case NSPauseFunctionKey: case NSSysReqFunctionKey: case NSBreakFunctionKey: case NSResetFunctionKey: case NSStopFunctionKey: case NSMenuFunctionKey: case NSUserFunctionKey:Lines 1–500 of 959. Load more
#define Rect RectC #import <Cocoa/Cocoa.h> #import <Metal/Metal.h> #import <QuartzCore/CAMetalLayer.h> #undef Rect #undef nil #define Point Point9 #include "u.h" #include "lib.h" #include "kern/dat.h" #include "kern/fns.h" #include "error.h" #include "user.h" #include <draw.h> #include <memdraw.h> #include "screen.h" #include "keyboard.h" #ifndef DEBUG #define DEBUG 0 #endif #define LOG(fmt, ...) if(DEBUG)NSLog((@"%s:%d %s " fmt), __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) Memimage *gscreen; @interface DrawLayer : CAMetalLayer @property id<MTLTexture> texture; @end @interface DrawtermView : NSView<NSTextInputClient> - (void)reshape; - (void)clearMods; - (void)clearInput; - (void)mouseevent:(NSEvent *)e; - (void)resetLastInputRect; - (void)enlargeLastInputRect:(NSRect)r; @end @interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate> @end static AppDelegate *myApp; static DrawtermView *myview; static NSCursor *currentCursor; static ulong pal[256]; static int readybit; static Rendez rend; static int isready(void*a) { return readybit; } void guimain(void) { LOG(); @autoreleasepool{ [NSApplication sharedApplication]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; myApp = [AppDelegate new]; [NSApp setDelegate:myApp]; [NSApp run]; } } void screeninit(void) { memimageinit(); NSSize s = [myview convertSizeToBacking:myview.frame.size]; screensize(Rect(0, 0, s.width, s.height), ARGB32); gscreen->clipr = Rect(0, 0, s.width, s.height); LOG(@"%g %g", s.width, s.height); terminit(); readybit = 1; wakeup(&rend); } void screensize(Rectangle r, ulong chan) { Memimage *i; if((i = allocmemimage(r, chan)) == nil) return; if(gscreen != nil) freememimage(gscreen); @autoreleasepool{ DrawLayer *layer = (DrawLayer *)myview.layer; MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm width:Dx(r) height:Dy(r) mipmapped:NO]; textureDesc.allowGPUOptimizedContents = YES; textureDesc.usage = MTLTextureUsageShaderRead; textureDesc.cpuCacheMode = MTLCPUCacheModeWriteCombined; layer.texture = [layer.device newTextureWithDescriptor:textureDesc]; CGFloat scale = myview.window.backingScaleFactor; [layer setDrawableSize:NSMakeSize(Dx(r), Dy(r))]; [layer setContentsScale:scale]; } gscreen = i; gscreen->clipr = ZR; } Memdata* attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen) { LOG(); *r = gscreen->clipr; *chan = gscreen->chan; *depth = gscreen->depth; *width = gscreen->width; *softscreen = 1; gscreen->data->ref++; return gscreen->data; } char * clipread(void) { @autoreleasepool{ NSPasteboard *pb = [NSPasteboard generalPasteboard]; NSString *s = [pb stringForType:NSPasteboardTypeString]; if(s) return strdup([s UTF8String]); } return nil; } int clipwrite(char *buf) { @autoreleasepool{ NSString *s = [[NSString alloc] initWithUTF8String:buf]; NSPasteboard *pb = [NSPasteboard generalPasteboard]; [pb clearContents]; [pb writeObjects:@[s]]; } return strlen(buf); } void flushmemscreen(Rectangle r) { LOG(@"<- %d %d %d %d", r.min.x, r.min.y, Dx(r), Dy(r)); if(rectclip(&r, gscreen->clipr) == 0) return; LOG(@"-> %d %d %d %d", r.min.x, r.min.y, Dx(r), Dy(r)); @autoreleasepool{ [((DrawLayer *)myview.layer).texture replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r)) mipmapLevel:0 withBytes:byteaddr(gscreen, Pt(r.min.x, r.min.y)) bytesPerRow:gscreen->width * 4]; NSRect sr = [[myview window] convertRectFromBacking:NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r))]; dispatch_async(dispatch_get_main_queue(), ^(void){@autoreleasepool{ LOG(@"setNeedsDisplayInRect %g %g %g %g", sr.origin.x, sr.origin.y, sr.size.width, sr.size.height); [myview setNeedsDisplayInRect:sr]; [myview enlargeLastInputRect:sr]; }}); // ReplaceRegion is somehow asynchronous since 10.14.5. We wait sometime to request a update again. dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 8 * NSEC_PER_MSEC); dispatch_after(time, dispatch_get_main_queue(), ^(void){@autoreleasepool{ LOG(@"setNeedsDisplayInRect %g %g %g %g again", sr.origin.x, sr.origin.y, sr.size.width, sr.size.height); [myview setNeedsDisplayInRect:sr]; }}); time = dispatch_time(DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC); dispatch_after(time, dispatch_get_main_queue(), ^(void){@autoreleasepool{ LOG(@"setNeedsDisplayInRect %g %g %g %g again", sr.origin.x, sr.origin.y, sr.size.width, sr.size.height); [myview setNeedsDisplayInRect:sr]; }}); } } void getcolor(ulong i, ulong *r, ulong *g, ulong *b) { ulong v; v = pal[i]; *r = (v>>16)&0xFF; *g = (v>>8)&0xFF; *b = v&0xFF; } void setcolor(ulong i, ulong r, ulong g, ulong b) { pal[i] = ((r&0xFF)<<16) & ((g&0xFF)<<8) & (b&0xFF); } void setcursor(void) { static unsigned char data[64], data2[256]; unsigned char *planes[2] = {&data[0], &data[32]}; unsigned char *planes2[2] = {&data2[0], &data2[128]}; unsigned int i, x, y, a; unsigned char pu, pb, pl, pr, pc; // upper, bottom, left, right, center unsigned char pul, pur, pbl, pbr; unsigned char ful, fur, fbl, fbr; lock(&cursor.lk); for(i = 0; i < 32; i++){ data[i] = ~cursor.set[i] & cursor.clr[i]; data[i+32] = cursor.set[i] | cursor.clr[i]; } for(a=0; a<2; a++){ for(y=0; y<16; y++){ for(x=0; x<2; x++){ pc = planes[a][x+2*y]; pu = y==0 ? pc : planes[a][x+2*(y-1)]; pb = y==15 ? pc : planes[a][x+2*(y+1)]; pl = (pc>>1) | (x==0 ? pc&0x80 : (planes[a][x-1+2*y]&1)<<7); pr = (pc<<1) | (x==1 ? pc&1 : (planes[a][x+1+2*y]&0x80)>>7); ful = ~(pl^pu) & (pl^pb) & (pu^pr); pul = (ful & pu) | (~ful & pc); fur = ~(pu^pr) & (pu^pl) & (pr^pb); pur = (fur & pr) | (~fur & pc); fbl = ~(pb^pl) & (pb^pr) & (pl^pu); pbl = (fbl & pl) | (~fbl & pc); fbr = ~(pr^pb) & (pr^pu) & (pb^pl); pbr = (fbr & pb) | (~fbr & pc); planes2[a][2*x+4*2*y] = (pul&0x80) | ((pul&0x40)>>1) | ((pul&0x20)>>2) | ((pul&0x10)>>3) | ((pur&0x80)>>1) | ((pur&0x40)>>2) | ((pur&0x20)>>3) | ((pur&0x10)>>4); planes2[a][2*x+1+4*2*y] = ((pul&0x8)<<4) | ((pul&0x4)<<3) | ((pul&0x2)<<2) | ((pul&0x1)<<1) | ((pur&0x8)<<3) | ((pur&0x4)<<2) | ((pur&0x2)<<1) | (pur&0x1); planes2[a][2*x+4*(2*y+1)] = (pbl&0x80) | ((pbl&0x40)>>1) | ((pbl&0x20)>>2) | ((pbl&0x10)>>3) | ((pbr&0x80)>>1) | ((pbr&0x40)>>2) | ((pbr&0x20)>>3) | ((pbr&0x10)>>4); planes2[a][2*x+1+4*(2*y+1)] = ((pbl&0x8)<<4) | ((pbl&0x4)<<3) | ((pbl&0x2)<<2) | ((pbl&0x1)<<1) | ((pbr&0x8)<<3) | ((pbr&0x4)<<2) | ((pbr&0x2)<<1) | (pbr&0x1); } } } NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:planes pixelsWide:16 pixelsHigh:16 bitsPerSample:1 samplesPerPixel:2 hasAlpha:YES isPlanar:YES colorSpaceName:NSDeviceWhiteColorSpace bitmapFormat:0 bytesPerRow:2 bitsPerPixel:0]; NSBitmapImageRep *rep2 = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:planes2 pixelsWide:32 pixelsHigh:32 bitsPerSample:1 samplesPerPixel:2 hasAlpha:YES isPlanar:YES colorSpaceName:NSDeviceWhiteColorSpace bitmapFormat:0 bytesPerRow:4 bitsPerPixel:0]; NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)]; [img addRepresentation:rep2]; [img addRepresentation:rep]; currentCursor = [[NSCursor alloc] initWithImage:img hotSpot:NSMakePoint(-cursor.offset.x, -cursor.offset.y)]; unlock(&cursor.lk); dispatch_async(dispatch_get_main_queue(), ^(void){ [[myview window] invalidateCursorRectsForView:myview]; }); } void mouseset(Point p) { dispatch_async(dispatch_get_main_queue(), ^(void){@autoreleasepool{ NSPoint s; if([[myview window] isKeyWindow]){ s = NSMakePoint(p.x, p.y); LOG(@"-> pixel %g %g", s.x, s.y); s = [[myview window] convertPointFromBacking:s]; LOG(@"-> point %g %g", s.x, s.y); s = [myview convertPoint:s toView:nil]; LOG(@"-> window %g %g", s.x, s.y); s = [[myview window] convertPointToScreen: s]; LOG(@"(%g, %g) <- toScreen", s.x, s.y); s.y = NSScreen.screens[0].frame.size.height - s.y; LOG(@"(%g, %g) <- setmouse", s.x, s.y); CGWarpMouseCursorPosition(s); CGAssociateMouseAndMouseCursorPosition(true); } }}); } @implementation AppDelegate { NSWindow *_window; } static void mainproc(void *aux) { cpubody(); } - (void) applicationDidFinishLaunching:(NSNotification *)aNotification { LOG(@"BEGIN"); NSMenu *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"]; NSMenu *m = [NSMenu new]; [m addItemWithTitle:@"DEVDRAW" action:NULL keyEquivalent:@""]; [m setSubmenu:sm forItem:[m itemWithTitle:@"DEVDRAW"]]; [NSApp setMainMenu:m]; const NSWindowStyleMask Winstyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; NSRect r = [[NSScreen mainScreen] visibleFrame]; r.size.width = r.size.width*3/4; r.size.height = r.size.height*3/4; r = [NSWindow contentRectForFrameRect:r styleMask:Winstyle]; _window = [[NSWindow alloc] initWithContentRect:r styleMask:Winstyle backing:NSBackingStoreBuffered defer:NO]; [_window setTitle:@"drawterm"]; [_window center]; [_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; [_window setContentMinSize:NSMakeSize(64,64)]; [_window setOpaque:YES]; [_window setRestorable:NO]; [_window setAcceptsMouseMovedEvents:YES]; [_window setDelegate:self]; myview = [DrawtermView new]; [_window setContentView:myview]; [NSEvent setMouseCoalescingEnabled:NO]; setcursor(); [_window makeKeyAndOrderFront:self]; [NSApp activateIgnoringOtherApps:YES]; LOG(@"launch mainproc"); kproc("mainproc", mainproc, 0); ksleep(&rend, isready, 0); } - (NSApplicationPresentationOptions) window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions { NSApplicationPresentationOptions o; o = proposedOptions; o &= ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar); o |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; return o; } - (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { return YES; } - (void) windowDidBecomeKey:(id)arg { NSPoint p; p = [_window convertPointToBacking:[_window mouseLocationOutsideOfEventStream]]; absmousetrack(p.x, [myview convertSizeToBacking:myview.frame.size].height - p.y, 0, ticks()); } - (void) windowDidResignKey:(id)arg { [myview clearMods]; } @end @implementation DrawtermView { NSMutableString *_tmpText; NSRange _markedRange; NSRange _selectedRange; NSRect _lastInputRect; // The view is flipped, this is not. BOOL _tapping; NSUInteger _tapFingers; NSUInteger _tapTime; BOOL _breakcompose; NSEventModifierFlags _mods; } - (id) initWithFrame:(NSRect)fr { LOG(@"BEGIN"); self = [super initWithFrame:fr]; [self setWantsLayer:YES]; [self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay]; [self setAllowedTouchTypes:NSTouchTypeMaskDirect|NSTouchTypeMaskIndirect]; _tmpText = [[NSMutableString alloc] initWithCapacity:2]; _markedRange = NSMakeRange(NSNotFound, 0); _selectedRange = NSMakeRange(0, 0); _breakcompose = NO; _mods = 0; LOG(@"END"); return self; } - (CALayer *) makeBackingLayer { return [DrawLayer layer]; } - (BOOL)wantsUpdateLayer { return YES; } - (BOOL)isOpaque { return YES; } - (BOOL)isFlipped { return YES; } static uint evkey(uint v) { switch(v){ 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 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 NSInsertFunctionKey: return Kins; case NSDeleteFunctionKey: return Kdel; case NSHomeFunctionKey: return Khome; case NSEndFunctionKey: return Kend; case NSPageUpFunctionKey: return Kpgup; case NSPageDownFunctionKey: return Kpgdown; case NSScrollLockFunctionKey: return Kscroll; case NSBeginFunctionKey: 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 NSPrintScreenFunctionKey: case NSPauseFunctionKey: case NSSysReqFunctionKey: case NSBreakFunctionKey: case NSResetFunctionKey: case NSStopFunctionKey: case NSMenuFunctionKey: case NSUserFunctionKey: