From adb71527d182d22365e387828b3496d6123f7660 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Wed, 28 May 2025 09:57:34 +0200 Subject: [PATCH 1/7] [add] mouse : add mouse relative coordinates support --- src/framebuffer-vncserver.c | 11 +++++++- src/mouse.c | 55 +++++++++++++++++++++++++++++-------- src/mouse.h | 1 + 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/framebuffer-vncserver.c b/src/framebuffer-vncserver.c index b62ff20..15e4a22 100644 --- a/src/framebuffer-vncserver.c +++ b/src/framebuffer-vncserver.c @@ -706,7 +706,16 @@ int main(int argc, char **argv) { // init touch only if there is a mouse device defined int ret = init_mouse(mouse_device, touch_rotate); - enable_mouse = (ret > 0); + if(ret == 3) + { + info_print("Trying to init with relative coordinates... "); + ret = init_mouse_rel(fb_xres, fb_yres, mouse_device, touch_rotate); + if(!ret) + { + info_print("Successful\n"); + } + } + enable_mouse = (!ret); } else { diff --git a/src/mouse.c b/src/mouse.c index 854b09d..a08a1cf 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -30,6 +30,7 @@ static int ymin, ymax; static int rotate; static int trkg_id = -1; static bool is_wheel_hires = false; +static bool is_relative_coords = false; #ifndef input_event_sec #define input_event_sec time.tv_sec @@ -59,13 +60,13 @@ int init_mouse(const char *touch_device, int vnc_rotate) if ((mousefd = open(touch_device, O_RDWR)) == -1) { error_print("cannot open mouse device %s\n", touch_device); - return 0; + return 1; } //REL_WHEEL_HI_RES if (ioctl(mousefd, EVIOCGBIT(EV_REL, sizeof(evtype_bitmask)), evtype_bitmask) < 0) { error_print("%s can't get evdev features: %s",touch_device, strerror(errno)); - return 0; + return 2; } #ifdef REL_WHEEL_HI_RES @@ -82,21 +83,36 @@ int init_mouse(const char *touch_device, int vnc_rotate) if (ioctl(mousefd, EVIOCGABS(ABS_X), &info)) { error_print("cannot get ABS_X info, %s\n", strerror(errno)); - return 0; + return 3; } xmin = info.minimum; xmax = info.maximum; if (ioctl(mousefd, EVIOCGABS(ABS_Y), &info)) { error_print("cannot get ABS_Y, %s\n", strerror(errno)); - return 0; + return 3; } ymin = info.minimum; ymax = info.maximum; rotate = vnc_rotate; info_print(" x:(%d %d) y:(%d %d) \n", xmin, xmax, ymin, ymax); - return 1; + return 0; +} + +int init_mouse_rel(int fb_xres, int fb_yres, const char *touch_device, int vnc_rotate) +{ + xmin = 0; + xmax = fb_xres; + ymin = 0; + ymax = fb_yres; + + rotate = vnc_rotate; + + is_relative_coords = true; + info_print(" x:(%d %d) y:(%d %d) \n", xmin, xmax, ymin, ymax); + + return 0; } void cleanup_mouse() @@ -238,9 +254,18 @@ void injectMouseEvent(struct fb_var_screeninfo *scrinfo, int buttonMask, int x, gettimeofday(&time, 0); ev.input_event_sec = time.tv_sec; ev.input_event_usec = time.tv_usec; - ev.type = EV_ABS; - ev.code = ABS_X; - ev.value = x; + + if(is_relative_coords) + { + ev.type = EV_REL; + ev.code = REL_X; + ev.value = dx; + } else + { + ev.type = EV_ABS; + ev.code = ABS_X; + ev.value = x; + } if (write(mousefd, &ev, sizeof(ev)) < 0) { error_print("write event failed, %s\n", strerror(errno)); @@ -254,9 +279,17 @@ void injectMouseEvent(struct fb_var_screeninfo *scrinfo, int buttonMask, int x, gettimeofday(&time, 0); ev.input_event_sec = time.tv_sec; ev.input_event_usec = time.tv_usec; - ev.type = EV_ABS; - ev.code = ABS_Y; - ev.value = y; + if(is_relative_coords) + { + ev.type = EV_REL; + ev.code = REL_Y; + ev.value = dy; + } else + { + ev.type = EV_ABS; + ev.code = ABS_Y; + ev.value = y; + } if (write(mousefd, &ev, sizeof(ev)) < 0) { error_print("write event failed, %s\n", strerror(errno)); diff --git a/src/mouse.h b/src/mouse.h index 4a919f9..4e2796a 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -1,5 +1,6 @@ #pragma once int init_mouse(const char *touch_device, int vnc_rotate); +int init_mouse_rel(int fb_xres, int fb_yres, const char *touch_device, int vnc_rotate); void cleanup_mouse(); void injectMouseEvent(struct fb_var_screeninfo *scrinfo, int buttonMask, int x, int y); From ccde0560e7c970ec0750def44147b89d689cdf8a Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Wed, 28 May 2025 14:32:21 +0200 Subject: [PATCH 2/7] [add] add support for rotating fb with 32 bits/pixel --- src/framebuffer-vncserver.c | 66 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/src/framebuffer-vncserver.c b/src/framebuffer-vncserver.c index 15e4a22..a0edcbf 100644 --- a/src/framebuffer-vncserver.c +++ b/src/framebuffer-vncserver.c @@ -482,11 +482,25 @@ static void update_screen(void) } } } - else if (bits_per_pixel == 16) + else if(vnc_rotate > 0 && (bits_per_pixel == 16 || bits_per_pixel == 32)) { - uint16_t *f = (uint16_t *)fbmmap; /* -> framebuffer */ - uint16_t *c = (uint16_t *)fbbuf; /* -> compare framebuffer */ - uint16_t *r = (uint16_t *)vncbuf; /* -> remote framebuffer */ + union + { + uint16_t * val16b; + uint32_t * val32b; + } f, c, r; + + if (bits_per_pixel == 16) + { + f.val16b = (uint16_t *)fbmmap; /* -> framebuffer */ + c.val16b = (uint16_t *)fbbuf; /* -> compare framebuffer */ + r.val16b = (uint16_t *)vncbuf; /* -> remote framebuffer */ + } else if (bits_per_pixel == 32) + { + f.val32b = (uint32_t *)fbmmap; /* -> framebuffer */ + c.val32b = (uint32_t *)fbbuf; /* -> compare framebuffer */ + r.val32b = (uint32_t *)vncbuf; /* -> remote framebuffer */ + } switch (vnc_rotate) { @@ -514,13 +528,30 @@ static void update_screen(void) int x; for (x = 0; x < (int)fb_xres; x++) { - uint16_t pixel = *f; + union { + uint16_t val16b; + uint32_t val32b; + } pixel; - if (pixel != *c) + if (bits_per_pixel == 16) { - int x2, y2; + pixel.val16b = *f.val16b; + } else if (bits_per_pixel == 32) + { + pixel.val32b = *f.val32b; + } - *c = pixel; + if (bits_per_pixel == 16 && pixel.val16b != *c.val16b + || bits_per_pixel == 32 && pixel.val32b != *c.val32b) + { + int x2, y2; + if (bits_per_pixel == 16) + { + *c.val16b = pixel.val16b; + } else if (bits_per_pixel == 32) + { + *c.val32b = pixel.val32b; + } switch (vnc_rotate) { case 0: @@ -547,7 +578,13 @@ static void update_screen(void) exit(EXIT_FAILURE); } - r[y2 * server->width + x2] = PIXEL_FB_TO_RFB(pixel, varblock.r_offset, varblock.g_offset, varblock.b_offset); + if (bits_per_pixel == 16) + { + r.val16b[y2 * server->width + x2] = PIXEL_FB_TO_RFB(pixel.val16b, varblock.r_offset, varblock.g_offset, varblock.b_offset); + } else if (bits_per_pixel == 32) + { + r.val32b[y2 * server->width + x2] = PIXEL_FB_TO_RFB(pixel.val32b, varblock.r_offset, varblock.g_offset, varblock.b_offset); + } if (x2 < varblock.min_i) varblock.min_i = x2; @@ -563,8 +600,15 @@ static void update_screen(void) } } - f++; - c++; + if (bits_per_pixel == 16) + { + f.val16b++; + c.val16b++; + } else if (bits_per_pixel == 32) + { + f.val32b++; + c.val32b++; + } } } } From 002d367ade6e1879ee3ff58582f90cc567bab9cf Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Mon, 2 Jun 2025 09:01:13 +0200 Subject: [PATCH 3/7] [fix] touchscreen pressure detection --- src/touch.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/touch.c b/src/touch.c index 8c8bb76..8bced7e 100644 --- a/src/touch.c +++ b/src/touch.c @@ -109,6 +109,7 @@ void injectTouchEvent(enum MouseAction mouseAction, int x, int y, struct fb_var_ bool sendTouch; int trkIdValue; int touchValue; + int pressureValue; struct timeval time; switch (mouseAction) @@ -118,12 +119,14 @@ void injectTouchEvent(enum MouseAction mouseAction, int x, int y, struct fb_var_ sendTouch = true; trkIdValue = ++trkg_id; touchValue = 1; + pressureValue = 11; break; case MouseRelease: sendPos = false; sendTouch = true; trkIdValue = -1; touchValue = 0; + pressureValue = 0; break; case MouseDrag: sendPos = true; @@ -212,6 +215,17 @@ void injectTouchEvent(enum MouseAction mouseAction, int x, int y, struct fb_var_ } } + gettimeofday(&time, 0); + ev.input_event_sec = time.tv_sec; + ev.input_event_usec = time.tv_usec; + ev.type = EV_ABS; + ev.code = ABS_PRESSURE; + ev.value = pressureValue; + if (write(touchfd, &ev, sizeof(ev)) < 0) + { + error_print("write event failed, %s\n", strerror(errno)); + } + // Finally send the SYN gettimeofday(&time, 0); ev.input_event_sec = time.tv_sec; @@ -223,5 +237,5 @@ void injectTouchEvent(enum MouseAction mouseAction, int x, int y, struct fb_var_ { error_print("write event failed, %s\n", strerror(errno)); } - debug_print("injectTouchEvent (screen(%d,%d) -> touch(%d,%d), mouse=%d)\n", xin, yin, x, y, mouseAction); + info_print("injectTouchEvent (screen(%d,%d) -> touch(%d,%d), mouse=%d)\n", xin, yin, x, y, mouseAction); } From e9e76d22f84844c0a84357f729244351948feec7 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Mon, 2 Jun 2025 09:06:47 +0200 Subject: [PATCH 4/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68dfe18..0bc7c42 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ with rotation: - [ ] 8 bit/pixel - [x] 16 bit/pixel - [ ] 24 bit/pixel -- [ ] 32 bit/pixel +- [x] 32 bit/pixel The code is based on a LibVNC example for Android: https://github.com/LibVNC/libvncserver/blob/master/examples/androidvncserver.c From bbafbc686df224cee1308ce16686f41b9455d317 Mon Sep 17 00:00:00 2001 From: Martin Leutelt Date: Thu, 20 Jun 2024 09:56:51 +0200 Subject: [PATCH 5/7] Add options for authentication by password or password file --- README.md | 2 + src/framebuffer-vncserver.c | 74 +++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/README.md b/README.md index 0bc7c42..0423d04 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ Using qmake: ./framebuffer-vncserver [-f device] [-p port] [-t touchscreen] [-m mouse] [-k keyboard] [-r rotation] [-R touchscreen rotation] [-F FPS] [-v] [-h] -p port: VNC port, default is 5900 + -a authentication: path to password file generated with 'storepasswd' + -A authentication: plain text password -f device: framebuffer device node, default is /dev/fb0 -k device: keyboard device node (example: /dev/input/event0) -t device: touchscreen device node (example:/dev/input/event2) diff --git a/src/framebuffer-vncserver.c b/src/framebuffer-vncserver.c index a0edcbf..46353b7 100644 --- a/src/framebuffer-vncserver.c +++ b/src/framebuffer-vncserver.c @@ -73,6 +73,9 @@ static unsigned int frame_size; static unsigned int fb_xres; static unsigned int fb_yres; int verbose = 0; +/* Can be either a path to a password file or a plain text password. */ +static char *authData = NULL; +static rfbBool authByFile = TRUE; #define UNUSED(x) (void)(x) @@ -222,6 +225,56 @@ a press and release of button 5. injectMouseEvent(&var_scrinfo, buttonMask, x, y); } +static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl, const char* response, int len) +{ + int i; + char *passwd=rfbDecryptPasswdFromFile(cl->screen->authPasswdData); + + if(!passwd) { + rfbErr("Couldn't read password file: %s\n",cl->screen->authPasswdData); + return(FALSE); + } + + rfbEncryptBytes(cl->authChallenge, passwd); + + /* Lose the password from memory */ + for (i = strlen(passwd); i >= 0; i--) { + passwd[i] = '\0'; + } + + free(passwd); + + if (memcmp(cl->authChallenge, response, len) != 0) { + rfbErr("authProcessClientMessage: authentication failed from %s\n", + cl->host); + return(FALSE); + } + + return(TRUE); +} + +rfbBool rfbCheckPasswordByList(rfbClientPtr cl, const char* response, int len) +{ + char **passwds; + int i=0; + + for(passwds=(char**)cl->screen->authPasswdData;*passwds;passwds++,i++) { + uint8_t auth_tmp[CHALLENGESIZE]; + memcpy((char *)auth_tmp, (char *)cl->authChallenge, CHALLENGESIZE); + rfbEncryptBytes(auth_tmp, *passwds); + + if (memcmp(auth_tmp, response, len) == 0) { + if(i>=cl->screen->authPasswdFirstViewOnly) + cl->viewOnly=TRUE; + return(TRUE); + } + } + + rfbErr("authProcessClientMessage: authentication failed from %s\n", + cl->host); + return(FALSE); +} + /*****************************************************************************/ static void init_fb_server(int argc, char **argv, rfbBool enable_touch, rfbBool enable_mouse) @@ -250,6 +303,8 @@ static void init_fb_server(int argc, char **argv, rfbBool enable_touch, rfbBool server->alwaysShared = TRUE; server->httpDir = NULL; server->port = vnc_port; + server->passwordCheck = authByFile ? rfbDefaultPasswordCheck : rfbCheckPasswordByList; + server->authPasswdData = (void *)authData; server->kbdAddEvent = keyevent; if (enable_touch) @@ -642,6 +697,8 @@ void print_usage(char **argv) { info_print("%s [-f device] [-p port] [-t touchscreen] [-m mouse] [-k keyboard] [-r rotation] [-R touchscreen rotation] [-F FPS] [-v] [-h]\n" "-p port: VNC port, default is 5900\n" + "-a authentication: path to password file generated with 'storepasswd'\n" + "-A authentication: plain text password\n" "-f device: framebuffer device node, default is /dev/fb0\n" "-k device: keyboard device node (example: /dev/input/event0)\n" "-t device: touchscreen device node (example:/dev/input/event2)\n" @@ -693,6 +750,22 @@ int main(int argc, char **argv) if (argv[i]) vnc_port = atoi(argv[i]); break; + case 'a': + i++; + if (argv[i]) + authData = argv[i]; + break; + case 'A': { + i++; + char **passwds = malloc(sizeof(char**)*2); + if (passwds && argv[i]) { + passwds[0] = argv[i]; + passwds[1] = NULL; + authByFile = FALSE; + authData = (char *)passwds; + } + break; + } case 'r': i++; if (argv[i]) @@ -771,6 +844,7 @@ int main(int argc, char **argv) info_print(" height: %d\n", (int)fb_yres); info_print(" bpp: %d\n", (int)var_scrinfo.bits_per_pixel); info_print(" port: %d\n", (int)vnc_port); + info_print(" authentication mode: %s\n", authByFile ? "file" : "password"); info_print(" rotate: %d\n", (int)vnc_rotate); info_print(" mouse/touch rotate: %d\n", (int)touch_rotate); info_print(" target FPS: %d\n", (int)target_fps); From bf4c44ff41ddb52c40987c74276ee9a14b277497 Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Tue, 3 Jun 2025 16:03:23 +0200 Subject: [PATCH 6/7] [fix] remove weird coordinate transformation in touch screen --- src/touch.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/touch.c b/src/touch.c index 8bced7e..afd19bc 100644 --- a/src/touch.c +++ b/src/touch.c @@ -98,10 +98,10 @@ void injectTouchEvent(enum MouseAction mouseAction, int x, int y, struct fb_var_ // Calculate the final x and y /* Fake touch screen always reports zero */ //???//if (xmin != 0 && xmax != 0 && ymin != 0 && ymax != 0) - { - x = xmin + (x * (xmax - xmin)) / (scrinfo->xres); - y = ymin + (y * (ymax - ymin)) / (scrinfo->yres); - } + // { + // x = xmin + (x * (xmax - xmin)) / (scrinfo->xres); + // y = ymin + (y * (ymax - ymin)) / (scrinfo->yres); + // } memset(&ev, 0, sizeof(ev)); @@ -213,18 +213,30 @@ void injectTouchEvent(enum MouseAction mouseAction, int x, int y, struct fb_var_ { error_print("write event failed, %s\n", strerror(errno)); } + + gettimeofday(&time, 0); + ev.input_event_sec = time.tv_sec; + ev.input_event_usec = time.tv_usec; + ev.type = EV_ABS; + ev.code = ABS_PRESSURE; + ev.value = pressureValue; + if (write(touchfd, &ev, sizeof(ev)) < 0) + { + error_print("write event failed, %s\n", strerror(errno)); + } + + gettimeofday(&time, 0); + ev.input_event_sec = time.tv_sec; + ev.input_event_usec = time.tv_usec; + ev.type = EV_ABS; + ev.code = ABS_MT_PRESSURE; + ev.value = pressureValue; + if (write(touchfd, &ev, sizeof(ev)) < 0) + { + error_print("write event failed, %s\n", strerror(errno)); + } } - gettimeofday(&time, 0); - ev.input_event_sec = time.tv_sec; - ev.input_event_usec = time.tv_usec; - ev.type = EV_ABS; - ev.code = ABS_PRESSURE; - ev.value = pressureValue; - if (write(touchfd, &ev, sizeof(ev)) < 0) - { - error_print("write event failed, %s\n", strerror(errno)); - } // Finally send the SYN gettimeofday(&time, 0); From d0a7d32d2f29c511f6488b54c9a8f5d6d0a8af4f Mon Sep 17 00:00:00 2001 From: Nicolas Gry Date: Thu, 5 Jun 2025 10:44:34 +0200 Subject: [PATCH 7/7] [fix] mouse : fix sync mouse position between client and server when server's mouse is in relative positioning mode --- README.md | 73 +++++++++++++++++++++++++++++++++++++ src/framebuffer-vncserver.c | 47 +++++++++++++++++++++++- src/mouse.c | 53 +++++++++++++++------------ src/mouse.h | 1 + 4 files changed, 150 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 0423d04..0ce4096 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Using qmake: -p port: VNC port, default is 5900 -a authentication: path to password file generated with 'storepasswd' -A authentication: plain text password + -c cursor: shared memory name for cursor data -f device: framebuffer device node, default is /dev/fb0 -k device: keyboard device node (example: /dev/input/event0) -t device: touchscreen device node (example:/dev/input/event2) @@ -65,6 +66,78 @@ Using qmake: -v: verbose -h: print this help +### Handling the mouse cursor + +In case the app you're running on your server isn't relying on an X server (that is, it manipulates the framebuffer directly), you will encounter the absolute mouse coordinates problem. More specifically, if it is impossible for you to retrieve the mouse absolute coordinates with `EV_ABS` and `ABS_X`/`ABS_Y`, you will have to do the following: + +* Write your own mouse driver to keep track of the cursor's absolute coordinates +* Make the driver write the mouse coordinates in a shared memory of chosen name (e.g `/cursor_pos`) using this struct: +```cpp +typedef struct { + int x; + int y; +} CursorPosition; +``` +* Use the flag `-c` when starting the vnc server. + +Here is a practical example using [lvgl](https://github.com/lvgl/lvgl) to manipulate the framebuffer: + +```cpp +// ------------------------- +// Driver's code + +CursorPosition *cursor_shared_mem = NULL; + +// Initialize shared memory +int init_shared_cursor_mem() { + + int fd = shm_open("/cursor_pos", O_CREAT | O_RDWR, 0666); + + if(fd < 0) + { + fprintf(stderr, "%s(): error while opening shared memory : %s", __FUNCTION__, strerror(errno)); + } + else + { + ftruncate(fd, sizeof(CursorPosition)); + cursor_shared_mem = (CursorPosition*) mmap(0, sizeof(CursorPosition), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + } + return fd; +} + +// Custom driver +static void mouse_custom_driver(lv_indev_t * indev, lv_indev_data_t * data) +{ + // ... some custom computation ... + + // Writing the cursor position in the shared memory : + if (cursor_shared_mem) { + cursor_shared_mem->x = data->point.x; + cursor_shared_mem->y = data->point.y; + } +} + +int main() +{ + // .. some init code ... + init_shared_cursor_mem(); + lv_indev_t *touch = lv_indev_create(); + if(touch != nullptr){ + lv_indev_set_type(touch, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(touch, mouse_custom_driver); // attaching custom driver as read callback + lv_indev_set_display(touch, disp); + } + + // ... + return 0; +} +``` + +Invoking the vnc server: +```bash +framebuffer-vncserver -c /cursor_pos -m /dev/input/event0 ... +``` + ## Run on startup as service To run at startup as a service using systemd, edit the file `fbvnc.service` make sure the path and command line arguments are correct and then run: diff --git a/src/framebuffer-vncserver.c b/src/framebuffer-vncserver.c index 46353b7..f4087d6 100644 --- a/src/framebuffer-vncserver.c +++ b/src/framebuffer-vncserver.c @@ -54,6 +54,7 @@ static char fb_device[256] = "/dev/fb0"; static char touch_device[256] = ""; static char kbd_device[256] = ""; static char mouse_device[256] = ""; +static char cursor_pos[256] = ""; static struct fb_var_screeninfo var_scrinfo; static struct fb_fix_screeninfo fix_scrinfo; @@ -72,6 +73,15 @@ static unsigned int bits_per_pixel; static unsigned int frame_size; static unsigned int fb_xres; static unsigned int fb_yres; + +static int shared_cursor_data_fd; +typedef struct { + int x; + int y; +} CursorPosition; + +CursorPosition *cursor_shared_mem = NULL; + int verbose = 0; /* Can be either a path to a password file or a plain text password. */ static char *authData = NULL; @@ -275,8 +285,19 @@ rfbBool rfbCheckPasswordByList(rfbClientPtr cl, const char* response, int len) return(FALSE); } -/*****************************************************************************/ +enum rfbNewClientAction onClientHook(struct _rfbClientRec* cl) +{ + if(strlen(mouse_device)>0) + { + if(cursor_shared_mem) + { + init_mouse_pos(cursor_shared_mem->x, cursor_shared_mem->y); + } + injectMouseEvent(&var_scrinfo, 0, cl->cursorX, cl->cursorY); + } +} +/*****************************************************************************/ static void init_fb_server(int argc, char **argv, rfbBool enable_touch, rfbBool enable_mouse) { info_print("Initializing server...\n"); @@ -305,6 +326,7 @@ static void init_fb_server(int argc, char **argv, rfbBool enable_touch, rfbBool server->port = vnc_port; server->passwordCheck = authByFile ? rfbDefaultPasswordCheck : rfbCheckPasswordByList; server->authPasswdData = (void *)authData; + server->newClientHook = onClientHook; server->kbdAddEvent = keyevent; if (enable_touch) @@ -691,6 +713,18 @@ static void update_screen(void) } } +int init_cursor_reader() { + int fd = shm_open(cursor_pos, O_RDONLY, 0666); + if (fd < 0) { + error_print("Error when trying to open %s: %s\n", cursor_pos, strerror(errno)); + exit(1); + } + + cursor_shared_mem = (CursorPosition*) mmap(0, sizeof(CursorPosition), PROT_READ, MAP_SHARED, fd, 0); + // close(fd); + return fd; +} + /*****************************************************************************/ void print_usage(char **argv) @@ -699,6 +733,7 @@ void print_usage(char **argv) "-p port: VNC port, default is 5900\n" "-a authentication: path to password file generated with 'storepasswd'\n" "-A authentication: plain text password\n" + "-c cursor: shared memory name for cursor data\n" "-f device: framebuffer device node, default is /dev/fb0\n" "-k device: keyboard device node (example: /dev/input/event0)\n" "-t device: touchscreen device node (example:/dev/input/event2)\n" @@ -766,6 +801,15 @@ int main(int argc, char **argv) } break; } + case 'c': + i++; + if (argv[i]) + { + info_print("Shared cursor data : %s\n", argv[i]); + strcpy(cursor_pos, argv[i]); + shared_cursor_data_fd = init_cursor_reader(); + } + break; case 'r': i++; if (argv[i]) @@ -832,6 +876,7 @@ int main(int argc, char **argv) info_print("Successful\n"); } } + enable_mouse = (!ret); } else diff --git a/src/mouse.c b/src/mouse.c index a08a1cf..e4234c5 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -23,14 +23,10 @@ #include "logging.h" -static int mousefd = -1; - -static int xmin, xmax; -static int ymin, ymax; -static int rotate; -static int trkg_id = -1; -static bool is_wheel_hires = false; -static bool is_relative_coords = false; +#define CHECK_BIT(var,pos) ((var) & (1<<(pos))) +#define MAP(x) { #x,x } +#define WHEEL_UP 3 +#define WHEEL_DOWN 4 #ifndef input_event_sec #define input_event_sec time.tv_sec @@ -43,10 +39,26 @@ typedef struct const int value; } map_t; -#define CHECK_BIT(var,pos) ((var) & (1<<(pos))) -#define MAP(x) { #x,x } -#define WHEEL_UP 3 -#define WHEEL_DOWN 4 +static int mousefd = -1; + +static int xmin, xmax; +static int ymin, ymax; +static int rotate; +static int trkg_id = -1; +static bool is_wheel_hires = false; +static bool is_relative_coords = false; +static const map_t mouseButtonMap[] = { + MAP(BTN_LEFT), + MAP(BTN_MIDDLE), + MAP(BTN_RIGHT), +}; +static const int buttonsNumber = sizeof(mouseButtonMap) / sizeof(mouseButtonMap[0]); +static int last_buttonMask; + +// last_x and last_y should be initialized with the cursor coordinates at the moment of the server start-up. +static int last_x = 0; +static int last_y = 0; +static int wheel_tick; int init_mouse(const char *touch_device, int vnc_rotate) { @@ -115,6 +127,12 @@ int init_mouse_rel(int fb_xres, int fb_yres, const char *touch_device, int vnc_r return 0; } +int init_mouse_pos(int first_x, int first_y) +{ + last_x = first_x; + last_y = first_y; +} + void cleanup_mouse() { if (mousefd != -1) @@ -133,17 +151,6 @@ void injectMouseEvent(struct fb_var_screeninfo *scrinfo, int buttonMask, int x, by a press and release of button 4, and each step downwards is represented by a press and release of button 5. From: http://www.vislab.usyd.edu.au/blogs/index.php/2009/05/22/an-headerless-indexed-protocol-for-input-1?blog=61 */ - - static map_t mouseButtonMap[] = { - MAP(BTN_LEFT), - MAP(BTN_MIDDLE), - MAP(BTN_RIGHT), - }; - static int buttonsNumber = sizeof(mouseButtonMap) / sizeof(mouseButtonMap[0]); - static int last_buttonMask; - static int last_x; - static int last_y; - static int wheel_tick; int last_wheel_tick = 0; diff --git a/src/mouse.h b/src/mouse.h index 4e2796a..96ac7ad 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -2,5 +2,6 @@ int init_mouse(const char *touch_device, int vnc_rotate); int init_mouse_rel(int fb_xres, int fb_yres, const char *touch_device, int vnc_rotate); +int init_mouse_pos(int first_x, int first_y); void cleanup_mouse(); void injectMouseEvent(struct fb_var_screeninfo *scrinfo, int buttonMask, int x, int y);