summaryrefslogtreecommitdiffstats
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
parent3ab7d5d7663bc995f463dcc23cb36b70e7c6e841 (diff)
downloadlibvncserver-a02607fe352eca4ba8efff8df52c9e5ab1d04e6c.zip
libvncserver-a02607fe352eca4ba8efff8df52c9e5ab1d04e6c.tar.gz
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--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);
}
OpenPOWER on IntegriCloud