summaryrefslogtreecommitdiffstats
path: root/client_examples/SDLvncviewer.c
diff options
context:
space:
mode:
authordscho <dscho>2009-03-07 19:18:26 +0000
committerdscho <dscho>2009-03-07 19:18:26 +0000
commita02607fe352eca4ba8efff8df52c9e5ab1d04e6c (patch)
tree9d938ea9f3b09275c68976a8f747be04893f5f51 /client_examples/SDLvncviewer.c
parent3ab7d5d7663bc995f463dcc23cb36b70e7c6e841 (diff)
downloadlibtdevnc-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>
Diffstat (limited to 'client_examples/SDLvncviewer.c')
-rw-r--r--client_examples/SDLvncviewer.c153
1 files changed, 145 insertions, 8 deletions
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);
}