959 lines · 23.3 KB · Objective-C
RawDownload
#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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t