History

Merging echoline's android and fbdev forks

Lorenzo Bivens committed 5 years ago

Commit 96209041 parent a130d4427 files · +2398 −0Browse files

Unified · Split

27 files
  1. Make.android +38 −0
  2. Make.android-386 +26 −0
  3. Make.android-amd64 +26 −0
  4. Make.android-arm +26 −0
  5. Make.android-arm64 +26 −0
  6. Make.fbdev +22 −0
  7. README +11 −0
  8. gui-android/AndroidManifest.xml +30 −0
  9. gui-android/Makefile +23 −0
  10. gui-android/cpp/android.c +230 −0
  11. gui-android/cpp/devandroid.c +248 −0
  12. gui-android/cpp/native-lib.c +173 −0
  13. gui-android/java/org/echoline/drawterm/DrawTermThread.java +32 −0
  14. gui-android/java/org/echoline/drawterm/MainActivity.java +437 −0
  15. gui-android/java/org/echoline/drawterm/MySurfaceView.java +91 −0
  16. gui-android/res/layout/activity_main.xml +24 −0
  17. gui-android/res/layout/content_main.xml +16 −0
  18. gui-android/res/layout/drawterm_main.xml +44 −0
  19. gui-android/res/layout/item_main.xml +8 −0
  20. gui-android/res/layout/server_main.xml +56 −0
  21. gui-android/res/values/colors.xml +6 −0
  22. gui-android/res/values/strings.xml +3 −0
  23. gui-android/res/values/styles.xml +8 −0
  24. gui-fbdev/Makefile +12 −0
  25. gui-fbdev/fbdev.c +673 −0
  26. kern/devaudio-alsa.c +108 −0
  27. main.c +1 −0
