commit be9978c3089de21a8a62e9fd04841951390e3053 Author: Lephenixnoir Date: Sat Mar 25 22:20:45 2023 +0100 vnc: first working RFB client, sends raw frames to SDL window diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..067cc4f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/vnc-client/build +/vnc-client/cgvm_vnc diff --git a/README.md b/README.md new file mode 100644 index 0000000..6c8f926 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +Setting up the extra display and starting wayvnc + +``` +% swaymsg create_output +% swaymsg output "HEADLESS-1" resolution 396x224 +% wayvnc -o HEADLESS-1 +``` + +Compiling and starting the VNC client + +``` +% cd vnc-client +% cmake -B build +% make -C build +% ./cgvm_vnc +``` diff --git a/vnc-client/CMakeLists.txt b/vnc-client/CMakeLists.txt new file mode 100644 index 0000000..d5bb8da --- /dev/null +++ b/vnc-client/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.15) +project(CGVirtualMonitorVNCClient VERSION 1.0 LANGUAGES C) + +find_package(LibVNCServer 0.9 REQUIRED) +find_package(SDL2 2.0 REQUIRED) + +add_executable(cgvm_vnc src/main.c) +set_target_properties(cgvm_vnc PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") +target_link_libraries(cgvm_vnc LibVNCServer::vncclient SDL2::SDL2) diff --git a/vnc-client/src/main.c b/vnc-client/src/main.c new file mode 100644 index 0000000..b0bba4e --- /dev/null +++ b/vnc-client/src/main.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include + +/* Application globals */ +struct app { + rfbClient *client; + SDL_Window *window; + SDL_Surface *surface; +}; +static struct app app = { 0 }; + +static void cleanup(void) +{ + if(app.client) + rfbClientCleanup(app.client); + if(app.window) + SDL_DestroyWindow(app.window); + SDL_Quit(); +} + +static void fb_update(rfbClient *client) +{ +/* SDL_LockSurface(app.surface); + assert(app.surface->format->BytesPerPixel == 4); + uint8_t *buffer = (void *)app.surface->pixels; + for(int y = 0; y < app.surface->h; y++) { + for(int x = 0; x < app.surface->w; x++) { + int offset = y * app.surface->pitch + 4 * x; + // R, G, B + buffer[offset + 2] = 255; + buffer[offset + 1] = 255; + buffer[offset + 0] = 0; + } + } + SDL_UnlockSurface(app.surface); */ + SDL_UpdateWindowSurface(app.window); +} + +int main(void) +{ + SDL_Init(SDL_INIT_VIDEO); + atexit(cleanup); + signal(SIGINT, exit); + + app.window = SDL_CreateWindow("CG Virtual Monitor test VNC client", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 396, 224, 0); + app.surface = SDL_GetWindowSurface(app.window); + + app.client = rfbGetClient(8, 3, 4); + app.client->FinishedFrameBufferUpdate = fb_update; + app.client->width = 396; + app.client->height = 224; + app.client->frameBuffer = app.surface->pixels; + + app.client->format.bitsPerPixel=32; + app.client->format.redShift=app.surface->format->Rshift; + app.client->format.greenShift=app.surface->format->Gshift; + app.client->format.blueShift=app.surface->format->Bshift; + app.client->format.redMax=app.surface->format->Rmask>>app.client->format.redShift; + app.client->format.greenMax=app.surface->format->Gmask>>app.client->format.greenShift; + app.client->format.blueMax=app.surface->format->Bmask>>app.client->format.blueShift; + SetFormatAndEncodings(app.client); + + int argc = 4; + char *argv[] = { "cgvm_vnc", "-encodings", "raw", "127.0.0.1", NULL }; + if(!rfbInitClient(app.client, &argc, argv)) { + fprintf(stderr, "rfbInitClient failed\n"); + app.client = NULL; + return 1; + } + + while(1) { + SDL_Event e; + while(SDL_PollEvent(&e)) { + if(e.type == SDL_QUIT) { + fprintf(stderr, "SDL_QUIT: Exiting...\n"); + exit(0); + } + } + + int i = WaitForMessage(app.client, 100); + if(i < 0) { + fprintf(stderr, "WaitForMessage() select: %d\n", i); + continue; + } + else if(i > 0 && !HandleRFBServerMessage(app.client)) { + fprintf(stderr, "HandleRFBServerMessage() failed\n"); + continue; + } + } + + return 0; +}