1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-06 00:13:33 +00:00

Updated timing logic for remote keyboard input

This commit is contained in:
Bryan Roe
2020-11-20 11:10:24 -08:00
parent 473777c14b
commit cb131ae141
5 changed files with 325 additions and 47 deletions

View File

@@ -23,6 +23,11 @@ extern int change_display;
x11tst_struct *x11tst_exports = NULL;
extern void kvm_keyboard_unmap_unicode_key(Display *display, int keycode);
extern int kvm_keyboard_map_unicode_key(Display *display, uint16_t unicode);
extern int kvm_keyboard_update_map_unicode_key(Display *display, uint16_t unicode, int keycode);
#define g_keyboardMapCount 8
int g_keyboardMap[g_keyboardMapCount] = { 0 };
int g_keyboardMapIndex = 0;
static struct keymap_t g_keymap[] = {
{ XK_BackSpace, VK_BACK },
@@ -216,10 +221,25 @@ void KeyAction(unsigned char vk, int up, Display *display)
//printf("%x %x %d %d\n", keysym, vk, keycode, up);
if (keycode != 0)
{
//ILIBLOGMESSAGEX("VK: %u [%d]", vk, up);
if (!x11tst_exports->XTestFakeKeyEvent(display, keycode, !up, 0)) { return; }
x11tst_exports->XFlush(display);
}
}
void KeyActionUnicode_UNMAP_ALL(Display *display)
{
int i;
for (i = 0; i < g_keyboardMapCount; ++i)
{
if (g_keyboardMap[i] != 0)
{
kvm_keyboard_unmap_unicode_key(display, g_keyboardMap[i]);
g_keyboardMap[i] = 0;
}
}
g_keyboardMapIndex = 0;
}
void KeyActionUnicode(uint16_t unicode, int up, Display *display)
{
if (change_display) { return; }
@@ -227,16 +247,64 @@ void KeyActionUnicode(uint16_t unicode, int up, Display *display)
if (up == 0)
{
int keycode = kvm_keyboard_map_unicode_key(display, unicode); // Create a key mapping on an unmapped key
if (keycode > 0)
{
x11tst_exports->XTestFakeKeyEvent(display, keycode, 1, 0);
x11tst_exports->XFlush(display);
//ILIBLOGMESSAGEX("UNICODE: %u [%d] <<%ull>>", unicode, up, CurrentTime);
//if (g_keyboardMap[g_keyboardMapIndex] != 0) { kvm_keyboard_unmap_unicode_key(display, g_keyboardMap[g_keyboardMapIndex]); g_keyboardMap[g_keyboardMapIndex] = 0; }
//g_keyboardMap[g_keyboardMapIndex] = kvm_keyboard_map_unicode_key(display, unicode); // Create a key mapping on an unmapped key
//if (g_keyboardMap[g_keyboardMapIndex] > 0)
//{
// //ILIBLOGMESSAGEX("<<%d>>", g_keyboardMap[g_keyboardMapIndex]);
// x11tst_exports->XTestFakeKeyEvent(display, g_keyboardMap[g_keyboardMapIndex], 1, 0);
// x11tst_exports->XFlush(display);
usleep(10000); // We need a short sleep between KeyDown and KeyUp, to register correctly.
x11tst_exports->XTestFakeKeyEvent(display, keycode, 0, 0);
x11tst_exports->XFlush(display);
kvm_keyboard_unmap_unicode_key(display, keycode); // Delete the key mapping we created above
// x11tst_exports->XTestFakeKeyEvent(display, g_keyboardMap[g_keyboardMapIndex], 0, 0);
// x11tst_exports->XFlush(display);
//
// if (++g_keyboardMapIndex >= g_keyboardMapCount)
// {
// g_keyboardMapIndex = 0;
// }
//}
if (g_keyboardMap[g_keyboardMapIndex] != 0)
{
g_keyboardMap[g_keyboardMapIndex] = kvm_keyboard_update_map_unicode_key(display, unicode, g_keyboardMap[g_keyboardMapIndex]); // Create a key mapping on an unmapped key
}
else
{
g_keyboardMap[g_keyboardMapIndex] = kvm_keyboard_map_unicode_key(display, unicode); // Create a key mapping on an unmapped key
}
if (g_keyboardMap[g_keyboardMapIndex] > 0)
{
//ILIBLOGMESSAGEX("<<%d>>", g_keyboardMap[g_keyboardMapIndex]);
x11tst_exports->XTestFakeKeyEvent(display, g_keyboardMap[g_keyboardMapIndex], 1, 0);
x11tst_exports->XTestFakeKeyEvent(display, g_keyboardMap[g_keyboardMapIndex], 0, 15);
x11tst_exports->XFlush(display);
if (++g_keyboardMapIndex >= g_keyboardMapCount)
{
g_keyboardMapIndex = 0;
}
}
//x11tst_exports->XTestFakeKeyEvent(display, x11tst_exports->XKeysymToKeycode(display, 65), 1, 0);
//x11tst_exports->XFlush(display);
//x11tst_exports->XTestFakeKeyEvent(display, x11tst_exports->XKeysymToKeycode(display, 65), 0, 0);
//x11tst_exports->XFlush(display);
//int keycode = kvm_keyboard_map_unicode_key(display, unicode); // Create a key mapping on an unmapped key
//if (keycode > 0)
//{
// x11tst_exports->XTestFakeKeyEvent(display, keycode, 1, 0);
// x11tst_exports->XFlush(display);
// //usleep(1000 * 15); // We need a short sleep between KeyDown and KeyUp, to register correctly.
// x11tst_exports->XTestFakeKeyEvent(display, keycode, 0, 0);
// x11tst_exports->XFlush(display);
// kvm_keyboard_unmap_unicode_key(display, keycode); // Delete the key mapping we created above
//}
}
}

View File

@@ -402,5 +402,7 @@ struct keymap_t {
extern void MouseAction(double absX, double absY, int button, short wheel, Display *display);
extern void KeyAction(unsigned char vk, int up, Display *display);
extern void KeyActionUnicode(uint16_t unicode, int up, Display *display);
extern void KeyActionUnicode_UNMAP_ALL(Display *display);
#endif /* LINUX_EVENTS_H_ */

View File

@@ -22,6 +22,7 @@ limitations under the License.
#include "microstack/ILibProcessPipe.h"
#include <sys/wait.h>
#include <limits.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -42,6 +43,15 @@ limitations under the License.
extern uint32_t crc32c(uint32_t crc, const unsigned char* buf, uint32_t len);
extern char* g_ILibCrashDump_path;
ILibQueue keyqueue = NULL;
typedef struct kvm_keydata
{
int delay;
uint8_t up;
uint16_t data;
}kvm_keydata;
typedef enum KVM_MouseCursors
{
KVM_MouseCursor_NOCHANGE = -1,
@@ -91,6 +101,7 @@ unsigned short current_display = 0;
pid_t g_slavekvm = 0;
int master2slave[2];
int slave2master[2];
FILE *logFile = NULL;
int g_enableEvents = 0;
extern int gRemoteMouseRenderDefault;
@@ -101,6 +112,8 @@ ILibQueue g_messageQ;
extern void* tilebuffer;
extern char **environ;
struct timespec inputtime;
uint32_t inputcounter = 0;
typedef struct x11ext_struct
{
@@ -155,7 +168,21 @@ void kvm_keyboard_unmap_unicode_key(Display *display, int keycode)
// Delete a keymapping that we created previously
KeySym keysym_list[] = { 0 };
x11_exports->XChangeKeyboardMapping(display, keycode, 1, keysym_list, 1);
x11_exports->XFlush(display);
x11_exports->XSync(display, 0);
}
int kvm_keyboard_update_map_unicode_key(Display *display, uint16_t unicode, int keycode)
{
char unicodestring[6];
// Convert the unicode character to something xorg will understand
if (sprintf_s(unicodestring, sizeof(unicodestring), "U%04X", unicode) < 0) { return(keycode); }
// Map the unicode character to one of the unused keys above
KeySym sym = x11_exports->XStringToKeysym(unicodestring);
KeySym keysym_list[] = { sym, sym };
x11_exports->XChangeKeyboardMapping(display, keycode, 2, keysym_list, 1);
x11_exports->XSync(display, 0);
return(keycode);
}
int kvm_keyboard_map_unicode_key(Display *display, uint16_t unicode)
{
@@ -185,13 +212,12 @@ int kvm_keyboard_map_unicode_key(Display *display, uint16_t unicode)
if (empty) { empty_keycode = i; break; } // Found it!
}
x11_exports->XFree(keysyms);
x11_exports->XFlush(display);
// Map the unicode character to one of the unused keys above
KeySym sym = x11_exports->XStringToKeysym(unicodestring);
KeySym keysym_list[] = { sym };
x11_exports->XChangeKeyboardMapping(display, empty_keycode, 1, keysym_list, 1);
x11_exports->XFlush(display);
KeySym keysym_list[] = { sym, sym };
x11_exports->XChangeKeyboardMapping(display, empty_keycode, 2, keysym_list, 1);
x11_exports->XSync(display, 0);
return(empty_keycode);
}
@@ -367,30 +393,6 @@ void kvm_send_display()
#define BUFSIZE 65535
int kvm_server_inputdata(char* block, int blocklen);
void* kvm_mainloopinput(void* parm)
{
int ptr = 0;
int ptr2 = 0;
int len = 0;
char pchRequest2[30000];
ssize_t cbBytesRead = 0;
while (!g_shutdown)
{
//fprintf(logFile, "Reading from master in kvm_mainloopinput\n");
cbBytesRead = read(master2slave[0], pchRequest2 + len, 30000 - len);
//fprintf(logFile, "Read %d bytes from master in kvm_mainloopinput\n", cbBytesRead);
if (cbBytesRead == -1 || cbBytesRead == 0 || g_shutdown) { /*ILIBMESSAGE("KVMBREAK-K1\r\n");*/ g_shutdown = 1; break; }
len += cbBytesRead;
ptr2 = 0;
while ((ptr2 = kvm_server_inputdata((char*)pchRequest2 + ptr, cbBytesRead - ptr)) != 0) { ptr += ptr2; }
if (ptr == len) { len = 0; ptr = 0; }
// TODO: else move the reminder.
}
return 0;
}
int lockfileCheckFn(const struct dirent *ent) {
if (ent == NULL) {
@@ -509,6 +511,8 @@ int kvm_init(int displayNo)
int dummy1, dummy2, dummy3;
char displayString[256] = "";
if (clock_gettime(CLOCK_MONOTONIC, &inputtime) != 0) { memset(&inputtime, 0, sizeof(inputtime)); }
if (x11ext_exports == NULL)
{
x11ext_exports = ILibMemory_SmartAllocate(sizeof(x11ext_struct));
@@ -559,8 +563,7 @@ int kvm_init(int displayNo)
((void**)x11_exports)[18] = (void*)dlsym(x11_exports->x11_lib, "XGetKeyboardMapping");
((void**)x11_exports)[19] = (void*)dlsym(x11_exports->x11_lib, "XStringToKeysym");
((void**)x11_exports)[20] = (void*)dlsym(x11_exports->x11_lib, "XChangeKeyboardMapping");
((void**)x11tst_exports)[4] = (void*)x11_exports->XFlush;
((void**)x11tst_exports)[5] = (void*)x11_exports->XKeysymToKeycode;
}
@@ -664,12 +667,68 @@ int kvm_server_inputdata(char* block, int blocklen)
{
case MNG_KVM_KEY_UNICODE: // Unicode Key
if (size != 7) break;
if (g_enableEvents) KeyActionUnicode(((((unsigned char)block[5]) << 8) + ((unsigned char)block[6])), block[4], eventdisplay);
if (g_enableEvents && block[4] == 0)
{
kvm_keydata *data;
struct timespec curtime; memset(&curtime, 0, sizeof(curtime));
while ((data = (kvm_keydata*)ILibCircularQueue_EnQueue(keyqueue)) == NULL)
{
data = (kvm_keydata*)ILibCircularQueue_DeQueue(keyqueue);
if (data->delay < 0)
{
KeyAction((unsigned char)data->data, data->up, eventdisplay);
}
else
{
KeyActionUnicode(data->data, data->up, eventdisplay);
}
}
data->data = ((((unsigned char)block[5]) << 8) + ((unsigned char)block[6])); // Unicode
data->up = block[4];
if (clock_gettime(CLOCK_MONOTONIC, &curtime) != 0 || ILibTime_timespec_subtract(&curtime, &inputtime) < 1000000000)
{
++inputcounter;
}
else
{
inputcounter = 0;
}
memcpy_s(&inputtime, sizeof(inputtime), &curtime, sizeof(curtime));
if (inputcounter > 8)
{
data->delay = (1000 * 1000);
inputcounter = 0;
}
else
{
data->delay = 0;
}
}
break;
case MNG_KVM_KEY: // Key
{
if (size != 6) break;
if (g_enableEvents) KeyAction(block[5], block[4], eventdisplay);
if (g_enableEvents)
{
kvm_keydata *data;
while ((data = (kvm_keydata*)ILibCircularQueue_EnQueue(keyqueue)) == NULL)
{
data = (kvm_keydata*)ILibCircularQueue_DeQueue(keyqueue);
if (data->delay == 0)
{
KeyAction((unsigned char)data->data, data->up, eventdisplay);
}
else
{
KeyActionUnicode(data->data, data->up, eventdisplay);
}
}
data->data = block[5]; // Unicode
data->up = block[4];
data->delay = -1;
}
break;
}
case MNG_KVM_MOUSE: // Mouse
@@ -916,8 +975,13 @@ void bitblt(char *sourcebitmap, int source_width, int source_height, int sx, int
ILibMemory_Free(drect);
}
void kvm_server_sighandler(int signum, siginfo_t *info, void *context)
{
g_shutdown = 1;
}
void* kvm_server_mainloop(void* parm)
{
int maxsleep;
Window rr, cr;
int rx, ry, wx, wy, rs;
unsigned int mr;
@@ -970,9 +1034,25 @@ void* kvm_server_mainloop(void* parm)
//fprintf(logFile, "After kvm_init.\n"); fflush(logFile);
g_shutdown = 0;
pthread_create(&kvmthread, NULL, kvm_mainloopinput, parm);
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_sigaction = kvm_server_sighandler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
ignore_result(sigaction(SIGTERM, &action, NULL));
//pthread_create(&kvmthread, NULL, kvm_mainloopinput, parm);
//fprintf(logFile, "Created the kvmthread.\n"); fflush(logFile);
int ptr = 0;
int ptr2 = 0;
int len = 0;
char pchRequest2[30000];
ssize_t cbBytesRead = 0;
keyqueue = ILibCircularQueue_Create(sizeof(kvm_keydata), 1024);
kvm_keydata *keydata;
while (!g_shutdown)
{
// Check if there are pending messages to be sent
@@ -1020,6 +1100,29 @@ void* kvm_server_mainloop(void* parm)
}
if (count == 100 && imagedisplay == NULL) { g_shutdown = 1; break; }
FD_ZERO(&readset);
FD_ZERO(&errorset);
FD_ZERO(&writeset);
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_SET(master2slave[0], &readset);
if (select(FD_SETSIZE, &readset, &writeset, &errorset, &tv) > 0 && FD_ISSET(master2slave[0], &readset))
{
//fprintf(logFile, "Reading from master in kvm_mainloopinput\n");
cbBytesRead = read(master2slave[0], pchRequest2 + len, 30000 - len);
//fprintf(logFile, "Read %d bytes from master in kvm_mainloopinput\n", cbBytesRead);
if (cbBytesRead == -1 || cbBytesRead == 0 || g_shutdown)
{
g_shutdown = 1;
break;
}
len += cbBytesRead;
ptr2 = 0;
while ((ptr2 = kvm_server_inputdata((char*)pchRequest2 + ptr, cbBytesRead - ptr)) != 0) { ptr += ptr2; }
if (ptr == len) { len = 0; ptr = 0; }
}
if (cursordisplay == NULL)
{
if ((cursordisplay = x11_exports->XOpenDisplay(displayString)))
@@ -1246,14 +1349,62 @@ void* kvm_server_mainloop(void* parm)
// We can't go full speed here, we need to slow this down.
height = FRAME_RATE_TIMER;
while (!g_shutdown && height > 0) { if (height > 50) { height -= 50; usleep(50000); } else { usleep(height * 1000); height = 0; } }
while (!g_shutdown && height > 0)
{
if (height > 50)
{
height -= 50;
maxsleep = 50000;
}
else
{
maxsleep = height * 1000;
height = 0;
}
while ((keydata = (kvm_keydata*)ILibCircularQueue_Peek(keyqueue)) != NULL)
{
if (keydata->delay > 0)
{
// Need to sleep, calculate how much
if (keydata->delay > maxsleep)
{
// Frame Rate Timer is smaller
keydata->delay -= maxsleep;
break;
}
else
{
// Frame Rate timer is larger
maxsleep -= keydata->delay;
usleep(keydata->delay);
keydata->delay = 0;
continue;
}
}
keydata = (kvm_keydata*)ILibCircularQueue_DeQueue(keyqueue);
if (keydata->delay == 0)
{
KeyActionUnicode(keydata->data, keydata->up, eventdisplay);
}
else
{
KeyAction((unsigned char)keydata->data, keydata->up, eventdisplay);
}
}
usleep(maxsleep);
}
}
ILibCircularQueue_Destroy(keyqueue);
close(slave2master[1]);
close(master2slave[0]);
slave2master[1] = 0;
master2slave[0] = 0;
KeyActionUnicode_UNMAP_ALL(eventdisplay);
x11_exports->XCloseDisplay(eventdisplay);
eventdisplay = NULL;
@@ -1263,8 +1414,6 @@ void* kvm_server_mainloop(void* parm)
cursordisplay = NULL;
}
pthread_join(kvmthread, NULL);
kvmthread = (pthread_t)NULL;
if (g_tileInfo != NULL)
{
for (r = 0; r < TILE_HEIGHT_COUNT; r++) { free(g_tileInfo[r]); }
@@ -1433,7 +1582,7 @@ void kvm_cleanup()
if (master2slave[1] != 0 && g_slavekvm != 0)
{
kill(g_slavekvm, SIGKILL);
kill(g_slavekvm, SIGTERM);
waitpid(g_slavekvm, &code, 0);
g_slavekvm = 0;
}

View File

@@ -4703,6 +4703,57 @@ struct ILibXMLNode *ILibParseXML(char *buffer, size_t offset, size_t length)
return RetVal;
}
typedef struct ILibCircularQueue_Record
{
void *next;
char data[];
}ILibCircularQueue_Record;
ILibQueue ILibCircularQueue_Create(size_t entrySize, size_t totalEntries)
{
totalEntries++;
size_t index;
void *ret = ILibMemory_SmartAllocateEx(2 * sizeof(void*), (sizeof(ILibCircularQueue_Record) + entrySize)*totalEntries);
((void**)ret)[0] = ((void**)ret)[1] = ILibMemory_Extra(ret);
char *data = (char*)ILibMemory_Extra(ret);
for (index = 0; index < totalEntries; ++index)
{
((ILibCircularQueue_Record*)data)->next = (index == totalEntries - 1) ? ILibMemory_Extra(ret) : (data + sizeof(ILibCircularQueue_Record) + entrySize);
data = ((ILibCircularQueue_Record*)data)->next;
}
return(ret);
}
void* ILibCircularQueue_EnQueue(ILibQueue circularQueue)
{
ILibCircularQueue_Record *head = (ILibCircularQueue_Record*)((void**)circularQueue)[0];
ILibCircularQueue_Record *tail = (ILibCircularQueue_Record*)((void**)circularQueue)[1];
ILibCircularQueue_Record *next = (ILibCircularQueue_Record*)tail->next;
if (next == head) { return(NULL); } // No Space
((void**)circularQueue)[1] = next;
return(tail->data);
}
void* ILibCircularQueue_DeQueue(ILibQueue circularQueue)
{
ILibCircularQueue_Record *head = (ILibCircularQueue_Record*)((void**)circularQueue)[0];
ILibCircularQueue_Record *tail = (ILibCircularQueue_Record*)((void**)circularQueue)[1];
if (head == tail) { return(NULL); } // Empty
((void**)circularQueue)[0] = head->next;
return(head->data);
}
void* ILibCircularQueue_Peek(ILibQueue circularQueue)
{
ILibCircularQueue_Record *head = (ILibCircularQueue_Record*)((void**)circularQueue)[0];
ILibCircularQueue_Record *tail = (ILibCircularQueue_Record*)((void**)circularQueue)[1];
if (head == tail) { return(NULL); } // Empty
return(head->data);
}
int ILibCircularQueue_IsEmpty(ILibQueue circularQueue)
{
return(((void**)circularQueue)[0] == ((void**)circularQueue)[1]);
}
/*! \fn ILibQueue_Create()
\brief Create an empty Queue
\return An empty queue

View File

@@ -515,6 +515,7 @@ int ILibIsRunningOnChainThread(void* chain);
time_t ILibTime_Parse(char *timeString);
char* ILibTime_Serialize(time_t timeVal);
long long ILibGetUptime();
#define ILibTime_timespec_subtract(bigger, smaller) ((uint64_t)(((bigger)->tv_sec - (smaller)->tv_sec) * 1000000000) + (uint64_t)((bigger)->tv_nsec - (smaller)->tv_nsec))
uint64_t ILibHTONLL(uint64_t v);
uint64_t ILibNTOHLL(uint64_t v);
@@ -904,6 +905,13 @@ int ILibIsRunningOnChainThread(void* chain);
\{
*/
typedef void* ILibQueue;
ILibQueue ILibCircularQueue_Create(size_t entrySize, size_t totalEntries);
void* ILibCircularQueue_EnQueue(ILibQueue circularQueue);
void* ILibCircularQueue_DeQueue(ILibQueue circularQueue);
void* ILibCircularQueue_Peek(ILibQueue circularQueue);
int ILibCircularQueue_IsEmpty(ILibQueue circularQueue);
#define ILibCircularQueue_Destroy(circularQueue) ILibMemory_Free(circularQueue)
ILibQueue ILibQueue_Create();
void ILibQueue_Destroy(ILibQueue q);
int ILibQueue_IsEmpty(ILibQueue q);