Make.android+38−0
@@ -0,0 +1,38 @@
1# Android
2SDKPREFIX=$(HOME)/Android/Sdk
3JAVA_HOME=/usr
4OBJS=lib/arm64-v8a/libdrawterm.so lib/armeabi-v7a/libdrawterm.so lib/x86/libdrawterm.so lib/x86_64/libdrawterm.so
5
6all: drawterm.apk
7
8clean:
9 rm -f *.apk lib/*/*.so
10
11lib/arm64-v8a/libdrawterm.so:
12 CONF=android-arm64 make -j5;
13 CONF=android-arm64 make clean;
14
15lib/armeabi-v7a/libdrawterm.so:
16 CONF=android-arm make -j5;
17 CONF=android-arm make clean;
18
19lib/x86/libdrawterm.so:
20 CONF=android-386 make -j5;
21 CONF=android-386 make clean;
22
23lib/x86_64/libdrawterm.so:
24 CONF=android-amd64 make -j5;
25 CONF=android-amd64 make clean;
26
27drawterm.apk: drawterm-signed.apk
28 $(SDKPREFIX)/build-tools/30.0.3/zipalign -v -f 4 $< $@
29
30drawterm-signed.apk: drawterm-unsigned.apk drawterm.keystore
31 $(JAVA_HOME)/bin/jarsigner -verbose -keystore ./drawterm.keystore -storepass glendarocks -keypass glendarocks -signedjar $@ $< drawtermKey
32
33drawterm-unsigned.apk: $(OBJS)
34 $(SDKPREFIX)/build-tools/30.0.3/aapt package -v -f -M gui-android/AndroidManifest.xml -S gui-android/res -I $(SDKPREFIX)/platforms/android-21/android.jar -F $@ gui-android/bin
35 $(SDKPREFIX)/build-tools/30.0.3/aapt add $@ $(OBJS)
36
37drawterm.keystore:
38 $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=9front,O=Android,C=US" -keystore $@ -storepass glendarocks -keypass glendarocks -alias drawtermKey -keyalg RSA -v
Make.android-386+26−0
@@ -0,0 +1,26 @@
1# Android
2SDKPREFIX=$(HOME)/Android/Sdk
3NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
4JAVA_HOME=/usr
5
6PTHREAD=-pthread
7AR=$(NDKPREFIX)/i686-linux-android-ar
8AS=$(NDKPREFIX)/i686-linux-android-as
9RANLIB=$(NDKPREFIX)/i686-linux-android-ranlib
10STRIP=$(NDKPREFIX)/i686-linux-android-strip
11CC=$(NDKPREFIX)/i686-linux-android21-clang
12CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
13O=o
14OS=posix
15GUI=android
16LDADD=-ggdb -lm -shared -llog -landroid
17LDFLAGS=$(PTHREAD)
18TARG=lib/x86/libdrawterm.so
19AUDIO=none
20
21all: default
22
23libmachdep.a:
24 arch=386; \
25 (cd posix-$$arch && make)
26
Make.android-amd64+26−0
@@ -0,0 +1,26 @@
1# Android
2SDKPREFIX=$(HOME)/Android/Sdk
3NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
4JAVA_HOME=/usr
5
6PTHREAD=-pthread
7AR=$(NDKPREFIX)/x86_64-linux-android-ar
8AS=$(NDKPREFIX)/x86_64-linux-android-as
9RANLIB=$(NDKPREFIX)/x86_64-linux-android-ranlib
10STRIP=$(NDKPREFIX)/x86_64-linux-android-strip
11CC=$(NDKPREFIX)/x86_64-linux-android21-clang
12CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
13O=o
14OS=posix
15GUI=android
16LDADD=-ggdb -lm -shared -llog -landroid
17LDFLAGS=$(PTHREAD)
18TARG=lib/x86_64/libdrawterm.so
19AUDIO=none
20
21all: default
22
23libmachdep.a:
24 arch=amd64; \
25 (cd posix-$$arch && make)
26
Make.android-arm+26−0
@@ -0,0 +1,26 @@
1# Android
2SDKPREFIX=$(HOME)/Android/Sdk
3NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
4JAVA_HOME=/usr
5
6PTHREAD=-pthread
7AR=$(NDKPREFIX)/arm-linux-androideabi-ar
8AS=$(NDKPREFIX)/arm-linux-androideabi-as
9RANLIB=$(NDKPREFIX)/arm-linux-androideabi-ranlib
10STRIP=$(NDKPREFIX)/arm-linux-androideabi-strip
11CC=$(NDKPREFIX)/armv7a-linux-androideabi21-clang
12CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
13O=o
14OS=posix
15GUI=android
16LDADD=-ggdb -lm -shared -llog -landroid
17LDFLAGS=$(PTHREAD)
18TARG=lib/armeabi-v7a/libdrawterm.so
19AUDIO=none
20
21all: default
22
23libmachdep.a:
24 arch=arm; \
25 (cd posix-$$arch && make)
26
Make.android-arm64+26−0
@@ -0,0 +1,26 @@
1# Android
2SDKPREFIX=$(HOME)/Android/Sdk
3NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
4JAVA_HOME=/usr
5
6PTHREAD=-pthread
7AR=$(NDKPREFIX)/aarch64-linux-android-ar
8AS=$(NDKPREFIX)/aarch64-linux-android-as
9RANLIB=$(NDKPREFIX)/aarch64-linux-android-ranlib
10STRIP=$(NDKPREFIX)/aarch64-linux-android-strip
11CC=$(NDKPREFIX)/aarch64-linux-android21-clang
12CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
13O=o
14OS=posix
15GUI=android
16LDADD=-ggdb -lm -shared -llog -landroid
17LDFLAGS=$(PTHREAD)
18TARG=lib/arm64-v8a/libdrawterm.so
19AUDIO=none
20
21all: default
22
23libmachdep.a:
24 arch=arm64; \
25 (cd posix-$$arch && make)
26
Make.fbdev+22−0
@@ -0,0 +1,22 @@
1# Unix
2#PTHREAD= # for Mac
3PTHREAD=-pthread
4AR=ar
5AS=as
6RANLIB=ranlib
7CC=gcc
8CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE $(PTHREAD) -O2
9O=o
10OS=posix
11GUI=fbdev
12LDADD=-ggdb -lm -lasound
13LDFLAGS=$(PTHREAD)
14TARG=drawterm
15# AUDIO=none
16AUDIO=alsa
17
18all: default
19
20libmachdep.a:
21 arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/'`; \
22 (cd posix-$$arch && make)
README+11−0
@@ -18,6 +18,17 @@ To build on Mac OS X with X11 (xquartz), run CONF=osx-x11 make. · 17 unmodified lines
18 18
19To build on Mac OS X with Cocoa, run CONF=osx-cocoa make and "cp drawterm gui-cocoa/drawterm.app/".19To build on Mac OS X with Cocoa, run CONF=osx-cocoa make and "cp drawterm gui-cocoa/drawterm.app/".
20 20
21To build for Android, make sure Make.android* and gui-android/Makefile are correct for your build and target systems, then run make -f Make.android
22
23USAGE
24-------
25On Android the five checkboxes at the top represent the three mouse buttons and mousewheel, determining which "buttons" are clicked. The "kb" button toggles the soft keyboard.
26
27
28CAVEATS
29--------
30Be aware that right now on Android the login details are saved as a plaintext string if saved, and there is no secstore support.
31
21 32
22BINARIES33BINARIES
23---------34---------
gui-android/AndroidManifest.xml+30−0
@@ -0,0 +1,30 @@
1<?xml version="1.0" encoding="utf-8"?>
2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="org.echoline.drawterm">
4
5 <supports-screens android:largeScreens="true"
6 android:normalScreens="true" android:smallScreens="true"
7 android:anyDensity="true" />
8
9 <application
10 android:allowBackup="true"
11 android:icon="@mipmap/ic_launcher"
12 android:label="@string/app_name"
13 android:supportsRtl="true"
14 android:theme="@style/AppTheme">
15 <activity
16 android:name=".MainActivity"
17 android:label="@string/app_name"
18 android:windowSoftInputMode="stateUnchanged|adjustNothing">
19 <intent-filter>
20 <action android:name="android.intent.action.MAIN" />
21 <category android:name="android.intent.category.LAUNCHER" />
22 </intent-filter>
23 </activity>
24 </application>
25 <uses-permission android:name="android.permission.INTERNET"/>
26 <!--<uses-permission android:name="android.permission.SET_DEBUG_APP"/>-->
27 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
28 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
29 <uses-permission android:name="android.permission.CAMERA"/>
30</manifest>
gui-android/Makefile+23−0
@@ -0,0 +1,23 @@
1ROOT=..
2include ../Make.config
3LIB=libgui.a
4
5OFILES=\
6 cpp/android.$O\
7 cpp/native-lib.$O\
8 cpp/devandroid.$O\
9
10default: $(LIB) gen/org/echoline/drawterm/R.java bin/classes.dex
11$(LIB): $(OFILES)
12 $(AR) r $(LIB) $(OFILES)
13 $(RANLIB) $(LIB)
14
15gen/org/echoline/drawterm/R.java: $(shell find res/ -type f)
16 $(SDKPREFIX)/build-tools/30.0.3/aapt package -f -m -M AndroidManifest.xml -I $(SDKPREFIX)/platforms/android-21/android.jar -S res/ -J gen
17
18bin/classes.dex: obj/org/echoline/drawterm/MainActivity.class obj/org/echoline/drawterm/DrawTermThread.class obj/org/echoline/drawterm/MySurfaceView.class
19 $(SDKPREFIX)/build-tools/30.0.3/dx --dex --verbose --output=$@ obj/
20
21obj/org/echoline/drawterm/%.class: java/org/echoline/drawterm/%.java
22 $(JAVA_HOME)/bin/javac -d obj/ -classpath $(SDKPREFIX)/platforms/android-21/android.jar -sourcepath java java/org/echoline/drawterm/$*.java gen/org/echoline/drawterm/R.java
23
gui-android/cpp/android.c+230−0
@@ -0,0 +1,230 @@
1#include <jni.h>
2#include <android/native_window.h>
3#include <android/log.h>
4
5#include "u.h"
6#include "lib.h"
7#include "dat.h"
8#include "fns.h"
9
10#include <draw.h>
11#include <memdraw.h>
12#include <keyboard.h>
13#include <cursor.h>
14#include "screen.h"
15
16Memimage *gscreen = nil;
17extern int screenWidth;
18extern int screenHeight;
19extern ANativeWindow *window;
20extern jobject mainActivityObj;
21extern JavaVM *jvm;
22
23char*
24clipread(void)
25{
26 char *ret;
27 const char *s;
28 JNIEnv *env;
29 jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
30 if (rs != JNI_OK) {
31 __android_log_print(ANDROID_LOG_WARN, "drawterm", "AttachCurrentThread returned error: %d", rs);
32 return strdup("");
33 }
34 jclass clazz = (*env)->GetObjectClass(env, mainActivityObj);
35 jmethodID methodID = (*env)->GetMethodID(env, clazz, "getClipBoard", "()Ljava/lang/String;");
36 jstring str = (jstring)(*env)->CallObjectMethod(env, mainActivityObj, methodID);
37 s = (*env)->GetStringUTFChars(env, str, NULL);
38 ret = strdup(s);
39 (*env)->ReleaseStringUTFChars(env, str, s);
40 (*jvm)->DetachCurrentThread(jvm);
41 return ret;
42}
43
44int
45clipwrite(char *buf)
46{
47 JNIEnv *env;
48 jint rs = (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6);
49 if(rs != JNI_OK) {
50 __android_log_print(ANDROID_LOG_WARN, "drawterm", "GetEnv returned error: %d", rs);
51 return 0;
52 }
53 jclass clazz = (*env)->GetObjectClass(env, mainActivityObj);
54 jmethodID methodID = (*env)->GetMethodID(env, clazz, "setClipBoard", "(Ljava/lang/String;)V");
55 jstring str = (*env)->NewStringUTF(env, buf);
56 (*env)->CallVoidMethod(env, mainActivityObj, methodID, str);
57 return 0;
58}
59
60void
61show_notification(char *buf)
62{
63 JNIEnv *env;
64 jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
65 if(rs != JNI_OK) {
66 __android_log_print(ANDROID_LOG_WARN, "drawterm", "AttachCurrentThread returned error: %d", rs);
67 return;
68 }
69 jclass clazz = (*env)->GetObjectClass(env, mainActivityObj);
70 jmethodID methodID = (*env)->GetMethodID(env, clazz, "showNotification", "(Ljava/lang/String;)V");
71 jstring str = (*env)->NewStringUTF(env, buf);
72 (*env)->CallVoidMethod(env, mainActivityObj, methodID, str);
73 (*jvm)->DetachCurrentThread(jvm);
74 return;
75}
76
77int
78num_cameras()
79{
80 JNIEnv *env;
81 int n;
82 jint rs = (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6);
83 if(rs != JNI_OK) {
84 __android_log_print(ANDROID_LOG_WARN, "drawterm", "GetEnv returned error: %d", rs);
85 return 0;
86 }
87 jclass clazz = (*env)->GetObjectClass(env, mainActivityObj);
88 jmethodID methodID = (*env)->GetMethodID(env, clazz, "numCameras", "()I");
89 n = (*env)->CallIntMethod(env, mainActivityObj, methodID);
90 return n;
91}
92
93void
94take_picture(int id)
95{
96 JNIEnv *env;
97 jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
98 if(rs != JNI_OK) {
99 __android_log_print(ANDROID_LOG_WARN, "drawterm", "AttachCurrentThread returned error: %d", rs);
100 return;
101 }
102 jclass clazz = (*env)->GetObjectClass(env, mainActivityObj);
103 jmethodID methodID = (*env)->GetMethodID(env, clazz, "takePicture", "(I)V");
104 (*env)->CallVoidMethod(env, mainActivityObj, methodID, id);
105 (*jvm)->DetachCurrentThread(jvm);
106 return;
107}
108
109void
110setcolor(ulong i, ulong r, ulong g, ulong b)
111{
112 return;
113}
114
115void
116getcolor(ulong v, ulong *r, ulong *g, ulong *b)
117{
118 *r = (v>>16)&0xFF;
119 *g = (v>>8)&0xFF;
120 *b = v&0xFF;
121}
122
123void
124flushmemscreen(Rectangle r)
125{
126 ANativeWindow_Buffer buffer;
127 uint8_t *pixels;
128 int x, y, o, b;
129 ARect bounds;
130
131 if (window == NULL)
132 return;
133
134 memset(&buffer, 0, sizeof(buffer));
135
136 bounds.left = r.min.x;
137 bounds.top = r.min.y;
138 bounds.right = r.max.x;
139 bounds.bottom = r.max.y;
140
141 if (ANativeWindow_lock(window, &buffer, &bounds) != 0) {
142 __android_log_print(ANDROID_LOG_WARN, "drawterm", "Unable to lock window buffer");
143 return;
144 }
145
146 r.min.x = bounds.left;
147 r.min.y = bounds.top;
148 r.max.x = bounds.right;
149 r.max.y = bounds.bottom;
150
151 pixels = (uint8_t*)buffer.bits;
152 for (y = r.min.y; y < r.max.y; y++)
153 for (x = r.min.x; x < r.max.x; x++) {
154 o = (y * screenWidth + x) * 4;
155 b = (y * buffer.stride + x) * 4;
156 pixels[b+3] = 0xFF;
157 pixels[b+2] = gscreen->data->bdata[o+0];
158 pixels[b+1] = gscreen->data->bdata[o+1];
159 pixels[b+0] = gscreen->data->bdata[o+2];
160 }
161
162 if (ANativeWindow_unlockAndPost(window) != 0) {
163 __android_log_print(ANDROID_LOG_WARN, "drawterm", "Unable to unlock and post window buffer");
164 }
165 return;
166}
167
168void
169screeninit(void)
170{
171 Rectangle r = Rect(0,0,screenWidth,screenHeight);
172 memimageinit();
173 screensize(r, XRGB32);
174 if (gscreen == nil)
175 panic("screensize failed");
176 gscreen->clipr = r;
177 terminit();
178 qlock(&drawlock);
179 flushmemscreen(r);
180 qunlock(&drawlock);
181 return;
182}
183
184void
185screensize(Rectangle r, ulong chan)
186{
187 Memimage *mi;
188
189 mi = allocmemimage(r, chan);
190 if (mi == nil)
191 return;
192
193 if (gscreen != nil)
194 freememimage(gscreen);
195
196 gscreen = mi;
197 gscreen->clipr = ZR;
198}
199
200Memdata*
201attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen)
202{
203 *r = gscreen->clipr;
204 *depth = gscreen->depth;
205 *chan = gscreen->chan;
206 *width = gscreen->width;
207 *softscreen = 1;
208
209 gscreen->data->ref++;
210 return gscreen->data;
211}
212
213void
214setcursor(void)
215{
216 return;
217}
218
219void
220mouseset(Point xy)
221{
222 return;
223}
224
225void
226guimain(void)
227{
228 cpubody();
229}
230
gui-android/cpp/devandroid.c+248−0
@@ -0,0 +1,248 @@
1#include "u.h"
2#include "lib.h"
3#include "dat.h"
4#include "fns.h"
5#include "error.h"
6
7#include <android/log.h>
8#include <android/sensor.h>
9
10void show_notification(char *buf);
11void take_picture(int id);
12int num_cameras();
13
14int Ncameras = 0;
15
16uchar *cambuf = nil;
17int camlen;
18
19ASensorManager *sensorManager = NULL;
20
21enum
22{
23 Qdir = 0,
24 Qcam = 1,
25 Qaccel = 2,
26 Qcompass = 4,
27 Qnotification = 6,
28};
29#define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y))
30
31static void androidinit(void);
32
33static void
34androidinit(void)
35{
36 sensorManager = ASensorManager_getInstance();
37
38 Ncameras = num_cameras();
39}
40
41static Chan*
42androidattach(char *param)
43{
44 Chan *c;
45
46 c = devattach('N', param);
47 c->qid.path = QID(0, 0, Qdir);
48 c->qid.type = QTDIR;
49 c->qid.vers = 0;
50
51 return c;
52}
53
54static int
55androidgen(Chan *c, char *n, Dirtab *d, int nd, int s, Dir *dp)
56{
57 Qid q;
58
59 if (s == DEVDOTDOT) {
60 mkqid(&q, Qdir, 0, QTDIR);
61 devdir(c, q, "#N", 0, eve, 0555, dp);
62 return 1;
63 }
64 if (s < Ncameras) {
65 sprintf(up->genbuf, "cam%d.jpg", s);
66 mkqid(&q, (s << 16) | Qcam, 0, QTFILE);
67 devdir(c, q, up->genbuf, 0, eve, 0444, dp);
68 return 1;
69 }
70 if (s == Ncameras) {
71 sprintf(up->genbuf, "accel");
72 mkqid(&q, Qaccel, 0, QTFILE);
73 devdir(c, q, up->genbuf, 0, eve, 0444, dp);
74 return 1;
75 }
76 if (s == (Ncameras+1)) {
77 sprintf(up->genbuf, "compass");
78 mkqid(&q, Qcompass, 0, QTFILE);
79 devdir(c, q, up->genbuf, 0, eve, 0444, dp);
80 return 1;
81 }
82 if (s == (Ncameras+2)) {
83 sprintf(up->genbuf, "notification");
84 mkqid(&q, Qnotification, 0, QTFILE);
85 devdir(c, q, up->genbuf, 0, eve, 0222, dp);
86 return 1;
87 }
88 return -1;
89}
90
91static Walkqid*
92androidwalk(Chan *c, Chan *nc, char **name, int nname)
93{
94 return devwalk(c, nc, name, nname, 0, 0, androidgen);
95}
96
97static int
98androidstat(Chan *c, uchar *db, int n)
99{
100 return devstat(c, db, n, 0, 0, androidgen);
101}
102
103static Chan*
104androidopen(Chan *c, int omode)
105{
106 p9_uvlong s;
107
108 c = devopen(c, omode, 0, 0, androidgen);
109
110 if (c->qid.path & Qcam) {
111 s = c->qid.path >> 16;
112 take_picture(s);
113 }
114 c->mode = openmode(omode);
115 c->flag |= COPEN;
116 c->offset = 0;
117 c->iounit = 8192;
118
119 return c;
120}
121
122static void
123androidclose(Chan *c)
124{
125 if (c->qid.path & Qcam && cambuf != nil) {
126 free(cambuf);
127 cambuf = nil;
128 }
129}
130
131static long
132androidread(Chan *c, void *v, long n, vlong off)
133{
134 char *a = v;
135 long l;
136 const ASensor *sensor;
137 ASensorEventQueue *queue = NULL;
138 ASensorEvent data;
139
140 switch((ulong)c->qid.path & 0xF) {
141 default:
142 error(Eperm);
143 return -1;
144
145 case Qcam:
146 while(cambuf == nil)
147 usleep(10 * 1000);
148
149 l = camlen - off;
150 if (l > n)
151 l = n;
152
153 if (l > 0)
154 memcpy(a, cambuf + off, l);
155
156 return l;
157 case Qaccel:
158 queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL);
159 if (queue == NULL)
160 return 0;
161 sensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
162 if (sensor == NULL) {
163 ASensorManager_destroyEventQueue(sensorManager, queue);
164 return 0;
165 }
166 if (ASensorEventQueue_enableSensor(queue, sensor)) {
167 ASensorEventQueue_disableSensor(queue, sensor);
168 ASensorManager_destroyEventQueue(sensorManager, queue);
169 return 0;
170 }
171 l = 0;
172 if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) {
173 if (ASensorEventQueue_getEvents(queue, &data, 1)) {
174 l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z);
175 }
176 }
177 ASensorEventQueue_disableSensor(queue, sensor);
178 ASensorManager_destroyEventQueue(sensorManager, queue);
179 return l;
180 case Qcompass:
181 queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL);
182 if (queue == NULL)
183 return 0;
184 sensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_MAGNETIC_FIELD);
185 if (sensor == NULL) {
186 ASensorManager_destroyEventQueue(sensorManager, queue);
187 return 0;
188 }
189 if (ASensorEventQueue_enableSensor(queue, sensor)) {
190 ASensorEventQueue_disableSensor(queue, sensor);
191 ASensorManager_destroyEventQueue(sensorManager, queue);
192 return 0;
193 }
194 l = 0;
195 if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) {
196 if (ASensorEventQueue_getEvents(queue, &data, 1)) {
197 l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z);
198 }
199 }
200 ASensorEventQueue_disableSensor(queue, sensor);
201 ASensorManager_destroyEventQueue(sensorManager, queue);
202 return l;
203 case Qdir:
204 return devdirread(c, a, n, 0, 0, androidgen);
205 }
206}
207
208static long
209androidwrite(Chan *c, void *vp, long n, vlong off)
210{
211 char *a = vp;
212 char *str;
213
214 switch((ulong)c->qid.path) {
215 case Qnotification:
216 str = malloc(n+1);
217 memcpy(str, a, n);
218 str[n] = '\0';
219 show_notification(str);
220 free(str);
221 return n;
222 default:
223 error(Eperm);
224 break;
225 }
226 return -1;
227}
228
229Dev androiddevtab = {
230 'N',
231 "android",
232
233 devreset,
234 androidinit,
235 devshutdown,
236 androidattach,
237 androidwalk,
238 androidstat,
239 androidopen,
240 devcreate,
241 androidclose,
242 androidread,
243 devbread,
244 androidwrite,
245 devbwrite,
246 devremove,
247 devwstat,
248};
gui-android/cpp/native-lib.c+173−0
@@ -0,0 +1,173 @@
1#include <jni.h>
2#include <android/native_window.h>
3#include <android/native_window_jni.h>
4#include <android/log.h>
5#include "u.h"
6#include "lib.h"
7#include "dat.h"
8#include "fns.h"
9#include "error.h"
10#include <draw.h>
11#include <string.h>
12#include <keyboard.h>
13
14void absmousetrack(int, int, int, ulong);
15ulong ticks(void);
16int dt_main(int, char**);
17int screenWidth;
18int screenHeight;
19Point mousept = {0, 0};
20int buttons = 0;
21float ws = 1;
22float hs = 1;
23extern char *snarfbuf;
24int mPaused = 0;
25ANativeWindow *window = NULL;
26jobject mainActivityObj;
27JavaVM *jvm;
28void flushmemscreen(Rectangle r);
29extern uchar *cambuf;
30extern int camlen;
31
32JNIEXPORT void JNICALL
33Java_org_echoline_drawterm_MainActivity_setObject(
34 JNIEnv *env,
35 jobject obj) {
36 mainActivityObj = (*env)->NewGlobalRef(env, obj);
37 jint rs = (*env)->GetJavaVM(env, &jvm);
38 assert(rs == JNI_OK);
39}
40
41JNIEXPORT void JNICALL
42Java_org_echoline_drawterm_MainActivity_keyDown(
43 JNIEnv *env,
44 jobject obj,
45 jint c) {
46 kbdkey(c, 1);
47}
48
49JNIEXPORT void JNICALL
50Java_org_echoline_drawterm_MainActivity_keyUp(
51 JNIEnv *env,
52 jobject obj,
53 jint c) {
54 kbdkey(c, 0);
55}
56
57JNIEXPORT void JNICALL
58Java_org_echoline_drawterm_MainActivity_setPass(
59 JNIEnv *env,
60 jobject obj,
61 jstring str) {
62 setenv("PASS", (char*)(*env)->GetStringUTFChars(env, str, 0), 1);
63}
64
65JNIEXPORT void JNICALL
66Java_org_echoline_drawterm_MainActivity_setWidth(
67 JNIEnv *env,
68 jobject obj,
69 jint width) {
70 screenWidth = width;
71}
72
73JNIEXPORT void JNICALL
74Java_org_echoline_drawterm_MainActivity_setHeight(
75 JNIEnv *env,
76 jobject obj,
77 jint height) {
78 screenHeight = height;
79}
80
81JNIEXPORT void JNICALL
82Java_org_echoline_drawterm_MainActivity_setWidthScale(
83 JNIEnv *env,
84 jobject obj,
85 jfloat s) {
86 ws = s;
87}
88
89JNIEXPORT void JNICALL
90Java_org_echoline_drawterm_MainActivity_setHeightScale(
91 JNIEnv *env,
92 jobject obj,
93 jfloat s) {
94 hs = s;
95}
96
97JNIEXPORT jint JNICALL
98Java_org_echoline_drawterm_MainActivity_dtmain(
99 JNIEnv *env,
100 jobject obj,
101 jobjectArray argv) {
102 int i, ret;
103 char **args = (char **) malloc(((*env)->GetArrayLength(env, argv)+1) * sizeof(char *));
104
105 for (i = 0; i < (*env)->GetArrayLength(env, argv); i++) {
106 jobject str = (jobject) (*env)->GetObjectArrayElement(env, argv, i);
107 args[i] = strdup((char*)(*env)->GetStringUTFChars(env, (jstring)str, 0));
108 }
109 args[(*env)->GetArrayLength(env, argv)] = NULL;
110
111 ret = dt_main(i, args);
112
113 for (i = 0; args[i] != NULL; i++) {
114 free(args[i]);
115 }
116 free(args);
117
118 return ret;
119}
120
121JNIEXPORT void JNICALL
122Java_org_echoline_drawterm_MainActivity_setMouse(
123 JNIEnv *env,
124 jobject obj,
125 jintArray args) {
126 jboolean isCopy;
127 jint *data;
128 if ((*env)->GetArrayLength(env, args) < 3)
129 return;
130 data = (*env)->GetIntArrayElements(env, args, &isCopy);
131 mousept.x = (int)(data[0] / ws);
132 mousept.y = (int)(data[1] / hs);
133 buttons = data[2];
134 (*env)->ReleaseIntArrayElements(env, args, data, 0);
135 absmousetrack(mousept.x, mousept.y, buttons, ticks());
136}
137
138JNIEXPORT void JNICALL
139Java_org_echoline_drawterm_MainActivity_setDTSurface(
140 JNIEnv* jenv,
141 jobject obj,
142 jobject surface) {
143 if (surface != NULL) {
144 window = ANativeWindow_fromSurface(jenv, surface);
145 ANativeWindow_setBuffersGeometry(window, screenWidth, screenHeight,
146 AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM);
147 flushmemscreen(Rect(0, 0, screenWidth, screenHeight));
148 } else if (window != NULL) {
149 ANativeWindow_release(window);
150 window = NULL;
151 }
152}
153
154JNIEXPORT void JNICALL
155Java_org_echoline_drawterm_MainActivity_exitDT(
156 JNIEnv* jenv,
157 jobject obj) {
158 exit(0);
159}
160
161JNIEXPORT void JNICALL
162Java_org_echoline_drawterm_MainActivity_sendPicture(
163 JNIEnv* env,
164 jobject obj,
165 jbyteArray array) {
166 jint len = (*env)->GetArrayLength(env, array);
167 jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
168 camlen = len;
169 cambuf = malloc(camlen);
170 memcpy(cambuf, bytes, camlen);
171 (*env)->ReleaseByteArrayElements(env, array, bytes, 0);
172}
173
gui-android/java/org/echoline/drawterm/DrawTermThread.java+32−0
@@ -0,0 +1,32 @@
1package org.echoline.drawterm;
2
3/**
4 * Created by eli on 12/4/17.
5 */
6
7public class DrawTermThread extends Thread {
8 private MainActivity m;
9 private String p;
10 private String []args;
11
12 public DrawTermThread(String []args, String p, MainActivity m) {
13 this.m = m;
14 this.p = p;
15 this.args = args;
16 }
17
18 @Override
19 public void run() {
20 if (p != null && !p.equals(""))
21 m.setPass(p);
22 m.dtmain(args);
23 m.runOnUiThread(new Runnable() {
24 @Override
25 public void run() {
26 m.exitDT();
27 m.setContentView(R.layout.server_main);
28 m.populateServers(m);
29 }
30 });
31 }
32}
gui-android/java/org/echoline/drawterm/MainActivity.java+437−0
@@ -0,0 +1,437 @@
1package org.echoline.drawterm;
2
3import android.content.Context;
4import android.content.SharedPreferences;
5import android.content.pm.ActivityInfo;
6import android.content.res.Resources;
7import android.graphics.Point;
8import android.os.Bundle;
9import android.os.Environment;
10
11import android.app.Activity;
12
13import android.app.Notification;
14import android.app.NotificationManager;
15
16import android.util.DisplayMetrics;
17import android.util.Log;
18import android.view.Display;
19import android.view.MotionEvent;
20import android.view.View;
21import android.view.Menu;
22import android.view.MenuItem;
23import android.view.WindowManager;
24import android.view.Surface;
25import android.view.inputmethod.InputMethodManager;
26import android.view.KeyEvent;
27import android.widget.ArrayAdapter;
28import android.widget.Button;
29import android.widget.EditText;
30import android.widget.LinearLayout;
31import android.widget.ListView;
32import android.widget.TextView;
33import android.content.ClipData;
34import android.content.ClipboardManager;
35import android.hardware.camera2.CameraManager;
36import android.hardware.camera2.CameraAccessException;
37import android.hardware.camera2.CameraDevice;
38import android.hardware.camera2.CaptureRequest;
39import android.hardware.camera2.CameraMetadata;
40import android.hardware.camera2.CameraCaptureSession;
41import android.hardware.camera2.TotalCaptureResult;
42import android.media.Image;
43import android.media.ImageReader;
44import android.graphics.ImageFormat;
45import android.os.Handler;
46import android.os.HandlerThread;
47
48import java.io.File;
49import java.util.Map;
50import java.nio.ByteBuffer;
51import java.util.List;
52import java.util.ArrayList;
53
54public class MainActivity extends Activity {
55 private Map<String, ?> map;
56 private MainActivity mainActivity;
57 private boolean dtrunning = false;
58 private DrawTermThread dthread;
59 private int notificationId;
60 private CameraDevice cameraDevice = null;
61 private byte []jpegBytes;
62
63 static {
64 System.loadLibrary("drawterm");
65 }
66
67 public void showNotification(String text) {
68 Notification.Builder builder = new Notification.Builder(this)
69 .setDefaults(Notification.DEFAULT_SOUND)
70 .setSmallIcon(R.drawable.ic_small)
71 .setContentText(text)
72 .setStyle(new Notification.BigTextStyle().bigText(text))
73 .setPriority(Notification.PRIORITY_DEFAULT);
74
75 ((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).notify(notificationId, builder.build());
76 notificationId++;
77 }
78
79 public int numCameras() {
80 try {
81 return ((CameraManager)getSystemService(Context.CAMERA_SERVICE)).getCameraIdList().length;
82 } catch (CameraAccessException e) {
83 Log.w("drawterm", e.toString());
84 return 0;
85 }
86 }
87
88 public void takePicture(int id) {
89 try {
90 HandlerThread mBackgroundThread = new HandlerThread("Camera Background");
91 mBackgroundThread.start();
92 Handler mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
93 CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
94 String []cameraIdList = manager.getCameraIdList();
95 manager.openCamera(cameraIdList[id], new CameraDevice.StateCallback() {
96 public void onOpened(CameraDevice device) {
97 cameraDevice = device;
98 }
99 public void onDisconnected(CameraDevice device) {
100 if (cameraDevice != null)
101 cameraDevice.close();
102 cameraDevice = null;
103 }
104 public void onError(CameraDevice device, int error) {
105 if (cameraDevice != null)
106 cameraDevice.close();
107 cameraDevice = null;
108 }
109 }, mBackgroundHandler);
110 ImageReader reader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);
111 CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
112 captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
113 captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
114 captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
115 captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getWindowManager().getDefaultDisplay().getRotation());
116 captureBuilder.addTarget(reader.getSurface());
117 reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
118 public void onImageAvailable(ImageReader reader) {
119 Image image = null;
120 try {
121 image = reader.acquireLatestImage();
122 ByteBuffer buffer = image.getPlanes()[0].getBuffer();
123 jpegBytes = new byte[buffer.capacity()];
124 buffer.get(jpegBytes);
125 } catch (Exception e) {
126 Log.w("drawterm", e.toString());
127 } finally {
128 if (image != null) {
129 image.close();
130 }
131 }
132 }
133 }, mBackgroundHandler);
134 List<Surface> outputSurfaces = new ArrayList<Surface>(1);
135 outputSurfaces.add(reader.getSurface());
136 cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
137 public void onConfigured(CameraCaptureSession session) {
138 try {
139 List<CaptureRequest> captureRequests = new ArrayList<CaptureRequest>(10);
140 for (int i = 0; i < 10; i++)
141 captureRequests.add(captureBuilder.build());
142 session.captureBurst(captureRequests, new CameraCaptureSession.CaptureCallback() {
143 public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) {
144 try {
145 sendPicture(jpegBytes);
146 mBackgroundThread.quitSafely();
147 mBackgroundThread.join();
148 } catch (Exception e) {
149 Log.w("drawterm", e.toString());
150 }
151 }
152 }, mBackgroundHandler);
153 } catch (CameraAccessException e) {
154 e.printStackTrace();
155 }
156 }
157 public void onConfigureFailed(CameraCaptureSession session) {
158 }
159 }, mBackgroundHandler);
160 } catch (Exception e) {
161 e.printStackTrace();
162 }
163 }
164
165 public void serverView(View v) {
166 setContentView(R.layout.server_main);
167 serverButtons();
168
169 String s = (String)map.get(((TextView)v).getText().toString());
170 String []a = s.split("\007");
171
172 ((EditText)findViewById(R.id.cpuServer)).setText((String)a[0]);
173 ((EditText)findViewById(R.id.authServer)).setText((String)a[1]);
174 ((EditText)findViewById(R.id.userName)).setText((String)a[2]);
175 if (a.length > 3)
176 ((EditText)findViewById(R.id.passWord)).setText((String)a[3]);
177 }
178
179 public void populateServers(Context context) {
180 ListView ll = (ListView)findViewById(R.id.servers);
181 ArrayAdapter<String> la = new ArrayAdapter<String>(this, R.layout.item_main);
182 SharedPreferences settings = getSharedPreferences("DrawtermPrefs", 0);
183 map = (Map<String, ?>)settings.getAll();
184 String key;
185 Object []keys = map.keySet().toArray();
186 for (int i = 0; i < keys.length; i++) {
187 key = (String)keys[i];
188 la.add(key);
189 }
190 ll.setAdapter(la);
191
192 setDTSurface(null);
193 dtrunning = false;
194 }
195
196 public void runDrawterm(String []args, String pass) {
197 Resources res = getResources();
198 DisplayMetrics dm = res.getDisplayMetrics();
199
200 int wp = dm.widthPixels;
201 int hp = dm.heightPixels;
202
203 setContentView(R.layout.drawterm_main);
204
205 Button kbutton = (Button)findViewById(R.id.keyboardToggle);
206 kbutton.setOnClickListener(new View.OnClickListener() {
207 @Override
208 public void onClick(final View view) {
209 InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
210 imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
211 }
212 });
213
214 int rid = res.getIdentifier("navigation_bar_height", "dimen", "android");
215 if (rid > 0) {
216 hp -= res.getDimensionPixelSize(rid);
217 }
218 LinearLayout ll = (LinearLayout)findViewById(R.id.dtButtons);
219 hp -= ll.getHeight();
220
221 int w = (int)(wp * (160.0/dm.xdpi));
222 int h = (int)(hp * (160.0/dm.ydpi));
223 float ws = (float)wp/w;
224 float hs = (float)hp/h;
225 // only scale up
226 if (ws < 1) {
227 ws = 1;
228 w = wp;
229 }
230 if (hs < 1) {
231 hs = 1;
232 h = hp;
233 }
234
235 MySurfaceView mView = new MySurfaceView(mainActivity, w, h, ws, hs);
236 mView.getHolder().setFixedSize(w, h);
237
238 LinearLayout l = (LinearLayout)findViewById(R.id.dlayout);
239 l.addView(mView, 1, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
240
241 dthread = new DrawTermThread(args, pass, mainActivity);
242 dthread.start();
243
244 dtrunning = true;
245 }
246
247 public void serverButtons() {
248 Button button = (Button)findViewById(R.id.save);
249 button.setOnClickListener(new View.OnClickListener() {
250 @Override
251 public void onClick(View v) {
252 String cpu = ((EditText)findViewById(R.id.cpuServer)).getText().toString();
253 String auth = ((EditText)findViewById(R.id.authServer)).getText().toString();
254 String user = ((EditText)findViewById(R.id.userName)).getText().toString();
255 String pass = ((EditText)findViewById(R.id.passWord)).getText().toString();
256
257 SharedPreferences settings = getSharedPreferences("DrawtermPrefs", 0);
258 SharedPreferences.Editor editor = settings.edit();
259 editor.putString(user + "@" + cpu + " (auth=" + auth + ")", cpu + "\007" + auth + "\007" + user + "\007" + pass);
260 editor.commit();
261 }
262 });
263
264 button = (Button) findViewById(R.id.connect);
265 button.setOnClickListener(new View.OnClickListener() {
266 @Override
267 public void onClick(final View view) {
268 String cpu = ((EditText)findViewById(R.id.cpuServer)).getText().toString();
269 String auth = ((EditText)findViewById(R.id.authServer)).getText().toString();
270 String user = ((EditText)findViewById(R.id.userName)).getText().toString();
271 String pass = ((EditText)findViewById(R.id.passWord)).getText().toString();
272
273 String args[] = {"drawterm", "-p", "-h", cpu, "-a", auth, "-u", user};
274 runDrawterm(args, pass);
275 }
276 });
277 }
278
279 @Override
280 protected void onCreate(Bundle savedInstanceState) {
281 super.onCreate(savedInstanceState);
282 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
283 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
284
285 mainActivity = this;
286 setObject();
287 setContentView(R.layout.activity_main);
288 populateServers(this);
289
290 View fab = findViewById(R.id.fab);
291 fab.setOnClickListener(new View.OnClickListener() {
292 @Override
293 public void onClick(View v) {
294 setContentView(R.layout.server_main);
295 serverButtons();
296 }
297 });
298 }
299
300 @Override
301 public boolean dispatchKeyEvent(KeyEvent event)
302 {
303 if (!dtrunning) {
304 return super.dispatchKeyEvent(event);
305 }
306
307 int k = event.getUnicodeChar();
308 if (k == 0) {
309 k = event.getDisplayLabel();
310 if (k >= 'A' && k <= 'Z')
311 k |= 0x20;
312 }
313 String chars = event.getCharacters();
314 if (k == 0 && chars != null) {
315 for (int i = 0; i < chars.length(); i++) {
316 k = chars.codePointAt(i);
317 keyDown(k);
318 keyUp(k);
319 }
320 return true;
321 }
322
323 if (k == 0) switch (event.getKeyCode()) {
324 case KeyEvent.KEYCODE_DEL:
325 k = 0x0008;
326 break;
327 case KeyEvent.KEYCODE_FORWARD_DEL:
328 k = 0x007F;
329 break;
330 case KeyEvent.KEYCODE_ESCAPE:
331 k = 0x001B;
332 break;
333 case KeyEvent.KEYCODE_MOVE_HOME:
334 k = 0xF00D;
335 break;
336 case KeyEvent.KEYCODE_MOVE_END:
337 k = 0xF018;
338 break;
339 case KeyEvent.KEYCODE_PAGE_UP:
340 k = 0xF00F;
341 break;
342 case KeyEvent.KEYCODE_PAGE_DOWN:
343 k = 0xF013;
344 break;
345 case KeyEvent.KEYCODE_INSERT:
346 k = 0xF014;
347 break;
348 case KeyEvent.KEYCODE_SYSRQ:
349 k = 0xF010;
350 break;
351 case KeyEvent.KEYCODE_DPAD_UP:
352 k = 0xF00E;
353 break;
354 case KeyEvent.KEYCODE_DPAD_LEFT:
355 k = 0xF011;
356 break;
357 case KeyEvent.KEYCODE_DPAD_RIGHT:
358 k = 0xF012;
359 break;
360 case KeyEvent.KEYCODE_DPAD_DOWN:
361 k = 0xF800;
362 break;
363 }
364
365 if (k == 0)
366 return true;
367
368 if (event.isCtrlPressed()) {
369 keyDown(0xF017);
370 }
371 if (event.isAltPressed() && k < 128) {
372 keyDown(0xF015);
373 }
374
375 if (event.getAction() == KeyEvent.ACTION_DOWN) {
376 keyDown(k);
377 }
378 else if (event.getAction() == KeyEvent.ACTION_UP) {
379 keyUp(k);
380 }
381
382 if (event.isCtrlPressed()) {
383 keyUp(0xF017);
384 }
385 if (event.isAltPressed() && k < 128) {
386 keyUp(0xF015);
387 }
388
389 return true;
390 }
391
392 @Override
393 public void onBackPressed()
394 {
395 }
396
397 @Override
398 public void onDestroy()
399 {
400 setDTSurface(null);
401 dtrunning = false;
402 exitDT();
403 super.onDestroy();
404 }
405
406 public void setClipBoard(String str) {
407 ClipboardManager cm = (ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
408 if (cm != null) {
409 ClipData cd = ClipData.newPlainText(null, str);
410 cm.setPrimaryClip(cd);
411 }
412 }
413
414 public String getClipBoard() {
415 ClipboardManager cm = (ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
416 if (cm != null) {
417 ClipData cd = cm.getPrimaryClip();
418 if (cd != null)
419 return (String)(cd.getItemAt(0).coerceToText(mainActivity.getApplicationContext()).toString());
420 }
421 return "";
422 }
423
424 public native void dtmain(Object[] args);
425 public native void setPass(String arg);
426 public native void setWidth(int arg);
427 public native void setHeight(int arg);
428 public native void setWidthScale(float arg);
429 public native void setHeightScale(float arg);
430 public native void setDTSurface(Surface surface);
431 public native void setMouse(int[] args);
432 public native void setObject();
433 public native void keyDown(int c);
434 public native void keyUp(int c);
435 public native void exitDT();
436 public native void sendPicture(byte[] array);
437}
gui-android/java/org/echoline/drawterm/MySurfaceView.java+91−0
@@ -0,0 +1,91 @@
1package org.echoline.drawterm;
2
3import android.util.Log;
4
5import android.content.Context;
6import android.graphics.Bitmap;
7import android.os.SystemClock;
8import android.view.MotionEvent;
9import android.view.SurfaceView;
10import android.view.SurfaceHolder;
11import android.view.View;
12import android.widget.CheckBox;
13import android.widget.EditText;
14
15import java.nio.ByteBuffer;
16import java.nio.IntBuffer;
17import java.security.spec.ECField;
18
19/**
20 * Created by eli on 12/3/17.
21 */
22public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
23 private int screenWidth, screenHeight;
24 private MainActivity mainActivity;
25 private float ws, hs;
26
27 public MySurfaceView(Context context, int w, int h, float ws, float hs) {
28 super(context);
29 screenHeight = h;
30 screenWidth = w;
31 this.ws = ws;
32 this.hs = hs;
33 mainActivity = (MainActivity)context;
34 mainActivity.setWidth(screenWidth);
35 mainActivity.setHeight(screenHeight);
36 mainActivity.setWidthScale(ws);
37 mainActivity.setHeightScale(hs);
38 setWillNotDraw(true);
39
40 getHolder().addCallback(this);
41
42 setOnTouchListener(new View.OnTouchListener() {
43 private int[] mouse = new int[3];
44
45 @Override
46 public boolean onTouch(View v, MotionEvent event) {
47 CheckBox left = (CheckBox)mainActivity.findViewById(R.id.mouseLeft);
48 CheckBox middle = (CheckBox)mainActivity.findViewById(R.id.mouseMiddle);
49 CheckBox right = (CheckBox)mainActivity.findViewById(R.id.mouseRight);
50 CheckBox up = (CheckBox)mainActivity.findViewById(R.id.mouseUp);
51 CheckBox down = (CheckBox)mainActivity.findViewById(R.id.mouseDown);
52 int buttons = (left.isChecked()? 1: 0) |
53 (middle.isChecked()? 2: 0) |
54 (right.isChecked()? 4: 0) |
55 (up.isChecked()? 8: 0) |
56 (down.isChecked()? 16: 0);
57 if (event.getAction() == MotionEvent.ACTION_DOWN) {
58 mouse[0] = Math.round(event.getX());
59 mouse[1] = Math.round(event.getY());
60 mouse[2] = buttons;
61 mainActivity.setMouse(mouse);
62 } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
63 mouse[0] = Math.round(event.getX());
64 mouse[1] = Math.round(event.getY());
65 mouse[2] = buttons;
66 mainActivity.setMouse(mouse);
67 } else if (event.getAction() == MotionEvent.ACTION_UP) {
68 mouse[0] = Math.round(event.getX());
69 mouse[1] = Math.round(event.getY());
70 mouse[2] = 0;
71 mainActivity.setMouse(mouse);
72 }
73 return true;
74 }
75 });
76 }
77
78 @Override
79 public void surfaceCreated(SurfaceHolder holder) {
80 mainActivity.setDTSurface(holder.getSurface());
81 }
82
83 @Override
84 public void surfaceChanged(SurfaceHolder holder, int w, int h, int format) {
85 }
86
87 @Override
88 public void surfaceDestroyed(SurfaceHolder holder) {
89 mainActivity.setDTSurface(null);
90 }
91}
gui-android/res/layout/activity_main.xml+24−0
@@ -0,0 +1,24 @@
1<?xml version="1.0" encoding="utf-8"?>
2<android.widget.FrameLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 xmlns:tools="http://schemas.android.com/tools"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context="org.echoline.drawterm.MainActivity">
9
10 <include layout="@layout/content_main" />
11
12 <LinearLayout
13 android:layout_width="wrap_content"
14 android:layout_height="wrap_content"
15 android:layout_gravity="bottom|end">
16
17 <Button
18 android:id="@+id/fab"
19 android:text="add server"
20 android:layout_width="wrap_content"
21 android:layout_height="wrap_content"/>
22 </LinearLayout>
23
24</android.widget.FrameLayout>
gui-android/res/layout/content_main.xml+16−0
@@ -0,0 +1,16 @@
1<?xml version="1.0" encoding="utf-8"?>
2<android.widget.FrameLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 xmlns:tools="http://schemas.android.com/tools"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context="org.echoline.drawterm.MainActivity"
9 tools:showIn="@layout/activity_main">
10 <ListView
11 android:id="@+id/servers"
12 android:layout_width="match_parent"
13 android:layout_height="match_parent"
14 android:orientation="vertical">
15 </ListView>
16</android.widget.FrameLayout>
gui-android/res/layout/drawterm_main.xml+44−0
@@ -0,0 +1,44 @@
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
4 android:id="@+id/dlayout"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:orientation="vertical"
8 tools:context="org.echoline.drawterm.MainActivity">
9
10 <LinearLayout
11 android:layout_width="match_parent"
12 android:layout_height="wrap_content"
13 android:layout_gravity="bottom"
14 android:gravity="center_horizontal"
15 android:orientation="horizontal"
16 android:id="@+id/dtButtons">
17
18 <CheckBox
19 android:id="@+id/mouseLeft"
20 android:layout_width="wrap_content"
21 android:layout_height="match_parent" />
22 <CheckBox
23 android:id="@+id/mouseMiddle"
24 android:layout_width="wrap_content"
25 android:layout_height="match_parent" />
26 <CheckBox
27 android:id="@+id/mouseRight"
28 android:layout_width="wrap_content"
29 android:layout_height="match_parent" />
30 <CheckBox
31 android:id="@+id/mouseUp"
32 android:layout_width="wrap_content"
33 android:layout_height="match_parent" />
34 <CheckBox
35 android:id="@+id/mouseDown"
36 android:layout_width="wrap_content"
37 android:layout_height="match_parent" />
38 <Button
39 android:id="@+id/keyboardToggle"
40 android:text="kb"
41 android:layout_width="wrap_content"
42 android:layout_height="wrap_content" />
43 </LinearLayout>
44</LinearLayout>
gui-android/res/layout/item_main.xml+8−0
@@ -0,0 +1,8 @@
1<?xml version="1.0" encoding="utf-8"?>
2<TextView xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent" android:layout_height="match_parent"
4 android:padding="10dp"
5 android:textSize="16sp"
6 android:onClick="serverView">
7</TextView>
8
gui-android/res/layout/server_main.xml+56−0
@@ -0,0 +1,56 @@
1<?xml version="1.0" encoding="utf-8"?>
2<android.widget.FrameLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 xmlns:tools="http://schemas.android.com/tools"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context="org.echoline.drawterm.MainActivity">
9
10 <LinearLayout
11 android:layout_height="match_parent"
12 android:layout_width="match_parent"
13 android:orientation="vertical">
14
15 <EditText
16 android:id="@+id/cpuServer"
17 android:layout_width="match_parent"
18 android:layout_height="wrap_content"
19 android:ems="10"
20 android:hint="CPU" />
21 <EditText
22 android:id="@+id/authServer"
23 android:layout_width="match_parent"
24 android:layout_height="wrap_content"
25 android:ems="10"
26 android:hint="Auth" />
27 <EditText
28 android:id="@+id/userName"
29 android:layout_width="match_parent"
30 android:layout_height="wrap_content"
31 android:ems="10"
32 android:hint="Username" />
33
34 <EditText
35 android:id="@+id/passWord"
36 android:layout_width="match_parent"
37 android:layout_height="wrap_content"
38 android:ems="10"
39 android:password="true"
40 android:hint="Password"/>
41
42 <Button
43 android:id="@+id/save"
44 android:layout_width="match_parent"
45 android:layout_height="wrap_content"
46 android:text="Save" />
47
48 <Button
49 android:id="@+id/connect"
50 android:layout_width="match_parent"
51 android:layout_height="wrap_content"
52 android:text="Connect" />
53
54 </LinearLayout>
55
56</android.widget.FrameLayout>
gui-android/res/values/colors.xml+6−0
@@ -0,0 +1,6 @@
1<?xml version="1.0" encoding="utf-8"?>
2<resources>
3 <color name="colorPrimary">#3F51B5</color>
4 <color name="colorPrimaryDark">#303F9F</color>
5 <color name="colorAccent">#3FB551</color>
6</resources>
gui-android/res/values/strings.xml+3−0
@@ -0,0 +1,3 @@
1<resources>
2 <string name="app_name">Drawterm</string>
3</resources>
gui-android/res/values/styles.xml+8−0
@@ -0,0 +1,8 @@
1<resources>
2
3 <!-- Base application theme. -->
4 <style name="AppTheme" parent="android:Theme.NoTitleBar">
5 <!-- Customize your theme here. -->
6 </style>
7
8</resources>
gui-fbdev/Makefile+12−0
@@ -0,0 +1,12 @@
1ROOT=..
2include ../Make.config
3LIB=libgui.a
4
5OFILES=\
6 fbdev.$O\
7
8default: $(LIB)
9$(LIB): $(OFILES)
10 $(AR) r $(LIB) $(OFILES)
11 $(RANLIB) $(LIB)
12
gui-fbdev/fbdev.c+673−0
@@ -0,0 +1,673 @@
1#include "u.h"
2#include "lib.h"
3#include "dat.h"
4#include "fns.h"
5#include "error.h"
6
7#include <draw.h>
8#include <memdraw.h>
9#include <keyboard.h>
10#include <cursor.h>
11#include "screen.h"
12
13#undef long
14#undef ulong
15
16#include <linux/fb.h>
17#include <linux/input.h>
18
19uchar* fbp;
20Memimage* screenimage;
21Memimage* backbuf;
22Rectangle screenr;
23char* snarfbuf;
24struct fb_fix_screeninfo finfo;
25struct fb_var_screeninfo vinfo;
26int *eventfds = NULL;
27int neventfds;
28Point mousexy;
29char shift_state;
30int ttyfd;
31char* tty;
32char hidden;
33int devicesfd;
34ulong chan;
35int depth;
36
37#include <sys/ioctl.h>
38#include <sys/mman.h>
39#include <limits.h>
40
41#include <fcntl.h>
42#include <termios.h>
43#include <poll.h>
44#include <sys/ioctl.h>
45#include <linux/keyboard.h>
46#include <signal.h>
47
48#include <termios.h>
49
50#define ulong p9_ulong
51
52int code2key[] = {
53 Kesc, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\x08',
54 '\x09', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
55 Kctl, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', Kshift,
56 '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', Kshift, '*', Kalt,
57 ' ', Kcaps, KF|1, KF|2, KF|3, KF|4, KF|5, KF|6, KF|7, KF|8, KF|9, KF|10,
58 Knum, Kscroll,
59 '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.',
60};
61
62int code2key_shift[] = {
63 Kesc, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\x08',
64 '\x09', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
65 Kctl, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', '~', Kshift,
66 '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', Kshift, '*', Kalt,
67 ' ', Kcaps, KF|1, KF|2, KF|3, KF|4, KF|5, KF|6, KF|7, KF|8, KF|9, KF|10,
68 Knum, Kscroll,
69 '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.',
70};
71
72Memimage *gscreen;
73char *snarfbuf = nil;
74
75int onevent(struct input_event*);
76void termctl(uint32_t o, int or);
77void ctrlc(int sig);
78
79void
80_fbput(Memimage *m, Rectangle r) {
81 int y;
82
83 for (y = r.min.y; y < r.max.y; y++){
84 long loc = y * finfo.line_length + r.min.x * depth;
85 void *ptr = m->data->bdata + y * m->width * 4 + r.min.x * depth;
86
87 memcpy(fbp + loc, ptr, Dx(r) * depth);
88 }
89}
90
91Memimage*
92fbattach(int fbdevidx)
93{
94 Rectangle r;
95 char devname[64];
96 size_t size;
97 int fd;
98
99 /*
100 * Connect to /dev/fb0
101 */
102 snprintf(devname, sizeof(devname) - 1, "/dev/fb%d", fbdevidx);
103 if ((fd = open(devname, O_RDWR)) < 0)
104 goto err;
105
106 if (ioctl(fd, FBIOGET_VSCREENINFO, &(vinfo)) < 0)
107 goto err;
108
109 switch (vinfo.bits_per_pixel) {
110 case 32:
111 chan = XRGB32;
112 depth = 4;
113 break;
114 case 16:
115 chan = RGB16;
116 depth = 2;
117 break;
118 default:
119 goto err;
120 }
121
122 if (ioctl(fd, FBIOGET_FSCREENINFO, &(finfo)) < 0)
123 goto err;
124
125 size = vinfo.yres_virtual * finfo.line_length;
126 if ((fbp = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0)) < 0)
127 goto err;
128 /*
129 * Figure out underlying screen format.
130 */
131 r = Rect(0, 0, vinfo.xres_virtual, vinfo.yres_virtual);
132
133 screenr = r;
134
135 screenimage = allocmemimage(r, chan);
136 backbuf = allocmemimage(r, chan);
137 return backbuf;
138
139err:
140 return nil;
141}
142
143int
144eventattach()
145{
146 char eventfile[PATH_MAX] = "";
147 char line[PATH_MAX];
148 FILE *devices;
149 char *ptr;
150
151 neventfds = 0;
152 devices = fopen("/proc/bus/input/devices", "r");
153 if (devices == NULL)
154 return -1;
155 while (fgets(line, sizeof(line)-1, devices) != NULL)
156 if (line[0] == 'H') {
157 ptr = strstr(line, "event");
158 if (ptr == NULL)
159 continue;
160 ptr[strcspn(ptr, " \r\n")] = '\0';
161 snprintf(eventfile, sizeof(eventfile)-1, "/dev/input/%s", ptr);
162 neventfds++;
163 eventfds = realloc(eventfds, neventfds * sizeof(int));
164 eventfds[neventfds-1] = open(eventfile, O_RDONLY);
165 if (eventfds[neventfds-1] < 0)
166 neventfds--;
167 }
168 fclose(devices);
169
170 if (neventfds == 0)
171 return -1;
172 return 1;
173}
174
175void
176flushmemscreen(Rectangle r)
177{
178 int x, y, i;
179 Point p;
180 long fbloc;
181 int x2, y2;
182
183 if (rectclip(&r, screenimage->r) == 0)
184 return;
185 if (Dx(r) == 0 || Dy(r) == 0)
186 return;
187
188 assert(!canqlock(&drawlock));
189
190 memimagedraw(screenimage, r, backbuf, r.min, nil, r.min, S);
191
192 if (hidden != 0)
193 return;
194
195 p = mousexy;
196
197 // draw cursor
198 for (x = 0; x < 16; x++) {
199 x2 = x + cursor.offset.x;
200
201 if ((p.x + x2) < 0)
202 continue;
203
204 if ((p.x + x2) >= screenimage->r.max.x)
205 break;
206
207 for (y = 0; y < 16; y++) {
208 y2 = y + cursor.offset.y;
209
210 if ((p.y + y2) < 0)
211 continue;
212
213 if ((p.y + y2) >= screenimage->r.max.y)
214 break;
215
216 i = y * 2 + x / 8;
217 fbloc = ((p.y+y2) * screenimage->r.max.x + (p.x+x2)) * depth;
218
219 if (cursor.clr[i] & (128 >> (x % 8))) {
220 switch (depth) {
221 case 2:
222 *((uint16_t*)(screenimage->data->bdata + fbloc)) = 0xFFFF;
223 break;
224 case 4:
225 *((uint32_t*)(screenimage->data->bdata + fbloc)) = 0xFFFFFFFF;
226 break;
227 }
228 }
229
230 if (cursor.set[i] & (128 >> (x % 8))) {
231 switch (depth) {
232 case 2:
233 *((uint16_t*)(screenimage->data->bdata + fbloc)) = 0x0000;
234 break;
235 case 4:
236 *((uint32_t*)(screenimage->data->bdata + fbloc)) = 0xFF000000;
237 break;
238 }
239 }
240 }
241 }
242
243 _fbput(screenimage, r);
244}
245
246static void
247fbproc(void *v)
248{
249 struct input_event data;
250 char buf[32];
251 struct pollfd *pfd;
252 int r;
253 int ioctlarg;
254
255 pfd = calloc(3, sizeof(struct pollfd));
256 pfd[0].fd = ttyfd; // for virtual console switches
257 pfd[0].events = POLLPRI;
258 pfd[1].fd = 0; // stdin goes to nowhere
259 pfd[1].events = POLLIN;
260 pfd[2].fd = open("/proc/bus/input/devices", O_RDONLY); // input hotplug
261 if (pfd[2].fd < 0)
262 panic("cannot open /proc/bus/input/devices: %r");
263 pfd[2].events = POLLIN;
264
265TOP:
266 while(read(pfd[2].fd, buf, 31) > 0);
267
268 pfd = realloc(pfd, sizeof(struct pollfd) * (neventfds + 3));
269 for (r = 0; r < neventfds; r++) {
270 pfd[r+3].fd = eventfds[r];
271 pfd[r+3].events = POLLIN;
272 }
273
274 for(;;) {
275 shift_state = 6;
276 if (ioctl(0, TIOCLINUX, &shift_state) < 0)
277 panic("ioctl TIOCLINUX 6: %r");
278
279 r = poll(pfd, 3+neventfds, -1);
280 if (r < 0)
281 oserror();
282 if (pfd[0].revents & POLLPRI) {
283 if ((r = read(ttyfd, buf, 31)) <= 0)
284 panic("ttyfd read: %r");
285 buf[r] = '\0';
286 if (strcmp(buf, tty) == 0) {
287 hidden = 0;
288 printf("\e[?25l");
289 fflush(stdout);
290 qlock(&drawlock);
291 flushmemscreen(gscreen->clipr);
292 qunlock(&drawlock);
293 }
294 else
295 hidden = 1;
296 close(ttyfd);
297 ttyfd = open("/sys/class/tty/tty0/active", O_RDONLY);
298 if (ttyfd < 0)
299 panic("cannot open tty active fd: %r");
300 pfd[0].fd = ttyfd;
301 read(ttyfd, buf, 0);
302 }
303 if (pfd[1].revents & POLLIN)
304 read(pfd[1].fd, buf, 31);
305 if (pfd[2].revents & POLLIN) {
306 for (r = 0; r < neventfds; r++)
307 close(eventfds[r]);
308 if(eventattach() < 0) {
309 panic("cannot open event files: %r");
310 }
311 goto TOP;
312 }
313 for (r = 0; r < neventfds; r++)
314 if (pfd[r+3].revents & POLLIN) {
315 if (read(pfd[r+3].fd, &data, sizeof(data)) != sizeof(data))
316 panic("eventfd read: %r");
317 if (onevent(&data) == 0) {
318 ioctlarg = 15;
319 if (ioctl(0, TIOCLINUX, &ioctlarg) != 0) {
320 ioctlarg = 4;
321 ioctl(0, TIOCLINUX, &ioctlarg);
322 qlock(&drawlock);
323 flushmemscreen(gscreen->clipr);
324 qunlock(&drawlock);
325 } else {
326 write(1, "\033[9;30]", 7);
327 }
328 }
329 }
330 }
331
332 printf("\e[?25h");
333 fflush(stdout);
334 termctl(ECHO, 1);
335 free(pfd);
336}
337
338void
339screensize(Rectangle r, ulong chan)
340{
341 gscreen = backbuf;
342 gscreen->clipr = ZR;
343}
344
345void
346screeninit(void)
347{
348 int r;
349 char buf[1];
350
351 // set up terminal
352 printf("\e[?25l");
353 fflush(stdout);
354 termctl(~(ICANON|ECHO), 0);
355 signal(SIGINT, ctrlc);
356
357 memimageinit();
358
359 // tty switching
360 ttyfd = open("/sys/class/tty/tty0/active", O_RDONLY);
361 if (ttyfd >= 0) {
362 tty = malloc(32);
363 r = read(ttyfd, tty, 31);
364 if (r >= 0)
365 tty[r] = '\0';
366 else
367 tty[0] = '\0';
368 close(ttyfd);
369 ttyfd = open("/sys/class/tty/tty0/active", O_RDONLY);
370 }
371 if (ttyfd < 0)
372 panic("cannot open tty active fd: %r");
373 read(ttyfd, buf, 0);
374 hidden = 0;
375
376 if(fbattach(0) == nil) {
377 panic("cannot open framebuffer: %r");
378 }
379
380 if(eventattach() < 0) {
381 panic("cannot open event files: %r");
382 }
383
384 screensize(screenr, chan);
385 if (gscreen == nil)
386 panic("screensize failed");
387
388 gscreen->clipr = screenr;
389 kproc("fbdev", fbproc, nil);
390
391 terminit();
392
393 qlock(&drawlock);
394 flushmemscreen(gscreen->clipr);
395 qunlock(&drawlock);
396}
397
398Memdata*
399attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen)
400{
401 *r = gscreen->clipr;
402 *chan = gscreen->chan;
403 *depth = gscreen->depth;
404 *width = gscreen->width;
405 *softscreen = 1;
406
407 gscreen->data->ref++;
408 return gscreen->data;
409}
410
411void
412getcolor(ulong i, ulong *r, ulong *g, ulong *b)
413{
414 ulong v;
415
416 v = cmap2rgb(i);
417 *r = (v>>16)&0xFF;
418 *g = (v>>8)&0xFF;
419 *b = v&0xFF;
420}
421
422void
423setcolor(ulong i, ulong r, ulong g, ulong b)
424{
425 /* no-op */
426 return;
427}
428
429char*
430clipread(void)
431{
432 if(snarfbuf)
433 return strdup(snarfbuf);
434 return nil;
435}
436
437int
438clipwrite(char *buf)
439{
440 if(snarfbuf)
441 free(snarfbuf);
442 snarfbuf = strdup(buf);
443 return 0;
444}
445
446void
447guimain(void)
448{
449 cpubody();
450}
451
452void
453termctl(uint32_t o, int or)
454{
455 struct termios t;
456
457 tcgetattr(0, &t);
458 if (or)
459 t.c_lflag |= o;
460 else
461 t.c_lflag &= o;
462 tcsetattr(0, TCSANOW, &t);
463}
464
465void
466ctrlc(int sig) {
467}
468
469int
470onevent(struct input_event *data)
471{
472 Rectangle old, new;
473 ulong msec;
474 static int buttons;
475 static Point coord;
476 static char touched;
477 static Point startmousept;
478 static Point startpt;
479 int key;
480 static ulong lastmsec = 0;
481
482 if (hidden != 0)
483 return -1;
484
485 msec = ticks();
486
487 old.min = mousexy;
488 old.max = addpt(old.min, Pt(16, 16));
489
490 buttons &= ~0x18;
491
492 switch(data->type) {
493 case 3:
494 switch(data->code) {
495 case 0:
496 coord.x = data->value;
497 break;
498 case 1:
499 coord.y = data->value;
500 break;
501 case 0x18:
502 case 0x1c:
503 if (data->value == 0)
504 touched = 0;
505 else if (data->value > 24) {
506 touched = 1;
507 startmousept = coord;
508 startpt = mousexy;
509 }
510 break;
511 default:
512 return -1;
513 }
514 if (touched)
515 mousexy = addpt(startpt, divpt(subpt(coord, startmousept), 4));
516 break;
517 case 2:
518 switch(data->code) {
519 case 0:
520 mousexy.x += data->value;
521 break;
522 case 1:
523 mousexy.y += data->value;
524 break;
525 case 8:
526 buttons |= data->value == 1? 8: 16;
527 break;
528 default:
529 return -1;
530 }
531 break;
532 case 1:
533 switch(data->code) {
534 case 0x110:
535 if (data->value == 1)
536 buttons |= 1;
537 else
538 buttons &= ~1;
539 break;
540 case 0x111:
541 if (data->value == 1)
542 buttons |= shift_state & (1 << KG_SHIFT)? 2: 4;
543 else
544 buttons &= ~(shift_state & (1 << KG_SHIFT)? 2: 4);
545 break;
546 case 0x112:
547 if (data->value == 1)
548 buttons |= 2;
549 else
550 buttons &= ~2;
551 break;
552 default:
553 if (hidden)
554 return 0;
555 if (data->code > 0 && data->code <= nelem(code2key)) {
556 if (shift_state & (1 << KG_SHIFT))
557 key = code2key_shift[data->code-1];
558 else
559 key = code2key[data->code-1];
560 if (key == Kshift)
561 return -1;
562 kbdkey(key, data->value);
563 return 0;
564 }
565 switch(data->code) {
566 case 87:
567 kbdkey(KF|11, data->value);
568 break;
569 case 88:
570 kbdkey(KF|12, data->value);
571 break;
572 case 96:
573 kbdkey('\n', data->value);
574 break;
575 case 97:
576 kbdkey(Kctl, data->value);
577 break;
578 case 98:
579 kbdkey('/', data->value);
580 break;
581 case 100:
582 kbdkey(Kalt, data->value);
583 break;
584 case 102:
585 kbdkey(Khome, data->value);
586 break;
587 case 103:
588 kbdkey(Kup, data->value);
589 break;
590 case 104:
591 kbdkey(Kpgup, data->value);
592 break;
593 case 105:
594 kbdkey(Kleft, data->value);
595 break;
596 case 106:
597 kbdkey(Kright, data->value);
598 break;
599 case 107:
600 kbdkey(Kend, data->value);
601 break;
602 case 108:
603 kbdkey(Kdown, data->value);
604 break;
605 case 109:
606 kbdkey(Kpgdown, data->value);
607 break;
608 case 110:
609 kbdkey(Kins, data->value);
610 break;
611 case 111:
612 kbdkey(Kdel, data->value);
613 break;
614 }
615 return 0;
616 }
617 break;
618 default:
619 return -1;
620 }
621
622 if (mousexy.x < screenimage->r.min.x)
623 mousexy.x = screenimage->r.min.x;
624 if (mousexy.y < screenimage->r.min.y)
625 mousexy.y = screenimage->r.min.y;
626 if (mousexy.x > screenimage->r.max.x)
627 mousexy.x = screenimage->r.max.x;
628 if (mousexy.y > screenimage->r.max.y)
629 mousexy.y = screenimage->r.max.y;
630
631 new.min = mousexy;
632 new.max = addpt(new.min, Pt(16, 16)); // size of cursor bitmap
633
634 combinerect(&new, old);
635 new.min = subpt(new.min, Pt(16, 16)); // to encompass any cursor->offset
636
637 qlock(&drawlock);
638 flushmemscreen(new);
639 qunlock(&drawlock);
640
641 if ((msec - lastmsec) < 10)
642 if (data->type != 1)
643 return 0;
644
645 lastmsec = msec;
646
647 absmousetrack(mousexy.x, mousexy.y, buttons, msec);
648
649 return 0;
650}
651
652void
653mouseset(Point p)
654{
655 qlock(&drawlock);
656 mousexy = p;
657 flushmemscreen(screenr);
658 qunlock(&drawlock);
659}
660
661void
662setcursor(void)
663{
664 qlock(&drawlock);
665 flushmemscreen(screenr);
666 qunlock(&drawlock);
667}
668
669void
670titlewrite(char* buf)
671{
672}
673
kern/devaudio-alsa.c+108−0
@@ -0,0 +1,108 @@
1/*
2 * ALSA
3 */
4#include <alsa/asoundlib.h>
5#include "u.h"
6#include "lib.h"
7#include "dat.h"
8#include "fns.h"
9#include "error.h"
10#include "devaudio.h"
11
12enum
13{
14 Channels = 2,
15 Rate = 44100,
16 Bits = 16,
17};
18
19static snd_pcm_t *playback;
20static snd_pcm_t *capture;
21static int speed = Rate;
22
23/* maybe this should return -1 instead of sysfatal */
24void
25audiodevopen(void)
26{
27 if(snd_pcm_open(&playback, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0)
28 error("snd_pcm_open playback");
29
30 if(snd_pcm_set_params(playback, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, speed, 1, 500000) < 0)
31 error("snd_pcm_set_params playback");
32
33 if(snd_pcm_prepare(playback) < 0)
34 error("snd_pcm_prepare playback");
35
36 if(snd_pcm_open(&capture, "default", SND_PCM_STREAM_CAPTURE, 0) < 0)
37 error("snd_pcm_open capture");
38
39 if(snd_pcm_set_params(capture, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, speed, 1, 500000) < 0)
40 error("snd_pcm_set_params capture");
41
42 if(snd_pcm_prepare(capture) < 0)
43 error("snd_pcm_prepare capture");
44}
45
46void
47audiodevclose(void)
48{
49 snd_pcm_drain(playback);
50 snd_pcm_close(playback);
51
52 snd_pcm_close(capture);
53}
54
55void
56audiodevsetvol(int what, int left, int right)
57{
58 if(what == Vspeed){
59 speed = left;
60 return;
61 }
62}
63
64void
65audiodevgetvol(int what, int *left, int *right)
66{
67 if(what == Vspeed){
68 *left = *right = speed;
69 return;
70 }
71
72 *left = *right = 100;
73}
74
75int
76audiodevwrite(void *v, int n)
77{
78 snd_pcm_sframes_t frames;
79 int tot, m;
80
81 for(tot = 0; tot < n; tot += m){
82 do {
83 frames = snd_pcm_writei(playback, v+tot, (n-tot)/4);
84 } while(frames == -EAGAIN);
85 if (frames < 0)
86 frames = snd_pcm_recover(playback, frames, 0);
87 if (frames < 0)
88 error((char*)snd_strerror(frames));
89 m = frames*4;
90 }
91
92 return tot;
93}
94
95int
96audiodevread(void *v, int n)
97{
98 snd_pcm_sframes_t frames;
99
100 do {
101 frames = snd_pcm_readi(capture, v, n/4);
102 } while(frames == -EAGAIN);
103
104 if (frames < 0)
105 error((char*)snd_strerror(frames));
106
107 return frames*4;
108}
main.c+1−0
@@ -54,6 +54,7 @@ main(int argc, char **argv) · 53 unmodified lines
54 if(bind("#U", "/root", MREPL) < 0)54 if(bind("#U", "/root", MREPL) < 0)
55 panic("bind #U: %r");55 panic("bind #U: %r");
56 bind("#A", "/dev", MAFTER);56 bind("#A", "/dev", MAFTER);
57 bind("#N", "/dev", MAFTER);
57 bind("#C", "/", MAFTER);58 bind("#C", "/", MAFTER);
58 59
59 if(open("/dev/cons", OREAD) != 0)60 if(open("/dev/cons", OREAD) != 0)

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