diff options
author | dscho <dscho> | 2009-03-07 19:18:26 +0000 |
---|---|---|
committer | dscho <dscho> | 2009-03-07 19:18:26 +0000 |
commit | a02607fe352eca4ba8efff8df52c9e5ab1d04e6c (patch) | |
tree | 9d938ea9f3b09275c68976a8f747be04893f5f51 | |
parent | 3ab7d5d7663bc995f463dcc23cb36b70e7c6e841 (diff) | |
download | libtdevnc-a02607fe352eca4ba8efff8df52c9e5ab1d04e6c.tar.gz libtdevnc-a02607fe352eca4ba8efff8df52c9e5ab1d04e6c.zip |
Teach SDLvncviewer to be resizable
Using "SDLvncviewer -resizable", you make the window resizable. This
means that you can shrink the window (e.g. when you are trying to access
an x11vnc from your little netbook), or you can enlarge it.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | client_examples/SDLvncviewer.c | 153 |
2 files changed, 148 insertions, 8 deletions
@@ -1,3 +1,6 @@ +2009-03-07 Johannes E. Schindelin <Johannes.Schindelin@gmx.de> + * client_examples/SDLvncviewer.c: make the viewer resizable + 2009-03-06 Johannes E. Schindelin <Johannes.Schindelin@gmx.de> * client_examples/SDLvncviewer.c: enable key repeat diff --git a/client_examples/SDLvncviewer.c b/client_examples/SDLvncviewer.c index 791c308..2f011ee 100644 --- a/client_examples/SDLvncviewer.c +++ b/client_examples/SDLvncviewer.c @@ -8,25 +8,37 @@ struct { int sdl; int rfb; } buttonMapping[]={ {0,0} }; -static rfbBool resize(rfbClient* client) { - static char first=TRUE; +static int enableResizable; #ifdef SDL_ASYNCBLIT - int flags=SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; + int sdlFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; #else - int flags=SDL_HWSURFACE|SDL_HWACCEL; + int sdlFlags = SDL_HWSURFACE | SDL_HWACCEL; #endif +static int realWidth, realHeight, bytesPerPixel, rowStride; +static char *sdlPixels; + +static rfbBool resize(rfbClient* client) { + static char first=TRUE; int width=client->width,height=client->height, depth=client->format.bitsPerPixel; + + if (enableResizable) + sdlFlags |= SDL_RESIZABLE; + client->updateRect.x = client->updateRect.y = 0; client->updateRect.w = width; client->updateRect.h = height; - rfbBool okay=SDL_VideoModeOK(width,height,depth,flags); + rfbBool okay=SDL_VideoModeOK(width,height,depth,sdlFlags); if(!okay) for(depth=24;!okay && depth>4;depth/=2) - okay=SDL_VideoModeOK(width,height,depth,flags); + okay=SDL_VideoModeOK(width,height,depth,sdlFlags); if(okay) { - SDL_Surface* sdl=SDL_SetVideoMode(width,height,depth,flags); + SDL_Surface* sdl=SDL_SetVideoMode(width,height,depth,sdlFlags); rfbClientSetClientData(client, SDL_Init, sdl); client->width = sdl->pitch / (depth / 8); + if (sdlPixels) { + free(client->frameBuffer); + sdlPixels = NULL; + } client->frameBuffer=sdl->pixels; if(first || depth!=client->format.bitsPerPixel) { first=FALSE; @@ -147,10 +159,124 @@ static rfbKeySym SDL_key2rfbKeySym(SDL_KeyboardEvent* e) { return k; } +static uint32_t get(rfbClient *cl, int x, int y) +{ + switch (bytesPerPixel) { + case 1: return ((uint8_t *)cl->frameBuffer)[x + y * cl->width]; + case 2: return ((uint16_t *)cl->frameBuffer)[x + y * cl->width]; + case 4: return ((uint32_t *)cl->frameBuffer)[x + y * cl->width]; + default: + rfbClientErr("Unknown bytes/pixel: %d", bytesPerPixel); + exit(1); + } +} + +static void put(int x, int y, uint32_t v) +{ + switch (bytesPerPixel) { + case 1: ((uint8_t *)sdlPixels)[x + y * rowStride] = v; break; + case 2: ((uint16_t *)sdlPixels)[x + y * rowStride] = v; break; + case 4: ((uint32_t *)sdlPixels)[x + y * rowStride] = v; break; + default: + rfbClientErr("Unknown bytes/pixel: %d", bytesPerPixel); + exit(1); + } +} + +static void resizeRectangleToReal(rfbClient *cl, int x, int y, int w, int h) +{ + int i0 = x * realWidth / cl->width; + int i1 = ((x + w) * realWidth - 1) / cl->width + 1; + int j0 = y * realHeight / cl->height; + int j1 = ((y + h) * realHeight - 1) / cl->height + 1; + int i, j; + + for (j = j0; j < j1; j++) + for (i = i0; i < i1; i++) { + int x0 = i * cl->width / realWidth; + int x1 = ((i + 1) * cl->width - 1) / realWidth + 1; + int y0 = j * cl->height / realHeight; + int y1 = ((j + 1) * cl->height - 1) / realHeight + 1; + uint32_t r = 0, g = 0, b = 0; + + for (y = y0; y < y1; y++) + for (x = x0; x < x1; x++) { + uint32_t v = get(cl, x, y); +#define REDSHIFT cl->format.redShift +#define REDMAX cl->format.redMax +#define GREENSHIFT cl->format.greenShift +#define GREENMAX cl->format.greenMax +#define BLUESHIFT cl->format.blueShift +#define BLUEMAX cl->format.blueMax + r += (v >> REDSHIFT) & REDMAX; + g += (v >> GREENSHIFT) & GREENMAX; + b += (v >> BLUESHIFT) & BLUEMAX; + } + r /= (x1 - x0) * (y1 - y0); + g /= (x1 - x0) * (y1 - y0); + b /= (x1 - x0) * (y1 - y0); + + put(i, j, (r << REDSHIFT) | (g << GREENSHIFT) | + (b << BLUESHIFT)); + } +} + static void update(rfbClient* cl,int x,int y,int w,int h) { + if (sdlPixels) { + resizeRectangleToReal(cl, x, y, w, h); + w = ((x + w) * realWidth - 1) / cl->width + 1; + h = ((y + h) * realHeight - 1) / cl->height + 1; + x = x * realWidth / cl->width; + y = y * realHeight / cl->height; + w -= x; + h -= y; + } SDL_UpdateRect(rfbClientGetClientData(cl, SDL_Init), x, y, w, h); } +static void setRealDimension(rfbClient *client, int w, int h) +{ + SDL_Surface* sdl; + + if (w < 0) { + const SDL_VideoInfo *info = SDL_GetVideoInfo(); + w = info->current_h; + h = info->current_w; + } + + if (w == realWidth && h == realHeight) + return; + + if (!sdlPixels) { + int size; + + sdlPixels = (char *)client->frameBuffer; + rowStride = client->width; + + bytesPerPixel = client->format.bitsPerPixel / 8; + size = client->width * bytesPerPixel * client->height; + client->frameBuffer = malloc(size); + if (!client->frameBuffer) { + rfbClientErr("Could not allocate %d bytes", size); + exit(1); + } + memcpy(client->frameBuffer, sdlPixels, size); + } + + sdl = rfbClientGetClientData(client, SDL_Init); + if (sdl->w != w || sdl->h != h) { + int depth = sdl->format->BitsPerPixel; + sdl = SDL_SetVideoMode(w, h, depth, sdlFlags); + rfbClientSetClientData(client, SDL_Init, sdl); + sdlPixels = sdl->pixels; + rowStride = sdl->pitch / (depth / 8); + } + + realWidth = w; + realHeight = h; + update(client, 0, 0, client->width, client->height); +} + static void kbd_leds(rfbClient* cl, int value, int pad) { /* note: pad is for future expansion 0=unused */ fprintf(stderr,"Led State= 0x%02X\n", value); @@ -231,8 +357,10 @@ int main(int argc,char** argv) { #endif for (i = 1, j = 1; i < argc; i++) - if (!strcmp(argv[1], "-viewonly")) + if (!strcmp(argv[i], "-viewonly")) viewOnly = 1; + else if (!strcmp(argv[i], "-resizable")) + enableResizable = 1; else { if (i != j) argv[j] = argv[i]; @@ -270,6 +398,11 @@ int main(int argc,char** argv) { break; int state=SDL_GetMouseState(&x,&y); int i; + + if (sdlPixels) { + x = x * cl->width / realWidth; + y = y * cl->height / realHeight; + } for(buttonMask=0,i=0;buttonMapping[i].sdl;i++) if(state&SDL_BUTTON(buttonMapping[i].sdl)) buttonMask|=buttonMapping[i].rfb; @@ -286,6 +419,10 @@ int main(int argc,char** argv) { return 0; case SDL_ACTIVEEVENT: break; + case SDL_VIDEORESIZE: + setRealDimension(cl, + e.resize.w, e.resize.h); + break; default: rfbClientLog("ignore SDL event: 0x%x\n",e.type); } |