summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--client_examples/SDLvncviewer.c153
2 files changed, 148 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 2327e6c..10b52bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);
}