shithub: drawterm

Download patch

ref: d951a96b9b176cd6a4dcb0772ad57febfff7688f
parent: 0748e023cf5eb117f0fa8b68cc0a8c9602e17bba
author: aiju <devnull@localhost>
date: Tue Jul 3 19:05:17 EDT 2018

add osx cocoa port

--- /dev/null
+++ b/Make.osx-cocoa
@@ -1,0 +1,20 @@
+# Mac OS X
+PTHREAD=	# for Mac
+AR=ar
+AS=as
+RANLIB=ranlib
+CC=gcc
+CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE $(PTHREAD) -O2
+O=o
+OS=posix
+GUI=cocoa
+LDADD=-ggdb -framework AppKit -framework OpenGL
+LDFLAGS=$(PTHREAD)
+TARG=drawterm
+AUDIO=none
+
+all: default
+
+libmachdep.a:
+	arch=`uname -m|sed 's/i.86/386/;s/x86_64/amd64/'`; \
+	(cd posix-$$arch &&  make)
--- /dev/null
+++ b/gui-cocoa/MainWindow.xib
@@ -1,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+            <connections>
+                <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application"/>
+        <customObject id="Voe-Tx-rLC" customClass="AppDelegate">
+            <connections>
+                <outlet property="view" destination="xvG-Jd-fNZ" id="fqw-g6-9Ci"/>
+                <outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
+        <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+            <items>
+                <menuItem title="drawterm" id="1Xt-HY-uBw">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="drawterm" systemMenu="apple" id="uQy-DD-JDr">
+                        <items>
+                            <menuItem title="Quit drawterm" keyEquivalent="q" id="4sb-4s-VLi">
+                                <connections>
+                                    <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+            </items>
+        </menu>
+        <window title="drawterm" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+            <rect key="contentRect" x="128" y="128" width="1024" height="768"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+            <view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
+                <rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xvG-Jd-fNZ" customClass="DrawtermView">
+                        <rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    </customView>
+                </subviews>
+            </view>
+        </window>
+    </objects>
+</document>
--- /dev/null
+++ b/gui-cocoa/Makefile
@@ -1,0 +1,17 @@
+ROOT=..
+include ../Make.config
+LIB=libgui.a
+
+OFILES=\
+	screen.$O
+
+default: $(LIB) drawterm.app/MainWindow.nib
+$(LIB): $(OFILES)
+	$(AR) r $(LIB) $(OFILES)
+	$(RANLIB) $(LIB)
+
+%.$O: %.m
+	$(CC) $(CFLAGS) -fobjc-arc $*.m
+
+drawterm.app/MainWindow.nib: MainWindow.xib
+	ibtool --compile $@ $<
--- /dev/null
+++ b/gui-cocoa/drawterm.app/Info.plist
@@ -1,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>drawterm</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>drawterm</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>drawterm</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2018 9front project. All cats reserved.</string>
+	<key>NSMainNibFile</key>
+	<string>MainWindow</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
--- /dev/null
+++ b/gui-cocoa/screen.m
@@ -1,0 +1,437 @@
+#define Rect RectC
+#import <Cocoa/Cocoa.h>
+#include <OpenGL/GL.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"
+
+Memimage *gscreen;
+
+static NSOpenGLView *myview;
+static NSSize winsize;
+static NSCursor *currentCursor;
+
+static GLuint tex;
+
+void
+guimain(void)
+{
+	static const char *args[] = {"drawterm", NULL};
+
+	NSApplicationMain(1, args);
+}
+
+void
+screeninit(void)
+{
+	NSRect r;
+
+	memimageinit();
+	r = [[NSScreen mainScreen] frame];
+	gscreen = allocmemimage(Rect(0, 0, r.size.width, r.size.height), ABGR32);
+	gscreen->clipr = Rect(0, 0, winsize.width, winsize.height);
+	terminit();
+}
+
+uchar *
+attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen)
+{
+	*r = gscreen->clipr;
+	*chan = gscreen->chan;
+	*depth = gscreen->depth;
+	*width = gscreen->width;
+	*softscreen = 1;
+	return gscreen->data->bdata;
+}
+
+char *
+clipread(void)
+{
+	NSPasteboard *pb = [NSPasteboard generalPasteboard];
+	NSArray *classes = [NSArray arrayWithObjects:[NSString class], nil];
+	NSDictionary *options = [NSDictionary dictionary];
+	NSArray *it = [pb readObjectsForClasses:classes options:options];
+	if(it != nil)
+		return strdup([it[0] UTF8String]);
+	return nil;
+}
+
+int
+clipwrite(char *buf)
+{
+	NSString *s = [[NSString alloc] initWithUTF8String:buf];
+	NSPasteboard *pb = [NSPasteboard generalPasteboard];
+	[pb clearContents];
+	[pb writeObjects:@[s]];
+	return strlen(buf);
+}
+
+void
+flushmemscreen(Rectangle r)
+{
+	uchar *buf;
+	ulong sz;
+
+	if(rectclip(&r, gscreen->clipr) == 0)
+		return;
+	sz = Dx(r) * Dy(r) * 4;
+	buf = malloc(sz);
+	unloadmemimage(gscreen, r, buf, sz);
+	dispatch_async(dispatch_get_main_queue(), ^(void){
+		[[myview openGLContext] makeCurrentContext];
+		glBindTexture(GL_TEXTURE_2D, tex);
+		glTexSubImage2D(GL_TEXTURE_2D, 0, r.min.x, r.min.y, Dx(r), Dy(r), GL_RGBA, GL_UNSIGNED_BYTE, buf);
+		free(buf);
+		[NSOpenGLContext clearCurrentContext];
+		[myview setNeedsDisplay:YES];
+	});
+}
+
+void
+getcolor(ulong a, ulong *b, ulong *c, ulong *d)
+{
+}
+
+void
+setcolor(ulong a, ulong b, ulong c, ulong d)
+{
+}
+
+void
+setcursor(void)
+{
+	static unsigned char data[64];
+	unsigned char *planes[2] = {&data[0], &data[32]};
+	int i;
+
+	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];
+	}
+	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];
+	NSImage *img = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)];
+	[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){
+		NSRect r;
+
+		r.origin.x = p.x;
+		r.origin.y = p.y;
+		r.size.width = 1;
+		r.size.height = 1;
+		r = [myview.window convertRectToScreen:r];
+		CGWarpMouseCursorPosition(r.origin);
+	});
+}
+
+void
+setterm(int x)
+{
+}
+
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+@end
+
+@interface AppDelegate ()
+@property (assign) IBOutlet NSWindow *window;
+@property (assign) IBOutlet NSOpenGLView *view;
+@end
+
+@implementation AppDelegate
+
+void
+mainproc(void *aux)
+{
+	cpubody();
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+	setcursor();
+	[_window setRestorable:NO];
+	[_window setAcceptsMouseMovedEvents:TRUE];
+	myview = _view;
+	winsize = _view.frame.size;
+	kproc("mainproc", mainproc, 0);
+}
+
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
+}
+
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
+	return YES;
+}
+
+@end
+
+@interface DrawtermView : NSOpenGLView
+- (void) drawRect:(NSRect)rect;
+- (void) keyDown:(NSEvent*)event;
+- (void) flagsChanged:(NSEvent*)event;
+- (void) keyUp:(NSEvent*)event;
+- (void) mouseDown:(NSEvent*)event;
+- (void) mouseDragged:(NSEvent*)event;
+- (void) mouseUp:(NSEvent*)event;
+- (void) mouseMoved:(NSEvent*)event;
+- (void) rightMouseDown:(NSEvent*)event;
+- (void) rightMouseDragged:(NSEvent*)event;
+- (void) rightMouseUp:(NSEvent*)event;
+- (void) otherMouseDown:(NSEvent*)event;
+- (void) otherMouseDragged:(NSEvent*)event;
+- (void) otherMouseUp:(NSEvent*)event;
+- (BOOL) acceptsFirstResponder;
+- (void) reshape;
+- (BOOL) acceptsMouseMovedEvents;
+- (void) prepareOpenGL;
+- (void) resetCursorRects;
+@end
+
+@implementation DrawtermView
+
+- (void) prepareOpenGL {
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glEnable(GL_TEXTURE_2D);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.frame.size.width, self.frame.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glOrtho(0, 1, 1, 0, -1, 1);
+	glMatrixMode(GL_MODELVIEW);
+}
+
+- (void) drawRect:(NSRect)rect
+{
+	glBindTexture(GL_TEXTURE_2D, tex);
+	glClearColor(0, 0, 0, 0);
+	glClear(GL_COLOR_BUFFER_BIT);
+	glColor4f(1.0, 1.0, 1.0, 1.0);
+	glBegin(GL_TRIANGLES);
+	glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
+	glTexCoord2f(1.0, 0.0); glVertex2f(1.0, 0.0);
+	glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 1.0);
+	glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 1.0);
+	glTexCoord2f(1.0, 0.0); glVertex2f(1.0, 0.0);
+	glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
+	glEnd();
+	glFlush();
+}
+
+static int
+evkey(NSEvent *event)
+{
+	NSString *s = [event charactersIgnoringModifiers];
+	int v = [s characterAtIndex:0];
+	switch(v){
+	case '\r': return '\n';
+	case '\b': return 127;
+	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 NSF13FunctionKey: return 0;
+	case NSF14FunctionKey: return 0;
+	case NSF15FunctionKey: return 0;
+	case NSF16FunctionKey: return 0;
+	case NSF17FunctionKey: return 0;
+	case NSF18FunctionKey: return 0;
+	case NSF19FunctionKey: return 0;
+	case NSF20FunctionKey: return 0;
+	case NSF21FunctionKey: return 0;
+	case NSF22FunctionKey: return 0;
+	case NSF23FunctionKey: return 0;
+	case NSF24FunctionKey: return 0;
+	case NSF25FunctionKey: return 0;
+	case NSF26FunctionKey: return 0;
+	case NSF27FunctionKey: return 0;
+	case NSF28FunctionKey: return 0;
+	case NSF29FunctionKey: return 0;
+	case NSF30FunctionKey: return 0;
+	case NSF31FunctionKey: return 0;
+	case NSF32FunctionKey: return 0;
+	case NSF33FunctionKey: return 0;
+	case NSF34FunctionKey: return 0;
+	case NSF35FunctionKey: return 0;
+	case NSInsertFunctionKey: return Kins;
+	case NSDeleteFunctionKey: return Kdel;
+	case NSHomeFunctionKey: return Khome;
+	case NSBeginFunctionKey: return 0;
+	case NSEndFunctionKey: return Kend;
+	case NSPageUpFunctionKey: return Kpgup;
+	case NSPageDownFunctionKey: return Kpgdown;
+	case NSPrintScreenFunctionKey: return 0;
+	case NSScrollLockFunctionKey: return Kscroll;
+	case NSPauseFunctionKey: return 0;
+	case NSSysReqFunctionKey: return 0;
+	case NSBreakFunctionKey: return 0;
+	case NSResetFunctionKey: return 0;
+	case NSStopFunctionKey: return 0;
+	case NSMenuFunctionKey: return 0;
+	case NSUserFunctionKey: return 0;
+	case NSSystemFunctionKey: return 0;
+	case NSPrintFunctionKey: return 0;
+	case NSClearLineFunctionKey: return 0;
+	case NSClearDisplayFunctionKey: return 0;
+	case NSInsertLineFunctionKey: return 0;
+	case NSDeleteLineFunctionKey: return 0;
+	case NSInsertCharFunctionKey: return 0;
+	case NSDeleteCharFunctionKey: return 0;
+	case NSPrevFunctionKey: return 0;
+	case NSNextFunctionKey: return 0;
+	case NSSelectFunctionKey: return 0;
+	case NSExecuteFunctionKey: return 0;
+	case NSUndoFunctionKey: return 0;
+	case NSRedoFunctionKey: return 0;
+	case NSFindFunctionKey: return 0;
+	case NSHelpFunctionKey: return 0;
+	case NSModeSwitchFunctionKey: return 0;
+	default: return v;
+	}
+}
+
+- (void)keyDown:(NSEvent*)event {
+	int m;
+
+	m = evkey(event);
+	if((event.modifierFlags & NSEventModifierFlagControl) != 0)
+		m &= 0x9f;
+	if(m != 0)
+		kbdkey(m, 1);
+}
+
+- (void)keyUp:(NSEvent*)event {
+	int m;
+
+	m = evkey(event);
+	if((event.modifierFlags & NSEventModifierFlagControl) != 0)
+		m &= 0x9f;
+	if(m != 0)
+		kbdkey(m, 0);
+}
+
+- (void)flagsChanged:(NSEvent*)event {
+	static NSEventModifierFlags y;
+	NSEventModifierFlags x;
+
+	x = [event modifierFlags];
+	if((x & ~y & NSEventModifierFlagShift) != 0)
+		kbdkey(Kshift, 1);
+	if((x & ~y & NSEventModifierFlagControl) != 0)
+		kbdkey(Kctl, 1);
+	if((x & ~y & NSEventModifierFlagOption) != 0)
+		kbdkey(Kalt, 1);
+	if((x & ~y & NSEventModifierFlagCapsLock) != 0)
+		kbdkey(Kcaps, 1);
+	if((~x & y & NSEventModifierFlagShift) != 0)
+		kbdkey(Kshift, 0);
+	if((~x & y & NSEventModifierFlagControl) != 0)
+		kbdkey(Kctl, 0);
+	if((~x & y & NSEventModifierFlagOption) != 0)
+		kbdkey(Kalt, 0);
+	if((x & ~y & NSEventModifierFlagCapsLock) != 0)
+		kbdkey(Kcaps, 0);
+	y = x;
+}
+
+- (void)mouseevent:(NSEvent*)event
+{
+	NSPoint p;
+	Point q;
+	NSUInteger u;
+
+	p = [self.window mouseLocationOutsideOfEventStream];
+	u = [NSEvent pressedMouseButtons];
+	q.x = p.x;
+	q.y = p.y;
+	if(!ptinrect(q, gscreen->clipr)) return;
+	u = u & ~6 | u << 1 & 4 | u >> 1 & 2;
+	absmousetrack(p.x, self.frame.size.height - p.y, u, ticks());
+}
+
+- (void) mouseDown:(NSEvent*)event { [self mouseevent:event]; }
+- (void) mouseDragged:(NSEvent*)event { [self mouseevent:event]; }
+- (void) mouseUp:(NSEvent*)event { [self mouseevent:event]; }
+- (void) mouseMoved:(NSEvent*)event { [self mouseevent:event]; }
+- (void) rightMouseDown:(NSEvent*)event { [self mouseevent:event]; }
+- (void) rightMouseDragged:(NSEvent*)event { [self mouseevent:event]; }
+- (void) rightMouseUp:(NSEvent*)event { [self mouseevent:event]; }
+- (void) otherMouseDown:(NSEvent*)event { [self mouseevent:event]; }
+- (void) otherMouseDragged:(NSEvent*)event { [self mouseevent:event]; }
+- (void) otherMouseUp:(NSEvent*)event { [self mouseevent:event]; }
+
+- (BOOL) acceptsFirstResponder {
+	return TRUE;
+}
+
+- (void) reshape {
+	winsize = self.frame.size;
+	NSOpenGLContext *ctxt = [NSOpenGLContext currentContext];
+	[[myview openGLContext] makeCurrentContext];
+	glBindTexture(GL_TEXTURE_2D, tex);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.frame.size.width, self.frame.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+	if(ctxt == nil)
+		[NSOpenGLContext clearCurrentContext];
+	else
+		[ctxt makeCurrentContext];
+	if(gscreen != nil){
+		screenresize(Rect(0, 0, winsize.width, winsize.height));
+		flushmemscreen(gscreen->clipr);
+	}
+}
+
+- (BOOL) acceptsMouseMovedEvents {
+	return TRUE;
+}
+
+- (void)resetCursorRects {
+	[super resetCursorRects];
+	[self addCursorRect:self.bounds cursor:currentCursor];
+}
+@end