Commit a02607fe authored by dscho's avatar dscho

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: 's avatarJohannes Schindelin <johannes.schindelin@gmx.de>
parent 3ab7d5d7
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
......
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment