diff -u -r vnc_unixsrc/vncviewer/README vnc_unixsrc.new/vncviewer/README --- vnc_unixsrc/vncviewer/README 2005-07-04 12:40:22.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/README 2006-06-16 10:50:23.000000000 -0500 @@ -59,6 +59,8 @@ been sent at the end of the update. In some cases this can save time by skipping intermediate screen states. +* The client can display a scaled output of the server desktop. + Resources --------- @@ -214,6 +216,16 @@ Similar to rawDelay, but highlights the areas copied using the copyrect encoding. + scaleNum + + The numerator for scaling the client's window with respect to the + server's desktop + + scaleDen + + The denominator for scaling the client's window with respect to the + server's desktop + How to customise the popup window --------------------------------- diff -u -r vnc_unixsrc/vncviewer/argsresources.c vnc_unixsrc.new/vncviewer/argsresources.c --- vnc_unixsrc/vncviewer/argsresources.c 2005-07-04 12:40:22.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/argsresources.c 2006-06-16 10:59:01.000000000 -0500 @@ -224,6 +224,15 @@ {"grabKeyboard", "GrabKeyboard", XtRBool, sizeof(Bool), XtOffsetOf(AppData, grabKeyboard), XtRImmediate, (XtPointer) False}, + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + command line scale parameters, like the Window's options */ + {"scaleNum", "ScaleNum", XtRInt, sizeof(int), + XtOffsetOf(AppData, scaleNum), XtRImmediate, (XtPointer) 1}, + + {"scaleDen", "ScaleDen", XtRInt, sizeof(int), + XtOffsetOf(AppData, scaleDen), XtRImmediate, (XtPointer) 1}, + /* Miguel end */ + {"autoPass", "AutoPass", XtRBool, sizeof(Bool), XtOffsetOf(AppData, autoPass), XtRImmediate, (XtPointer) False} }; @@ -253,7 +262,12 @@ {"-nojpeg", "*enableJPEG", XrmoptionNoArg, "False"}, {"-nocursorshape", "*useRemoteCursor", XrmoptionNoArg, "False"}, {"-x11cursor", "*useX11Cursor", XrmoptionNoArg, "True"}, - {"-autopass", "*autoPass", XrmoptionNoArg, "True"} + {"-autopass", "*autoPass", XrmoptionNoArg, "True"}, + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + command line scale parameters, like the Window's options */ + {"-scale_num", "*scaleNum", XrmoptionSepArg, 0}, + {"-scale_den", "*scaleDen", XrmoptionSepArg, 0} + /* Miguel end */ }; @@ -315,6 +329,11 @@ " -shared (set by default)\n" " -noshared\n" " -viewonly\n" + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + command line scale parameters, like the Window's options */ + " -scale_num (for scaling)\n" + " -scale_den (for scaling)\n" + /* Miguel end */ " -fullscreen\n" " -noraiseonbeep\n" " -passwd (standard VNC authentication)\n" @@ -337,6 +356,15 @@ exit(1); } +/* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + to simplify the factors, like the Window's options */ +/* Greatest common denominator, by Euclid */ +int gcd( int a, int b) { + if ( a < b) return gcd( b, a); + if ( b == 0) return a; + return gcd( b, a % b); +} +/* Miguel end */ /* * GetArgsAndResources() deals with resources and any command-line arguments @@ -357,6 +385,20 @@ XtGetApplicationResources(toplevel, &appData, appDataResourceList, XtNumber(appDataResourceList), 0, 0); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's simplify the scale factors */ + if ( appData.scaleNum < 1) appData.scaleNum = 1; + if ( appData.scaleDen < 1) appData.scaleDen = 1; + if ( appData.scaleNum == appData.scaleDen) { + appData.scaled = 0; + } else { + appData.scaled = 1; + } + i = gcd( appData.scaleNum, appData.scaleDen); + appData.scaleNum /= i; + appData.scaleDen /= i; + /* Miguel end */ + /* Add our actions to the actions table so they can be used in widget resource specs */ diff -u -r vnc_unixsrc/vncviewer/corre.c vnc_unixsrc.new/vncviewer/corre.c --- vnc_unixsrc/vncviewer/corre.c 2000-06-11 07:00:53.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/corre.c 2006-06-16 10:50:23.000000000 -0500 @@ -54,7 +54,9 @@ #endif XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, rx, ry, rw, rh); if (!ReadFromRFBServer(buffer, hdr.nSubrects * (4 + (BPP / 8)))) return False; @@ -76,7 +78,9 @@ #endif XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, rx + x, ry + y, w, h); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, rx + x, ry + y, w, h); } return True; diff -u -r vnc_unixsrc/vncviewer/cursor.c vnc_unixsrc.new/vncviewer/cursor.c --- vnc_unixsrc/vncviewer/cursor.c 2003-01-15 03:46:52.000000000 -0600 +++ vnc_unixsrc.new/vncviewer/cursor.c 2006-06-16 10:50:23.000000000 -0500 @@ -459,10 +459,14 @@ if (appData.useShm) XSync(dpy, False); #endif - XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XCopyAreaScaled(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0); } else { /* Restore screen area. */ - XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XCopyAreaScaled(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y); } } diff -u -r vnc_unixsrc/vncviewer/desktop.c vnc_unixsrc.new/vncviewer/desktop.c --- vnc_unixsrc/vncviewer/desktop.c 2004-05-28 12:29:29.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/desktop.c 2006-06-16 10:50:24.000000000 -0500 @@ -73,8 +73,10 @@ XtNborderWidth, 0, NULL); - XtVaSetValues(desktop, XtNwidth, si.framebufferWidth, - XtNheight, si.framebufferHeight, NULL); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ + XtVaSetValues(desktop, XtNwidth, appData.windowWidth, + XtNheight, appData.windowHeight, NULL); XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask, True, HandleBasicDesktopEvent, NULL); @@ -93,8 +95,10 @@ #endif if (!image) { + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, - si.framebufferWidth, si.framebufferHeight, + appData.windowWidth, appData.windowHeight, BitmapPad(dpy), 0); image->data = malloc(image->bytes_per_line * image->height); @@ -161,19 +165,28 @@ /* sometimes due to scrollbars being added/removed we get an expose outside the actual desktop area. Make sure we don't pass it on to the RFB server. */ - - if (ev->xexpose.x + ev->xexpose.width > si.framebufferWidth) { - ev->xexpose.width = si.framebufferWidth - ev->xexpose.x; - if (ev->xexpose.width <= 0) break; - } - - if (ev->xexpose.y + ev->xexpose.height > si.framebufferHeight) { - ev->xexpose.height = si.framebufferHeight - ev->xexpose.y; - if (ev->xexpose.height <= 0) break; + { + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale back the coordinates */ + int Width = si.framebufferWidth; + int Height = si.framebufferHeight; + int x = ev->xexpose.x, y = ev->xexpose.y; + int width = ev->xexpose.width, height = ev->xexpose.height; + + GetOriginalDimensions( &x, &y, &width, &height); + + if (x + width > Width) { + width = Width - x; + if (width <= 0) break; + } + + if (y + height > Height) { + height = Height - y; + if (height <= 0) break; + } + + SendFramebufferUpdateRequest(x, y, width, height, False); } - - SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y, - ev->xexpose.width, ev->xexpose.height, False); break; case LeaveNotify: @@ -291,20 +304,26 @@ while (XCheckTypedWindowEvent(dpy, desktopWin, MotionNotify, ev)) ; /* discard all queued motion notify events */ - SendPointerEvent(ev->xmotion.x, ev->xmotion.y, - (ev->xmotion.state & 0x1f00) >> 8); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale back the coordinates */ + SendPointerEventScaled(ev->xmotion.x, ev->xmotion.y, + (ev->xmotion.state & 0x1f00) >> 8); return; case ButtonPress: - SendPointerEvent(ev->xbutton.x, ev->xbutton.y, - (((ev->xbutton.state & 0x1f00) >> 8) | - (1 << (ev->xbutton.button - 1)))); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale back the coordinates */ + SendPointerEventScaled(ev->xbutton.x, ev->xbutton.y, + (((ev->xbutton.state & 0x1f00) >> 8) | + (1 << (ev->xbutton.button - 1)))); return; case ButtonRelease: - SendPointerEvent(ev->xbutton.x, ev->xbutton.y, - (((ev->xbutton.state & 0x1f00) >> 8) & - ~(1 << (ev->xbutton.button - 1)))); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale back the coordinates */ + SendPointerEventScaled(ev->xbutton.x, ev->xbutton.y, + (((ev->xbutton.state & 0x1f00) >> 8) & + ~(1 << (ev->xbutton.button - 1)))); return; case KeyPress: @@ -356,9 +375,38 @@ * CopyDataToScreen. */ +/* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ +void ScaleImageData( int bytesPerPixel, int dstRowStride, int srcRowStride, + int x, int y, + int srcWidth, int srcHeight, const char *srcImage, + int dst_x, int dst_y, + int dstWidth, int dstHeight, char *dstImage ) { + int h, w, ip; + + for ( h = 0; h < dstHeight; h++) { + int org_h = ( int)( 0.5 + ( double)( ( h + dst_y) * appData.scaleDen) / ( double)appData.scaleNum) - y; + if ( org_h >= srcHeight) org_h = srcHeight - 1; + if ( org_h < 0) org_h = 0; + for ( w = 0; w < dstWidth; w++) { + int org_w = ( int)( 0.5 + ( double)( ( w + dst_x) * appData.scaleDen) / ( double)appData.scaleNum) - x; + if ( org_w >= srcWidth) org_w = srcWidth - 1; + if ( org_w < 0) org_w = 0; + for ( ip = 0; ip < bytesPerPixel; ip++) { + dstImage[ dstRowStride * ( dst_y + h) + ( w + dst_x) * bytesPerPixel + ip] = + srcImage[ srcRowStride * org_h + org_w * bytesPerPixel + ip]; + } + } + } +} +/* Miguel end */ + void CopyDataToScreen(char *buf, int x, int y, int width, int height) { + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + nothing to do */ + if ( !width || !height) return; if (appData.rawDelay != 0) { XFillRectangle(dpy, desktopWin, gc, x, y, width, height); @@ -368,17 +416,52 @@ } if (!appData.useBGR233) { - int h; - int widthInBytes = width * myFormat.bitsPerPixel / 8; - int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8; - - char *scr = (image->data + y * scrWidthInBytes - + x * myFormat.bitsPerPixel / 8); - - for (h = 0; h < height; h++) { - memcpy(scr, buf, widthInBytes); - buf += widthInBytes; - scr += scrWidthInBytes; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + at the moment we only know how to scale with bitsPerPixel >= 8 */ + if ( !appData.scaled || ( myFormat.bitsPerPixel < 8)) { + int h; + int widthInBytes = width * myFormat.bitsPerPixel / 8; + int scrWidthInBytes = appData.windowWidth * myFormat.bitsPerPixel / 8; + char *scr = (image->data + y * scrWidthInBytes + + x * myFormat.bitsPerPixel / 8); + + for (h = 0; h < height; h++) { + memcpy(scr, buf, widthInBytes); + buf += widthInBytes; + scr += scrWidthInBytes; + } + } else { + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data and coordinates */ + int dst_x = x; + int dst_y = y; + int dst_width = width; + int dst_height = height; + int bufWidthInBytes = width * myFormat.bitsPerPixel / 8; + int scrWidthInBytes = appData.windowWidth * myFormat.bitsPerPixel / 8; /* de momento */ + + char *scr; + + int h, w, ip; + int tam_buf_tmp = 0; + int tmp_WidthInBytes = dst_width * myFormat.bitsPerPixel / 8; + char *tmp; + + ScaleDimensions( &dst_x, &dst_y, &dst_width, &dst_height); + + scr = (image->data + dst_y * scrWidthInBytes + dst_x * myFormat.bitsPerPixel / 8); + if ( height && width && dst_width && dst_height) { + scr = image->data; + ScaleImageData( myFormat.bitsPerPixel / 8, scrWidthInBytes, bufWidthInBytes, + x, y, width, height, buf, + dst_x, dst_y, dst_width, dst_height, scr); + } + + x = dst_x; + y = dst_y; + width = dst_width; + height = dst_height; + /* Miguel end */ } } else { CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height); @@ -407,9 +490,11 @@ int fbwb = si.framebufferWidth / 8; CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8; CARD8 *scrt; - CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x; - CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x; - CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ + CARD8 *scr8 = ((CARD8 *)image->data) + y * appData.windowWidth + x; + CARD16 *scr16 = ((CARD16 *)image->data) + y * appData.windowWidth + x; + CARD32 *scr32 = ((CARD32 *)image->data) + y * appData.windowWidth + x; switch (visbpp) { @@ -437,7 +522,9 @@ for (p = 0; p < width; p++) { *(scr8++) = BGR233ToPixel[*(buf++)]; } - scr8 += si.framebufferWidth - width; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ + scr8 += appData.windowWidth - width; } break; @@ -446,7 +533,9 @@ for (p = 0; p < width; p++) { *(scr16++) = BGR233ToPixel[*(buf++)]; } - scr16 += si.framebufferWidth - width; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ + scr16 += appData.windowWidth - width; } break; @@ -455,8 +544,11 @@ for (p = 0; p < width; p++) { *(scr32++) = BGR233ToPixel[*(buf++)]; } - scr32 += si.framebufferWidth - width; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ + scr32 += appData.windowWidth - width; } break; } } + diff -u -r vnc_unixsrc/vncviewer/hextile.c vnc_unixsrc.new/vncviewer/hextile.c --- vnc_unixsrc/vncviewer/hextile.c 2000-06-11 07:00:53.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/hextile.c 2006-06-16 10:50:24.000000000 -0500 @@ -73,7 +73,9 @@ gcv.foreground = bg; XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, x, y, w, h); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, x, y, w, h); if (subencoding & rfbHextileForegroundSpecified) if (!ReadFromRFBServer((char *)&fg, sizeof(fg))) @@ -108,7 +110,9 @@ gcv.foreground = fg; XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); } } else { @@ -131,7 +135,9 @@ sw = rfbHextileExtractW(*ptr); sh = rfbHextileExtractH(*ptr); ptr++; - XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); } } } diff -u -r vnc_unixsrc/vncviewer/misc.c vnc_unixsrc.new/vncviewer/misc.c --- vnc_unixsrc/vncviewer/misc.c 2003-01-15 01:58:32.000000000 -0600 +++ vnc_unixsrc.new/vncviewer/misc.c 2006-06-16 10:50:24.000000000 -0500 @@ -57,8 +57,10 @@ sprintf(title, titleFormat, desktopName); XtVaSetValues(toplevel, XtNtitle, title, XtNiconName, title, NULL); - XtVaSetValues(toplevel, XtNmaxWidth, si.framebufferWidth, - XtNmaxHeight, si.framebufferHeight, NULL); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ + XtVaSetValues(toplevel, XtNmaxWidth, appData.windowWidth, + XtNmaxHeight, appData.windowHeight, NULL); dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); @@ -80,8 +82,10 @@ if (geometry == NULL) { Dimension toplevelX, toplevelY; - Dimension toplevelWidth = si.framebufferWidth; - Dimension toplevelHeight = si.framebufferHeight; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ + Dimension toplevelWidth = appData.windowWidth; + Dimension toplevelHeight = appData.windowHeight; if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) toplevelWidth = dpyWidth - appData.wmDecorationWidth; diff -u -r vnc_unixsrc/vncviewer/rfbproto.c vnc_unixsrc.new/vncviewer/rfbproto.c --- vnc_unixsrc/vncviewer/rfbproto.c 2004-03-11 12:14:39.000000000 -0600 +++ vnc_unixsrc.new/vncviewer/rfbproto.c 2006-06-16 10:50:24.000000000 -0500 @@ -918,6 +918,17 @@ return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); } +/* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ +Bool SendPointerEventScaled(int x, int y, int buttonMask) { + int nx = x, ny = y; + if ( appData.scaled) { + nx = ( int)( 0.5 + ( double)( x * appData.scaleDen) / ( double)appData.scaleNum); + ny = ( int)( 0.5 + ( double)( y * appData.scaleDen) / ( double)appData.scaleNum); + } + SendPointerEvent( nx, ny, buttonMask); +} +/* Miguel end */ /* * SendKeyEvent. @@ -1092,24 +1103,29 @@ /* If RichCursor encoding is used, we should extend our "cursor lock area" (previously set to destination rectangle) to the source rectangle as well. */ - SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); + SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); if (appData.copyRectDelay != 0) { - XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); - XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, + XFillRectangleScaled(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); XSync(dpy,False); usleep(appData.copyRectDelay * 1000); - XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); - XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, + XFillRectangleScaled(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); } - - XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, - rect.r.w, rect.r.h, rect.r.x, rect.r.y); - + + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XCopyAreaScaled(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, + rect.r.w, rect.r.h, rect.r.x, rect.r.y); break; } diff -u -r vnc_unixsrc/vncviewer/rre.c vnc_unixsrc.new/vncviewer/rre.c --- vnc_unixsrc/vncviewer/rre.c 2000-06-11 07:00:53.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/rre.c 2006-06-16 10:50:24.000000000 -0500 @@ -53,7 +53,10 @@ #endif XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); + +/* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, rx, ry, rw, rh); for (i = 0; i < hdr.nSubrects; i++) { if (!ReadFromRFBServer((char *)&pix, sizeof(pix))) @@ -74,8 +77,10 @@ #endif XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y, - subrect.w, subrect.h); + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y, + subrect.w, subrect.h); } return True; diff -u -r vnc_unixsrc/vncviewer/shm.c vnc_unixsrc.new/vncviewer/shm.c --- vnc_unixsrc/vncviewer/shm.c 2000-06-11 07:00:53.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/shm.c 2006-06-16 10:50:24.000000000 -0500 @@ -57,8 +57,10 @@ if (!XShmQueryExtension(dpy)) return NULL; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + size of the scaled desktop */ image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, - si.framebufferWidth, si.framebufferHeight); + appData.windowWidth, appData.windowHeight); if (!image) return NULL; shminfo.shmid = shmget(IPC_PRIVATE, diff -u -r vnc_unixsrc/vncviewer/tight.c vnc_unixsrc.new/vncviewer/tight.c --- vnc_unixsrc/vncviewer/tight.c 2002-04-30 08:07:31.000000000 -0500 +++ vnc_unixsrc.new/vncviewer/tight.c 2006-06-16 10:50:24.000000000 -0500 @@ -136,7 +136,10 @@ #endif XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); + + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ + XFillRectangleScaled(dpy, desktopWin, gc, rx, ry, rw, rh); return True; } diff -u -r vnc_unixsrc/vncviewer/vncviewer.c vnc_unixsrc.new/vncviewer/vncviewer.c --- vnc_unixsrc/vncviewer/vncviewer.c 2004-01-13 08:22:05.000000000 -0600 +++ vnc_unixsrc.new/vncviewer/vncviewer.c 2006-06-16 10:50:24.000000000 -0500 @@ -98,6 +98,16 @@ /* Create the "desktop" widget, and perform initialisation which needs doing before the widgets are realized */ + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + compute the window size if scaled */ + appData.windowWidth = si.framebufferWidth; + appData.windowHeight = si.framebufferHeight; + if ( appData.scaled && ( myFormat.bitsPerPixel >= 8)) { + appData.windowWidth = appData.windowWidth * appData.scaleNum / appData.scaleDen; + appData.windowHeight = appData.windowHeight * appData.scaleNum / appData.scaleDen; + } + /* Miguel end */ + ToplevelInitBeforeRealization(); DesktopInitBeforeRealization(); diff -u -r vnc_unixsrc/vncviewer/vncviewer.h vnc_unixsrc.new/vncviewer/vncviewer.h --- vnc_unixsrc/vncviewer/vncviewer.h 2004-03-11 12:14:40.000000000 -0600 +++ vnc_unixsrc.new/vncviewer/vncviewer.h 2006-06-16 10:50:24.000000000 -0500 @@ -110,6 +110,15 @@ Bool useX11Cursor; Bool autoPass; + /* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + data needed to scale up/down the view */ + Bool scaled; + int scaleNum; + int scaleDen; + int windowWidth; + int windowHeight; + /* Miguel end */ + } AppData; extern AppData appData; @@ -231,6 +240,10 @@ extern void PrintPixelFormat(rfbPixelFormat *format); +/* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + let's scale the data */ +extern Bool SendPointerEventScaled(int x, int y, int buttonMask); + /* selection.c */ extern void InitialiseSelection(); @@ -271,3 +284,66 @@ extern XtAppContext appContext; extern Display* dpy; extern Widget toplevel; + +/* Miguel Pasenau: 16 May 2003 miguel@cimne.upc.es + functions to scale dimensions */ + +static void ScaleDimensions( int *x, int *y, int *width, int *height) { + if ( appData.scaled) { + int dst_x = ( int)( 0.5 + ( double)( *x * appData.scaleNum) / ( double)appData.scaleDen); + int dst_y = ( int)( 0.5 + ( double)( *y * appData.scaleNum) / ( double)appData.scaleDen); + int dst_width = ( int)( 0.5 + ( double)( ( *x + *width) * appData.scaleNum) / ( double)appData.scaleDen) - dst_x; + int dst_height = ( int)( 0.5 + ( double)( ( *y + *height) * appData.scaleNum) / ( double)appData.scaleDen) - dst_y; + + if ( width && ( dst_width < 1)) dst_width = 1; + if ( height && ( dst_height < 1)) dst_height = 1; + if ( dst_x >= appData.windowWidth) dst_x = appData.windowWidth - 1; + if ( dst_y >= appData.windowHeight) dst_y = appData.windowHeight - 1; + if ( dst_width + dst_x >= appData.windowWidth) dst_width = appData.windowWidth - dst_x - 1; + if ( dst_height + dst_y >= appData.windowHeight) dst_height = appData.windowHeight - dst_y - 1; + + *x = dst_x; + *y = dst_y; + *width = dst_width; + *height = dst_height; + } +} + +static void GetOriginalDimensions( int *x, int *y, int *width, int *height) { + if ( appData.scaled) { + int org_x = ( int)( 0.5 + ( double)( *x * appData.scaleDen) / ( double)appData.scaleNum); + int org_y = ( int)( 0.5 + ( double)( *y * appData.scaleDen) / ( double)appData.scaleNum); + int org_width = ( int)( 0.5 + ( double)( ( *x + *width) * appData.scaleDen) / ( double)appData.scaleNum) - org_x; + int org_height = ( int)( 0.5 + ( double)( ( *y + *height) * appData.scaleDen) / ( double)appData.scaleNum) - org_y; + + if ( width && ( org_width < 1)) org_width = 1; + if ( height && ( org_height < 1)) org_height = 1; + if ( org_x >= si.framebufferWidth) org_x = si.framebufferWidth - 1; + if ( org_y >= si.framebufferHeight) org_y = si.framebufferHeight - 1; + if ( org_width + org_x >= si.framebufferWidth) org_width = si.framebufferWidth - org_x - 1; + if ( org_height + org_y >= si.framebufferHeight) org_height = si.framebufferHeight - org_y - 1; + + *x = org_x; + *y = org_y; + *width = org_width; + *height = org_height; + } +} + +static int XFillRectangleScaled( Display *display, Drawable d, GC gc, + int x, int y, unsigned int width, unsigned int height) { + int nx = x, ny = y, nw = width, nh = height; + ScaleDimensions( &nx, &ny, &nw, &nh); + return XFillRectangle( display, d, gc, nx, ny, nw, nh); +} + +static int XCopyAreaScaled( Display *display, Drawable src, Drawable dest, GC gc, + int src_x, int src_y, unsigned int width, unsigned int height, + int dest_x, int dest_y) { + int sx = src_x, sy = src_y, dx = dest_x, dy = dest_y; + int sw = width, sh = height, dw = width, dh = height; + ScaleDimensions( &sx, &sy, &sw, &sh); + ScaleDimensions( &dx, &dy, &dw, &dh); + return XCopyArea( display, src, dest, gc, sx, sy, sw, sh, dx, dy); +} +/* Miguel end */ diff -u -r vnc_unixsrc/vncviewer/vncviewer.man vnc_unixsrc.new/vncviewer/vncviewer.man --- vnc_unixsrc/vncviewer/vncviewer.man 2004-03-11 12:14:40.000000000 -0600 +++ vnc_unixsrc.new/vncviewer/vncviewer.man 2006-06-16 10:50:24.000000000 -0500 @@ -168,6 +168,10 @@ \fB\-autopass\fR Read a plain-text password from stdin. This option affects only the standard VNC authentication. +.TP +\fB\-scale_num \fInumerator\fR\fB, \-scale_den \fIdenominator\fR +The client's windows is scaled \fInumerator / denominator\fR with +respect to the server's desktop size. .SH ENCODINGS The server supplies information in whatever format is desired by the client, in order to make the client as easy as possible to implement.