From 21e8a9be68a59cfe486ae81a1421e4f9603f47e8 Mon Sep 17 00:00:00 2001 From: Twaik Yont <9674930+twaik@users.noreply.github.com> Date: Sat, 21 Dec 2024 23:18:13 +0200 Subject: [PATCH] enhancement: split jni code related to different processes into 2 files --- app/src/main/cpp/lorie/activity.c | 309 +++++++++++++++ .../cpp/lorie/{android.c => cmdentrypoint.c} | 355 +----------------- app/src/main/cpp/lorie/lorie.h | 63 ++++ app/src/main/cpp/recipes/xserver.cmake | 3 +- 4 files changed, 375 insertions(+), 355 deletions(-) create mode 100644 app/src/main/cpp/lorie/activity.c rename app/src/main/cpp/lorie/{android.c => cmdentrypoint.c} (62%) diff --git a/app/src/main/cpp/lorie/activity.c b/app/src/main/cpp/lorie/activity.c new file mode 100644 index 000000000..0cf3a78ce --- /dev/null +++ b/app/src/main/cpp/lorie/activity.c @@ -0,0 +1,309 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lorie.h" + +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma ide diagnostic ignored "cppcoreguidelines-narrowing-conversions" +#define log(prio, ...) __android_log_print(ANDROID_LOG_ ## prio, "LorieNative", __VA_ARGS__) + +extern char *__progname; // NOLINT(bugprone-reserved-identifier) +static int conn_fd = -1; + +static struct { + jclass self; + jmethodID forName; + jmethodID decode; +} Charset = {0}; + +static struct { + jclass self; + jmethodID toString; +} CharBuffer = {0}; + +static jclass FindClassOrDie(JNIEnv *env, const char* name) { + jclass clazz = (*env)->FindClass(env, name); + if (!clazz) { + char buffer[1024] = {0}; + sprintf(buffer, "class %s not found", name); + log(ERROR, "%s", buffer); + (*env)->FatalError(env, buffer); + return NULL; + } + + return (*env)->NewGlobalRef(env, clazz); +} + +static jclass FindMethodOrDie(JNIEnv *env, jclass clazz, const char* name, const char* signature, jboolean isStatic) { + __typeof__((*env)->GetMethodID) getMethodID = isStatic ? (*env)->GetStaticMethodID : (*env)->GetMethodID; + jmethodID method = getMethodID(env, clazz, name, signature); + if (!method) { + char buffer[1024] = {0}; + sprintf(buffer, "method %s %s not found", name, signature); + log(ERROR, "%s", buffer); + (*env)->FatalError(env, buffer); + return NULL; + } + + return method; +} + +static inline void checkConnection(JNIEnv* env) { + int retval, b = 0; + + if (conn_fd == -1) + return; + + if ((retval = recv(conn_fd, &b, 1, MSG_PEEK)) <= 0 && errno != EAGAIN) { + log(DEBUG, "recv %d %s", retval, strerror(errno)); + jclass cls = (*env)->FindClass(env, "com/termux/x11/CmdEntryPoint"); + jmethodID method = !cls ? NULL : (*env)->GetStaticMethodID(env, cls, "requestConnection", "()V"); + if (method) + (*env)->CallStaticVoidMethod(env, cls, method); + + close(conn_fd); + conn_fd = -1; + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_connect(__unused JNIEnv* env, __unused jobject cls, jint fd) { + if (!Charset.self) { + // Init clipboard-related JNI stuff + Charset.self = FindClassOrDie(env, "java/nio/charset/Charset"); + Charset.forName = FindMethodOrDie(env, Charset.self, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;", JNI_TRUE); + Charset.decode = FindMethodOrDie(env, Charset.self, "decode", "(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;", JNI_FALSE); + + CharBuffer.self = FindClassOrDie(env, "java/nio/CharBuffer"); + CharBuffer.toString = FindMethodOrDie(env, CharBuffer.self, "toString", "()Ljava/lang/String;", JNI_FALSE); + } + + conn_fd = fd; + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); + checkConnection(env); + log(DEBUG, "XCB connection is successfull"); +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_handleXEvents(JNIEnv *env, jobject thiz) { + checkConnection(env); + if (conn_fd != -1) { + lorieEvent e = {0}; + + again: + if (read(conn_fd, &e, sizeof(e)) == sizeof(e)) { + switch(e.type) { + case EVENT_CLIPBOARD_SEND: { + if (!e.clipboardSend.count) + break; + char clipboard[e.clipboardSend.count + 1]; + memset(clipboard, 0, e.clipboardSend.count + 1); + read(conn_fd, clipboard, sizeof(clipboard)); + clipboard[e.clipboardSend.count] = 0; + log(DEBUG, "Clipboard content (%zu symbols) is %s", strlen(clipboard), clipboard); + jmethodID id = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, thiz), "setClipboardText","(Ljava/lang/String;)V"); + jobject bb = (*env)->NewDirectByteBuffer(env, clipboard, strlen(clipboard)); + jobject charset = (*env)->CallStaticObjectMethod(env, Charset.self, Charset.forName, (*env)->NewStringUTF(env, "UTF-8")); + jobject cb = (*env)->CallObjectMethod(env, charset, Charset.decode, bb); + (*env)->DeleteLocalRef(env, bb); + + jstring str = (*env)->CallObjectMethod(env, cb, CharBuffer.toString); + (*env)->CallVoidMethod(env, thiz, id, str); + break; + } + case EVENT_CLIPBOARD_REQUEST: { + (*env)->CallVoidMethod(env, thiz, (*env)->GetMethodID(env, (*env)->GetObjectClass(env, thiz), "requestClipboard", "()V")); + break; + } + } + } + + int n; + if (ioctl(conn_fd, FIONREAD, &n) >= 0 && n > sizeof(e)) + goto again; + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_startLogcat(JNIEnv *env, __unused jobject cls, jint fd) { + log(DEBUG, "Starting logcat with output to given fd"); + + switch(fork()) { + case -1: + log(ERROR, "fork: %s", strerror(errno)); + return; + case 0: + dup2(fd, 1); + dup2(fd, 2); + prctl(PR_SET_PDEATHSIG, SIGTERM); + char buf[64] = {0}; + sprintf(buf, "--pid=%d", getppid()); + execl("/system/bin/logcat", "logcat", buf, NULL); + log(ERROR, "exec logcat: %s", strerror(errno)); + (*env)->FatalError(env, "Exiting"); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_setClipboardSyncEnabled(__unused JNIEnv* env, __unused jobject cls, jboolean enable, __unused jboolean ignored) { + if (conn_fd != -1) { + lorieEvent e = { .clipboardEnable = { .t = EVENT_CLIPBOARD_ENABLE, .enable = enable } }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_sendClipboardAnnounce(JNIEnv *env, __unused jobject thiz) { + if (conn_fd != -1) { + lorieEvent e = { .type = EVENT_CLIPBOARD_ANNOUNCE }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_sendClipboardEvent(JNIEnv *env, __unused jobject thiz, jbyteArray text) { + if (conn_fd != -1 && text) { + jsize length = (*env)->GetArrayLength(env, text); + jbyte* str = (*env)->GetByteArrayElements(env, text, NULL); + lorieEvent e = { .clipboardSend = { .t = EVENT_CLIPBOARD_SEND, .count = length } }; + write(conn_fd, &e, sizeof(e)); + write(conn_fd, str, length); + (*env)->ReleaseByteArrayElements(env, text, str, JNI_ABORT); + checkConnection(env); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_sendWindowChange(__unused JNIEnv* env, __unused jobject cls, jint width, jint height, jint framerate) { + if (conn_fd != -1) { + lorieEvent e = { .screenSize = { .t = EVENT_SCREEN_SIZE, .width = width, .height = height, .framerate = framerate } }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_sendMouseEvent(__unused JNIEnv* env, __unused jobject cls, jfloat x, jfloat y, jint which_button, jboolean button_down, jboolean relative) { + if (conn_fd != -1) { + lorieEvent e = { .mouse = { .t = EVENT_MOUSE, .x = x, .y = y, .detail = which_button, .down = button_down, .relative = relative } }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_sendTouchEvent(__unused JNIEnv* env, __unused jobject cls, jint action, jint id, jint x, jint y) { + if (conn_fd != -1 && action != -1) { + lorieEvent e = { .touch = { .t = EVENT_TOUCH, .type = action, .id = id, .x = x, .y = y } }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_sendStylusEvent(JNIEnv *env, __unused jobject thiz, jfloat x, jfloat y, + jint pressure, jint tilt_x, jint tilt_y, + jint orientation, jint buttons, jboolean eraser, jboolean mouse) { + if (conn_fd != -1) { + lorieEvent e = { .stylus = { .t = EVENT_STYLUS, .x = x, .y = y, .pressure = pressure, .tilt_x = tilt_x, .tilt_y = tilt_y, .orientation = orientation, .buttons = buttons, .eraser = eraser, .mouse = mouse } }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_requestStylusEnabled(JNIEnv *env, __unused jclass clazz, jboolean enabled) { + if (conn_fd != -1) { + lorieEvent e = { .stylusEnable = { .t = EVENT_STYLUS_ENABLE, .enable = enabled } }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } +} + +JNIEXPORT jboolean JNICALL +Java_com_termux_x11_LorieView_sendKeyEvent(__unused JNIEnv* env, __unused jobject cls, jint scan_code, jint key_code, jboolean key_down) { + if (conn_fd != -1) { + int code = (scan_code) ?: android_to_linux_keycode[key_code]; + log(DEBUG, "Sending key: %d (%d %d %d)", code + 8, scan_code, key_code, key_down); + lorieEvent e = { .key = { .t = EVENT_KEY, .key = code + 8, .state = key_down } }; + write(conn_fd, &e, sizeof(e)); + checkConnection(env); + } + + return true; +} + +JNIEXPORT void JNICALL +Java_com_termux_x11_LorieView_sendTextEvent(JNIEnv *env, __unused jobject thiz, jbyteArray text) { + if (conn_fd != -1 && text) { + jsize length = (*env)->GetArrayLength(env, text); + jbyte *str = (*env)->GetByteArrayElements(env, text, NULL); + char *p = (char*) str; + mbstate_t state = { 0 }; + if (!length) + return; + + log(DEBUG, "Parsing text: %.*s", length, str); + + while (*p) { + wchar_t wc; + size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &state); + + if (len == (size_t)-1 || len == (size_t)-2) { + log(ERROR, "Invalid UTF-8 sequence encountered"); + break; + } + + if (len == 0) + break; + + log(DEBUG, "Sending unicode event: %lc (U+%X)", wc, wc); + lorieEvent e = { .unicode = { .t = EVENT_UNICODE, .code = wc } }; + write(conn_fd, &e, sizeof(e)); + p += len; + if (p - (char*) str >= length) + break; + usleep(30000); + } + + (*env)->ReleaseByteArrayElements(env, text, str, JNI_ABORT); + checkConnection(env); + } +} + +#if 1 +// It is needed to redirect stderr to logcat +static void* stderrToLogcatThread(__unused void* cookie) { + FILE *fp; + int p[2]; + size_t len; + char *line = NULL; + pipe(p); + + fp = fdopen(p[0], "r"); + + dup2(p[1], 2); + dup2(p[1], 1); + while ((getline(&line, &len, fp)) != -1) { + log(DEBUG, "%s%s", line, (line[len - 1] == '\n') ? "" : "\n"); + } + + return NULL; +} + +__attribute__((constructor)) static void init(void) { + pthread_t t; + if (!strcmp("com.termux.x11", __progname)) + pthread_create(&t, NULL, stderrToLogcatThread, NULL); +} +#endif diff --git a/app/src/main/cpp/lorie/android.c b/app/src/main/cpp/lorie/cmdentrypoint.c similarity index 62% rename from app/src/main/cpp/lorie/android.c rename to app/src/main/cpp/lorie/cmdentrypoint.c index fc75a384a..dc8252e46 100644 --- a/app/src/main/cpp/lorie/android.c +++ b/app/src/main/cpp/lorie/cmdentrypoint.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,6 @@ static int argc = 0; static char** argv = NULL; static int conn_fd = -1; -extern char *__progname; // NOLINT(bugprone-reserved-identifier) extern DeviceIntPtr lorieMouse, lorieTouch, lorieKeyboard, loriePen, lorieEraser; extern ScreenPtr pScreenPtr; extern int ucs2keysym(long ucs); @@ -40,108 +38,12 @@ void lorieKeysymKeyboardEvent(KeySym keysym, int down); char *xtrans_unix_path_x11 = NULL; char *xtrans_unix_dir_x11 = NULL; -typedef enum { - EVENT_SCREEN_SIZE, - EVENT_TOUCH, - EVENT_MOUSE, - EVENT_KEY, - EVENT_STYLUS, - EVENT_STYLUS_ENABLE, - EVENT_UNICODE, - EVENT_CLIPBOARD_ENABLE, - EVENT_CLIPBOARD_ANNOUNCE, - EVENT_CLIPBOARD_REQUEST, - EVENT_CLIPBOARD_SEND, -} eventType; -typedef union { - uint8_t type; - struct { - uint8_t t; - uint16_t width, height, framerate; - } screenSize; - struct { - uint8_t t; - uint16_t type, id, x, y; - } touch; - struct { - uint8_t t; - float x, y; - uint8_t detail, down, relative; - } mouse; - struct { - uint8_t t; - uint16_t key; - uint8_t state; - } key; - struct { - uint8_t t; - float x, y; - uint16_t pressure; - int8_t tilt_x, tilt_y; - int16_t orientation; - uint8_t buttons, eraser, mouse; - } stylus; - struct { - uint8_t t, enable; - } stylusEnable; - struct { - uint8_t t; - uint32_t code; - } unicode; - struct { - uint8_t t; - uint8_t enable; - } clipboardEnable; - struct { - uint8_t t; - uint32_t count; - } clipboardSend; -} lorieEvent; - -static struct { - jclass self; - jmethodID forName; - jmethodID decode; -} Charset = {0}; - -static struct { - jclass self; - jmethodID toString; -} CharBuffer = {0}; - static void* startServer(__unused void* cookie) { lorieSetVM((JavaVM*) cookie); char* envp[] = { NULL }; exit(dix_main(argc, (char**) argv, envp)); } -static jclass FindClassOrDie(JNIEnv *env, const char* name) { - jclass clazz = (*env)->FindClass(env, name); - if (!clazz) { - char buffer[1024] = {0}; - sprintf(buffer, "class %s not found", name); - log(ERROR, "%s", buffer); - (*env)->FatalError(env, buffer); - return NULL; - } - - return (*env)->NewGlobalRef(env, clazz); -} - -static jclass FindMethodOrDie(JNIEnv *env, jclass clazz, const char* name, const char* signature, jboolean isStatic) { - __typeof__((*env)->GetMethodID) getMethodID = isStatic ? (*env)->GetStaticMethodID : (*env)->GetMethodID; - jmethodID method = getMethodID(env, clazz, name, signature); - if (!method) { - char buffer[1024] = {0}; - sprintf(buffer, "method %s %s not found", name, signature); - log(ERROR, "%s", buffer); - (*env)->FatalError(env, buffer); - return NULL; - } - - return method; -} - JNIEXPORT jboolean JNICALL Java_com_termux_x11_CmdEntryPoint_start(JNIEnv *env, __unused jclass cls, jobjectArray args) { pthread_t t; @@ -243,7 +145,7 @@ Java_com_termux_x11_CmdEntryPoint_start(JNIEnv *env, __unused jclass cls, jobjec // proot case if (access("/usr/share/X11/xkb", F_OK) == 0) setenv("XKB_CONFIG_ROOT", "/usr/share/X11/xkb", 1); - // Termux case + // Termux case else if (access("/data/data/com.termux/files/usr/share/X11/xkb", F_OK) == 0) setenv("XKB_CONFIG_ROOT", "/data/data/com.termux/files/usr/share/X11/xkb", 1); } @@ -576,232 +478,6 @@ Java_com_termux_x11_CmdEntryPoint_listenForConnections(JNIEnv *env, jobject thiz } } close(client); - client = -1; - } -} - -static inline void checkConnection(JNIEnv* env) { - int retval, b = 0; - - if (conn_fd == -1) - return; - - if ((retval = recv(conn_fd, &b, 1, MSG_PEEK)) <= 0 && errno != EAGAIN) { - log(DEBUG, "recv %d %s", retval, strerror(errno)); - jclass cls = (*env)->FindClass(env, "com/termux/x11/CmdEntryPoint"); - jmethodID method = !cls ? NULL : (*env)->GetStaticMethodID(env, cls, "requestConnection", "()V"); - if (method) - (*env)->CallStaticVoidMethod(env, cls, method); - - close(conn_fd); - conn_fd = -1; - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_connect(__unused JNIEnv* env, __unused jobject cls, jint fd) { - if (!Charset.self) { - // Init clipboard-related JNI stuff - Charset.self = FindClassOrDie(env, "java/nio/charset/Charset"); - Charset.forName = FindMethodOrDie(env, Charset.self, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;", JNI_TRUE); - Charset.decode = FindMethodOrDie(env, Charset.self, "decode", "(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;", JNI_FALSE); - - CharBuffer.self = FindClassOrDie(env, "java/nio/CharBuffer"); - CharBuffer.toString = FindMethodOrDie(env, CharBuffer.self, "toString", "()Ljava/lang/String;", JNI_FALSE); - } - - conn_fd = fd; - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); - checkConnection(env); - log(DEBUG, "XCB connection is successfull"); -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_handleXEvents(JNIEnv *env, jobject thiz) { - checkConnection(env); - if (conn_fd != -1) { - lorieEvent e = {0}; - - again: - if (read(conn_fd, &e, sizeof(e)) == sizeof(e)) { - switch(e.type) { - case EVENT_CLIPBOARD_SEND: { - if (!e.clipboardSend.count) - break; - char clipboard[e.clipboardSend.count + 1]; - memset(clipboard, 0, e.clipboardSend.count + 1); - read(conn_fd, clipboard, sizeof(clipboard)); - clipboard[e.clipboardSend.count] = 0; - log(DEBUG, "Clipboard content (%zu symbols) is %s", strlen(clipboard), clipboard); - jmethodID id = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, thiz), "setClipboardText","(Ljava/lang/String;)V"); - jobject bb = (*env)->NewDirectByteBuffer(env, clipboard, strlen(clipboard)); - jobject charset = (*env)->CallStaticObjectMethod(env, Charset.self, Charset.forName, (*env)->NewStringUTF(env, "UTF-8")); - jobject cb = (*env)->CallObjectMethod(env, charset, Charset.decode, bb); - (*env)->DeleteLocalRef(env, bb); - - jstring str = (*env)->CallObjectMethod(env, cb, CharBuffer.toString); - (*env)->CallVoidMethod(env, thiz, id, str); - break; - } - case EVENT_CLIPBOARD_REQUEST: { - (*env)->CallVoidMethod(env, thiz, (*env)->GetMethodID(env, (*env)->GetObjectClass(env, thiz), "requestClipboard", "()V")); - break; - } - } - } - - int n; - if (ioctl(conn_fd, FIONREAD, &n) >= 0 && n > sizeof(e)) - goto again; - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_startLogcat(JNIEnv *env, __unused jobject cls, jint fd) { - log(DEBUG, "Starting logcat with output to given fd"); - - switch(fork()) { - case -1: - log(ERROR, "fork: %s", strerror(errno)); - return; - case 0: - dup2(fd, 1); - dup2(fd, 2); - prctl(PR_SET_PDEATHSIG, SIGTERM); - char buf[64] = {0}; - sprintf(buf, "--pid=%d", getppid()); - execl("/system/bin/logcat", "logcat", buf, NULL); - log(ERROR, "exec logcat: %s", strerror(errno)); - (*env)->FatalError(env, "Exiting"); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_setClipboardSyncEnabled(__unused JNIEnv* env, __unused jobject cls, jboolean enable, __unused jboolean ignored) { - if (conn_fd != -1) { - lorieEvent e = { .clipboardEnable = { .t = EVENT_CLIPBOARD_ENABLE, .enable = enable } }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_sendClipboardAnnounce(JNIEnv *env, __unused jobject thiz) { - if (conn_fd != -1) { - lorieEvent e = { .type = EVENT_CLIPBOARD_ANNOUNCE }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_sendClipboardEvent(JNIEnv *env, __unused jobject thiz, jbyteArray text) { - if (conn_fd != -1 && text) { - jsize length = (*env)->GetArrayLength(env, text); - jbyte* str = (*env)->GetByteArrayElements(env, text, NULL); - lorieEvent e = { .clipboardSend = { .t = EVENT_CLIPBOARD_SEND, .count = length } }; - write(conn_fd, &e, sizeof(e)); - write(conn_fd, str, length); - (*env)->ReleaseByteArrayElements(env, text, str, JNI_ABORT); - checkConnection(env); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_sendWindowChange(__unused JNIEnv* env, __unused jobject cls, jint width, jint height, jint framerate) { - if (conn_fd != -1) { - lorieEvent e = { .screenSize = { .t = EVENT_SCREEN_SIZE, .width = width, .height = height, .framerate = framerate } }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_sendMouseEvent(__unused JNIEnv* env, __unused jobject cls, jfloat x, jfloat y, jint which_button, jboolean button_down, jboolean relative) { - if (conn_fd != -1) { - lorieEvent e = { .mouse = { .t = EVENT_MOUSE, .x = x, .y = y, .detail = which_button, .down = button_down, .relative = relative } }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_sendTouchEvent(__unused JNIEnv* env, __unused jobject cls, jint action, jint id, jint x, jint y) { - if (conn_fd != -1 && action != -1) { - lorieEvent e = { .touch = { .t = EVENT_TOUCH, .type = action, .id = id, .x = x, .y = y } }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_sendStylusEvent(JNIEnv *env, __unused jobject thiz, jfloat x, jfloat y, - jint pressure, jint tilt_x, jint tilt_y, - jint orientation, jint buttons, jboolean eraser, jboolean mouse) { - if (conn_fd != -1) { - lorieEvent e = { .stylus = { .t = EVENT_STYLUS, .x = x, .y = y, .pressure = pressure, .tilt_x = tilt_x, .tilt_y = tilt_y, .orientation = orientation, .buttons = buttons, .eraser = eraser, .mouse = mouse } }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_requestStylusEnabled(JNIEnv *env, __unused jclass clazz, jboolean enabled) { - if (conn_fd != -1) { - lorieEvent e = { .stylusEnable = { .t = EVENT_STYLUS_ENABLE, .enable = enabled } }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } -} - -JNIEXPORT jboolean JNICALL -Java_com_termux_x11_LorieView_sendKeyEvent(__unused JNIEnv* env, __unused jobject cls, jint scan_code, jint key_code, jboolean key_down) { - if (conn_fd != -1) { - int code = (scan_code) ?: android_to_linux_keycode[key_code]; - log(DEBUG, "Sending key: %d (%d %d %d)", code + 8, scan_code, key_code, key_down); - lorieEvent e = { .key = { .t = EVENT_KEY, .key = code + 8, .state = key_down } }; - write(conn_fd, &e, sizeof(e)); - checkConnection(env); - } - - return true; -} - -JNIEXPORT void JNICALL -Java_com_termux_x11_LorieView_sendTextEvent(JNIEnv *env, __unused jobject thiz, jbyteArray text) { - if (conn_fd != -1 && text) { - jsize length = (*env)->GetArrayLength(env, text); - jbyte *str = (*env)->GetByteArrayElements(env, text, NULL); - char *p = (char*) str; - mbstate_t state = { 0 }; - if (!length) - return; - - log(DEBUG, "Parsing text: %.*s", length, str); - - while (*p) { - wchar_t wc; - size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &state); - - if (len == (size_t)-1 || len == (size_t)-2) { - log(ERROR, "Invalid UTF-8 sequence encountered"); - break; - } - - if (len == 0) - break; - - log(DEBUG, "Sending unicode event: %lc (U+%X)", wc, wc); - lorieEvent e = { .unicode = { .t = EVENT_UNICODE, .code = wc } }; - write(conn_fd, &e, sizeof(e)); - p += len; - if (p - (char*) str >= length) - break; - usleep(30000); - } - - (*env)->ReleaseByteArrayElements(env, text, str, JNI_ABORT); - checkConnection(env); } } @@ -812,32 +488,3 @@ void abort(void) { void exit(int code) { _exit(code); } - -#if 1 -// It is needed to redirect stderr to logcat -static void* stderrToLogcatThread(__unused void* cookie) { - FILE *fp; - int p[2]; - size_t len; - char *line = NULL; - pipe(p); - - fp = fdopen(p[0], "r"); - - dup2(p[1], 2); - dup2(p[1], 1); - while ((getline(&line, &len, fp)) != -1) { - log(DEBUG, "%s%s", line, (line[len - 1] == '\n') ? "" : "\n"); - } - - return NULL; -} - -__attribute__((constructor)) static void init(void) { - pthread_t t; - if (!strcmp("com.termux.x11", __progname)) - pthread_create(&t, NULL, stderrToLogcatThread, NULL); -} - -#endif - diff --git a/app/src/main/cpp/lorie/lorie.h b/app/src/main/cpp/lorie/lorie.h index 71ecc667d..3a84a7410 100644 --- a/app/src/main/cpp/lorie/lorie.h +++ b/app/src/main/cpp/lorie/lorie.h @@ -1,8 +1,12 @@ #pragma once #include +#include + +#include #include #include +#include #include "linux/input-event-codes.h" void lorieSetVM(JavaVM* vm); @@ -20,6 +24,65 @@ void lorieSetStylusEnabled(Bool enabled); void lorieTriggerWorkingQueue(void); void lorieChoreographerFrameCallback(__unused long t, AChoreographer* d); +typedef enum { + EVENT_SCREEN_SIZE, + EVENT_TOUCH, + EVENT_MOUSE, + EVENT_KEY, + EVENT_STYLUS, + EVENT_STYLUS_ENABLE, + EVENT_UNICODE, + EVENT_CLIPBOARD_ENABLE, + EVENT_CLIPBOARD_ANNOUNCE, + EVENT_CLIPBOARD_REQUEST, + EVENT_CLIPBOARD_SEND, +} eventType; + +typedef union { + uint8_t type; + struct { + uint8_t t; + uint16_t width, height, framerate; + } screenSize; + struct { + uint8_t t; + uint16_t type, id, x, y; + } touch; + struct { + uint8_t t; + float x, y; + uint8_t detail, down, relative; + } mouse; + struct { + uint8_t t; + uint16_t key; + uint8_t state; + } key; + struct { + uint8_t t; + float x, y; + uint16_t pressure; + int8_t tilt_x, tilt_y; + int16_t orientation; + uint8_t buttons, eraser, mouse; + } stylus; + struct { + uint8_t t, enable; + } stylusEnable; + struct { + uint8_t t; + uint32_t code; + } unicode; + struct { + uint8_t t; + uint8_t enable; + } clipboardEnable; + struct { + uint8_t t; + uint32_t count; + } clipboardSend; +} lorieEvent; + static int android_to_linux_keycode[304] = { [ 4 /* ANDROID_KEYCODE_BACK */] = KEY_ESC, [ 7 /* ANDROID_KEYCODE_0 */] = KEY_0, diff --git a/app/src/main/cpp/recipes/xserver.cmake b/app/src/main/cpp/recipes/xserver.cmake index 6278b40ef..7bbef974f 100644 --- a/app/src/main/cpp/recipes/xserver.cmake +++ b/app/src/main/cpp/recipes/xserver.cmake @@ -265,7 +265,8 @@ add_library(Xlorie SHARED "xserver/hw/xquartz/keysym2ucs.c" "libxcvt/lib/libxcvt.c" "lorie/shm/shmem.c" - "lorie/android.c" + "lorie/cmdentrypoint.c" + "lorie/activity.c" "lorie/clipboard.c" "lorie/dri3.c" "lorie/InitOutput.c"