summaryrefslogtreecommitdiffstats
path: root/x11vnc/misc/enhanced_tightvnc_viewer/src/patches
diff options
context:
space:
mode:
authorrunge <runge>2008-10-19 16:33:22 +0000
committerrunge <runge>2008-10-19 16:33:22 +0000
commit8938cda1e7e09d946475fddaba46194baf7e6388 (patch)
tree6aacd449c9b71749d4b05d6278011b2615377e36 /x11vnc/misc/enhanced_tightvnc_viewer/src/patches
parent73f19d71e0dbdf4f5237e89bd431b971dacbca99 (diff)
downloadlibtdevnc-8938cda1e7e09d946475fddaba46194baf7e6388.tar.gz
libtdevnc-8938cda1e7e09d946475fddaba46194baf7e6388.zip
Sync SSVNC changes: fullscreen fixes, local scaling, -chatonly, iso-8859-1/utf8 etc., etc.
Diffstat (limited to 'x11vnc/misc/enhanced_tightvnc_viewer/src/patches')
-rwxr-xr-xx11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle2
-rw-r--r--x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch5474
2 files changed, 4506 insertions, 970 deletions
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle
index bcd18a8..cf14543 100755
--- a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle
@@ -1,7 +1,7 @@
#!/bin/sh
rm -rf ./src/tmp/* || exit 1
-vers=1.0.20
+vers=1.0.21
cd .. || exit 1
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch
index ce0c545..e8897a9 100644
--- a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch
+++ b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch
@@ -664,7 +664,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/Vncviewer vnc_unixsrc/vncview
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/vncviewer/argsresources.c
--- vnc_unixsrc.orig/vncviewer/argsresources.c 2007-02-04 17:10:31.000000000 -0500
-+++ vnc_unixsrc/vncviewer/argsresources.c 2008-09-14 14:27:29.000000000 -0400
++++ vnc_unixsrc/vncviewer/argsresources.c 2008-10-17 22:04:19.000000000 -0400
@@ -31,9 +31,9 @@
char *fallback_resources[] = {
@@ -677,7 +677,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
<Enter>: SelectionToVNC()\\n\
<Leave>: SelectionFromVNC()",
-@@ -45,8 +45,58 @@
+@@ -45,8 +45,60 @@
"*viewport.useRight: True",
"*viewport*Scrollbar*thumb: None",
@@ -732,15 +732,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+
"*desktop.baseTranslations:\
- <Key>F8: ShowPopup()\\n\
-+ <Key>F8: ShowPopup()\\n\
-+ <Key>F9: ToggleFullScreen()\\n\
++ <KeyPress>F8: ShowPopup()\\n\
++ <KeyRelease>F8: Noop()\\n\
++ <KeyPress>F9: ToggleFullScreen()\\n\
++ <KeyRelease>F9: Noop()\\n\
<ButtonPress>: SendRFBEvent()\\n\
<ButtonRelease>: SendRFBEvent()\\n\
<Motion>: SendRFBEvent()\\n\
-@@ -58,23 +108,58 @@
+@@ -58,23 +110,65 @@
"*serverDialog.dialog.value.translations: #override\\n\
<Key>Return: ServerDialogDone()",
++ "*scaleDialogPREV.dialog.label: Scale: Enter 'none' 'auto' 'aspect'\\nor fraction (e.g. 0.75 or 3/4).\\ncurrent value:",
++
++ "*scaleDialog.dialog.label: Scale: Enter 'none' (same as '1' or '1.0'),\\na geometry WxH (e.g. 1280x1024), or\\na fraction (e.g. 0.75 or 3/4).\\nUse 'fit' for full screen size.\\nUse 'auto' to match window size.\\nCurrent value:",
++ "*scaleDialog.dialog.value:",
++ "*scaleDialog.dialog.value.translations: #override\\n\
++ <Key>Return: ScaleDialogDone()",
++
+ "*ycropDialog.dialog.label: Y Crop (max-height in pixels):",
+ "*ycropDialog.dialog.value:",
+ "*ycropDialog.dialog.value.translations: #override\\n\
@@ -751,10 +760,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ "*scbarDialog.dialog.value.translations: #override\\n\
+ <Key>Return: ScbarDialogDone()",
+
-+ "*scaleDialog.dialog.label: Integer n for 1/n server scaling:",
-+ "*scaleDialog.dialog.value:",
-+ "*scaleDialog.dialog.value.translations: #override\\n\
-+ <Key>Return: ScaleDialogDone()",
++ "*scaleNDialog.dialog.label: Integer n for 1/n server scaling:",
++ "*scaleNDialog.dialog.value:",
++ "*scaleNDialog.dialog.value.translations: #override\\n\
++ <Key>Return: ScaleNDialogDone()",
+
"*passwordDialog.dialog.label: Password:",
"*passwordDialog.dialog.value:",
@@ -801,7 +810,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
"*popup*button1.label: Dismiss popup",
"*popup*button1.translations: #override\\n\
-@@ -84,7 +169,7 @@
+@@ -84,7 +178,7 @@
"*popup*button2.translations: #override\\n\
<Btn1Down>,<Btn1Up>: Quit()",
@@ -810,7 +819,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
"*popup*button3.type: toggle",
"*popup*button3.translations: #override\\n\
<Visible>: SetFullScreenState()\\n\
-@@ -105,16 +190,315 @@
+@@ -105,16 +199,323 @@
"*popup*button7.label: Send ctrl-alt-del",
"*popup*button7.translations: #override\\n\
<Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\
@@ -931,48 +940,56 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ <Visible>: Set8ColorsState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()",
+
-+ "*popup*button27.label: Set Y Crop (y-max)",
++ "*popup*button27.label: Scale Viewer",
+ "*popup*button27.translations: #override\\n\
-+ <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop()",
++ <Btn1Down>,<Btn1Up>: HidePopup() SetScale()",
+
-+ "*popup*button28.label: Set Scrollbar Width",
++ "*popup*button28.label: Set Y Crop (y-max)",
+ "*popup*button28.translations: #override\\n\
-+ <Btn1Down>,<Btn1Up>: HidePopup() SetScbar()",
++ <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop()",
+
-+ "*popup*button29.label: UltraVNC Extensions:",
++ "*popup*button29.label: Set Scrollbar Width",
+ "*popup*button29.translations: #override\\n\
-+ <Btn1Down>,<Btn1Up>: HidePopup()",
++ <Btn1Down>,<Btn1Up>: HidePopup() SetScbar()",
+
-+ "*popup*button30.label: - Set 1/n Server Scale",
++ "*popup*button30.label: XGrabServer",
++ "*popup*button30.type: toggle",
+ "*popup*button30.translations: #override\\n\
-+ <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN()",
++ <Visible>: SetXGrabState()\\n\
++ <Btn1Down>,<Btn1Up>: toggle() ToggleXGrab() HidePopup()",
+
-+ "*popup*button31.label: - Text Chat",
-+ "*popup*button31.type: toggle",
++ "*popup*button31.label: UltraVNC Extensions:",
+ "*popup*button31.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: HidePopup()",
++
++ "*popup*button32.label: - Set 1/n Server Scale",
++ "*popup*button32.translations: #override\\n\
++ <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN()",
++
++ "*popup*button33.label: - Text Chat",
++ "*popup*button33.type: toggle",
++ "*popup*button33.translations: #override\\n\
+ <Visible>: SetTextChatState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()",
+
-+ "*popup*button32.label: - File Transfer",
-+ "*popup*button32.type: toggle",
-+ "*popup*button32.translations: #override\\n\
++ "*popup*button34.label: - File Transfer",
++ "*popup*button34.type: toggle",
++ "*popup*button34.translations: #override\\n\
+ <Visible>: SetFileXferState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleFileXfer() HidePopup()",
+
-+ "*popup*button33.label: - Single Window",
-+ "*popup*button33.type: toggle",
-+ "*popup*button33.translations: #override\\n\
++ "*popup*button35.label: - Single Window",
++ "*popup*button35.type: toggle",
++ "*popup*button35.translations: #override\\n\
+ <Visible>: SetSingleWindowState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()",
+
-+ "*popup*button34.label: - Disable Remote Input",
-+ "*popup*button34.type: toggle",
-+ "*popup*button34.translations: #override\\n\
++ "*popup*button36.label: - Disable Remote Input",
++ "*popup*button36.type: toggle",
++ "*popup*button36.translations: #override\\n\
+ <Visible>: SetServerInputState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()",
+
-+ "*popup*button35.label:",
-+ "*popup*button36.label:",
+ "*popup*button37.label:",
+ "*popup*button38.label:",
+
@@ -1131,7 +1148,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
NULL
};
-@@ -124,7 +508,7 @@
+@@ -124,7 +525,7 @@
* from a dialog box.
*/
@@ -1140,7 +1157,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
int vncServerPort = 0;
-@@ -135,6 +519,7 @@
+@@ -135,6 +536,7 @@
*/
AppData appData;
@@ -1148,7 +1165,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
static XtResource appDataResourceList[] = {
{"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool),
-@@ -155,14 +540,38 @@
+@@ -155,14 +557,38 @@
{"userLogin", "UserLogin", XtRString, sizeof(String),
XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0},
@@ -1189,7 +1206,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
{"nColours", "NColours", XtRInt, sizeof(int),
XtOffsetOf(AppData, nColours), XtRImmediate, (XtPointer) 256},
-@@ -179,9 +588,12 @@
+@@ -179,9 +605,12 @@
{"requestedDepth", "RequestedDepth", XtRInt, sizeof(int),
XtOffsetOf(AppData, requestedDepth), XtRImmediate, (XtPointer) 0},
@@ -1203,7 +1220,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
{"wmDecorationWidth", "WmDecorationWidth", XtRInt, sizeof(int),
XtOffsetOf(AppData, wmDecorationWidth), XtRImmediate, (XtPointer) 4},
-@@ -191,6 +603,9 @@
+@@ -191,6 +620,9 @@
{"popupButtonCount", "PopupButtonCount", XtRInt, sizeof(int),
XtOffsetOf(AppData, popupButtonCount), XtRImmediate, (XtPointer) 0},
@@ -1213,21 +1230,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
{"debug", "Debug", XtRBool, sizeof(Bool),
XtOffsetOf(AppData, debug), XtRImmediate, (XtPointer) False},
-@@ -206,8 +621,13 @@
- {"bumpScrollPixels", "BumpScrollPixels", XtRInt, sizeof(int),
+@@ -207,7 +639,7 @@
XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20},
-+#if 0
{"compressLevel", "CompressionLevel", XtRInt, sizeof(int),
- XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1},
-+#endif
-+
-+ {"compressLevel", "CompressionLevel", XtRInt, sizeof(int),
+- XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1},
+ XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) 7},
{"qualityLevel", "QualityLevel", XtRInt, sizeof(int),
XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6},
-@@ -218,14 +638,55 @@
+@@ -218,14 +650,58 @@
{"useRemoteCursor", "UseRemoteCursor", XtRBool, sizeof(Bool),
XtOffsetOf(AppData, useRemoteCursor), XtRImmediate, (XtPointer) True},
@@ -1254,13 +1266,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"grabAll", "GrabAll", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, grabAll), XtRImmediate, (XtPointer) False},
+
-+#if 0
-+ {"useBackingstore", "UseBackingstore", XtRBool, sizeof(Bool),
-+ XtOffsetOf(AppData, useBackingstore), XtRImmediate, (XtPointer) True},
-+#else
-+ {"useBackingstore", "UseBackingstore", XtRBool, sizeof(Bool),
-+ XtOffsetOf(AppData, useBackingstore), XtRImmediate, (XtPointer) False},
-+#endif
++ {"useXserverBackingStore", "UseXserverBackingStore", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, useXserverBackingStore), XtRImmediate, (XtPointer) False},
+
+ {"overrideRedir", "OverrideRedir", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, overrideRedir), XtRImmediate, (XtPointer) True},
@@ -1277,15 +1284,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"chatActive", "ChatActive", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, chatActive), XtRImmediate, (XtPointer) False},
+
++ {"chatOnly", "ChatOnly", XtRBool, sizeof(Bool),
++ XtOffsetOf(AppData, chatOnly), XtRImmediate, (XtPointer) False},
++
+ {"fileActive", "FileActive", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, fileActive), XtRImmediate, (XtPointer) False},
+
+ {"popupFix", "PopupFix", XtRBool, sizeof(Bool),
-+ XtOffsetOf(AppData, popupFix), XtRImmediate, (XtPointer) False}
++ XtOffsetOf(AppData, popupFix), XtRImmediate, (XtPointer) False},
++
++ {"scale", "Scale", XtRString, sizeof(String),
++ XtOffsetOf(AppData, scale), XtRImmediate, (XtPointer) 0}
++
++ /* check commas */
};
-@@ -242,8 +703,26 @@
+@@ -242,8 +718,25 @@
{"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"},
{"-passwd", "*passwordFile", XrmoptionSepArg, 0},
{"-user", "*userLogin", XrmoptionSepArg, 0},
@@ -1307,13 +1322,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"-sbwidth", "*sbwidth", XrmoptionSepArg, 0},
+ {"-env", "*envDummy", XrmoptionSepArg, 0},
+ {"-ycrop", "*yCrop", XrmoptionSepArg, 0},
-+ {"-sbwidth", "*sbwidth", XrmoptionSepArg, 0},
+ {"-rawlocal", "*useRawLocal", XrmoptionNoArg, "True"},
+ {"-alpha", "*useCursorAlpha", XrmoptionNoArg, "True"},
{"-owncmap", "*forceOwnCmap", XrmoptionNoArg, "True"},
{"-truecolor", "*forceTrueColour", XrmoptionNoArg, "True"},
{"-truecolour", "*forceTrueColour", XrmoptionNoArg, "True"},
-@@ -253,7 +732,19 @@
+@@ -253,7 +746,21 @@
{"-nojpeg", "*enableJPEG", XrmoptionNoArg, "False"},
{"-nocursorshape", "*useRemoteCursor", XrmoptionNoArg, "False"},
{"-x11cursor", "*useX11Cursor", XrmoptionNoArg, "True"},
@@ -1326,17 +1340,21 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"-grabkeyboard", "*grabKeyboard", XrmoptionNoArg, "True"},
+ {"-nograbkeyboard","*grabKeyboard", XrmoptionNoArg, "False"},
+ {"-nooverride", "*overrideRedir", XrmoptionNoArg, "False"},
-+ {"-bs", "*useBackingstore", XrmoptionNoArg, "True"},
-+ {"-nobs", "*useBackingstore", XrmoptionNoArg, "False"},
++ {"-bs", "*useXserverBackingStore", XrmoptionNoArg, "True"},
++ {"-nobs", "*useXserverBackingStore", XrmoptionNoArg, "False"},
+ {"-popupfix", "*popupFix", XrmoptionNoArg, "True"},
+ {"-noshm", "*useShm", XrmoptionNoArg, "False"},
-+ {"-termchat", "*termChat", XrmoptionNoArg, "True"}
++ {"-termchat", "*termChat", XrmoptionNoArg, "True"},
++ {"-chatonly", "*chatOnly", XrmoptionNoArg, "True"},
++ {"-scale", "*scale", XrmoptionSepArg, 0},
};
-@@ -268,15 +759,77 @@
+@@ -267,16 +774,84 @@
+ static XtActionsRec actions[] = {
{"SendRFBEvent", SendRFBEvent},
{"ShowPopup", ShowPopup},
++ {"Noop", Noop},
{"HidePopup", HidePopup},
+ {"HideScaleN", HideScaleN},
+ {"HideQuality", HideQuality},
@@ -1352,11 +1370,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
{"ServerDialogDone", ServerDialogDone},
+ {"YCropDialogDone", YCropDialogDone},
+ {"ScbarDialogDone", ScbarDialogDone},
++ {"ScaleNDialogDone", ScaleNDialogDone},
+ {"ScaleDialogDone", ScaleDialogDone},
{"PasswordDialogDone", PasswordDialogDone},
{"Pause", Pause},
{"RunCommand", RunCommand},
{"Quit", Quit},
++ {"HideChat", HideChat},
+ {"Toggle8bpp", Toggle8bpp},
+ {"Toggle16bpp", Toggle16bpp},
+ {"ToggleFullColor", ToggleFullColor},
@@ -1377,7 +1397,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"ToggleSingleWindow", ToggleSingleWindow},
+ {"ToggleTextChat", ToggleTextChat},
+ {"ToggleFileXfer", ToggleFileXfer},
++ {"ToggleXGrab", ToggleXGrab},
+ {"DoServerScale", DoServerScale},
++ {"SetScale", SetScale},
+ {"SetYCrop", SetYCrop},
+ {"SetScbar", SetScbar},
+ {"ShowScaleN", ShowScaleN},
@@ -1408,11 +1430,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ {"SetServerInputState", SetServerInputState},
+ {"SetSingleWindowState", SetSingleWindowState},
+ {"SetTextChatState", SetTextChatState},
-+ {"SetFileXferState", SetFileXferState}
++ {"SetFileXferState", SetFileXferState},
++ {"SetXGrabState", SetXGrabState}
};
-@@ -302,11 +855,13 @@
+@@ -302,11 +877,14 @@
void
usage(void)
{
@@ -1424,11 +1447,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
"Usage: %s [<OPTIONS>] [<HOST>][:<DISPLAY#>]\n"
" %s [<OPTIONS>] [<HOST>][::<PORT#>]\n"
+ " %s [<OPTIONS>] exec=[CMD ARGS...]\n"
++ " %s [<OPTIONS>] fd=n\n"
+ " %s [<OPTIONS>] /path/to/unix/socket\n"
" %s [<OPTIONS>] -listen [<DISPLAY#>]\n"
" %s -help\n"
"\n"
-@@ -332,10 +887,209 @@
+@@ -332,10 +910,230 @@
" -autopass\n"
"\n"
"Option names may be abbreviated, e.g. -bgr instead of -bgr233.\n"
@@ -1459,7 +1483,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " that does not involve a listening socket. This mode does\n"
+ " not work for -listen reverse connections.\n"
+ "\n"
-+ " Note: If the host:port contains a '/' it is interpreted as a\n"
++ " If the host:port is specified as \"fd=n\" then it is assumed\n"
++ " n is an already opened file descriptor to the socket. (i.e\n"
++ " the parent did fork+exec)\n"
++ "\n"
++ " If the host:port contains a '/' it is interpreted as a\n"
+ " unix-domain socket (AF_LOCAL insead of AF_INET)\n"
+ "\n"
+ " -multilisten As in -listen (reverse connection listening) except\n"
@@ -1487,6 +1515,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " requires: x11vnc server, both client and server\n"
+ " must be 32bpp and same endianness.\n"
+ "\n"
++ " -scale str Scale the desktop locally. The string \"str\" can\n"
++ " a floating point ratio, e.g. \"0.9\", or a fraction,\n"
++ " e.g. \"3/4\", or WxH, e.g. 1280x1024. Use \"fit\"\n"
++ " to fit in the current screen size. Use \"auto\" to\n"
++ " fit in the window size.\n"
++ "\n"
++ " Note that scaling is done in software and can be slow\n"
++ " and requires more memory. \"str\" can also be set by\n"
++ " the env. var. SSVNC_SCALE.\n"
++ "\n"
+ " -ycrop n Only show the top n rows of the framebuffer. For\n"
+ " use with x11vnc -ncache client caching option\n"
+ " to help \"hide\" the pixel cache region.\n"
@@ -1587,6 +1625,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " RFB data sent so as to work with the UltraVNC Server. For\n"
+ " some reason, each RFB msg type must be sent twice under DSM.\n"
+ "\n"
++ " -chatonly Try to be a client that only does UltraVNC text chat. This\n"
++ " mode is used by x11vnc to present a chat window on the\n"
++ " physical X11 console (i.e. chat with the person at the\n"
++ " display).\n"
++ "\n"
+ " -env VAR=VALUE To save writing a shell script to set environment variables,\n"
+ " specify as many as you need on the command line. For\n"
+ " example, -env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi\n"
@@ -1615,8 +1658,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " 256 colors ~ -bgr233 default # of colors.\n"
+ " 64 colors ~ -bgr222 / -use64\n"
+ " 8 colors ~ -bgr111 / -use8\n"
++ " Scale Viewer ~ -scale\n"
+ " Set Y Crop (y-max) ~ -ycrop\n"
+ " Set Scrollbar Width ~ -sbwidth\n"
++ " XGrabServer ~ -graball\n"
+ "\n"
+ " UltraVNC Extensions:\n"
+ "\n"
@@ -1631,7 +1676,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ " Note: the Ultravnc extensions only apply to servers that support\n"
+ " them. x11vnc/libvncserver supports some of them.\n"
+ "\n"
-+ "\n", programName, programName, programName, programName, programName, programName);
++ "\n", programName, programName, programName, programName, programName, programName, programName);
exit(1);
}
+#if 0
@@ -1640,18 +1685,30 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
/*
-@@ -350,6 +1104,7 @@
- int i;
- char *vncServerName, *colonPos;
- int len, portOffset;
-+ int disp;
+@@ -347,73 +1145,153 @@
+ void
+ GetArgsAndResources(int argc, char **argv)
+ {
+- int i;
+- char *vncServerName, *colonPos;
+- int len, portOffset;
++ int i;
++ char *vncServerName, *colonPos;
++ int len, portOffset;
++ int disp;
/* Turn app resource specs into our appData structure for the rest of the
program to use */
-@@ -357,6 +1112,29 @@
- XtGetApplicationResources(toplevel, &appData, appDataResourceList,
- XtNumber(appDataResourceList), 0, 0);
+- XtGetApplicationResources(toplevel, &appData, appDataResourceList,
+- XtNumber(appDataResourceList), 0, 0);
++ XtGetApplicationResources(toplevel, &appData, appDataResourceList,
++ XtNumber(appDataResourceList), 0, 0);
++
++ /*
++ * we allow setting of some by env, to avoid clash with other
++ * viewer's cmdlines (e.g. change viewer in SSVNC).
++ */
+ if (getenv("VNCVIEWER_ALPHABLEND")) {
+ appData.useCursorAlpha = True;
+ }
@@ -1667,66 +1724,175 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v
+ appData.yCrop = n;
+ }
+ }
++ if (getenv("VNCVIEWER_RFBVERSION") && strcmp(getenv("VNCVIEWER_RFBVERSION"), "")) {
++ appData.rfbVersion = strdup(getenv("VNCVIEWER_RFBVERSION"));
++ }
++ if (getenv("VNCVIEWER_ENCODINGS") && strcmp(getenv("VNCVIEWER_ENCODINGS"), "")) {
++ appData.encodingsString = strdup(getenv("VNCVIEWER_ENCODINGS"));
++ }
++ if (getenv("VNCVIEWER_NOBELL")) {
++ appData.useBell = False;
++ }
++ if (getenv("VNCVIEWER_X11CURSOR")) {
++ appData.useX11Cursor = True;
++ }
++ if (getenv("VNCVIEWER_RAWLOCAL")) {
++ appData.useRawLocal = True;
++ }
++ if (getenv("VNCVIEWER_SBWIDTH")) {
++ int n = atoi(getenv("VNCVIEWER_SBWIDTH"));
++ if (n != 0) {
++ appData.sbWidth = n;
++ }
++ }
+ if (getenv("VNCVIEWER_ULTRADSM")) {
+ appData.ultraDSM = True;
+ }
+ if (getenv("SSVNC_ULTRA_DSM") && strcmp(getenv("SSVNC_ULTRA_DSM"), "")) {
+ appData.ultraDSM = True;
+ }
++ if (getenv("SSVNC_NO_ULTRA_DSM")) {
++ appData.ultraDSM = False;
++ }
++ if (getenv("SSVNC_SCALE") && strcmp(getenv("SSVNC_SCALE"), "")) {
++ if (appData.scale == NULL) {
++ appData.scale = strdup(getenv("SSVNC_SCALE"));
++ }
++ }
+
-+
+
/* Add our actions to the actions table so they can be used in widget
resource specs */
-@@ -376,6 +1154,10 @@
- return;
- }
+- XtAppAddActions(appContext, actions, XtNumber(actions));
++ XtAppAddActions(appContext, actions, XtNumber(actions));
+ /* Check any remaining command-line arguments. If -listen was specified
+ there should be none. Otherwise the only argument should be the VNC
+ server name. If not given then pop up a dialog box and wait for the
+ server name to be entered. */
+
+- if (listenSpecified) {
+- if (argc != 1) {
+- fprintf(stderr,"\n%s -listen: invalid command line argument: %s\n",
+- programName, argv[1]);
+- usage();
+- }
+- return;
+- }
+-
+- if (argc == 1) {
+- vncServerName = DoServerDialog();
+- appData.passwordDialog = True;
+- } else if (argc != 2) {
+- usage();
+- } else {
+- vncServerName = argv[1];
+-
+- if (!isatty(0))
+- appData.passwordDialog = True;
+- if (vncServerName[0] == '-')
+- usage();
+- }
+-
+- if (strlen(vncServerName) > 255) {
+- fprintf(stderr,"VNC server name too long\n");
+- exit(1);
+- }
+-
+- colonPos = strchr(vncServerName, ':');
+- if (colonPos == NULL) {
+- /* No colon -- use default port number */
+- strcpy(vncServerHost, vncServerName);
+- vncServerPort = SERVER_PORT_OFFSET;
+- } else {
+- memcpy(vncServerHost, vncServerName, colonPos - vncServerName);
+- vncServerHost[colonPos - vncServerName] = '\0';
+- len = strlen(colonPos + 1);
+- portOffset = SERVER_PORT_OFFSET;
+- if (colonPos[1] == ':') {
+- /* Two colons -- interpret as a port number */
+- colonPos++;
+- len--;
+- portOffset = 0;
+- }
+- if (!len || strspn(colonPos + 1, "0123456789") != len) {
+- usage();
+- }
+- vncServerPort = atoi(colonPos + 1) + portOffset;
+- }
++ if (listenSpecified) {
++ if (argc != 1) {
++ fprintf(stderr,"\n%s -listen: invalid command line argument: %s\n",
++ programName, argv[1]);
++ usage();
++ }
++ return;
++ }
++
+ if (appData.useBGR233 && appData.useBGR565) {
+ appData.useBGR233 = 0;
+ }
+
- if (argc == 1) {
- vncServerName = DoServerDialog();
- appData.passwordDialog = True;
-@@ -390,13 +1172,23 @@
- usage();
- }
-
++ if (argc == 1) {
++ vncServerName = DoServerDialog();
++ appData.passwordDialog = True;
++ } else if (argc != 2) {
++ usage();
++ } else {
++ vncServerName = argv[1];
+
- if (strlen(vncServerName) > 255) {
- fprintf(stderr,"VNC server name too long\n");
- exit(1);
- }
-
- colonPos = strchr(vncServerName, ':');
-- if (colonPos == NULL) {
-+ if (strstr(vncServerName, "exec=") == vncServerName) {
-+ /* special exec-external-command case */
-+ strcpy(vncServerHost, vncServerName);
-+ vncServerPort = SERVER_PORT_OFFSET;
-+ if (! appData.ultraDSM) {
-+ if (strstr(vncServerName, "ultravnc_dsm_helper")) {
-+ appData.ultraDSM = True;
-+ }
-+ }
-+ } else if (colonPos == NULL) {
- /* No colon -- use default port number */
- strcpy(vncServerHost, vncServerName);
- vncServerPort = SERVER_PORT_OFFSET;
-@@ -414,6 +1206,13 @@
- if (!len || strspn(colonPos + 1, "0123456789") != len) {
- usage();
- }
++ if (!isatty(0)) {
++ appData.passwordDialog = True;
++ }
++ if (vncServerName[0] == '-') {
++ usage();
++ }
++ }
++
++
++ if (strlen(vncServerName) > 255) {
++ fprintf(stderr,"VNC server name too long\n");
++ exit(1);
++ }
++
++ colonPos = strchr(vncServerName, ':');
++ if (strstr(vncServerName, "exec=") == vncServerName) {
++ /* special exec-external-command case */
++ strcpy(vncServerHost, vncServerName);
++ vncServerPort = SERVER_PORT_OFFSET;
++ } else if (strstr(vncServerName, "fd=") == vncServerName) {
++ /* special exec-external-command case */
++ strcpy(vncServerHost, vncServerName);
++ vncServerPort = SERVER_PORT_OFFSET;
++ } else if (colonPos == NULL) {
++ /* No colon -- use default port number */
++ strcpy(vncServerHost, vncServerName);
++ vncServerPort = SERVER_PORT_OFFSET;
++ } else {
++ memcpy(vncServerHost, vncServerName, colonPos - vncServerName);
++ vncServerHost[colonPos - vncServerName] = '\0';
++ len = strlen(colonPos + 1);
++ portOffset = SERVER_PORT_OFFSET;
++ if (colonPos[1] == ':') {
++ /* Two colons -- interpret as a port number */
++ colonPos++;
++ len--;
++ portOffset = 0;
++ }
++ if (!len || strspn(colonPos + 1, "0123456789") != len) {
++ usage();
++ }
+#if 0
- vncServerPort = atoi(colonPos + 1) + portOffset;
++ vncServerPort = atoi(colonPos + 1) + portOffset;
+#else
-+ disp = atoi(colonPos + 1);
-+ if (portOffset != 0 && disp >= 100)
-+ portOffset = 0;
-+ vncServerPort = disp + portOffset;
++ disp = atoi(colonPos + 1);
++ if (portOffset != 0 && disp >= 100) {
++ portOffset = 0;
++ }
++ vncServerPort = disp + portOffset;
+#endif
- }
++ }
}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewer/colour.c
--- vnc_unixsrc.orig/vncviewer/colour.c 2002-04-30 09:07:31.000000000 -0400
@@ -2066,7 +2232,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewe
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer/corre.c
--- vnc_unixsrc.orig/vncviewer/corre.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/corre.c 2007-02-17 22:50:15.000000000 -0500
++++ vnc_unixsrc/vncviewer/corre.c 2008-10-05 15:16:01.000000000 -0400
@@ -29,6 +29,18 @@
#define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP)
#define CARDBPP CONCAT2E(CARD,BPP)
@@ -2075,7 +2241,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer
+ { \
+ XGCValues _gcv; \
+ _gcv.foreground = color; \
-+ if (!appData.useBackingstore) { \
++ if (!appData.useXserverBackingStore) { \
+ FillScreen(x, y, w, h, _gcv.foreground); \
+ } else { \
+ XChangeGC(dpy, gc, GCForeground, &_gcv); \
@@ -2149,17 +2315,22 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cp_it vnc_unixsrc/vncviewer/c
+ls -l ./vncviewer $dest $yy $HOME/etv_col/Linux.i686/vncviewer
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewer/cursor.c
--- vnc_unixsrc.orig/vncviewer/cursor.c 2003-01-15 04:46:52.000000000 -0500
-+++ vnc_unixsrc/vncviewer/cursor.c 2007-03-17 22:48:34.000000000 -0400
-@@ -39,7 +39,7 @@
++++ vnc_unixsrc/vncviewer/cursor.c 2008-10-18 09:35:02.000000000 -0400
+@@ -38,8 +38,11 @@
+
static Bool prevSoftCursorSet = False;
- static Pixmap rcSavedArea;
+-static Pixmap rcSavedArea;
-static CARD8 *rcSource, *rcMask;
++static Pixmap rcSavedArea, rcSavedArea_0;
++static int rcSavedArea_w = -1, rcSavedArea_h = -1;
++static char *rcSavedScale = NULL;
++static int rcSavedScale_len = 0;
+static CARD8 *rcSource = NULL, *rcMask;
static int rcHotX, rcHotY, rcWidth, rcHeight;
static int rcCursorX = 0, rcCursorY = 0;
static int rcLockX, rcLockY, rcLockWidth, rcLockHeight;
-@@ -48,8 +48,8 @@
+@@ -48,8 +51,13 @@
static Bool SoftCursorInLockedArea(void);
static void SoftCursorCopyArea(int oper);
static void SoftCursorDraw(void);
@@ -2167,78 +2338,488 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
-static void FreeX11Cursor();
+void FreeSoftCursor(void);
+void FreeX11Cursor();
++
++extern XImage *image;
++extern XImage *image_scale;
++extern int scale_x, scale_y;
++int scale_round(int n, double factor);
/* Copied from Xvnc/lib/font/util/utilbitmap.c */
static unsigned char _reverse_byte[0x100] = {
-@@ -195,6 +195,7 @@
- buf = malloc(bytesMaskData);
- if (buf == NULL) {
- free(rcSource);
-+ rcSource = NULL;
- return False;
- }
+@@ -91,6 +99,8 @@
+ static Bool prevXCursorSet = False;
+ static Cursor prevXCursor;
-@@ -209,6 +210,7 @@
- /* Read and convert background and foreground colors. */
- if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) {
- free(rcSource);
-+ rcSource = NULL;
- free(buf);
- return False;
- }
-@@ -218,6 +220,7 @@
- /* Read 1bpp pixel data into a temporary buffer. */
- if (!ReadFromRFBServer(buf, bytesMaskData)) {
- free(rcSource);
-+ rcSource = NULL;
- free(buf);
- return False;
- }
-@@ -257,6 +260,7 @@
++extern double scale_factor_x;
++extern double scale_factor_y;
- if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) {
- free(rcSource);
-+ rcSource = NULL;
- free(buf);
- return False;
- }
-@@ -267,6 +271,7 @@
+ Bool HandleXCursor(int xhot, int yhot, int width, int height)
+ {
+@@ -167,148 +177,179 @@
- if (!ReadFromRFBServer(buf, bytesMaskData)) {
- free(rcSource);
-+ rcSource = NULL;
- free(buf);
- return False;
- }
-@@ -274,6 +279,7 @@
- rcMask = malloc(width * height);
- if (rcMask == NULL) {
- free(rcSource);
-+ rcSource = NULL;
- free(buf);
- return False;
- }
-@@ -429,41 +435,63 @@
- rcLockY + rcLockHeight > rcCursorY - rcHotY);
+ Bool HandleCursorShape(int xhot, int yhot, int width, int height, CARD32 enc)
+ {
+- int bytesPerPixel;
+- size_t bytesPerRow, bytesMaskData;
+- Drawable dr;
+- rfbXCursorColors rgb;
+- CARD32 colors[2];
+- char *buf;
+- CARD8 *ptr;
+- int x, y, b;
+-
+- bytesPerPixel = myFormat.bitsPerPixel / 8;
+- bytesPerRow = (width + 7) / 8;
+- bytesMaskData = bytesPerRow * height;
+- dr = DefaultRootWindow(dpy);
+-
+- FreeSoftCursor();
++ int bytesPerPixel;
++ size_t bytesPerRow, bytesMaskData;
++ Drawable dr;
++ rfbXCursorColors rgb;
++ CARD32 colors[2];
++ char *buf;
++ CARD8 *ptr;
++ int x, y, b;
++
++ bytesPerPixel = myFormat.bitsPerPixel / 8;
++ bytesPerRow = (width + 7) / 8;
++ bytesMaskData = bytesPerRow * height;
++ dr = DefaultRootWindow(dpy);
+
+- if (width * height == 0)
+- return True;
+-
+- /* Allocate memory for pixel data and temporary mask data. */
++ FreeSoftCursor();
+
+- rcSource = malloc(width * height * bytesPerPixel);
+- if (rcSource == NULL)
+- return False;
+-
+- buf = malloc(bytesMaskData);
+- if (buf == NULL) {
+- free(rcSource);
+- return False;
+- }
++ if (width * height == 0) {
++ return True;
++ }
+
+- /* Read and decode cursor pixel data, depending on the encoding type. */
++ /* Allocate memory for pixel data and temporary mask data. */
+
+- if (enc == rfbEncodingXCursor) {
+- if (appData.useX11Cursor) {
+- HandleXCursor(xhot, yhot, width, height);
+- return True;
+- }
++ rcSource = malloc(width * height * bytesPerPixel);
++ if (rcSource == NULL) {
++ return False;
++ }
+
+- /* Read and convert background and foreground colors. */
+- if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) {
+- free(rcSource);
+- free(buf);
+- return False;
+- }
+- colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue);
+- colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue);
++ buf = malloc(bytesMaskData);
++ if (buf == NULL) {
++ free(rcSource);
++ rcSource = NULL;
++ return False;
++ }
+
+- /* Read 1bpp pixel data into a temporary buffer. */
+- if (!ReadFromRFBServer(buf, bytesMaskData)) {
+- free(rcSource);
+- free(buf);
+- return False;
+- }
++ /* Read and decode cursor pixel data, depending on the encoding type. */
+
+- /* Convert 1bpp data to byte-wide color indices. */
+- ptr = rcSource;
+- for (y = 0; y < height; y++) {
+- for (x = 0; x < width / 8; x++) {
+- for (b = 7; b >= 0; b--) {
+- *ptr = buf[y * bytesPerRow + x] >> b & 1;
+- ptr += bytesPerPixel;
+- }
+- }
+- for (b = 7; b > 7 - width % 8; b--) {
+- *ptr = buf[y * bytesPerRow + x] >> b & 1;
+- ptr += bytesPerPixel;
+- }
+- }
++ if (enc == rfbEncodingXCursor) {
++ if (appData.useX11Cursor) {
++ HandleXCursor(xhot, yhot, width, height);
++ return True;
++ }
++
++ /* Read and convert background and foreground colors. */
++ if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) {
++ free(rcSource);
++ rcSource = NULL;
++ free(buf);
++ return False;
++ }
++ colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue);
++ colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue);
++
++ /* Read 1bpp pixel data into a temporary buffer. */
++ if (!ReadFromRFBServer(buf, bytesMaskData)) {
++ free(rcSource);
++ rcSource = NULL;
++ free(buf);
++ return False;
++ }
++
++ /* Convert 1bpp data to byte-wide color indices. */
++ ptr = rcSource;
++ for (y = 0; y < height; y++) {
++ for (x = 0; x < width / 8; x++) {
++ for (b = 7; b >= 0; b--) {
++ *ptr = buf[y * bytesPerRow + x] >> b & 1;
++ ptr += bytesPerPixel;
++ }
++ }
++ for (b = 7; b > 7 - width % 8; b--) {
++ *ptr = buf[y * bytesPerRow + x] >> b & 1;
++ ptr += bytesPerPixel;
++ }
++ }
++
++ /* Convert indices into the actual pixel values. */
++ switch (bytesPerPixel) {
++ case 1:
++ for (x = 0; x < width * height; x++) {
++ rcSource[x] = (CARD8)colors[rcSource[x]];
++ }
++ break;
++ case 2:
++ for (x = 0; x < width * height; x++) {
++ ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]];
++ }
++ break;
++ case 4:
++ for (x = 0; x < width * height; x++) {
++ ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]];
++ }
++ break;
++ }
++
++ } else { /* enc == rfbEncodingRichCursor */
++ if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) {
++ free(rcSource);
++ rcSource = NULL;
++ free(buf);
++ return False;
++ }
++ }
+
+- /* Convert indices into the actual pixel values. */
+- switch (bytesPerPixel) {
+- case 1:
+- for (x = 0; x < width * height; x++)
+- rcSource[x] = (CARD8)colors[rcSource[x]];
+- break;
+- case 2:
+- for (x = 0; x < width * height; x++)
+- ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]];
+- break;
+- case 4:
+- for (x = 0; x < width * height; x++)
+- ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]];
+- break;
+- }
++ /* Read and decode mask data. */
+
+- } else { /* enc == rfbEncodingRichCursor */
++ if (!ReadFromRFBServer(buf, bytesMaskData)) {
++ free(rcSource);
++ rcSource = NULL;
++ free(buf);
++ return False;
++ }
+
+- if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) {
+- free(rcSource);
+- free(buf);
+- return False;
+- }
++ rcMask = malloc(width * height);
++ if (rcMask == NULL) {
++ free(rcSource);
++ rcSource = NULL;
++ free(buf);
++ return False;
++ }
+
+- }
++ ptr = rcMask;
++ for (y = 0; y < height; y++) {
++ for (x = 0; x < width / 8; x++) {
++ for (b = 7; b >= 0; b--) {
++ *ptr++ = buf[y * bytesPerRow + x] >> b & 1;
++ }
++ }
++ for (b = 7; b > 7 - width % 8; b--) {
++ *ptr++ = buf[y * bytesPerRow + x] >> b & 1;
++ }
++ }
+
+- /* Read and decode mask data. */
++ free(buf);
+
+- if (!ReadFromRFBServer(buf, bytesMaskData)) {
+- free(rcSource);
+- free(buf);
+- return False;
+- }
++ /* Set remaining data associated with cursor. */
+
+- rcMask = malloc(width * height);
+- if (rcMask == NULL) {
+- free(rcSource);
+- free(buf);
+- return False;
+- }
++ dr = DefaultRootWindow(dpy);
+
+- ptr = rcMask;
+- for (y = 0; y < height; y++) {
+- for (x = 0; x < width / 8; x++) {
+- for (b = 7; b >= 0; b--) {
+- *ptr++ = buf[y * bytesPerRow + x] >> b & 1;
+- }
+- }
+- for (b = 7; b > 7 - width % 8; b--) {
+- *ptr++ = buf[y * bytesPerRow + x] >> b & 1;
+- }
+- }
++ if (scale_x > 0) {
++ int w = scale_round(width, scale_factor_x) + 2;
++ int h = scale_round(height, scale_factor_y) + 2;
++ rcSavedArea = XCreatePixmap(dpy, dr, w, h, visdepth);
++ rcSavedArea_w = w;
++ rcSavedArea_h = h;
++ } else {
++ rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth);
++ rcSavedArea_w = width;
++ rcSavedArea_h = height;
++ }
++ rcSavedArea_0 = XCreatePixmap(dpy, dr, width, height, visdepth);
+
+- free(buf);
++if (0) fprintf(stderr, "rcSavedArea_wh: %d %d scale_x: %d\n", rcSavedArea_w, rcSavedArea_h, scale_x);
+
+- /* Set remaining data associated with cursor. */
++ if (rcSavedScale_len < 4 * width * height + 4096) {
++ if (rcSavedScale) {
++ free(rcSavedScale);
++ }
++ rcSavedScale = (char *) malloc(2 * 4 * width * height + 4096);
++ }
+
+- dr = DefaultRootWindow(dpy);
+- rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth);
+- rcHotX = xhot;
+- rcHotY = yhot;
+- rcWidth = width;
+- rcHeight = height;
++ rcHotX = xhot;
++ rcHotY = yhot;
++ rcWidth = width;
++ rcHeight = height;
+
+- SoftCursorCopyArea(OPER_SAVE);
+- SoftCursorDraw();
++ SoftCursorCopyArea(OPER_SAVE);
++ SoftCursorDraw();
+
+- rcCursorHidden = False;
+- rcLockSet = False;
++ rcCursorHidden = False;
++ rcLockSet = False;
+
+- prevSoftCursorSet = True;
+- return True;
++ prevSoftCursorSet = True;
++ return True;
}
-+extern XImage *image;
+ /*********************************************************************
+@@ -319,20 +360,27 @@
+
+ Bool HandleCursorPos(int x, int y)
+ {
+- if (appData.useX11Cursor) {
+- if (appData.fullScreen)
+- XWarpPointer(dpy, None, desktopWin, 0, 0, 0, 0, x, y);
+-
+- return True;
+- }
++ if (x < 0) x = 0;
++ if (y < 0) y = 0;
+
+- if (x >= si.framebufferWidth)
+- x = si.framebufferWidth - 1;
+- if (y >= si.framebufferHeight)
+- y = si.framebufferHeight - 1;
++ //fprintf(stderr, "xy: %d %d\n", x, y);
+
+- SoftCursorMove(x, y);
+- return True;
++ if (x >= si.framebufferWidth) {
++ x = si.framebufferWidth - 1;
++ }
++ if (y >= si.framebufferHeight) {
++ y = si.framebufferHeight - 1;
++ }
++
++ if (appData.useX11Cursor) {
++ if (appData.fullScreen) {
++ XWarpPointer(dpy, None, desktopWin, 0, 0, 0, 0, x, y);
++ }
++ return True;
++ }
+
- static void SoftCursorCopyArea(int oper)
++ SoftCursorMove(x, y);
++ return True;
+ }
+
+ /*********************************************************************
+@@ -348,30 +396,31 @@
{
+ int newX, newY;
+
+- if (!prevSoftCursorSet)
+- return;
++ if (!prevSoftCursorSet) {
++ return;
++ }
+
+- if (!rcLockSet) {
+- rcLockX = x;
+- rcLockY = y;
+- rcLockWidth = w;
+- rcLockHeight = h;
+- rcLockSet = True;
+- } else {
+- newX = (x < rcLockX) ? x : rcLockX;
+- newY = (y < rcLockY) ? y : rcLockY;
+- rcLockWidth = (x + w > rcLockX + rcLockWidth) ?
+- (x + w - newX) : (rcLockX + rcLockWidth - newX);
+- rcLockHeight = (y + h > rcLockY + rcLockHeight) ?
+- (y + h - newY) : (rcLockY + rcLockHeight - newY);
+- rcLockX = newX;
+- rcLockY = newY;
+- }
++ if (!rcLockSet) {
++ rcLockX = x;
++ rcLockY = y;
++ rcLockWidth = w;
++ rcLockHeight = h;
++ rcLockSet = True;
++ } else {
++ newX = (x < rcLockX) ? x : rcLockX;
++ newY = (y < rcLockY) ? y : rcLockY;
++ rcLockWidth = (x + w > rcLockX + rcLockWidth) ?
++ (x + w - newX) : (rcLockX + rcLockWidth - newX);
++ rcLockHeight = (y + h > rcLockY + rcLockHeight) ?
++ (y + h - newY) : (rcLockY + rcLockHeight - newY);
++ rcLockX = newX;
++ rcLockY = newY;
++ }
+
+- if (!rcCursorHidden && SoftCursorInLockedArea()) {
+- SoftCursorCopyArea(OPER_RESTORE);
+- rcCursorHidden = True;
+- }
++ if (!rcCursorHidden && SoftCursorInLockedArea()) {
++ SoftCursorCopyArea(OPER_RESTORE);
++ rcCursorHidden = True;
++ }
+ }
+
+ /*********************************************************************
+@@ -381,15 +430,16 @@
+
+ void SoftCursorUnlockScreen(void)
+ {
+- if (!prevSoftCursorSet)
+- return;
++ if (!prevSoftCursorSet) {
++ return;
++ }
+
+- if (rcCursorHidden) {
+- SoftCursorCopyArea(OPER_SAVE);
+- SoftCursorDraw();
+- rcCursorHidden = False;
+- }
+- rcLockSet = False;
++ if (rcCursorHidden) {
++ SoftCursorCopyArea(OPER_SAVE);
++ SoftCursorDraw();
++ rcCursorHidden = False;
++ }
++ rcLockSet = False;
+ }
+
+ /*********************************************************************
+@@ -401,19 +451,19 @@
+
+ void SoftCursorMove(int x, int y)
+ {
+- if (prevSoftCursorSet && !rcCursorHidden) {
+- SoftCursorCopyArea(OPER_RESTORE);
+- rcCursorHidden = True;
+- }
++ if (prevSoftCursorSet && !rcCursorHidden) {
++ SoftCursorCopyArea(OPER_RESTORE);
++ rcCursorHidden = True;
++ }
+
+- rcCursorX = x;
+- rcCursorY = y;
++ rcCursorX = x;
++ rcCursorY = y;
+
+- if (prevSoftCursorSet && !(rcLockSet && SoftCursorInLockedArea())) {
+- SoftCursorCopyArea(OPER_SAVE);
+- SoftCursorDraw();
+- rcCursorHidden = False;
+- }
++ if (prevSoftCursorSet && !(rcLockSet && SoftCursorInLockedArea())) {
++ SoftCursorCopyArea(OPER_SAVE);
++ SoftCursorDraw();
++ rcCursorHidden = False;
++ }
+ }
+
+
+@@ -429,41 +479,170 @@
+ rcLockY + rcLockHeight > rcCursorY - rcHotY);
+ }
+
+-static void SoftCursorCopyArea(int oper)
+-{
- int x, y, w, h;
-+ int x, y, w, h;
++void new_pixmap(int w, int h) {
- x = rcCursorX - rcHotX;
- y = rcCursorY - rcHotY;
- if (x >= si.framebufferWidth || y >= si.framebufferHeight)
- return;
-+ x = rcCursorX - rcHotX;
-+ y = rcCursorY - rcHotY;
-+ if (x >= si.framebufferWidth || y >= si.framebufferHeight) {
-+ return;
-+ }
-
+-
- w = rcWidth;
- h = rcHeight;
- if (x < 0) {
@@ -2253,6 +2834,51 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
- } else if (y + h > si.framebufferHeight) {
- h = si.framebufferHeight - y;
- }
++ XFreePixmap(dpy, rcSavedArea);
+
+- if (oper == OPER_SAVE) {
+- /* Save screen area in memory. */
+-#ifdef MITSHM
+- if (appData.useShm)
+- XSync(dpy, False);
+-#endif
+- XCopyArea(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);
+- }
++ if (w > 0 && h > 0) {
++ rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), w, h, visdepth);
++ rcSavedArea_w = w;
++ rcSavedArea_h = h;
++
++ } else if (image_scale != NULL && scale_x > 0) {
++ int w2 = scale_round(rcWidth, scale_factor_x) + 2;
++ int h2 = scale_round(rcHeight, scale_factor_y) + 2;
++ rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), w2, h2, visdepth);
++ rcSavedArea_w = w2;
++ rcSavedArea_h = h2;
++ } else {
++ rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), rcWidth, rcHeight, visdepth);
++ rcSavedArea_w = rcWidth;
++ rcSavedArea_h = rcHeight;
++ }
++}
++
++extern int XError_ign;
++
++static void SoftCursorCopyArea(int oper) {
++ int x, y, w, h;
++ int xs, ys, ws, hs;
++ static int scale_saved = 0, ss_w, ss_h;
++ int db = 0;
++
++ x = rcCursorX - rcHotX;
++ y = rcCursorY - rcHotY;
++ if (x >= si.framebufferWidth || y >= si.framebufferHeight) {
++ return;
++ }
++
+ w = rcWidth;
+ h = rcHeight;
+ if (x < 0) {
@@ -2267,50 +2893,124 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
+ } else if (y + h > si.framebufferHeight) {
+ h = si.framebufferHeight - y;
+ }
-
-- if (oper == OPER_SAVE) {
-- /* Save screen area in memory. */
++
++ if (image_scale != NULL && scale_x > 0) {
++ int i, t = 1;
++ xs = (int) (x * scale_factor_x);
++ ys = (int) (y * scale_factor_y);
++ ws = scale_round(w, scale_factor_x);
++ hs = scale_round(h, scale_factor_y);
++
++ if (xs > 0) xs -= 1;
++ if (ys > 0) ys -= 1;
++ ws += 2;
++ hs += 2;
++ }
++
++ XError_ign = 1;
++
+ if (oper == OPER_SAVE) {
+ /* Save screen area in memory. */
-+//fprintf(stderr, "OPER_SAVE\n");
-+#if 0
- #ifdef MITSHM
-- if (appData.useShm)
-- XSync(dpy, False);
-+ if (appData.useShm) {
-+ XSync(dpy, False);
-+ } else
- #endif
-- XCopyArea(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);
-- }
-+ {
-+ XSync(dpy, False);
-+ }
-+#endif
-+ if (appData.useBackingstore) {
++ scale_saved = 0;
++ if (appData.useXserverBackingStore) {
+ XSync(dpy, False);
+ XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0);
+ } else {
-+ XPutImage(dpy, rcSavedArea, gc, image, x, y, 0, 0, w, h);
++ if (image_scale != NULL && scale_x > 0) {
++ int Bpp = image_scale->bits_per_pixel / 8;
++ int Bpl = image_scale->bytes_per_line;
++ int i;
++ char *src = image_scale->data + y * Bpl + x * Bpp;
++ char *dst = rcSavedScale;
++
++ if (ws > rcSavedArea_w || hs > rcSavedArea_h) {
++ new_pixmap(0, 0);
++ }
++
++if (db) fprintf(stderr, "save: %dx%d+%d+%d\n", ws, hs, xs, ys);
++
++ XPutImage(dpy, rcSavedArea, gc, image, xs, ys, 0, 0, ws, hs);
++
++ XPutImage(dpy, rcSavedArea_0, gc, image_scale, x, y, 0, 0, w, h);
++
++ scale_saved = 1;
++ ss_w = ws;
++ ss_h = hs;
++
++ for (i=0; i < h; i++) {
++ memcpy(dst, src, Bpp * w);
++ src += Bpl;
++ dst += Bpp * w;
++ }
++ } else {
++if (db) fprintf(stderr, "SAVE: %dx%d+%d+%d\n", w, h, x, y);
++ if (w > rcSavedArea_w || h > rcSavedArea_h) {
++ new_pixmap(0, 0);
++ }
++
++ XPutImage(dpy, rcSavedArea, gc, image, x, y, 0, 0, w, h);
++ }
+ }
+ } else {
-+//fprintf(stderr, "OPER_RESTORE\n");
++
++#define XE(s) if (XError_ign > 1) {fprintf(stderr, "X-%d\n", (s)); db = 1;}
++
+ /* Restore screen area. */
-+ if (appData.useBackingstore) {
++ if (appData.useXserverBackingStore) {
+ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
++XE(1)
+ XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y);
++XE(2)
++
+ } else {
-+ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
-+ XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y);
++ if (image_scale != NULL && scale_x > 0) {
++ int Bpp = image_scale->bits_per_pixel / 8;
++ int Bpl = image_scale->bytes_per_line;
++ int i;
++ char *dst = image_scale->data + y * Bpl + x * Bpp;
++ char *src = rcSavedScale;
++
++ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, ws, hs, xs, ys);
++XE(3)
++ XGetSubImage(dpy, rcSavedArea, 0, 0, ws, hs, AllPlanes, ZPixmap, image, xs, ys);
++XE(4)
++if (db) fprintf(stderr, "rstr: %dx%d+%d+%d\n", ws, hs, xs, ys);
++
++ for (i=0; i < h; i++) {
++ memcpy(dst, src, Bpp * w);
++ src += Bpp * w;
++ dst += Bpl;
++ }
++ } else {
++
++ if (scale_saved) {
++ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, ss_w, ss_h, x, y);
++XE(5)
++ XGetSubImage(dpy, rcSavedArea, 0, 0, ss_w, ss_h, AllPlanes, ZPixmap, image, x, y);
++XE(6)
++ new_pixmap(w, h);
++ } else {
++ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
++XE(7)
++ XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y);
++XE(8)
++ }
++
++if (db) fprintf(stderr, "RSTR: %dx%d+%d+%d\n", w, h, x, y);
++
++ }
+ }
+ }
++
++ if (XError_ign > 1) {
++ fprintf(stderr, "XError_ign: %d, oper: %s\n", XError_ign, oper ? "restore" : "save");
++ }
++
++ XError_ign = 0;
}
static void SoftCursorDraw(void)
-@@ -472,6 +500,139 @@
+@@ -472,43 +651,182 @@
int offset, bytesPerPixel;
char *pos;
@@ -2327,13 +3027,25 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
+ alphablend = 1;
+ }
+
-+ bytesPerPixel = myFormat.bitsPerPixel / 8;
-+
+ bytesPerPixel = myFormat.bitsPerPixel / 8;
+
+- /* FIXME: Speed optimization is possible. */
+- for (y = 0; y < rcHeight; y++) {
+- y0 = rcCursorY - rcHotY + y;
+- if (y0 >= 0 && y0 < si.framebufferHeight) {
+- for (x = 0; x < rcWidth; x++) {
+- x0 = rcCursorX - rcHotX + x;
+- if (x0 >= 0 && x0 < si.framebufferWidth) {
+- offset = y * rcWidth + x;
+- if (rcMask[offset]) {
+- pos = (char *)&rcSource[offset * bytesPerPixel];
+- CopyDataToScreen(pos, x0, y0, 1, 1);
+- }
+ if (alphablend && bytesPerPixel == 4) {
+ unsigned long pixel, put, *upos, *upix;
+ int got_alpha = 0, rsX, rsY, rsW, rsH;
+ static XImage *alpha_image = NULL;
-+ static int iwidth = 128;
++ static int iwidth = 192;
+
+ if (! alpha_image) {
+ /* watch out for tiny fb (rare) */
@@ -2347,7 +3059,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
+ /* initialize an XImage with a chunk of desktopWin */
+ alpha_image = XGetImage(dpy, desktopWin, 0, 0, iwidth, iwidth,
+ AllPlanes, ZPixmap);
-+ }
+ }
+- }
+- }
+
+ /* first check if there is any non-zero alpha channel data at all: */
+ for (y = 0; y < rcHeight; y++) {
@@ -2374,9 +3088,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
+ goto oldway;
+ }
+
-+ /* load the saved fb patch in to image (faster way?) */
-+ XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight,
-+ AllPlanes, ZPixmap, alpha_image, 0, 0);
++ /* load the saved fb patch in to alpha_image (faster way?) */
++ if (image_scale != NULL && scale_x > 0) {
++ XGetSubImage(dpy, rcSavedArea_0, 0, 0, rcWidth, rcHeight, AllPlanes, ZPixmap, alpha_image, 0, 0);
++ } else {
++ XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight, AllPlanes, ZPixmap, alpha_image, 0, 0);
++ }
++
+ upix = (unsigned long *)alpha_image->data;
+
+ /* if the richcursor is clipped, the fb patch will be smaller */
@@ -2443,17 +3161,28 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
+ }
+ }
+ return;
-+ }
+ }
+oldway:
+#endif
+
- bytesPerPixel = myFormat.bitsPerPixel / 8;
-
- /* FIXME: Speed optimization is possible. */
-@@ -490,25 +651,26 @@
- }
- }
- }
++ bytesPerPixel = myFormat.bitsPerPixel / 8;
++
++ /* FIXME: Speed optimization is possible. */
++ for (y = 0; y < rcHeight; y++) {
++ y0 = rcCursorY - rcHotY + y;
++ if (y0 >= 0 && y0 < si.framebufferHeight) {
++ for (x = 0; x < rcWidth; x++) {
++ x0 = rcCursorX - rcHotX + x;
++ if (x0 >= 0 && x0 < si.framebufferWidth) {
++ offset = y * rcWidth + x;
++ if (rcMask[offset]) {
++ pos = (char *)&rcSource[offset * bytesPerPixel];
++ CopyDataToScreen(pos, x0, y0, 1, 1);
++ }
++ }
++ }
++ }
++ }
+ XSync(dpy, False);
}
@@ -2470,6 +3199,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
+ if (prevSoftCursorSet) {
+ SoftCursorCopyArea(OPER_RESTORE);
+ XFreePixmap(dpy, rcSavedArea);
++ XFreePixmap(dpy, rcSavedArea_0);
+ free(rcSource);
+ rcSource = NULL;
+ free(rcMask);
@@ -2493,22 +3223,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe
-
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncviewer/desktop.c
--- vnc_unixsrc.orig/vncviewer/desktop.c 2004-05-28 13:29:29.000000000 -0400
-+++ vnc_unixsrc/vncviewer/desktop.c 2008-09-05 19:12:25.000000000 -0400
-@@ -28,21 +28,40 @@
++++ vnc_unixsrc/vncviewer/desktop.c 2008-10-17 22:12:57.000000000 -0400
+@@ -28,28 +28,473 @@
#include <X11/extensions/XShm.h>
#endif
-+/* we don't have Xvlib working yet... not all cards supply RGB @ 32bpp */
-+#define XVLIB__dont
-+#ifdef XVLIB
-+#include <X11/extensions/Xvlib.h>
-+XvImage *xv_image;
-+XvPortID xv_port = None;
-+int xv_width = 640;
-+int xv_height = 480;
-+#endif
-+
-+
+#include <X11/cursorfont.h>
+
GC gc;
@@ -2518,6 +3237,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+Cursor dotCursor3 = None;
+Cursor dotCursor4 = None;
+Cursor bogoCursor = None;
++Cursor waitCursor = None;
Widget form, viewport, desktop;
static Bool modifierPressed[256];
@@ -2525,6 +3245,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
-static XImage *image = NULL;
+XImage *image = NULL;
+XImage *image_ycrop = NULL;
++XImage *image_scale = NULL;
++
++int image_is_shm = 0;
static Cursor CreateDotCursor();
+static Cursor CreateBogoCursor();
@@ -2536,100 +3259,399 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+
static XtResource desktopBackingStoreResources[] = {
{
- XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0,
-@@ -50,6 +69,138 @@
+- XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0,
+- XtRImmediate, (XtPointer) Always,
++ XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0,
++ XtRImmediate, (XtPointer) Always,
},
};
-+#ifdef XVLIB
-+void setup_xv(void) {
-+ int a, p, f;
-+ int num_adaptors;
-+ XvAdaptorInfo *adaptor_info;
-+ XvImageFormatValues *formats, *format = NULL;
-+ int nformats;
++double scale_factor_x = 0.0;
++double scale_factor_y = 0.0;
++int scale_x = 0, scale_y = 0;
++int scale_round(int len, double fac);
+
-+ if (xv_port != None) {
-+ return;
++double last_rescale = 0.0;
++double last_fullscreen = 0.0;
++double start_time = 0.0;
++
++int prev_fb_width = -1;
++int prev_fb_height = -1;
++
++void get_scale_values(double *fx, double *fy) {
++ char *s = appData.scale;
++ double f, frac_x = -1.0, frac_y = -1.0;
++ int n, m;
++ int xmax = si.framebufferWidth;
++ int ymax = si.framebufferHeight;
++
++ if (appData.yCrop > 0) {
++ ymax = appData.yCrop;
+ }
-+ XvQueryAdaptors (dpy, RootWindow(dpy, DefaultScreen(dpy)), &num_adaptors, &adaptor_info);
-+ for (a = 0; a < num_adaptors; a++) {
-+ fprintf(stderr, "Adapator \"%s\" has %d ports\n",
-+ adaptor_info[a].name,
-+ adaptor_info[a].num_ports);
++
++ if (sscanf(s, "%d/%d", &n, &m) == 2) {
++ if (m == 0) {
++ frac_x = 1.0;
++ } else {
++ frac_x = ((double) n) / ((double) m);
++ }
+ }
-+ for (a = 0; a < num_adaptors; a++) {
-+ for (p = 0; a < adaptor_info[a].num_ports; p++) {
-+ if (XvGrabPort(dpy, adaptor_info[a].base_id + p, CurrentTime) == Success) {
-+ xv_port = adaptor_info[a].base_id + p;
-+ break;
-+ }
++ if (sscanf(s, "%dx%d", &n, &m) == 2) {
++ frac_x = ((double) n) / ((double) xmax);
++ frac_y = ((double) m) / ((double) ymax);
++ }
++ if (!strcasecmp(s, "fit")) {
++ frac_x = ((double) dpyWidth) / ((double) xmax);
++ frac_y = ((double) dpyHeight) / ((double) ymax);
++ }
++ if (!strcasecmp(s, "auto")) {
++ Dimension w, h;
++ XtVaGetValues(toplevel, XtNheight, &h, XtNwidth, &w, NULL);
++ fprintf(stderr, "auto: %dx%d\n", w, h);
++ if (w > 32 && h > 32) {
++ frac_x = ((double) w) / ((double) xmax);
++ frac_y = ((double) h) / ((double) ymax);
+ }
+ }
-+ formats = XvListImageFormats (dpy, xv_port, &nformats);
-+ for (f=0; f < nformats; f++) {
-+fprintf(stderr, "f=%d\n", f);
-+fprintf(stderr, "formats[f].type: %d\n", formats[f].type);
-+fprintf(stderr, "formats[f].format: %d\n", formats[f].format);
-+fprintf(stderr, "formats[f].bits_per_pixel: %d\n", formats[f].bits_per_pixel);
-+fprintf(stderr, "formats[f].num_planes: %d\n", formats[f].num_planes);
-+fprintf(stderr, "formats[f].scanline_order: %d\n", formats[f].scanline_order);
-+fprintf(stderr, "formats[f].component_order: %s\n", formats[f].component_order);
-+ if (formats[f].type != XvRGB) continue;
-+ if (formats[f].format != XvPacked) continue;
-+ if (formats[f].bits_per_pixel != 32) continue;
-+ if (formats[f].num_planes != 1) continue;
-+ if (formats[f].scanline_order != XvTopToBottom) continue;
-+ if (strcmp (formats[f].component_order, "BGRX") != 0) continue;
-+ format = &formats[f];
-+ break;
++ if (frac_x < 0.0 && sscanf(s, "%lf", &f) == 1) {
++ if (f > 0.0) {
++ frac_x = f;
++ }
+ }
-+// fprintf(stderr, "y_sample_bits %d u_sample_bits %d v_sample_bits %d\n",
-+// format->y_sample_bits, format->u_sample_bits, format->v_sample_bits);
-+// fprintf(stderr, "component_order: %s\n", format->component_order);
+
-+ xv_image = XvCreateImage (dpy, xv_port, format->id, NULL, si.framebufferWidth, si.framebufferHeight);
++ if (frac_y < 0.0) {
++ frac_y = frac_x;
++ }
++
++ if (fx != NULL) {
++ *fx = frac_x;
++ }
++ if (fy != NULL) {
++ *fy = frac_y;
++ }
+}
-+#endif
+
-+void create_image() {
-+ image = NULL;
-+ image_ycrop = NULL;
++void try_create_image(void);
++void put_image(int src_x, int src_y, int dst_x, int dst_y, int width, int height, int solid);
++void create_image();
+
-+//fprintf(stderr, "useShm: %d\n", appData.useShm);
++// toplevel -> form -> viewport -> desktop
+
++void adjust_Xt_win(int w, int h) {
++ int x, y, dw, dh, h0 = h;
++ int mw = w, mh = h;
++ int autoscale = 0;
+
-+#ifdef MITSHM
++ if (!appData.fullScreen && appData.scale != NULL && !strcmp(appData.scale, "auto")) {
++ autoscale = 1;
++ mw = dpyWidth;
++ mh = dpyHeight;
++ }
++
++ if (appData.yCrop > 0) {
++ int ycrop = appData.yCrop;
++ if (image_scale && scale_factor_y > 0.0) {
++ ycrop = scale_round(ycrop, scale_factor_y);
++ if (!autoscale) {
++ mh = ycrop;
++ }
++ }
++ XtVaSetValues(toplevel, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, ycrop, NULL);
++ XtVaSetValues(form, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, ycrop, NULL);
++ h0 = ycrop;
++ } else {
++ XtVaSetValues(toplevel, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, h, NULL);
++ }
++
++ fprintf(stderr, "adjust_Xt_win: %dx%d & %dx%d\n", w, h, w, h0);
++
++ XtVaSetValues(desktop, XtNwidth, w, XtNheight, h, NULL);
++
++ XtResizeWidget(desktop, w, h, 0);
++
++ if (!autoscale) {
++ dw = appData.wmDecorationWidth;
++ dh = appData.wmDecorationHeight;
++
++ x = (dpyWidth - w - dw)/2;
++ y = (dpyHeight - h0 - dh)/2;
++
++ XtConfigureWidget(toplevel, x + dw, y + dh, w, h0, 0);
++ }
++}
++
++void rescale_image(void) {
++ double frac_x, frac_y;
++ int w, h;
++
++ if (image == NULL) {
++ create_image();
++ return;
++ }
++
++ if (appData.useXserverBackingStore) {
++ create_image();
++ return;
++ }
++
++ if (image == NULL && image_scale == NULL) {
++ create_image();
++ return;
++ }
++
++ if (appData.scale == NULL) {
++ /* switching to not scaled */
++ frac_x = frac_y = 1.0;
++ } else {
++ get_scale_values(&frac_x, &frac_y);
++ if (frac_x < 0.0) {
++ create_image();
++ return;
++ }
++ }
++
++ last_rescale = dnow();
++
++ SoftCursorLockArea(0, 0, si.framebufferWidth, si.framebufferHeight);
++
++ if (image_scale == NULL) {
++ /* switching from not scaled */
++ int i, start_over = 0;
++ int Bpl = image->bytes_per_line;
++ char *dst, *src = image->data;
++
++ image_scale = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
++ si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0);
++
++ image_scale->data = (char *) malloc(image_scale->bytes_per_line * image_scale->height);
++
++ fprintf(stderr, "rescale_image: switching from not scaled. created image_scale %dx%d\n", image_scale->width, image_scale->height);
++ fprintf(stderr, "rescale_image: copying image -> image_scale %dx%d -> %dx%d\n", image->width, image->height, image_scale->width, image_scale->height);
++
++ dst = image_scale->data;
++
++ /* copy from image->data */
++ for (i=0; i < image->height; i++) {
++ memcpy(dst, src, Bpl);
++ dst += Bpl;
++ src += Bpl;
++ }
++ }
++
++ /* now destroy image */
++ if (image && image->data) {
++ if (UsingShm()) {
++ ShmCleanup();
++ }
++ XDestroyImage(image);
++ fprintf(stderr, "rescale_image: destroyed 'image'\n");
++ image = NULL;
++ }
++ if (image_ycrop && image_ycrop->data) {
++ XDestroyImage(image_ycrop);
++ fprintf(stderr, "rescale_image: destroyed 'image_ycrop'\n");
++ image_ycrop = NULL;
++ }
++
++ if (frac_x == 1.0 && frac_y == 1.0) {
++ /* switching to not scaled */
++ fprintf(stderr, "rescale_image: switching to not scaled.\n");
++ w = si.framebufferWidth;
++ h = si.framebufferHeight;
++
++ scale_factor_x = 0.0;
++ scale_factor_y = 0.0;
++ scale_x = 0;
++ scale_y = 0;
++ } else {
++ w = scale_round(si.framebufferWidth, frac_x);
++ h = scale_round(si.framebufferHeight, frac_y);
++
++ scale_factor_x = frac_x;
++ scale_factor_y = frac_y;
++ scale_x = w;
++ scale_y = h;
++ }
++
++ adjust_Xt_win(w, h);
++
++ fprintf(stderr, "rescale: %dx%d %.4f %.4f\n", w, h, scale_factor_x, scale_factor_y);
++
++ try_create_image();
++
++ if (image && image->data && image_scale && frac_x == 1.0 && frac_y == 1.0) {
++ /* switched to not scaled */
++ int i;
++ int Bpl = image->bytes_per_line;
++ char *dst = image->data;
++ char *src = image_scale->data;
++
++ fprintf(stderr, "rescale_image: switching to not scaled.\n");
++
++ for (i=0; i < image->height; i++) {
++ memcpy(dst, src, Bpl);
++ dst += Bpl;
++ src += Bpl;
++ }
++ XDestroyImage(image_scale);
++ fprintf(stderr, "rescale_image: destroyed 'image_scale'\n");
++ image_scale = NULL;
++ }
++
++ if (appData.yCrop > 0) {
++ int ycrop = appData.yCrop;
++ /* do the top part first so they can see it earlier */
++ put_image(0, 0, 0, 0, si.framebufferWidth, ycrop, 0);
++ if (si.framebufferHeight > ycrop) {
++ /* this is a big fb and so will take a long time */
++ if (waitCursor != None) {
++ XDefineCursor(dpy, desktopWin, waitCursor);
++ XSync(dpy, False);
++ }
++ put_image(0, 0, 0, 0, si.framebufferWidth, si.framebufferHeight - ycrop, 0);
++ if (waitCursor != None) {
++ Xcursors(1);
++ if (appData.useX11Cursor) {
++ XSetWindowAttributes attr;
++ unsigned long valuemask = 0;
++ if (appData.viewOnly) {
++ attr.cursor = dotCursor4;
++ } else {
++ attr.cursor = dotCursor3;
++ }
++ valuemask |= CWCursor;
++ XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
++ }
++ }
++ }
++ } else {
++ put_image(0, 0, 0, 0, si.framebufferWidth, si.framebufferHeight, 0);
++ }
++
++ SoftCursorUnlockScreen();
++
++ fprintf(stderr, "rescale: image_scale=0x%x image=0x%x image_ycrop=0x%x\n", image_scale, image, image_ycrop);
++ last_rescale = dnow();
++
++}
++
++void try_create_image(void) {
++
++ image_is_shm = 0;
+ if (appData.useShm) {
++#ifdef MITSHM
+ image = CreateShmImage(0);
+ if (!image) {
+ if (appData.yCrop > 0) {
-+ image_ycrop = CreateShmImage(1);
-+ if (!image_ycrop) {
-+ appData.useShm = False;
++ if (appData.scale != NULL && scale_x > 0) {
++ ;
+ } else {
-+ fprintf(stderr, "created smaller image_ycrop "
-+ "shm image\n");
++ image_ycrop = CreateShmImage(1);
++ if (!image_ycrop) {
++ appData.useShm = False;
++ } else {
++ fprintf(stderr, "created smaller image_ycrop shm image: %dx%d\n",
++ image_ycrop->width, image_ycrop->height);
++ }
+ }
+ } else {
+ appData.useShm = False;
+ }
++ } else {
++ image_is_shm = 1;
++ fprintf(stderr, "created shm image: %dx%d\n", image->width, image->height);
+ }
-+ }
+#endif
++ }
+
+ if (!image) {
-+ image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
-+ si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0);
++ fprintf(stderr, "try_create_image: shm image create fail: image == NULL\n");
++ if (scale_x > 0) {
++ image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
++ scale_x, scale_y, BitmapPad(dpy), 0);
++ } else {
++ image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
++ si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0);
++ }
+
+ image->data = malloc(image->bytes_per_line * image->height);
++
+ if (!image->data) {
-+ fprintf(stderr,"malloc failed\n");
++ fprintf(stderr, "try_create_image: malloc failed\n");
+ exit(1);
+ } else {
-+ fprintf(stderr, "created non-shm image\n");
++ fprintf(stderr, "try_create_image: created *non-shm* image: %dx%d\n", image->width, image->height);
++ }
++ }
++}
++
++void create_image() {
++ image = NULL;
++ image_ycrop = NULL;
++ image_scale = NULL;
++
++ fprintf(stderr, "create_image()\n");
++
++ if (CreateShmImage(-1) == NULL) {
++ appData.useShm = False;
++ }
++ if (appData.scale != NULL) {
++ if (appData.useXserverBackingStore) {
++ fprintf(stderr, "Cannot scale when using X11 backingstore.\n");
++ } else {
++ double frac_x = -1.0, frac_y = -1.0;
++
++ scale_factor_x = 0.0;
++ scale_factor_y = 0.0;
++ scale_x = 0;
++ scale_y = 0;
++
++ get_scale_values(&frac_x, &frac_y);
++
++ if (frac_x < 0.0) {
++ fprintf(stderr, "Cannot figure out scale factor!\n");
++ } else {
++ int w, h, hyc;
++
++ w = scale_round(si.framebufferWidth, frac_x);
++ h = scale_round(si.framebufferHeight, frac_y);
++ hyc = h;
++ if (appData.yCrop > 0) {
++ hyc = scale_round(appData.yCrop, frac_y);
++ }
++
++ /* image scale is full framebuffer */
++ image_scale = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
++ si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0);
++
++ image_scale->data = (char *) malloc(image_scale->bytes_per_line * image_scale->height);
++
++ fprintf(stderr, "create_image: created image_scale %dx%d\n", image_scale->width, image_scale->height);
++
++ if (!image_scale->data) {
++ fprintf(stderr, "create_image: malloc failed\n");
++ XDestroyImage(image_scale);
++ fprintf(stderr, "create_image: destroyed 'image_scale'\n");
++ image_scale = NULL;
++ } else {
++ int h2;
++ scale_factor_x = frac_x;
++ scale_factor_y = frac_y;
++ scale_x = w;
++ scale_y = h;
++
++ XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, hyc, NULL);
++
++ h2 = scale_round(si.framebufferHeight, frac_y);
++ XtVaSetValues(desktop, XtNwidth, w, XtNheight, h2, NULL);
++
++ }
++ fprintf(stderr, "create_image: scale: %dx%d %.4f %.4f\n", w, h,
++ scale_factor_x, scale_factor_y);
++ }
+ }
+ }
++ try_create_image();
+}
+
+int old_width = 0;
@@ -2652,8 +3674,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ return 864;
+ } else if (w == 1280) {
+ return 1024;
++ } else if (w == 1440) {
++ return 900;
+ } else if (w == 1600) {
+ return 1200;
++ } else if (w == 1680) {
++ return 1050;
+ } else if (w == 1920) {
+ return 1200;
+ } else {
@@ -2676,12 +3702,26 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
/*
* DesktopInitBeforeRealization creates the "desktop" widget and the viewport
-@@ -59,89 +210,320 @@
+@@ -59,91 +504,964 @@
void
DesktopInitBeforeRealization()
{
- int i;
+ int i;
++ int h = si.framebufferHeight;
++ int w = si.framebufferWidth;
++ double frac_x = 1.0, frac_y = 1.0;
++
++ start_time = dnow();
++
++ prev_fb_width = si.framebufferWidth;
++ prev_fb_height = si.framebufferHeight;
++
++ if (appData.scale != NULL) {
++ get_scale_values(&frac_x, &frac_y);
++ w = scale_round(w, frac_x);
++ h = scale_round(h, frac_y);
++ }
- form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel,
- XtNborderWidth, 0,
@@ -2700,51 +3740,28 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- NULL);
+ desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport,
+ XtNborderWidth, 0, NULL);
-+
-+ XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
-+ XtNheight, si.framebufferHeight, NULL);
-+
-+ XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask,
-+ True, HandleBasicDesktopEvent, NULL);
-+
-+
-+ check_tall();
-+
-+ if (appData.yCrop) {
-+ int wm, hm;
-+ if (appData.yCrop < 0) {
-+ appData.yCrop = guessCrop();
-+ fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop);
-+ }
-+ hm = appData.yCrop;
-+ if (0 && appData.sbWidth <= 6 && appData.sbWidth > 0) {
-+ hm += appData.sbWidth;
-+ }
-+ XtVaSetValues(toplevel, XtNmaxHeight, hm, NULL);
-+ XtVaSetValues(form, XtNmaxHeight, hm, NULL);
-+ XtVaSetValues(viewport, XtNforceBars, False, NULL);
-+ }
-+ old_width = si.framebufferWidth;
-+ old_height = si.framebufferHeight;
- XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
- XtNheight, si.framebufferHeight, NULL);
-+ for (i = 0; i < 256; i++) {
-+ modifierPressed[i] = False;
-+ }
++ XtVaSetValues(desktop, XtNwidth, w, XtNheight, h, NULL);
- XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask,
- True, HandleBasicDesktopEvent, NULL);
-+ create_image();
-+}
++ XtAddEventHandler(desktop, LeaveWindowMask|EnterWindowMask|ExposureMask,
++ True, HandleBasicDesktopEvent, NULL);
- for (i = 0; i < 256; i++)
- modifierPressed[i] = False;
-+static Widget scrollbar_y = NULL;
++ if (appData.yCrop) {
++ int wm, hm;
++ if (appData.yCrop < 0) {
++ appData.yCrop = guessCrop();
++ fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop);
++ }
++ hm = appData.yCrop;
- image = NULL;
-+static int xsst = 2;
-+#include <X11/Xaw/Scrollbar.h>
++ fprintf(stderr, "ycrop h: %d -> %d\n", hm, (int) (hm*frac_y));
-#ifdef MITSHM
- if (appData.useShm) {
@@ -2753,7 +3770,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- appData.useShm = False;
- }
-#endif
--
++ hm *= frac_y;
+
- if (!image) {
- image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
- si.framebufferWidth, si.framebufferHeight,
@@ -2765,6 +3783,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- exit(1);
- }
- }
++ XtVaSetValues(toplevel, XtNmaxHeight, hm, XtNheight, hm, NULL);
++ XtVaSetValues(form, XtNmaxHeight, hm, XtNheight, hm, NULL);
++ XtVaSetValues(viewport, XtNforceBars, False, NULL);
++ XSync(dpy, False);
++ }
++
++ old_width = si.framebufferWidth;
++ old_height = si.framebufferHeight;
++
++ for (i = 0; i < 256; i++) {
++ modifierPressed[i] = False;
++ }
++
++ create_image();
+ }
+
++static Widget scrollbar_y = NULL;
++
++static int xsst = 2;
++#include <X11/Xaw/Scrollbar.h>
++
+static XtCallbackProc Scrolled(Widget w, XtPointer closure, XtPointer call_data) {
+ Position x, y;
+ XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL);
@@ -2779,7 +3818,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ float t = 0.0;
+ XtVaSetValues(w, XtNtopOfThumb, &t, NULL);
+ }
- }
++}
++
+static XtCallbackProc Jumped(Widget w, XtPointer closure, XtPointer call_data) {
+ float top = *((float *) call_data);
+ Position x, y;
@@ -2799,7 +3839,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ }
+}
+
-+
+extern double dnow(void);
+
+void check_things() {
@@ -2810,12 +3849,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ int h = si.framebufferHeight;
+ double now = dnow();
+ static double last = 0;
++ double fac = image_scale ? scale_factor_y : 1.0;
+
+ if (first) {
+ first = 0;
+ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
+ }
-+ if (appData.yCrop > 0 && appData.yCrop < dpyHeight && h > 2*w && now > last_scrollbar + 0.25) {
++ if (appData.yCrop > 0 && appData.yCrop * fac < dpyHeight && h > 2*w && now > last_scrollbar + 0.25) {
+ Widget wv, wh, wc;
+ Position x0, y0;
+ Position x1, y1;
@@ -2836,13 +3876,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ sb = 2;
+ }
+ if (w0 != sb || h1 != sb) {
-+ fprintf(stderr, "Very tall (-ncache) fb, setting scrollbar thickness to: %d pixels\n", sb);
++ fprintf(stderr, "Very tall (-ncache) fb, setting scrollbar thickness to: %d pixels (%d/%d)\n\n", sb, w0, h1);
+
+ XtUnmanageChild(wv);
+ XtUnmanageChild(wh);
+ XtUnmanageChild(wc);
+
-+ XtVaSetValues(wv, XtNwidth, sb, XtNx, x0 + (w0 - sb), NULL);
++ XtVaSetValues(wv, XtNwidth, sb, XtNx, x0 + (w0 - sb), NULL);
+ XtVaSetValues(wh, XtNheight, sb, XtNy, y1 + (h1 - sb), NULL);
+ w2 = w2 + (w0 - sb);
+ h2 = h2 + (h1 - sb);
@@ -2853,18 +3893,54 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ XtManageChild(wv);
+ XtManageChild(wh);
+ XtManageChild(wc);
++
++ appData.sbWidth = sb;
+ }
+ }
+ last_scrollbar = dnow();
+ }
+
-+ if (now <= last + 1.0) {
++ if (now <= last + 0.25) {
+ return;
+ }
-
++
++ /* e.g. xrandr resize */
+ dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
+ dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
+
++ if (appData.scale != NULL) {
++ static Dimension last_w = 0, last_h = 0;
++ static double last_resize = 0.0;
++ Dimension w, h;
++ if (last_w == 0) {
++ XtVaGetValues(toplevel, XtNwidth, &last_w, XtNheight, &last_h, NULL);
++ last_resize = now;
++ }
++ if (now < last_resize + 0.5) {
++ ;
++ } else if (appData.fullScreen) {
++ ;
++ } else if (!strcmp(appData.scale, "auto")) {
++ XtVaGetValues(toplevel, XtNwidth, &w, XtNheight, &h, NULL);
++ if (w < 32 || h < 32) {
++ ;
++ } else if (last_w != w || last_h != h) {
++ Window rr, cr, r = DefaultRootWindow(dpy);
++ int rx, ry, wx, wy;
++ unsigned int mask;
++ /* make sure mouse buttons not pressed */
++ if (XQueryPointer(dpy, r, &rr, &cr, &rx, &ry, &wx, &wy, &mask)) {
++ if (mask == 0) {
++ rescale_image();
++ last_w = w;
++ last_h = h;
++ last_resize = dnow();
++ }
++ }
++ }
++ }
++ }
++
+ last = dnow();
+}
@@ -2943,15 +4019,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+ NULL, 0);
+
-+ if (appData.useBackingstore) {
++ if (appData.useXserverBackingStore) {
+ Screen *s = DefaultScreenOfDisplay(dpy);
+ if (DoesBackingStore(s) != Always) {
+ fprintf(stderr, "X server does not do backingstore, disabling it.\n");
-+ appData.useBackingstore = False;
++ appData.useXserverBackingStore = False;
+ }
+ }
+
-+ if (appData.useBackingstore) {
++ if (appData.useXserverBackingStore) {
+ XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store,
+ desktopBackingStoreResources, 1, NULL);
+ valuemask |= CWBackingStore;
@@ -2970,6 +4046,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ valuemask |= CWCursor;
+ }
+ bogoCursor = XCreateFontCursor(dpy, XC_bogosity);
++ waitCursor = XCreateFontCursor(dpy, XC_watch);
+
+ XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
+
@@ -3002,36 +4079,603 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ FreeX11Cursor();
+ FreeSoftCursor();
+}
++
++
++#define CEIL(x) ( (double) ((int) (x)) == (x) ? \
++ (double) ((int) (x)) : (double) ((int) (x) + 1) )
++#define FLOOR(x) ( (double) ((int) (x)) )
++
++#if 0
++static int nfix(int i, int n) {
++ if (i < 0) {
++ i = 0;
++ } else if (i >= n) {
++ i = n - 1;
++ }
++ return i;
++}
++#else
++#define nfix(i, n) ( i < 0 ? 0 : ( (i >= n) ? (n - 1) : i ) )
++#endif
++
++int scale_round(int len, double fac) {
++ double eps = 0.000001;
++
++ len = (int) (len * fac + eps);
++ if (len < 1) {
++ len = 1;
++ }
++ return len;
++}
++
++static void scale_rect(double factor_x, double factor_y, int blend, int interpolate,
++ int *px, int *py, int *pw, int *ph, int solid) {
++
++ int i, j, i1, i2, j1, j2; /* indices for scaled fb (dest) */
++ int I, J, I1, I2, J1, J2; /* indices for main fb (source) */
++
++ double w, wx, wy, wtot; /* pixel weights */
++
++ double x1, y1, x2, y2; /* x-y coords for destination pixels edges */
++ double dx, dy; /* size of destination pixel */
++ double ddx=0, ddy=0; /* for interpolation expansion */
++
++ char *src, *dest; /* pointers to the two framebuffers */
++
++ unsigned short us = 0;
++ unsigned char uc = 0;
++ unsigned int ui = 0;
++
++ int use_noblend_shortcut = 1;
++ int shrink; /* whether shrinking or expanding */
++ static int constant_weights = -1, mag_int = -1;
++ static int last_Nx = -1, last_Ny = -1, cnt = 0;
++ static double last_factor = -1.0;
++ int b, k;
++ double pixave[4]; /* for averaging pixel values */
++
++ /* internal */
++
++ int X1, X2, Y1, Y2;
++
++ int Nx = si.framebufferWidth;
++ int Ny = si.framebufferHeight;
++
++ int nx = scale_round(Nx, factor_x);
++ int ny = scale_round(Ny, factor_y);
++
++ int Bpp = image->bits_per_pixel / 8;
++ int dst_bytes_per_line = image->bytes_per_line;
++ int src_bytes_per_line = image_scale->bytes_per_line;
++
++ unsigned long main_red_mask = image->red_mask;
++ unsigned long main_green_mask = image->green_mask;
++ unsigned long main_blue_mask = image->blue_mask;
++ int mark = 1, n;
++
++ char *src_fb = image_scale->data;
++ char *dst_fb = image->data;
++
++ static int nosolid = -1;
++ int sbdy = 3;
++ double fmax = factor_x > factor_y ? factor_x : factor_y;
++ double fmin = factor_x < factor_y ? factor_x : factor_y;
- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
-+void put_image(int src_x, int src_y, int dst_x, int dst_y, int width,
-+ int height) {
-+
-+#ifdef XVLIB
-+ if (xv_width > 0) {
-+ if (xv_port == None) {
-+ setup_xv();
-+ }
-+ if (xv_port != None) {
-+ double ratw = (double) xv_width / si.framebufferWidth;
-+ double rath = (double) xv_height / si.framebufferHeight;
-+ XvPutImage(dpy, xv_port, desktopWin, gc, xv_image,
-+ src_x, src_y, width, height,
-+ (int) ratw * dst_x, (int) rath * dst_y,
-+ (int) ratw * width, (int) rath * height);
-+ return;
++ X1 = *px;
++ X2 = *px + *pw;
++ Y1 = *py;
++ Y2 = *py + *ph;
++
++ if (fmax > 1.0) {
++ /* try to avoid problems with bleeding... */
++ sbdy = (int) (2.0 * fmax * sbdy);
++ }
++
++ //fprintf(stderr, "scale_rect: %dx%d+%d+%d\n", *pw, *ph, *px, *py);
++
++ *px = (int) (*px * factor_x);
++ *py = (int) (*py * factor_y);
++ *pw = scale_round(*pw, factor_x);
++ *ph = scale_round(*ph, factor_y);
++
++ if (nosolid < 0) {
++ if (getenv("SSVNC_NOSOLID")) {
++ nosolid = 1;
++ } else {
++ nosolid = 0;
+ }
+ }
-+#endif
++ if (nosolid) solid = 0;
++
++#define rfbLog printf
++/* Begin taken from x11vnc scale: */
++
++ if (factor_x <= 1.0 || factor_y <= 1.0) {
++ shrink = 1;
++ } else {
++ shrink = 0;
++ interpolate = 1;
++ }
++
++ /*
++ * N.B. width and height (real numbers) of a scaled pixel.
++ * both are > 1 (e.g. 1.333 for -scale 3/4)
++ * they should also be equal but we don't assume it.
++ *
++ * This new way is probably the best we can do, take the inverse
++ * of the scaling factor to double precision.
++ */
++ dx = 1.0/factor_x;
++ dy = 1.0/factor_y;
++
++ /*
++ * There is some speedup if the pixel weights are constant, so
++ * let's special case these.
++ *
++ * If scale = 1/n and n divides Nx and Ny, the pixel weights
++ * are constant (e.g. 1/2 => equal on 2x2 square).
++ */
++ if (factor_x != last_factor || Nx != last_Nx || Ny != last_Ny) {
++ constant_weights = -1;
++ mag_int = -1;
++ last_Nx = Nx;
++ last_Ny = Ny;
++ last_factor = factor_x;
++ }
++
++ if (constant_weights < 0 && factor_x != factor_y) {
++ constant_weights = 0;
++ mag_int = 0;
++ } else if (constant_weights < 0) {
++ int n = 0;
++ double factor = factor_x;
++
++ constant_weights = 0;
++ mag_int = 0;
++
++ for (i = 2; i<=128; i++) {
++ double test = ((double) 1)/ i;
++ double diff, eps = 1.0e-7;
++ diff = factor - test;
++ if (-eps < diff && diff < eps) {
++ n = i;
++ break;
++ }
++ }
++ if (! blend || ! shrink || interpolate) {
++ ;
++ } else if (n != 0) {
++ if (Nx % n == 0 && Ny % n == 0) {
++ static int didmsg = 0;
++ if (mark && ! didmsg) {
++ didmsg = 1;
++ rfbLog("scale_and_mark_rect: using "
++ "constant pixel weight speedup "
++ "for 1/%d\n", n);
++ }
++ constant_weights = 1;
++ }
++ }
++
++ n = 0;
++ for (i = 2; i<=32; i++) {
++ double test = (double) i;
++ double diff, eps = 1.0e-7;
++ diff = factor - test;
++ if (-eps < diff && diff < eps) {
++ n = i;
++ break;
++ }
++ }
++ if (! blend && factor > 1.0 && n) {
++ mag_int = n;
++ }
++ }
++if (0) fprintf(stderr, "X1: %d Y1: %d X2: %d Y2: %d\n", X1, Y1, X2, Y2);//G
++
++ if (mark && !shrink && blend) {
++ /*
++ * kludge: correct for interpolating blurring leaking
++ * up or left 1 destination pixel.
++ */
++ if (X1 > 0) X1--;
++ if (Y1 > 0) Y1--;
++ }
++
++ /*
++ * find the extent of the change the input rectangle induces in
++ * the scaled framebuffer.
++ */
++
++ /* Left edges: find largest i such that i * dx <= X1 */
++ i1 = FLOOR(X1/dx);
++
++ /* Right edges: find smallest i such that (i+1) * dx >= X2+1 */
++ i2 = CEIL( (X2+1)/dx ) - 1;
++
++ /* To be safe, correct any overflows: */
++ i1 = nfix(i1, nx);
++ i2 = nfix(i2, nx) + 1; /* add 1 to make a rectangle upper boundary */
++
++ /* Repeat above for y direction: */
++ j1 = FLOOR(Y1/dy);
++ j2 = CEIL( (Y2+1)/dy ) - 1;
++
++ j1 = nfix(j1, ny);
++ j2 = nfix(j2, ny) + 1;
++
++ /*
++ * special case integer magnification with no blending.
++ * vision impaired magnification usage is interested in this case.
++ */
++ if (mark && ! blend && mag_int && Bpp != 3) {
++ int jmin, jmax, imin, imax;
++
++ /* outer loop over *source* pixels */
++ for (J=Y1; J < Y2; J++) {
++ jmin = J * mag_int;
++ jmax = jmin + mag_int;
++ for (I=X1; I < X2; I++) {
++ /* extract value */
++ src = src_fb + J*src_bytes_per_line + I*Bpp;
++ if (Bpp == 4) {
++ ui = *((unsigned int *)src);
++ } else if (Bpp == 2) {
++ us = *((unsigned short *)src);
++ } else if (Bpp == 1) {
++ uc = *((unsigned char *)src);
++ }
++ imin = I * mag_int;
++ imax = imin + mag_int;
++ /* inner loop over *dest* pixels */
++ for (j=jmin; j<jmax; j++) {
++ dest = dst_fb + j*dst_bytes_per_line + imin*Bpp;
++ for (i=imin; i<imax; i++) {
++ if (Bpp == 4) {
++ *((unsigned int *)dest) = ui;
++ } else if (Bpp == 2) {
++ *((unsigned short *)dest) = us;
++ } else if (Bpp == 1) {
++ *((unsigned char *)dest) = uc;
++ }
++ dest += Bpp;
++ }
++ }
++ }
++ }
++ goto markit;
++ }
++
++ /* set these all to 1.0 to begin with */
++ wx = 1.0;
++ wy = 1.0;
++ w = 1.0;
++
++ /*
++ * Loop over destination pixels in scaled fb:
++ */
++ for (j=j1; j<j2; j++) {
++ int jbdy = 1, I1_solid;
++
++ y1 = j * dy; /* top edge */
++ if (y1 > Ny - 1) {
++ /* can go over with dy = 1/scale_fac */
++ y1 = Ny - 1;
++ }
++ y2 = y1 + dy; /* bottom edge */
++
++ /* Find main fb indices covered by this dest pixel: */
++ J1 = (int) FLOOR(y1);
++ J1 = nfix(J1, Ny);
++
++ if (shrink && ! interpolate) {
++ J2 = (int) CEIL(y2) - 1;
++ J2 = nfix(J2, Ny);
++ } else {
++ J2 = J1 + 1; /* simple interpolation */
++ ddy = y1 - J1;
++ }
++
++ /* destination char* pointer: */
++ dest = dst_fb + j*dst_bytes_per_line + i1*Bpp;
++
++ if (solid) {
++ if (j1+sbdy <= j && j < j2-sbdy) {
++ jbdy = 0;
++ x1 = (i1+sbdy) * dx;
++ if (x1 > Nx - 1) {
++ x1 = Nx - 1;
++ }
++ I1_solid = (int) FLOOR(x1);
++ if (I1_solid >= Nx) I1_solid = Nx - 1;
++ }
++ }
++
++ for (i=i1; i<i2; i++) {
++ int solid_skip = 0;
++
++ if (solid) {
++ /* if the region is solid, we can use the noblend speedup */
++ if (!jbdy && i1+sbdy <= i && i < i2-sbdy) {
++ solid_skip = 1;
++ /* pixels all the same so use X1: */
++ I1 = I1_solid;
++ goto jsolid;
++ }
++ }
++
++ x1 = i * dx; /* left edge */
++ if (x1 > Nx - 1) {
++ /* can go over with dx = 1/scale_fac */
++ x1 = Nx - 1;
++ }
++ x2 = x1 + dx; /* right edge */
++
++ /* Find main fb indices covered by this dest pixel: */
++ I1 = (int) FLOOR(x1);
++ if (I1 >= Nx) I1 = Nx - 1;
++
++ jsolid:
++ cnt++;
++
++ if ((!blend && use_noblend_shortcut) || solid_skip) {
++ /*
++ * The noblend case involves no weights,
++ * and 1 pixel, so just copy the value
++ * directly.
++ */
++ src = src_fb + J1*src_bytes_per_line + I1*Bpp;
++ if (Bpp == 4) {
++ *((unsigned int *)dest)
++ = *((unsigned int *)src);
++ } else if (Bpp == 2) {
++ *((unsigned short *)dest)
++ = *((unsigned short *)src);
++ } else if (Bpp == 1) {
++ *(dest) = *(src);
++ } else if (Bpp == 3) {
++ /* rare case */
++ for (k=0; k<=2; k++) {
++ *(dest+k) = *(src+k);
++ }
++ }
++ dest += Bpp;
++ continue;
++ }
++
++ if (shrink && ! interpolate) {
++ I2 = (int) CEIL(x2) - 1;
++ if (I2 >= Nx) I2 = Nx - 1;
++ } else {
++ I2 = I1 + 1; /* simple interpolation */
++ ddx = x1 - I1;
++ }
++//if (first) fprintf(stderr, " I1=%d I2=%d J1=%d J2=%d\n", I1, I2, J1, J2);//G
++
++ /* Zero out accumulators for next pixel average: */
++ for (b=0; b<4; b++) {
++ pixave[b] = 0.0; /* for RGB weighted sums */
++ }
++
++ /*
++ * wtot is for accumulating the total weight.
++ * It should always sum to 1/(scale_fac * scale_fac).
++ */
++ wtot = 0.0;
++
++ /*
++ * Loop over source pixels covered by this dest pixel.
++ *
++ * These "extra" loops over "J" and "I" make
++ * the cache/cacheline performance unclear.
++ * For example, will the data brought in from
++ * src for j, i, and J=0 still be in the cache
++ * after the J > 0 data have been accessed and
++ * we are at j, i+1, J=0? The stride in J is
++ * main_bytes_per_line, and so ~4 KB.
++ *
++ * Typical case when shrinking are 2x2 loop, so
++ * just two lines to worry about.
++ */
++ for (J=J1; J<=J2; J++) {
++ /* see comments for I, x1, x2, etc. below */
++ if (constant_weights) {
++ ;
++ } else if (! blend) {
++ if (J != J1) {
++ continue;
++ }
++ wy = 1.0;
++
++ /* interpolation scheme: */
++ } else if (! shrink || interpolate) {
++ if (J >= Ny) {
++ continue;
++ } else if (J == J1) {
++ wy = 1.0 - ddy;
++ } else if (J != J1) {
++ wy = ddy;
++ }
++
++ /* integration scheme: */
++ } else if (J < y1) {
++ wy = J+1 - y1;
++ } else if (J+1 > y2) {
++ wy = y2 - J;
++ } else {
++ wy = 1.0;
++ }
++
++ src = src_fb + J*src_bytes_per_line + I1*Bpp;
++
++ for (I=I1; I<=I2; I++) {
++
++ /* Work out the weight: */
++
++ if (constant_weights) {
++ ;
++ } else if (! blend) {
++ /*
++ * Ugh, PseudoColor colormap is
++ * bad news, to avoid random
++ * colors just take the first
++ * pixel. Or user may have
++ * specified :nb to fraction.
++ * The :fb will force blending
++ * for this case.
++ */
++ if (I != I1) {
++ continue;
++ }
++ wx = 1.0;
++
++ /* interpolation scheme: */
++ } else if (! shrink || interpolate) {
++ if (I >= Nx) {
++ continue; /* off edge */
++ } else if (I == I1) {
++ wx = 1.0 - ddx;
++ } else if (I != I1) {
++ wx = ddx;
++ }
++
++ /* integration scheme: */
++ } else if (I < x1) {
++ /*
++ * source left edge (I) to the
++ * left of dest left edge (x1):
++ * fractional weight
++ */
++ wx = I+1 - x1;
++ } else if (I+1 > x2) {
++ /*
++ * source right edge (I+1) to the
++ * right of dest right edge (x2):
++ * fractional weight
++ */
++ wx = x2 - I;
++ } else {
++ /*
++ * source edges (I and I+1) completely
++ * inside dest edges (x1 and x2):
++ * full weight
++ */
++ wx = 1.0;
++ }
++
++ w = wx * wy;
++ wtot += w;
++
++ /*
++ * We average the unsigned char value
++ * instead of char value: otherwise
++ * the minimum (char 0) is right next
++ * to the maximum (char -1)! This way
++ * they are spread between 0 and 255.
++ */
++ if (Bpp == 4) {
++ /* unroll the loops, can give 20% */
++ pixave[0] += w * ((unsigned char) *(src ));
++ pixave[1] += w * ((unsigned char) *(src+1));
++ pixave[2] += w * ((unsigned char) *(src+2));
++ pixave[3] += w * ((unsigned char) *(src+3));
++ } else if (Bpp == 2) {
++ /*
++ * 16bpp: trickier with green
++ * split over two bytes, so we
++ * use the masks:
++ */
++ us = *((unsigned short *) src);
++ pixave[0] += w*(us & main_red_mask);
++ pixave[1] += w*(us & main_green_mask);
++ pixave[2] += w*(us & main_blue_mask);
++ } else if (Bpp == 1) {
++ pixave[0] += w *
++ ((unsigned char) *(src));
++ } else {
++ for (b=0; b<Bpp; b++) {
++ pixave[b] += w *
++ ((unsigned char) *(src+b));
++ }
++ }
++ src += Bpp;
++ }
++ }
++
++ if (wtot <= 0.0) {
++ wtot = 1.0;
++ }
++ wtot = 1.0/wtot; /* normalization factor */
++
++ /* place weighted average pixel in the scaled fb: */
++ if (Bpp == 4) {
++ *(dest ) = (char) (wtot * pixave[0]);
++ *(dest+1) = (char) (wtot * pixave[1]);
++ *(dest+2) = (char) (wtot * pixave[2]);
++ *(dest+3) = (char) (wtot * pixave[3]);
++ } else if (Bpp == 2) {
++ /* 16bpp / 565 case: */
++ pixave[0] *= wtot;
++ pixave[1] *= wtot;
++ pixave[2] *= wtot;
++ us = (main_red_mask & (int) pixave[0])
++ | (main_green_mask & (int) pixave[1])
++ | (main_blue_mask & (int) pixave[2]);
++ *( (unsigned short *) dest ) = us;
++ } else if (Bpp == 1) {
++ *(dest) = (char) (wtot * pixave[0]);
++ } else {
++ for (b=0; b<Bpp; b++) {
++ *(dest+b) = (char) (wtot * pixave[b]);
++ }
++ }
++ dest += Bpp;
++ }
++ }
++ markit:
++/* End taken from x11vnc scale: */
++ if (0) {}
++}
++
++void put_image(int src_x, int src_y, int dst_x, int dst_y, int width,
++ int height, int solid) {
++ int db = 0;
++ int xmax = si.framebufferWidth;
++ int ymax = si.framebufferHeight;
+
++if (db || 0) fprintf(stderr, "put_image(%d %d %d %d %d %d)\n", src_x, src_y, dst_x, dst_y, width, height);
++
++ if (image_scale) {
++ int i;
++ for (i=0; i < 2; i++) {
++ if (src_x > 0) src_x--;
++ if (src_y > 0) src_y--;
++ }
++ for (i=0; i < 4; i++) {
++ if (src_x + width < xmax) width++;
++ if (src_y + height < ymax) height++;
++ }
++if (db) fprintf(stderr, "put_image(%d %d %d %d %d %d)\n", src_x, src_y, dst_x, dst_y, width, height);
++if (db) fprintf(stderr, "scale_rect(%d %d %d %d)\n", src_x, src_y, width, height);
++
++ scale_rect(scale_factor_x, scale_factor_y, 1, 0, &src_x, &src_y, &width, &height, solid);
++ dst_x = src_x;
++ dst_y = src_y;
++ }
++
+#ifdef MITSHM
+ if (appData.useShm) {
++ double fac = image_scale ? scale_factor_y : 1.0;
+ if (image_ycrop == NULL) {
-+//fprintf(stderr, "shm not image_ycrop\n");
-+ XShmPutImage(dpy, desktopWin, gc, image, src_x, src_y,
-+ dst_x, dst_y, width, height, False);
-+ } else if ((width < 32 && height < 32) || height > appData.yCrop) {
-+//fprintf(stderr, "non-shmB image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
++ if (image_is_shm) {
++ XShmPutImage(dpy, desktopWin, gc, image, src_x, src_y,
++ dst_x, dst_y, width, height, False);
++ } else {
++ XPutImage(dpy, desktopWin, gc, image, src_x, src_y,
++ dst_x, dst_y, width, height);
++ }
++ } else if ((width < 32 && height < 32) || height > appData.yCrop * fac) {
+ XPutImage(dpy, desktopWin, gc, image, src_x, src_y,
+ dst_x, dst_y, width, height);
+ } else {
@@ -3046,29 +4690,60 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ src += Bpl;
+ dst += Bpl2;
+ }
-+//fprintf(stderr, "shm image_ycrop %d %d %d %d %d %d\n", 0, 0, dst_x, dst_y, width, height);
+ XShmPutImage(dpy, desktopWin, gc, image_ycrop, 0, 0,
+ dst_x, dst_y, width, height, False);
+ }
+ } else
+#endif
+ {
-+//fprintf(stderr, "non-shmA image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
+ XPutImage(dpy, desktopWin, gc, image, src_x, src_y,
+ dst_x, dst_y, width, height);
+ }
++}
++
++//fprintf(stderr, "non-shmB image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
++//fprintf(stderr, "shm image_ycrop %d %d %d %d %d %d\n", 0, 0, dst_x, dst_y, width, height);
++//fprintf(stderr, "non-shmA image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
++
++void releaseAllPressedModifiers(void) {
++ int i;
++ static int debug_release = -1;
++ if (debug_release < 0) {
++ if (getenv("SSVNC_DEBUG_RELEASE")) {
++ debug_release = 1;
++ } else {
++ debug_release = 0;
++ }
++ }
++ if (debug_release) fprintf(stderr, "into releaseAllPressedModifiers()\n");
++ for (i = 0; i < 256; i++) {
++ if (modifierPressed[i]) {
++ SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False);
++ modifierPressed[i] = False;
++ if (debug_release) fprintf(stderr, "releasing[%d] %s\n", i, XKeysymToString(XKeycodeToKeysym(dpy, i, 0)));
++ }
++ }
}
++#define PR_EXPOSE fprintf(stderr, "Expose: %04dx%04d+%04d+%04d %04d/%04d/%04d now: %8.4f rescale: %8.4f fullscreen: %8.4f\n", width, height, x, y, si.framebufferWidth, appData.yCrop, si.framebufferHeight, now - start_time, now - last_rescale, now - last_fullscreen);
-@@ -152,39 +534,53 @@
+ /*
+ * HandleBasicDesktopEvent - deal with expose and leave events.
+@@ -152,39 +1470,116 @@
static void
HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
{
- int i;
+ int i, x, y, width, height;
++ static double last_expose = 0.0;
++ double now = dnow();
- switch (ev->type) {
++ if (0) {
++ PR_EXPOSE;
++ }
++
+ switch (ev->type) {
case Expose:
case GraphicsExpose:
@@ -3080,11 +4755,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ width = ev->xexpose.width;
+ height = ev->xexpose.height;
+
-+//fprintf(stderr, "Expose: %dx%d+%d+%d\n", width, height, x, y);
-+ if (x + width > si.framebufferWidth) {
-+ width = si.framebufferWidth - x;
-+ if (width <= 0) {
-+ break;
++ if (image_scale) {
++ int i;
++ x /= scale_factor_x;
++ y /= scale_factor_y;
++ width /= scale_factor_x;
++ height /= scale_factor_y;
++ /* make them a little wider to avoid painting errors */
++ for (i=0; i < 3; i++) {
++ if (x > 0) x--;
++ if (y > 0) y--;
++ }
++ for (i=0; i < 6; i++) {
++ if (x + width < si.framebufferWidth) width++;
++ if (y + height < si.framebufferHeight) height++;
+ }
+ }
@@ -3092,7 +4776,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- ev->xexpose.width = si.framebufferWidth - ev->xexpose.x;
- if (ev->xexpose.width <= 0) break;
- }
--
++ if (x + width > si.framebufferWidth) {
++ width = si.framebufferWidth - x;
++ if (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;
@@ -3107,11 +4797,49 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y,
- ev->xexpose.width, ev->xexpose.height, False);
- break;
-+ if (appData.useBackingstore) {
++ if (appData.useXserverBackingStore) {
+ SendFramebufferUpdateRequest(x, y, width, height, False);
+ } else {
-+ put_image(x, y, x, y, width, height);
-+ XSync(dpy, False);
++ int ok = 1;
++ double delay = 2.5;
++ if (appData.fullScreen && now < last_fullscreen + delay) {
++ int xmax = si.framebufferWidth;
++ int ymax = si.framebufferHeight;
++ if (appData.yCrop > 0) {
++ ymax = appData.yCrop;
++ }
++ xmax = scale_round(xmax, scale_factor_x);
++ ymax = scale_round(ymax, scale_factor_y);
++ if (dpyWidth < xmax) {
++ xmax = dpyWidth;
++ }
++ if (dpyHeight < ymax) {
++ ymax = dpyHeight;
++ }
++ if (x != 0 && y != 0) {
++ ok = 0;
++ }
++ if (width < 0.9 * xmax) {
++ ok = 0;
++ }
++ if (height < 0.9 * ymax) {
++ ok = 0;
++ }
++ }
++ if (appData.yCrop > 0) {
++ if (now < last_fullscreen + delay || now < last_rescale + delay) {
++ if (y + height > appData.yCrop) {
++ height = appData.yCrop - y;
++ }
++ }
++ }
++ if (ok) {
++ put_image(x, y, x, y, width, height, 0);
++ XSync(dpy, False);
++ } else {
++ fprintf(stderr, "Skip ");
++ PR_EXPOSE;
++ }
+ }
+ break;
@@ -3123,11 +4851,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- }
- }
- break;
-+ for (i = 0; i < 256; i++) {
-+ if (modifierPressed[i]) {
-+ SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False);
-+ modifierPressed[i] = False;
-+ }
++ releaseAllPressedModifiers();
++ if (appData.fullScreen) {
++ fs_ungrab(1);
++ }
++ break;
++ case EnterNotify:
++ if (appData.fullScreen) {
++ fs_grab(1);
+ }
+ break;
}
@@ -3135,7 +4866,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
}
-@@ -201,6 +597,13 @@
+@@ -201,6 +1596,13 @@
* button2 down, 3 for both, etc).
*/
@@ -3149,7 +4880,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
void
SendRFBEvent(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
-@@ -208,12 +611,62 @@
+@@ -208,12 +1610,71 @@
char keyname[256];
int buttonMask, x, y;
@@ -3157,6 +4888,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- if (BumpScroll(ev))
- return;
- }
++ if (ev->type == MotionNotify || ev->type == KeyRelease) {
++ static double last = 0.0;
++ double now = dnow();
++ if (now > last + 0.25) {
++ check_things();
++ last = now;
++ }
++ }
++
+ if (appData.fullScreen && ev->type == MotionNotify) {
+ if (BumpScroll(ev)) {
+ return;
@@ -3217,7 +4957,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
if (*num_params != 0) {
if (strncasecmp(params[0],"key",3) == 0) {
-@@ -329,26 +782,161 @@
+@@ -245,8 +1706,8 @@
+ fprintf(stderr, "Invalid params: SendRFBEvent(fbupdate)\n");
+ return;
+ }
+- SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
+- si.framebufferHeight, False);
++ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
++
+ } else if (strcasecmp(params[0],"ptr") == 0) {
+ if (*num_params == 4) {
+ x = atoi(params[1]);
+@@ -329,26 +1790,185 @@
* CreateDotCursor.
*/
@@ -3284,7 +5035,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1);
+ XFreePixmap(dpy, src);
+ XFreePixmap(dpy, msk);
-+
+
+- return cursor;
+ return cursor;
+}
+#endif
@@ -3312,9 +5064,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+void
+FillScreen(int x, int y, int width, int height, unsigned long fill)
+{
-+ int bpp = image->bits_per_pixel;
-+ int Bpp = image->bits_per_pixel / 8;
-+ int Bpl = image->bytes_per_line;
++ XImage *im = image_scale ? image_scale : image;
++ int bpp = im->bits_per_pixel;
++ int Bpp = im->bits_per_pixel / 8;
++ int Bpl = im->bytes_per_line;
+ int h, widthInBytes = width * Bpp;
+ static char *buf = NULL;
+ static int buflen = 0;
@@ -3325,6 +5078,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ int b0, b1, b2;
+
+//fprintf(stderr, "FillImage bpp=%d %04dx%04d+%04d+%04d -- 0x%x\n", bpp, width, height, x, y, fill);
++ if (appData.chatOnly) {
++ return;
++ }
+
+ if (widthInBytes > buflen || !buf) {
+ if (buf) {
@@ -3356,46 +5112,65 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ *(uip+h) = (unsigned int) fill;
+ }
+ }
-
-- return cursor;
-+ scr = image->data + y * Bpl + x * Bpp;
++
++ scr = im->data + y * Bpl + x * Bpp;
+
+ for (h = 0; h < height; h++) {
+ memcpy(scr, buf, widthInBytes);
+ scr += Bpl;
+ }
-+ put_image(x, y, x, y, width, height);
++ put_image(x, y, x, y, width, height, 1);
+ maybe_sync(width, height);
+}
+
+void copy_rect(int x, int y, int width, int height, int src_x, int src_y) {
+ char *src, *dst;
+ int i;
-+ int Bpp = image->bits_per_pixel / 8;
-+ int Bpl = image->bytes_per_line;
++ XImage *im = image_scale ? image_scale : image;
++ int Bpp = im->bits_per_pixel / 8;
++ int Bpl = im->bytes_per_line;
++ int did2 = 0;
+
+//fprintf(stderr, "copy_rect: %04dx%04d+%04d+%04d -- %04d %04d Bpp=%d Bpl=%d\n", width, height, x, y, src_x, src_y, Bpp, Bpl);
++ copyrect2:
++
+ if (y < src_y) {
-+ src = image->data + src_y * Bpl + src_x * Bpp;
-+ dst = image->data + y * Bpl + x * Bpp;
++ src = im->data + src_y * Bpl + src_x * Bpp;
++ dst = im->data + y * Bpl + x * Bpp;
+ for (i = 0; i < height; i++) {
+ memmove(dst, src, Bpp * width);
+ src += Bpl;
+ dst += Bpl;
+ }
+ } else {
-+ src = image->data + (src_y + height - 1) * Bpl + src_x * Bpp;
-+ dst = image->data + (y + height - 1) * Bpl + x * Bpp;
++ src = im->data + (src_y + height - 1) * Bpl + src_x * Bpp;
++ dst = im->data + (y + height - 1) * Bpl + x * Bpp;
+ for (i = 0; i < height; i++) {
+ memmove(dst, src, Bpp * width);
+ src -= Bpl;
+ dst -= Bpl;
+ }
+ }
++
++ if (image_scale && !did2) {
++ im = image;
++ Bpp = im->bits_per_pixel / 8;
++ Bpl = im->bytes_per_line;
++
++ x *= scale_factor_x;
++ y *= scale_factor_y;
++ src_x *= scale_factor_x;
++ src_y *= scale_factor_y;
++ width = scale_round(width, scale_factor_x);
++ height = scale_round(height, scale_factor_y);
++
++ did2 = 1;
++ goto copyrect2;
++ }
}
-@@ -359,38 +947,35 @@
+@@ -359,38 +1979,37 @@
void
CopyDataToScreen(char *buf, int x, int y, int width, int height)
{
@@ -3406,6 +5181,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
-
- usleep(appData.rawDelay * 1000);
- }
++ if (appData.chatOnly) {
++ return;
++ }
+ if (appData.rawDelay != 0) {
+ XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
+ XSync(dpy,False);
@@ -3436,12 +5214,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ int h;
+ int widthInBytes = width * myFormat.bitsPerPixel / 8;
+ int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
++ XImage *im = image_scale ? image_scale : image;
+
-+ char *scr = (image->data + y * scrWidthInBytes
++ char *scr = (im->data + y * scrWidthInBytes
+ + x * myFormat.bitsPerPixel / 8);
+
-+//fprintf(stderr, "CopyDataToScreen %dx%d+%d+%d\n", width, height, x, y);
-+
+ for (h = 0; h < height; h++) {
+ memcpy(scr, buf, widthInBytes);
+ buf += widthInBytes;
@@ -3456,12 +5233,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
- }
-#endif
- XPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height);
-+ put_image(x, y, x, y, width, height);
++ put_image(x, y, x, y, width, height, 0);
+ maybe_sync(width, height);
}
-@@ -401,62 +986,228 @@
+@@ -401,62 +2020,295 @@
static void
CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height)
{
@@ -3478,11 +5255,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ int xoff = 7 - (x & 7);
+ int xcur;
+ int fbwb = si.framebufferWidth / 8;
-+ CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
++ XImage *im = image_scale ? image_scale : image;
++ CARD8 *scr1 = ((CARD8 *)im->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;
++ CARD8 *scr8 = ( (CARD8 *)im->data) + y * si.framebufferWidth + x;
++ CARD16 *scr16 = ((CARD16 *)im->data) + y * si.framebufferWidth + x;
++ CARD32 *scr32 = ((CARD32 *)im->data) + y * si.framebufferWidth + x;
+ int b0, b1, b2;
- switch (visbpp) {
@@ -3542,7 +5320,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ } else {
+ b0 = 2; b1 = 1; b2 = 0;
+ }
-+ scr8 = ((CARD8 *)image->data) + (y * si.framebufferWidth + x) * 3;
++ scr8 = ((CARD8 *)im->data) + (y * si.framebufferWidth + x) * 3;
+ for (q = 0; q < height; q++) {
+ for (p = 0; p < width; p++) {
+ CARD32 v = BGR233ToPixel[*(buf++)];
@@ -3583,7 +5361,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+{
+ int p, q;
+ int b0, b1, b2;
-+ unsigned char *scr= (unsigned char *)image->data + (y * si.framebufferWidth + x) * 3;
++ XImage *im = image_scale ? image_scale : image;
++ unsigned char *scr= (unsigned char *)im->data + (y * si.framebufferWidth + x) * 3;
+
+ if (isLSB) {
+ b0 = 0; b1 = 1; b2 = 2;
@@ -3625,7 +5404,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width, int height)
+{
+ int p, q;
-+ CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
++ XImage *im = image_scale ? image_scale : image;
++ CARD32 *scr32 = ((CARD32 *)im->data) + y * si.framebufferWidth + x;
+
+ if (visbpp == 24) {
+ BGR565_24bpp(buf, x, y, width, height);
@@ -3647,22 +5427,37 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ }
+ if (image && image->data) {
+ XDestroyImage(image);
++ fprintf(stderr, "reset_image: destroyed 'image'\n");
+ }
+ image = NULL;
+ if (image_ycrop && image_ycrop->data) {
+ XDestroyImage(image_ycrop);
++ fprintf(stderr, "reset_image: destroyed 'image_ycrop'\n");
+ }
+ image_ycrop = NULL;
++ if (image_scale && image_scale->data) {
++ XDestroyImage(image_scale);
++ fprintf(stderr, "reset_image: destroyed 'image_scale'\n");
++ }
++ image_scale = NULL;
++
+ create_image();
+ XFlush(dpy);
+}
+
+void ReDoDesktop(void) {
-+ int w, h, x, y, dw, dh;
++ int w, h, h0, x, y, dw, dh;
++ int fs = 0;
++ int autoscale = 0;
++
++ if (!appData.fullScreen && appData.scale != NULL && !strcmp(appData.scale, "auto")) {
++ autoscale = 1;
++ }
+
-+fprintf(stderr, "ReDoDesktop: ycrop: %d\n", appData.yCrop);
++ fprintf(stderr, "ReDoDesktop: ycrop: %d\n", appData.yCrop);
+
+ check_tall();
++
+ if (appData.yCrop) {
+ if (appData.yCrop < 0 || old_width <= 0) {
+ appData.yCrop = guessCrop();
@@ -3678,10 +5473,40 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ }
+ fprintf(stderr, "Using -ycrop: %d\n", appData.yCrop);
+ }
++
+ old_width = si.framebufferWidth;
+ old_height = si.framebufferHeight;
+
+ if (appData.fullScreen) {
++ if (prev_fb_width != si.framebufferWidth || prev_fb_height != si.framebufferHeight) {
++ int xmax = si.framebufferWidth;
++ int ymax = si.framebufferHeight;
++ if (appData.yCrop > 0) {
++ ymax = appData.yCrop;
++ }
++ if (scale_x > 0) {
++ xmax = scale_round(xmax, scale_factor_x);
++ ymax = scale_round(ymax, scale_factor_y);
++ }
++ if (xmax < dpyWidth || ymax < dpyHeight) {
++ FullScreenOff();
++ fs = 1;
++ }
++ }
++ }
++
++ prev_fb_width = si.framebufferWidth;
++ prev_fb_height = si.framebufferHeight;
++
++ if (appData.fullScreen) {
++
++ int xmax = si.framebufferWidth;
++ int ymax = si.framebufferHeight;
++ if (scale_x > 0) {
++ xmax = scale_round(xmax, scale_factor_x);
++ ymax = scale_round(ymax, scale_factor_y);
++ }
++
+ if (image && image->data) {
+ int len;
+ int h = image->height;
@@ -3692,7 +5517,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ XPutImage(dpy, XtWindow(desktop), gc, image, 0, 0, 0, 0, w, h);
+ XFlush(dpy);
+ }
-+ XtResizeWidget(desktop, si.framebufferWidth, si.framebufferHeight, 0);
++
++ /* XXX scaling?? */
++ XtResizeWidget(desktop, xmax, ymax, 0);
++
+ XSync(dpy, False);
+ usleep(100*1000);
+ FullScreenOn();
@@ -3707,11 +5535,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+
+ w = si.framebufferWidth;
+ h = si.framebufferHeight;
++ h0 = h;
+ if (appData.yCrop > 0) {
+ h = appData.yCrop;
-+ if (0 && appData.sbWidth <= 6 && appData.sbWidth > 0) {
-+ h += appData.sbWidth;
-+ }
++ }
++ if (image_scale) {
++ w = scale_round(w, scale_factor_x);
++ h = scale_round(h, scale_factor_y);
++ h0 = scale_round(h0, scale_factor_y);
+ }
+
+ if (w + dw >= dpyWidth) {
@@ -3721,41 +5552,130 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview
+ h = dpyHeight - dh;
+ }
+
-+ XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL);
++ if (!autoscale) {
++ XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL);
++ } else {
++ XtVaSetValues(toplevel, XtNmaxWidth, dpyWidth, XtNmaxHeight, dpyHeight, NULL);
++ }
+
-+ XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
-+ XtNheight, si.framebufferHeight, NULL);
++ XtVaSetValues(desktop, XtNwidth, w, XtNheight, h0, NULL);
+
+ x = (dpyWidth - w - dw)/2;
+ y = (dpyHeight - h - dh)/2;
+
-+ XtResizeWidget(desktop, si.framebufferWidth, si.framebufferHeight, 0);
++ XtResizeWidget(desktop, w, h0, 0);
+
+ if (appData.yCrop > 0) {
-+ XtVaSetValues(toplevel, XtNmaxHeight, appData.yCrop, NULL);
-+ XtVaSetValues(form, XtNmaxHeight, appData.yCrop, NULL);
++ int ycrop = appData.yCrop;
++ if (image_scale) {
++ ycrop *= scale_factor_y;
++ }
++ XtVaSetValues(toplevel, XtNmaxHeight, ycrop, NULL);
++ XtVaSetValues(form, XtNmaxHeight, ycrop, NULL);
+ }
+
-+ XtConfigureWidget(toplevel, x + dw, y + dh, w, h, 0);
++ if (!autoscale) {
++ XtConfigureWidget(toplevel, x + dw, y + dh, w, h, 0);
++ }
+
+ reset_image();
++
++ if (fs) {
++ FullScreenOn();
++ }
}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncviewer/dialogs.c
--- vnc_unixsrc.orig/vncviewer/dialogs.c 2000-10-26 15:19:19.000000000 -0400
-+++ vnc_unixsrc/vncviewer/dialogs.c 2008-02-16 19:04:46.000000000 -0500
-@@ -26,6 +26,208 @@
++++ vnc_unixsrc/vncviewer/dialogs.c 2008-10-10 15:46:43.000000000 -0400
+@@ -26,6 +26,299 @@
static Bool serverDialogDone = False;
static Bool passwordDialogDone = False;
+static Bool ycropDialogDone = False;
-+static Bool scbarDialogDone = False;
+static Bool scaleDialogDone = False;
++static Bool scbarDialogDone = False;
++static Bool scaleNDialogDone = False;
+static Bool qualityDialogDone = False;
+static Bool compressDialogDone = False;
+
+extern void popupFixer(Widget wid);
+
+void
++ScaleDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
++{
++ scaleDialogDone = True;
++}
++
++void dialog_over(Widget wid) {
++ if (appData.fullScreen) {
++ if (!net_wm_supported()) {
++ XtVaSetValues(wid, XtNoverrideRedirect, True, NULL);
++ XSync(dpy, True);
++ }
++ }
++}
++
++extern int XError_ign;
++
++void dialog_input(Widget wid) {
++ XError_ign = 1;
++ XSetInputFocus(dpy, XtWindow(wid), RevertToParent, CurrentTime);
++ XSync(dpy, False);
++ usleep(30 * 1000);
++ XSync(dpy, False);
++ usleep(20 * 1000);
++ XSync(dpy, False);
++ XError_ign = 0;
++}
++
++char *
++DoScaleDialog()
++{
++ Widget pshell, dialog;
++ char *scaleValue;
++ char *valueString;
++
++ pshell = XtVaCreatePopupShell("scaleDialog", transientShellWidgetClass,
++ toplevel, NULL);
++ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
++
++ dialog_over(pshell);
++
++ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
++ HeightOfScreen(XtScreen(pshell))*2/5);
++ XtPopup(pshell, XtGrabNonexclusive);
++ XtRealizeWidget(pshell);
++
++ if (appData.scale != NULL) {
++ String label;
++ char tmp[410];
++ XtVaGetValues(dialog, XtNlabel, &label, NULL);
++ if (strlen(label) + strlen(appData.scale) < 400) {
++ sprintf(tmp, "%s %s", label, appData.scale);
++ XtVaSetValues(dialog, XtNlabel, tmp, NULL);
++ }
++ }
++
++
++ if (appData.popupFix) {
++ popupFixer(pshell);
++ }
++ dialog_input(pshell);
++
++ scaleDialogDone = False;
++
++ while (!scaleDialogDone) {
++ XtAppProcessEvent(appContext, XtIMAll);
++ }
++
++ valueString = XawDialogGetValueString(dialog);
++ scaleValue = XtNewString(valueString);
++
++ XtPopdown(pshell);
++ return scaleValue;
++}
++
++void
+YCropDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ ycropDialogDone = True;
@@ -3772,6 +5692,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
++ dialog_over(pshell);
++
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
@@ -3780,6 +5702,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
++ dialog_input(pshell);
+
+ ycropDialogDone = False;
+
@@ -3811,6 +5734,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
++ dialog_over(pshell);
++
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
@@ -3819,6 +5744,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
++ dialog_input(pshell);
+
+ scbarDialogDone = False;
+
@@ -3834,22 +5760,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+}
+
+void
-+ScaleDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
++ScaleNDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
-+ scaleDialogDone = True;
++ scaleNDialogDone = True;
+}
+
+char *
-+DoScaleDialog()
++DoScaleNDialog()
+{
+ Widget pshell, dialog;
-+ char *scaleValue;
++ char *scaleNValue;
+ char *valueString;
+
-+ pshell = XtVaCreatePopupShell("scaleDialog", transientShellWidgetClass,
++ pshell = XtVaCreatePopupShell("scaleNDialog", transientShellWidgetClass,
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
++ dialog_over(pshell);
++
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
@@ -3858,18 +5786,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
++ dialog_input(pshell);
+
-+ scaleDialogDone = False;
++ scaleNDialogDone = False;
+
-+ while (!scaleDialogDone) {
++ while (!scaleNDialogDone) {
+ XtAppProcessEvent(appContext, XtIMAll);
+ }
+
+ valueString = XawDialogGetValueString(dialog);
-+ scaleValue = XtNewString(valueString);
++ scaleNValue = XtNewString(valueString);
+
+ XtPopdown(pshell);
-+ return scaleValue;
++ return scaleNValue;
+}
+
+void
@@ -3889,6 +5818,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
++ dialog_over(pshell);
++
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
@@ -3897,6 +5828,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
++ dialog_input(pshell);
+
+ qualityDialogDone = False;
+
@@ -3928,6 +5860,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
++ dialog_over(pshell);
++
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
@@ -3936,6 +5870,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
++ dialog_input(pshell);
+
+ compressDialogDone = False;
+
@@ -3952,31 +5887,47 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview
void
ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
-@@ -49,6 +251,10 @@
+@@ -44,11 +337,18 @@
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
++ dialog_over(pshell);
++
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
XtPopup(pshell, XtGrabNonexclusive);
XtRealizeWidget(pshell);
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
++ dialog_input(pshell);
+
serverDialogDone = False;
while (!serverDialogDone) {
-@@ -85,6 +291,10 @@
+@@ -80,11 +380,18 @@
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
++ dialog_over(pshell);
++
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
XtPopup(pshell, XtGrabNonexclusive);
XtRealizeWidget(pshell);
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
++ dialog_input(pshell);
+
passwordDialogDone = False;
while (!passwordDialogDone) {
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncviewer/fullscreen.c
--- vnc_unixsrc.orig/vncviewer/fullscreen.c 2003-10-09 05:23:49.000000000 -0400
-+++ vnc_unixsrc/vncviewer/fullscreen.c 2008-02-22 09:03:22.000000000 -0500
++++ vnc_unixsrc/vncviewer/fullscreen.c 2008-10-12 15:12:52.000000000 -0400
@@ -27,7 +27,9 @@
#include <X11/Xaw/Toggle.h>
@@ -3987,111 +5938,240 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncv
static XtIntervalId timer;
static Bool timerSet = False;
static Bool scrollLeft, scrollRight, scrollUp, scrollDown;
-@@ -85,10 +87,14 @@
- Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight;
- Position viewportX, viewportY;
+@@ -36,6 +38,7 @@
+ static Dimension scrollbarWidth, scrollbarHeight;
-+ Bool fsAlready = appData.fullScreen, toobig = False;
-+
- appData.fullScreen = True;
- if (si.framebufferWidth > dpyWidth || si.framebufferHeight > dpyHeight) {
-+ int eff_height = si.framebufferHeight;
++int scale_round(int len, double fac);
-+ toobig = True;
- XtVaSetValues(viewport, XtNforceBars, True, NULL);
- XtVaGetValues(viewport, XtNwidth, &oldViewportWidth,
- XtNheight, &oldViewportHeight, NULL);
-@@ -105,16 +111,23 @@
- toplevelWidth = dpyWidth;
- }
+ /*
+ * FullScreenOn goes into full-screen mode. It makes the toplevel window
+@@ -78,112 +81,450 @@
+ * variables so that FullScreenOff can use them.
+ */
+-void
+-FullScreenOn()
+-{
+- Dimension toplevelWidth, toplevelHeight;
+- Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight;
+- Position viewportX, viewportY;
+-
+- appData.fullScreen = True;
+-
+- if (si.framebufferWidth > dpyWidth || si.framebufferHeight > dpyHeight) {
+-
+- XtVaSetValues(viewport, XtNforceBars, True, NULL);
+- XtVaGetValues(viewport, XtNwidth, &oldViewportWidth,
+- XtNheight, &oldViewportHeight, NULL);
+- XtVaGetValues(XtNameToWidget(viewport, "clip"),
+- XtNwidth, &clipWidth, XtNheight, &clipHeight, NULL);
+-
+- scrollbarWidth = oldViewportWidth - clipWidth;
+- scrollbarHeight = oldViewportHeight - clipHeight;
+-
+- if (si.framebufferWidth > dpyWidth) {
+- viewportWidth = toplevelWidth = dpyWidth + scrollbarWidth;
+- } else {
+- viewportWidth = si.framebufferWidth + scrollbarWidth;
+- toplevelWidth = dpyWidth;
+- }
+-
- if (si.framebufferHeight > dpyHeight) {
-+ if (appData.yCrop > 0) {
-+ eff_height = appData.yCrop;
-+ }
-+
-+ if (eff_height > dpyHeight) {
- viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight;
- } else {
+- viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight;
+- } else {
- viewportHeight = si.framebufferHeight + scrollbarHeight;
-+ viewportHeight = eff_height + scrollbarHeight;
- toplevelHeight = dpyHeight;
- }
-
- } else {
- viewportWidth = si.framebufferWidth;
- viewportHeight = si.framebufferHeight;
-+ if (appData.yCrop > 0) {
-+ viewportHeight = appData.yCrop;
+- toplevelHeight = dpyHeight;
+- }
+-
+- } else {
+- viewportWidth = si.framebufferWidth;
+- viewportHeight = si.framebufferHeight;
+- toplevelWidth = dpyWidth;
+- toplevelHeight = dpyHeight;
+- }
++int net_wm_supported(void) {
++ unsigned char *data;
++ unsigned long items_read, items_left, i;
++ int ret, format;
++ Window wm;
++ Atom type;
++ Atom _NET_SUPPORTING_WM_CHECK;
++ Atom _NET_SUPPORTED;
++ Atom _NET_WM_STATE;
++ Atom _NET_WM_STATE_FULLSCREEN;
++
++ static time_t last_check = 0;
++ static int fs_supported = -1;
++
++ if (fs_supported >= 0 && time(NULL) < last_check + 600) {
++ static int first = 1;
++ if (first) {
++ fprintf(stderr, "fs_supported: %d\n", fs_supported);
++ }
++ first = 0;
++ return fs_supported;
+ }
- toplevelWidth = dpyWidth;
- toplevelHeight = dpyHeight;
- }
-@@ -129,7 +142,12 @@
- reparenting our window to the root. The window manager will get a
- ReparentNotify and hopefully clean up its frame window. */
-
-+if (! fsAlready) {
-+ XUnmapWindow(dpy, XtWindow(toplevel));
- XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL);
-+ XtVaSetValues(viewport, XtNoverrideRedirect, True, NULL);
-+ XtVaSetValues(desktop, XtNoverrideRedirect, True, NULL);
-+ XtVaSetValues(popup, XtNoverrideRedirect, True, NULL);
-
- XReparentWindow(dpy, XtWindow(toplevel), DefaultRootWindow(dpy), 0, 0);
-
-@@ -139,6 +157,8 @@
- with XReparentWindow. The last XSync seems to prevent losing
- focus, but I don't know why. */
- XSync(dpy, False);
-+XMapWindow(dpy, XtWindow(toplevel));
-+XRaiseWindow(dpy, XtWindow(toplevel));
- XMoveWindow(dpy, XtWindow(toplevel), 0, 0);
- XSync(dpy, False);
-
-@@ -164,25 +184,67 @@
++ last_check = time(NULL);
++
++ fs_supported = 0;
++
++ _NET_SUPPORTING_WM_CHECK = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
++ _NET_SUPPORTED = XInternAtom(dpy, "_NET_SUPPORTED", False);
++ _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False);
++ _NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
++
++ ret = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTING_WM_CHECK,
++ 0L, 1L, False, XA_WINDOW, &type, &format, &items_read, &items_left, &data);
++
++ if (ret != Success || !items_read) {
++ if (ret == Success) {
++ XFree(data);
++ }
++ return fs_supported;
++ }
++
++ wm = ((Window*) data)[0];
++ XFree(data);
++
++ ret = XGetWindowProperty(dpy, wm, _NET_SUPPORTING_WM_CHECK,
++ 0L, 1L, False, XA_WINDOW, &type, &format, &items_read, &items_left, &data);
++
++ if (ret != Success || !items_read) {
++ if (ret == Success) {
++ XFree(data);
++ }
++ return fs_supported;
++ }
++
++ if (wm != ((Window*) data)[0]) {
++ XFree(data);
++ return fs_supported;
++ }
++
++ ret = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTED,
++ 0L, 8192L, False, XA_ATOM, &type, &format, &items_read, &items_left, &data);
++
++ if (ret != Success || !items_read) {
++ if (ret == Success) {
++ XFree(data);
++ }
++ return fs_supported;
++ }
++
++ for (i=0; i < items_read; i++) {
++ if ( ((Atom*) data)[i] == _NET_WM_STATE_FULLSCREEN) {
++ fs_supported = 1;
++ }
++ }
++ XFree(data);
- XtManageChild(viewport);
+- viewportX = (toplevelWidth - viewportWidth) / 2;
+- viewportY = (toplevelHeight - viewportHeight) / 2;
++ return fs_supported;
++}
-- /* Now we can set "toplevel" to its proper size. */
-+} else {
++static void net_wm_fullscreen(int to_fs) {
++
++ int _NET_WM_STATE_REMOVE = 0;
++ int _NET_WM_STATE_ADD = 1;
++ int _NET_WM_STATE_TOGGLE = 2;
++ Atom _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False);
++ Atom _NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
++ XEvent xev;
++
++ if (to_fs == 2) {
++ XChangeProperty(dpy, XtWindow(toplevel), _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char*)&_NET_WM_STATE_FULLSCREEN, 1);
++ } else {
++ xev.xclient.type = ClientMessage;
++ xev.xclient.window = XtWindow(toplevel);
++ xev.xclient.message_type = _NET_WM_STATE;
++ xev.xclient.serial = 0;
++ xev.xclient.display = dpy;
++ xev.xclient.send_event = True;
++ xev.xclient.format = 32;
++ xev.xclient.data.l[0] = to_fs ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
++ xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
++ xev.xclient.data.l[2] = 0;
++ xev.xclient.data.l[3] = 0;
++ xev.xclient.data.l[4] = 0;
++ XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
++ }
+
+- /* We want to stop the window manager from managing our toplevel window.
+- This is not really a nice thing to do, so may not work properly with every
+- window manager. We do this simply by setting overrideRedirect and
+- reparenting our window to the root. The window manager will get a
+- ReparentNotify and hopefully clean up its frame window. */
+ XSync(dpy, False);
+}
-+ /* Now we can set "toplevel" to its proper size. */
- XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
+- XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL);
++time_t main_grab = 0;
-- /* Set the popup to overrideRedirect too */
-+if (fsAlready) {
-+ XtResizeWidget(viewport, viewportWidth, viewportHeight, 0);
-+ if (! toobig) {
-+ XtVaSetValues(viewport, XtNforceBars, False, NULL);
-+ }
-+ XMoveWindow(dpy, XtWindow(viewport), viewportX, viewportY);
-+ XSync(dpy, False);
+- XReparentWindow(dpy, XtWindow(toplevel), DefaultRootWindow(dpy), 0, 0);
++void fs_ungrab(int check) {
++ if (check) {
++ if (time(NULL) <= main_grab + 2) {
++ return;
++ }
++ if (net_wm_supported()) {
++ return;
++ }
++ }
++ fprintf(stderr, "calling fs_ungrab()\n");
++ if (appData.grabAll) { /* runge top of FullScreenOff */
++ fprintf(stderr, "calling XUngrabServer(dpy)\n");
++ XUngrabServer(dpy);
++ }
++ if (appData.grabKeyboard) {
++ fprintf(stderr, "calling XUngrabKeyboard(dpy)\n");
++ XtUngrabKeyboard(desktop, CurrentTime);
++ }
+}
-- XtVaSetValues(popup, XtNoverrideRedirect, True, NULL);
-+ /* Set the popup to overrideRedirect too */
-
- /* Try to get the input focus. */
-
-+#if 0
- XSetInputFocus(dpy, DefaultRootWindow(dpy), RevertToPointerRoot,
- CurrentTime);
-+#else
-+ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot,
-+ CurrentTime);
-+#endif
+- /* Some WMs does not obey x,y values of XReparentWindow; the window
+- is not placed in the upper, left corner. The code below fixes
+- this: It manually moves the window, after the Xserver is done
+- with XReparentWindow. The last XSync seems to prevent losing
+- focus, but I don't know why. */
+- XSync(dpy, False);
+- XMoveWindow(dpy, XtWindow(toplevel), 0, 0);
+- XSync(dpy, False);
+-
+- /* Now we want to fix the size of "viewport". We shouldn't just change it
+- directly. Instead we set "toplevel" to the required size (which should
+- propagate through "form" to "viewport"). Then we remove "viewport" from
+- being managed by "form", change its resources to position it and make sure
+- that "form" won't attempt to resize it, then ask "form" to manage it
+- again. */
+-
+- XtResizeWidget(toplevel, viewportWidth, viewportHeight, 0);
+-
+- XtUnmanageChild(viewport);
+-
+- XtVaSetValues(viewport,
+- XtNhorizDistance, viewportX,
+- XtNvertDistance, viewportY,
+- XtNleft, XtChainLeft,
+- XtNright, XtChainLeft,
+- XtNtop, XtChainTop,
+- XtNbottom, XtChainTop,
+- NULL);
++void fs_grab(int check) {
++ if (check) {
++ if (time(NULL) <= main_grab + 2) {
++ return;
++ }
++ if (net_wm_supported()) {
++ return;
++ }
++ }
+
-
- /* Optionally, grab the keyboard. */
-
-- if (appData.grabKeyboard &&
-- XtGrabKeyboard(desktop, True, GrabModeAsync,
-- GrabModeAsync, CurrentTime) != GrabSuccess) {
-- fprintf(stderr, "XtGrabKeyboard() failed.\n");
++ main_grab = time(NULL);
++
++ fprintf(stderr, "calling fs_grab()\n");
++
+#define FORCE_UP \
+ XSync(dpy, False); \
+ XUnmapWindow(dpy, XtWindow(toplevel)); \
@@ -4100,73 +6180,640 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncv
+ XRaiseWindow(dpy, XtWindow(toplevel)); \
+ XSync(dpy, False);
+
-+ if (appData.grabKeyboard && XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
-+ fprintf(stderr, "XtGrabKeyboard() failed.\n");
-+ XSync(dpy, False);
-+ usleep(200 * 1000);
-+ FORCE_UP
++ if (appData.grabKeyboard && XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
++ fprintf(stderr, "XtGrabKeyboard() failed.\n");
++ XSync(dpy, False);
++ usleep(100 * 1000);
++ FORCE_UP
+
-+ if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
-+ fprintf(stderr, "XtGrabKeyboard() failed again.\n");
-+ usleep(200 * 1000);
-+ XSync(dpy, True);
-+ if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
-+ fprintf(stderr, "XtGrabKeyboard() failed 3rd time.\n");
++ if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
++ fprintf(stderr, "XtGrabKeyboard() failed again.\n");
++ usleep(200 * 1000);
++ XSync(dpy, False);
++ if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
++ fprintf(stderr, "XtGrabKeyboard() failed 3rd time.\n");
++ } else {
++ fprintf(stderr, "XtGrabKeyboard() OK 3rd try.\n");
++ }
++ } else {
++ fprintf(stderr, "XtGrabKeyboard() OK 2nd try.\n");
++ }
++ XRaiseWindow(dpy, XtWindow(toplevel));
++ }
++
++ if (appData.grabAll) {
++ fprintf(stderr, "calling XGrabServer(dpy)\n");
++ if (! XGrabServer(dpy)) {
++ XSync(dpy, False);
++ usleep(100 * 1000);
++ fprintf(stderr, "calling XGrabServer(dpy) 2nd time\n");
++ if (!XGrabServer(dpy)) {
++ XSync(dpy, False);
++ usleep(200 * 1000);
++ fprintf(stderr, "calling XGrabServer(dpy) 3rd time\n");
++ if (XGrabServer(dpy)) {
++ fprintf(stderr, "XGrabServer(dpy) OK 3rd time\n");
++ }
++ } else {
++ fprintf(stderr, "XGrabServer(dpy) OK 2nd time\n");
++ }
++ XSync(dpy, False);
++ }
++ if (getenv("VNCVIEWER_FORCE_UP")) {
++ fprintf(stderr, "FORCE_UP\n");
++ FORCE_UP
++ }
++ }
++}
++
++extern int fullscreen_startup;
++extern double last_fullscreen;
++
++#define set_size_hints() \
++{ \
++ long supplied; \
++ XSizeHints *sizehints = XAllocSizeHints(); \
++ XGetWMSizeHints(dpy, topwin, sizehints, &supplied, XA_WM_NORMAL_HINTS); \
++ if (sizehints->base_width < toplevelWidth) { \
++ sizehints->base_width = toplevelWidth; \
++ } \
++ if (sizehints->base_height < toplevelHeight) { \
++ sizehints->base_height = toplevelHeight; \
++ } \
++ if (sizehints->max_width < toplevelWidth) { \
++ sizehints->max_width = toplevelWidth; \
++ } \
++ if (sizehints->max_height < toplevelHeight) { \
++ sizehints->max_height = toplevelHeight; \
++ } \
++ XSetWMSizeHints(dpy, topwin, sizehints, XA_WM_NORMAL_HINTS); \
++ XFree(sizehints); \
++}
+
+- XtManageChild(viewport);
++extern int scale_x, scale_y;
++extern double scale_factor_y;
++
++void
++FullScreenOn()
++{
++ Dimension toplevelWidth, toplevelHeight;
++ Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight;
++ Position viewportX, viewportY;
++ int do_net_wm = net_wm_supported();
++ int fbW = si.framebufferWidth;
++ int fbH = si.framebufferHeight;
++ int eff_height;
++
++ Bool fsAlready = appData.fullScreen, toobig = False;
++ Window topwin = XtWindow(toplevel);
++
++ appData.fullScreen = True;
++
++ last_fullscreen = dnow();
++
++ if (scale_x > 0) {
++ fbW = scale_x;
++ fbH = scale_y;
++ }
++
++ eff_height = fbH;
++ if (appData.yCrop > 0) {
++ eff_height = appData.yCrop;
++ if (scale_y > 0) {
++ eff_height = scale_round(eff_height, scale_factor_y);
++ }
++ }
++
++ if (fbW > dpyWidth || eff_height > dpyHeight) {
++
++ toobig = True;
++
++ /*
++ * This is a crazy thing to have the scrollbars hang
++ * just a bit offscreen to the right and below. the user
++ * will not see them and bumpscroll will work.
++ */
++
++ XtVaSetValues(viewport, XtNforceBars, True, NULL);
++ XtVaGetValues(viewport, XtNwidth, &oldViewportWidth, XtNheight, &oldViewportHeight, NULL);
++ XtVaGetValues(XtNameToWidget(viewport, "clip"), XtNwidth, &clipWidth, XtNheight, &clipHeight, NULL);
++
++ scrollbarWidth = oldViewportWidth - clipWidth;
++ scrollbarHeight = oldViewportHeight - clipHeight;
++
++ if (fbW > dpyWidth) {
++ viewportWidth = toplevelWidth = dpyWidth + scrollbarWidth;
++ } else {
++ viewportWidth = fbW + scrollbarWidth;
++ toplevelWidth = dpyWidth;
++ }
++
++ if (eff_height > dpyHeight) {
++ viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight;
+ } else {
-+ fprintf(stderr, "XtGrabKeyboard() OK 3rd try.\n");
++ viewportHeight = eff_height + scrollbarHeight;
++ toplevelHeight = dpyHeight;
+ }
++ if (do_net_wm) {
++ /* but for _NET_WM we make toplevel be correct dpy size */
++ toplevelWidth = dpyWidth;
++ toplevelHeight = dpyHeight;
++ }
++
+ } else {
-+ fprintf(stderr, "XtGrabKeyboard() OK 2nd try.\n");
++ viewportWidth = fbW;
++ viewportHeight = eff_height;
++ toplevelWidth = dpyWidth;
++ toplevelHeight = dpyHeight;
+ }
-+ XRaiseWindow(dpy, XtWindow(toplevel));
-+ } else if (appData.grabAll) { /* runge bot of FullScreenOn */
-+ fprintf(stderr, "calling XGrabServer(dpy)\n");
-+ XGrabServer(dpy);
- }
+
+- /* Now we can set "toplevel" to its proper size. */
++ viewportX = (toplevelWidth - viewportWidth) / 2;
++ viewportY = (toplevelHeight - viewportHeight) / 2;
+
+- XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
++ if (viewportX < 0) viewportX = 0;
++ if (viewportY < 0) viewportY = 0;
+
+- /* Set the popup to overrideRedirect too */
+
+- XtVaSetValues(popup, XtNoverrideRedirect, True, NULL);
++ /* We want to stop the window manager from managing our toplevel window.
++ This is not really a nice thing to do, so may not work properly with every
++ window manager. We do this simply by setting overrideRedirect and
++ reparenting our window to the root. The window manager will get a
++ ReparentNotify and hopefully clean up its frame window. */
+
+- /* Try to get the input focus. */
++ if (! fsAlready) {
++ if (!do_net_wm) {
++ /* added to try to raise it on top for some cirumstances */
++ XUnmapWindow(dpy, topwin);
++
++ XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL);
++ //XtVaSetValues(viewport, XtNoverrideRedirect, True, NULL);
++ //XtVaSetValues(desktop, XtNoverrideRedirect, True, NULL);
++ XtVaSetValues(popup, XtNoverrideRedirect, True, NULL);
++
++ XReparentWindow(dpy, topwin, DefaultRootWindow(dpy), 0, 0);
++
++ /* Some WMs does not obey x,y values of XReparentWindow; the window
++ is not placed in the upper, left corner. The code below fixes
++ this: It manually moves the window, after the Xserver is done
++ with XReparentWindow. The last XSync seems to prevent losing
++ focus, but I don't know why. */
++
++ XSync(dpy, False);
++
++ /* added to try to raise it on top for some cirumstances */
++ XMapRaised(dpy, topwin);
++
++ XMoveWindow(dpy, topwin, 0, 0);
++ XSync(dpy, False);
++ }
++
++ /* Now we want to fix the size of "viewport". We shouldn't just change it
++ directly. Instead we set "toplevel" to the required size (which should
++ propagate through "form" to "viewport"). Then we remove "viewport" from
++ being managed by "form", change its resources to position it and make sure
++ that "form" won't attempt to resize it, then ask "form" to manage it
++ again. */
++
++ XtResizeWidget(toplevel, viewportWidth, viewportHeight, 0);
++
++ XtUnmanageChild(viewport);
++
++ XtVaSetValues(viewport,
++ XtNhorizDistance, viewportX,
++ XtNvertDistance, viewportY,
++ XtNleft, XtChainLeft,
++ XtNright, XtChainLeft,
++ XtNtop, XtChainTop,
++ XtNbottom, XtChainTop,
++ NULL);
++
++ XtManageChild(viewport);
++ XSync(dpy, False);
++ } else {
++ XSync(dpy, False);
++ }
++
++ /* Now we can set "toplevel" to its proper size. */
++
++// XtVaSetValues(toplevel, XtNwidth, toplevelWidth, XtNheight, toplevelHeight, NULL);
++// XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
++ XResizeWindow(dpy, topwin, toplevelWidth, toplevelHeight);
++
++ if (do_net_wm) {
++ XWindowAttributes attr;
++ int ok = 0, i, delay = 20;
++
++ usleep(delay * 1000);
++
++#define GSIZE() \
++ XGetWindowAttributes(dpy, topwin, &attr);
++
++#define PSIZE(s) \
++ XSync(dpy, False); \
++ XGetWindowAttributes(dpy, topwin, &attr); \
++ fprintf(stderr, "%s %dx%d+%d+%d\n", s, attr.width, attr.height, attr.x, attr.y);
++
++ PSIZE("size-A:");
++
++ set_size_hints();
++
++ net_wm_fullscreen(1);
++
++ PSIZE("size-B:");
++
++ for (i=0; i < 30; i++) {
++ usleep(delay * 1000);
++ GSIZE();
++ fprintf(stderr, "size[%d] %dx%d+%d+%d\n", i, attr.width, attr.height, attr.x, attr.y);
++ if (attr.width == toplevelWidth && attr.height == toplevelHeight) {
++ ok = 1;
++ fprintf(stderr, "size ok.\n");
++ XSync(dpy, False);
++ break;
++ }
++ set_size_hints();
++ XResizeWindow(dpy, topwin, toplevelWidth, toplevelHeight);
++ XMoveWindow(dpy, topwin, 0, 0);
++ XSync(dpy, False);
++ }
++
++ PSIZE("size-C:");
++ }
++
++ fprintf(stderr, "\ntoplevel: %dx%d viewport: %dx%d\n", toplevelWidth, toplevelHeight, viewportWidth, viewportHeight);
++
++#if defined (__SVR4) && defined (__sun)
++ if (!do_net_wm) {
++ /* CDE */
++ XSync(dpy, False);
++ usleep(200 * 1000);
++ XMoveWindow(dpy, topwin, 0, 0);
++ XMapRaised(dpy, topwin);
++ XSync(dpy, False);
++ }
++#endif
++
++ if (fsAlready) {
++ XtResizeWidget(viewport, viewportWidth, viewportHeight, 0);
++ if (! toobig) {
++ XtVaSetValues(viewport, XtNforceBars, False, NULL);
++ }
++ XMoveWindow(dpy, topwin, viewportX, viewportY);
++ XSync(dpy, False);
++ }
++
++ /* Try to get the input focus. */
+
+- XSetInputFocus(dpy, DefaultRootWindow(dpy), RevertToPointerRoot,
+- CurrentTime);
++ // original vnc: DefaultRootWindow(dpy) instead of PointerRoot
++ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+
+- /* Optionally, grab the keyboard. */
++ /* Optionally, grab the keyboard. */
++ fs_grab(0);
+
+- if (appData.grabKeyboard &&
+- XtGrabKeyboard(desktop, True, GrabModeAsync,
+- GrabModeAsync, CurrentTime) != GrabSuccess) {
+- fprintf(stderr, "XtGrabKeyboard() failed.\n");
+- }
++ /* finally done. */
}
-@@ -210,8 +272,14 @@
- appData.fullScreen = False;
+@@ -205,28 +546,52 @@
+ void
+ FullScreenOff()
+ {
+- int toplevelWidth = si.framebufferWidth;
+- int toplevelHeight = si.framebufferHeight;
+-
+- appData.fullScreen = False;
++ int toplevelWidth, toplevelHeight;
++ int do_net_wm = net_wm_supported();
++ int fbW = si.framebufferWidth;
++ int fbH = si.framebufferHeight;
++ int eff_height;
++
++ appData.fullScreen = False;
++
++ last_fullscreen = dnow();
++
++ if (scale_x > 0) {
++ fbW = scale_x;
++ fbH = scale_y;
++ }
++
++ eff_height = fbH;
++ if (appData.yCrop > 0) {
++ eff_height = appData.yCrop;
++ if (scale_y > 0) {
++ eff_height = scale_round(eff_height, scale_factor_y);
++ }
++ }
++
++ toplevelWidth = fbW;
++ toplevelHeight = eff_height;
++
++ fs_ungrab(0);
++
++ if (do_net_wm) {
++ net_wm_fullscreen(0);
++ } else {
++ XtUnmapWidget(toplevel);
++ }
- if (appData.grabKeyboard)
- XtUngrabKeyboard(desktop, CurrentTime);
+-
+- XtUnmapWidget(toplevel);
+-
+- XtResizeWidget(toplevel,
++ XtResizeWidget(toplevel,
+ viewportWidth - scrollbarWidth,
+ viewportHeight - scrollbarHeight, 0);
+- XtResizeWidget(viewport,
++ XtResizeWidget(viewport,
+ viewportWidth - scrollbarWidth,
+ viewportHeight - scrollbarHeight, 0);
+
+- XtVaSetValues(viewport, XtNforceBars, False, NULL);
++ XtVaSetValues(viewport, XtNforceBars, False, NULL);
+
+- XtUnmanageChild(viewport);
++ XtUnmanageChild(viewport);
+
+- XtVaSetValues(viewport,
++ XtVaSetValues(viewport,
+ XtNhorizDistance, 0,
+ XtNvertDistance, 0,
+ XtNleft, XtChainLeft,
+@@ -235,24 +600,40 @@
+ XtNbottom, XtChainBottom,
+ NULL);
+
+- XtManageChild(viewport);
+-
+- XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL);
+-
+- if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth)
+- toplevelWidth = dpyWidth - appData.wmDecorationWidth;
+-
+- if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight)
+- toplevelHeight = dpyHeight - appData.wmDecorationHeight;
+-
+- XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
+-
+- XtMapWidget(toplevel);
+- XSync(dpy, False);
++ XtManageChild(viewport);
+
+- /* Set the popup back to non-overrideRedirect */
+-
+- XtVaSetValues(popup, XtNoverrideRedirect, False, NULL);
++ if (!do_net_wm) {
++ XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL);
++ //XtVaSetValues(viewport, XtNoverrideRedirect, False, NULL);
++ //XtVaSetValues(desktop, XtNoverrideRedirect, False, NULL);
++ XtVaSetValues(popup, XtNoverrideRedirect, False, NULL);
++ }
+
-+ if (appData.grabAll) { /* runge top of FullScreenOff */
-+ fprintf(stderr, "calling XUngrabServer(dpy)\n");
-+ XUngrabServer(dpy);
-+ }
-+ if (appData.grabKeyboard) {
-+ XtUngrabKeyboard(desktop, CurrentTime);
-+ }
++ if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth)
++ toplevelWidth = dpyWidth - appData.wmDecorationWidth;
++
++ if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight)
++ toplevelHeight = dpyHeight - appData.wmDecorationHeight;
++
++ XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
++
++ if (!do_net_wm) {
++ XtMapWidget(toplevel);
++ }
++ XSync(dpy, False);
++
++ /* Set the popup back to non-overrideRedirect */
++
++ XtVaSetValues(popup, XtNoverrideRedirect, False, NULL);
++
++ if (!do_net_wm) {
++ int x = (dpyWidth - toplevelWidth) / 2;
++ int y = (dpyHeight - toplevelHeight) / 2;
++ if (x > 0 && y > 0) {
++ XSync(dpy, False);
++ XMoveWindow(dpy, XtWindow(toplevel), x, y);
++ }
++ }
+ }
+
- XtUnmapWidget(toplevel);
+@@ -264,10 +645,11 @@
+ void
+ SetFullScreenState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+ {
+- if (appData.fullScreen)
+- XtVaSetValues(w, XtNstate, True, NULL);
+- else
+- XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.fullScreen) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+ }
-@@ -238,6 +306,9 @@
- XtManageChild(viewport);
- XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL);
-+ XtVaSetValues(viewport, XtNoverrideRedirect, False, NULL);
-+ XtVaSetValues(desktop, XtNoverrideRedirect, False, NULL);
-+ XtVaSetValues(popup, XtNoverrideRedirect, False, NULL);
+@@ -278,11 +660,11 @@
+ void
+ ToggleFullScreen(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+ {
+- if (appData.fullScreen) {
+- FullScreenOff();
+- } else {
+- FullScreenOn();
+- }
++ if (appData.fullScreen) {
++ FullScreenOff();
++ } else {
++ FullScreenOn();
++ }
+ }
- if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth)
- toplevelWidth = dpyWidth - appData.wmDecorationWidth;
-@@ -345,7 +416,9 @@
- }
- if (scrollDown) {
-- if (desktopY < si.framebufferHeight - dpyHeight) {
-+ if (appData.yCrop > 0 && desktopY + dpyHeight >= appData.yCrop) {
-+ ;
-+ } else if (desktopY < si.framebufferHeight - dpyHeight) {
- desktopY += appData.bumpScrollPixels;
- if (desktopY > si.framebufferHeight - dpyHeight)
- desktopY = si.framebufferHeight - dpyHeight;
-@@ -375,3 +448,115 @@
+@@ -294,84 +676,220 @@
+ Bool
+ BumpScroll(XEvent *ev)
{
- DoBumpScroll();
+- scrollLeft = scrollRight = scrollUp = scrollDown = False;
++ scrollLeft = scrollRight = scrollUp = scrollDown = False;
+
+- if (ev->xmotion.x_root >= dpyWidth - 3)
+- scrollRight = True;
+- else if (ev->xmotion.x_root <= 2)
+- scrollLeft = True;
+-
+- if (ev->xmotion.y_root >= dpyHeight - 3)
+- scrollDown = True;
+- else if (ev->xmotion.y_root <= 2)
+- scrollUp = True;
+-
+- if (scrollLeft || scrollRight || scrollUp || scrollDown) {
+- if (timerSet)
+- return True;
+-
+- XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL);
+- desktopX = -desktopX;
+- desktopY = -desktopY;
+-
+- return DoBumpScroll();
+- }
+-
+- if (timerSet) {
+- XtRemoveTimeOut(timer);
+- timerSet = False;
+- }
++ if (ev->xmotion.x_root >= dpyWidth - 3)
++ scrollRight = True;
++ else if (ev->xmotion.x_root <= 2)
++ scrollLeft = True;
++
++ if (ev->xmotion.y_root >= dpyHeight - 3)
++ scrollDown = True;
++ else if (ev->xmotion.y_root <= 2)
++ scrollUp = True;
++
++ if (scrollLeft || scrollRight || scrollUp || scrollDown) {
++ if (timerSet)
++ return True;
++
++ XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL);
++ desktopX = -desktopX;
++ desktopY = -desktopY;
++
++ return DoBumpScroll();
++ }
++
++ if (timerSet) {
++ XtRemoveTimeOut(timer);
++ timerSet = False;
++ }
+
+- return False;
++ return False;
}
+
+ static Bool
+ DoBumpScroll()
+ {
+- int oldx = desktopX, oldy = desktopY;
+-
+- if (scrollRight) {
+- if (desktopX < si.framebufferWidth - dpyWidth) {
+- desktopX += appData.bumpScrollPixels;
+- if (desktopX > si.framebufferWidth - dpyWidth)
+- desktopX = si.framebufferWidth - dpyWidth;
+- }
+- } else if (scrollLeft) {
+- if (desktopX > 0) {
+- desktopX -= appData.bumpScrollPixels;
+- if (desktopX < 0)
+- desktopX = 0;
+- }
+- }
+-
+- if (scrollDown) {
+- if (desktopY < si.framebufferHeight - dpyHeight) {
+- desktopY += appData.bumpScrollPixels;
+- if (desktopY > si.framebufferHeight - dpyHeight)
+- desktopY = si.framebufferHeight - dpyHeight;
+- }
+- } else if (scrollUp) {
+- if (desktopY > 0) {
+- desktopY -= appData.bumpScrollPixels;
+- if (desktopY < 0)
+- desktopY = 0;
+- }
+- }
+-
+- if (oldx != desktopX || oldy != desktopY) {
+- XawViewportSetCoordinates(viewport, desktopX, desktopY);
+- timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime,
+- BumpScrollTimerCallback, NULL);
+- timerSet = True;
+- return True;
+- }
++ int oldx = desktopX, oldy = desktopY;
++ int fbW = si.framebufferWidth;
++ int fbH = si.framebufferHeight;
++
++ if (scale_x > 0) {
++ fbW = scale_x;
++ fbH = scale_y;
++ }
++
++ if (scrollRight) {
++ if (desktopX < fbW - dpyWidth) {
++ desktopX += appData.bumpScrollPixels;
++ if (desktopX > fbW - dpyWidth) {
++ desktopX = fbW - dpyWidth;
++ }
++ }
++ } else if (scrollLeft) {
++ if (desktopX > 0) {
++ desktopX -= appData.bumpScrollPixels;
++ if (desktopX < 0) {
++ desktopX = 0;
++ }
++ }
++ }
++
++ if (scrollDown) {
++ int ycrop = appData.yCrop;
++ if (scale_y > 0) {
++ ycrop = scale_round(ycrop, scale_factor_y);
++ }
++ if (ycrop > 0 && desktopY + dpyHeight >= ycrop) {
++ ;
++ } else if (desktopY < fbH - dpyHeight) {
++ desktopY += appData.bumpScrollPixels;
++ if (desktopY > fbH - dpyHeight) {
++ desktopY = fbH - dpyHeight;
++ }
++ }
++ } else if (scrollUp) {
++ if (desktopY > 0) {
++ desktopY -= appData.bumpScrollPixels;
++ if (desktopY < 0) {
++ desktopY = 0;
++ }
++ }
++ }
++
++ if (oldx != desktopX || oldy != desktopY) {
++ XawViewportSetCoordinates(viewport, desktopX, desktopY);
++ timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime, BumpScrollTimerCallback, NULL);
++ timerSet = True;
++ return True;
++ }
+
+- timerSet = False;
+- return False;
++ timerSet = False;
++ return False;
+ }
+
+ static void
+ BumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id)
+ {
+- DoBumpScroll();
++ DoBumpScroll();
++}
+
+/* not working: */
+
@@ -4216,14 +6863,22 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncv
+static Bool
+DoJumpScroll() {
+ int oldx = desktopX, oldy = desktopY;
-+ int jumpH = si.framebufferWidth / 4;
-+ int jumpV = si.framebufferHeight / 4;
++ int jumpH, jumpV;
++ int fbW = si.framebufferWidth;
++ int fbH = si.framebufferHeight;
++
++ if (scale_x > 0) {
++ fbW = scale_x;
++ fbH = scale_y;
++ }
++ jumpH = fbW / 4;
++ jumpV = fbH / 4;
+
+ if (scrollRight) {
-+ if (desktopX < si.framebufferWidth - dpyWidth) {
++ if (desktopX < fbW - dpyWidth) {
+ desktopX += jumpH;
-+ if (desktopX > si.framebufferWidth - dpyWidth)
-+ desktopX = si.framebufferWidth - dpyWidth;
++ if (desktopX > fbW - dpyWidth)
++ desktopX = fbW - dpyWidth;
+ }
+ } else if (scrollLeft) {
+ if (desktopX > 0) {
@@ -4236,10 +6891,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncv
+ if (scrollDown) {
+ if (appData.yCrop > 0 && desktopY + dpyHeight >= appData.yCrop) {
+ ;
-+ } else if (desktopY < si.framebufferHeight - dpyHeight) {
++ } else if (desktopY < fbH - dpyHeight) {
+ desktopY += jumpV;
-+ if (desktopY > si.framebufferHeight - dpyHeight)
-+ desktopY = si.framebufferHeight - dpyHeight;
++ if (desktopY > fbH - dpyHeight)
++ desktopY = fbH - dpyHeight;
+ }
+ } else if (scrollUp) {
+ if (desktopY > 0) {
@@ -4273,7 +6928,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncv
+}
+void JumpUp(Widget w, XEvent *ev, String *params, Cardinal *num_params) {
+ JumpScroll(1, 1);
-+}
+ }
+void JumpDown(Widget w, XEvent *ev, String *params, Cardinal *num_params) {
+ JumpScroll(0, 1);
+}
@@ -4295,7 +6950,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/h2html.pl vnc_unixsrc/vncview
+}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncviewer/hextile.c
--- vnc_unixsrc.orig/vncviewer/hextile.c 2007-02-17 22:33:46.000000000 -0500
-+++ vnc_unixsrc/vncviewer/hextile.c 2007-02-17 22:48:39.000000000 -0500
++++ vnc_unixsrc/vncviewer/hextile.c 2008-10-05 15:16:24.000000000 -0400
@@ -30,6 +30,18 @@
#define CARDBPP CONCAT2E(CARD,BPP)
#define GET_PIXEL CONCAT2E(GET_PIXEL,BPP)
@@ -4304,7 +6959,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncview
+ { \
+ XGCValues _gcv; \
+ _gcv.foreground = color; \
-+ if (!appData.useBackingstore) { \
++ if (!appData.useXserverBackingStore) { \
+ FillScreen(x, y, w, h, _gcv.foreground); \
+ } else { \
+ XChangeGC(dpy, gc, GCForeground, &_gcv); \
@@ -4420,8 +7075,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncview
+#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewer/listen.c
--- vnc_unixsrc.orig/vncviewer/listen.c 2001-01-16 03:07:57.000000000 -0500
-+++ vnc_unixsrc/vncviewer/listen.c 2008-09-07 11:23:30.000000000 -0400
-@@ -58,6 +58,8 @@
++++ vnc_unixsrc/vncviewer/listen.c 2008-09-26 15:43:23.000000000 -0400
+@@ -32,6 +32,7 @@
+ #define FLASHDELAY 1 /* seconds */
+
+ Bool listenSpecified = False;
++pid_t listenParent = 0;
+ int listenPort = 0, flashPort = 0;
+
+ static Font flashFont;
+@@ -58,8 +59,11 @@
int n;
int i;
char *displayname = NULL;
@@ -4429,12 +7092,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe
+ int totalconn = 0, maxconn = 0;
listenSpecified = True;
++ listenParent = getpid();
+
+ for (i = 1; i < *argc; i++) {
+ if (strcmp(argv[i], "-display") == 0 && i+1 < *argc) {
+@@ -108,23 +112,40 @@
+ exit(1);
+ }
-@@ -111,20 +113,36 @@
- getFlashFont(d);
+- getFlashFont(d);
++//getFlashFont(d);
listenSocket = ListenAtTcpPort(listenPort);
- flashSocket = ListenAtTcpPort(flashPort);
++
+//flashSocket = ListenAtTcpPort(flashPort);
+ flashSocket = 1234;
@@ -4472,7 +7143,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe
/* discard any X events */
while (XCheckIfEvent(d, &ev, AllXEventsPredicate, NULL))
-@@ -132,12 +150,24 @@
+@@ -132,12 +153,24 @@
FD_ZERO(&fds);
@@ -4498,7 +7169,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe
if (FD_ISSET(flashSocket, &fds)) {
sock = AcceptTcpConnection(flashSocket);
-@@ -151,11 +181,48 @@
+@@ -151,11 +184,48 @@
}
close(sock);
}
@@ -4550,7 +7221,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe
XCloseDisplay(d);
-@@ -175,6 +242,7 @@
+@@ -170,18 +240,23 @@
+ case 0:
+ /* child - return to caller */
+ close(listenSocket);
+- close(flashSocket);
++// close(flashSocket);
+ return;
default:
/* parent - go round and listen again */
@@ -4558,10 +7235,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe
close(rfbsock);
if (!(d = XOpenDisplay(displayname))) {
fprintf(stderr,"%s: unable to open display %s\n",
-@@ -182,6 +250,10 @@
+ programName, XDisplayName(displayname));
exit(1);
}
- getFlashFont(d);
+- getFlashFont(d);
++// getFlashFont(d);
+ fprintf(stderr,"\n\n%s -listen: Listening on port %d\n",
+ programName,listenPort);
+ fprintf(stderr,"%s -listen: Cmdline errors are not reported until "
@@ -4569,21 +7247,451 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe
break;
}
}
+@@ -200,6 +275,13 @@
+ char **fontNames;
+ int nFontNames;
+
++#if 1
++
++ /* no longer used */
++ return;
++
++#else
++
+ sprintf(fontName,"-*-courier-bold-r-*-*-%d-*-*-*-*-*-iso8859-1",
+ FLASHWIDTH);
+ fontNames = XListFonts(d, fontName, 1, &nFontNames);
+@@ -209,6 +291,9 @@
+ sprintf(fontName,"fixed");
+ }
+ flashFont = XLoadFont(d, fontName);
++
++#endif
++
+ }
+
+
+@@ -222,6 +307,11 @@
+ Window w1, w2, w3, w4;
+ XSetWindowAttributes attr;
+
++#if 1
++ /* no longer used */
++ return;
++#else
++
+ XBell(d, 0);
+
+ XForceScreenSaver(d, ScreenSaverReset);
+@@ -284,6 +374,9 @@
+ XDestroyWindow(d, w3);
+ XDestroyWindow(d, w4);
+ XFlush(d);
++
++#endif
++
+ }
+
+ /*
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/misc.c
--- vnc_unixsrc.orig/vncviewer/misc.c 2003-01-15 02:58:32.000000000 -0500
-+++ vnc_unixsrc/vncviewer/misc.c 2007-05-26 13:29:19.000000000 -0400
-@@ -287,6 +287,7 @@
- if (appData.useShm)
- ShmCleanup();
++++ vnc_unixsrc/vncviewer/misc.c 2008-10-14 22:32:04.000000000 -0400
+@@ -33,12 +33,14 @@
+
+ Dimension dpyWidth, dpyHeight;
+ Atom wmDeleteWindow, wmState;
++int fullscreen_startup = 0;
+
+ static Bool xloginIconified = False;
+ static XErrorHandler defaultXErrorHandler;
+ static XIOErrorHandler defaultXIOErrorHandler;
+ static XtErrorHandler defaultXtErrorHandler;
+
++int XError_ign = 0;
+
+ /*
+ * ToplevelInitBeforeRealization sets the title, geometry and other resources
+@@ -48,87 +50,103 @@
+ void
+ ToplevelInitBeforeRealization()
+ {
+- char *titleFormat;
+- char *title;
+- char *geometry;
+-
+- XtVaGetValues(toplevel, XtNtitle, &titleFormat, NULL);
+- title = XtMalloc(strlen(titleFormat) + strlen(desktopName) + 1);
+- sprintf(title, titleFormat, desktopName);
+- XtVaSetValues(toplevel, XtNtitle, title, XtNiconName, title, NULL);
+-
+- XtVaSetValues(toplevel, XtNmaxWidth, si.framebufferWidth,
+- XtNmaxHeight, si.framebufferHeight, NULL);
+-
+- dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
+- dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
+-
+- if (appData.fullScreen) {
+-
+- /* full screen - set position to 0,0, but defer size calculation until
+- widgets are realized */
+-
+- XtVaSetValues(toplevel, XtNoverrideRedirect, True,
+- XtNgeometry, "+0+0", NULL);
+-
+- } else {
+-
+- /* not full screen - work out geometry for middle of screen unless
+- specified by user */
+-
+- XtVaGetValues(toplevel, XtNgeometry, &geometry, NULL);
+-
+- if (geometry == NULL) {
+- Dimension toplevelX, toplevelY;
+- Dimension toplevelWidth = si.framebufferWidth;
+- Dimension toplevelHeight = si.framebufferHeight;
+-
+- if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth)
+- toplevelWidth = dpyWidth - appData.wmDecorationWidth;
+-
+- if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight)
+- toplevelHeight = dpyHeight - appData.wmDecorationHeight;
+-
+- toplevelX = (dpyWidth - toplevelWidth - appData.wmDecorationWidth) / 2;
+-
+- toplevelY = (dpyHeight - toplevelHeight - appData.wmDecorationHeight) /2;
+-
+- /* set position via "geometry" so that window manager thinks it's a
+- user-specified position and therefore honours it */
+-
+- geometry = XtMalloc(256);
+-
+- sprintf(geometry, "%dx%d+%d+%d",
+- toplevelWidth, toplevelHeight, toplevelX, toplevelY);
+- XtVaSetValues(toplevel, XtNgeometry, geometry, NULL);
+- }
+- }
++ char *titleFormat;
++ char *title;
++ char *geometry;
++ int h = si.framebufferHeight;
++ int w = si.framebufferWidth;
++
++ check_tall();
++ if (appData.yCrop < 0) {
++ appData.yCrop = guessCrop();
++ fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop);
++ if (appData.yCrop > 0) {
++ h = appData.yCrop;
++ }
++ }
++
++ XtVaGetValues(toplevel, XtNtitle, &titleFormat, NULL);
++ title = XtMalloc(strlen(titleFormat) + strlen(desktopName) + 1);
++ sprintf(title, titleFormat, desktopName);
++ XtVaSetValues(toplevel, XtNtitle, title, XtNiconName, title, NULL);
++
++ if (appData.scale != NULL) {
++ /* switched to not scaled */
++ double frac_x, frac_y;
++ get_scale_values(&frac_x, &frac_y);
++ if (frac_x > 0.0) {
++ w = scale_round(w, frac_x);
++ h = scale_round(h, frac_y);
++ }
++ }
++ XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL);
++
++ dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
++ dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
++
++ if (appData.fullScreen) {
++ /* full screen - set position to 0,0, but defer size calculation until widgets are realized */
++
++ if (!net_wm_supported()) {
++ XtVaSetValues(toplevel, XtNoverrideRedirect, True, XtNgeometry, "+0+0", NULL);
++ } else {
++ fullscreen_startup = 1;
++ }
++
++ } else {
++
++ /* not full screen - work out geometry for middle of screen unless specified by user */
++
++ XtVaGetValues(toplevel, XtNgeometry, &geometry, NULL);
++
++ if (geometry == NULL) {
++ Dimension toplevelX, toplevelY;
++ Dimension toplevelWidth = w;
++ Dimension toplevelHeight = h;
++
++ if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) {
++ toplevelWidth = dpyWidth - appData.wmDecorationWidth;
++ }
++
++ if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) {
++ toplevelHeight = dpyHeight - appData.wmDecorationHeight;
++ }
++
++ toplevelX = (dpyWidth - toplevelWidth - appData.wmDecorationWidth) / 2;
++ toplevelY = (dpyHeight - toplevelHeight - appData.wmDecorationHeight) /2;
++
++ /* set position via "geometry" so that window manager thinks it's a
++ user-specified position and therefore honours it */
++
++ geometry = XtMalloc(256);
++
++ sprintf(geometry, "%dx%d+%d+%d", toplevelWidth, toplevelHeight, toplevelX, toplevelY);
++ fprintf(stderr, "geometry: %s ycrop: %d\n", geometry, appData.yCrop);
++ XtVaSetValues(toplevel, XtNgeometry, geometry, NULL);
++ }
++ }
+
+ /* Test if the keyboard is grabbed. If so, it's probably because the
+ XDM login window is up, so try iconifying it to release the grab */
+
+- if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync,
+- GrabModeSync, CurrentTime) == GrabSuccess) {
+- XUngrabKeyboard(dpy, CurrentTime);
+- } else {
+- wmState = XInternAtom(dpy, "WM_STATE", False);
+-
+- if (IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", False)) {
+- xloginIconified = True;
+- XSync(dpy, False);
+- sleep(1);
+- }
+- }
+-
+- /* Set handlers for signals and X errors to perform cleanup */
+-
+- signal(SIGHUP, CleanupSignalHandler);
+- signal(SIGINT, CleanupSignalHandler);
+- signal(SIGTERM, CleanupSignalHandler);
+- defaultXErrorHandler = XSetErrorHandler(CleanupXErrorHandler);
+- defaultXIOErrorHandler = XSetIOErrorHandler(CleanupXIOErrorHandler);
+- defaultXtErrorHandler = XtAppSetErrorHandler(appContext,
+- CleanupXtErrorHandler);
++ if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync, GrabModeSync, CurrentTime) == GrabSuccess) {
++ XUngrabKeyboard(dpy, CurrentTime);
++ } else {
++ wmState = XInternAtom(dpy, "WM_STATE", False);
++ if (IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", False)) {
++ xloginIconified = True;
++ XSync(dpy, False);
++ sleep(1);
++ }
++ }
++
++ /* Set handlers for signals and X errors to perform cleanup */
++ signal(SIGHUP, CleanupSignalHandler);
++ signal(SIGINT, CleanupSignalHandler);
++ signal(SIGTERM, CleanupSignalHandler);
++ defaultXErrorHandler = XSetErrorHandler(CleanupXErrorHandler);
++ defaultXIOErrorHandler = XSetIOErrorHandler(CleanupXIOErrorHandler);
++ defaultXtErrorHandler = XtAppSetErrorHandler(appContext, CleanupXtErrorHandler);
+ }
+
+
+@@ -141,14 +159,22 @@
+ void
+ ToplevelInitAfterRealization()
+ {
+- if (appData.fullScreen) {
+- FullScreenOn();
+- }
+-
+- wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+- XSetWMProtocols(dpy, XtWindow(toplevel), &wmDeleteWindow, 1);
+- XtOverrideTranslations
+- (toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()"));
++ if (appData.fullScreen) {
++ FullScreenOn();
++ if (net_wm_supported()) {
++ /* problem with scroll bars sticking: */
++ XSync(dpy, False);
++ usleep(50 * 1000);
++ FullScreenOff();
++ XSync(dpy, False);
++ usleep(50 * 1000);
++ FullScreenOn();
++ }
++ }
++
++ wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
++ XSetWMProtocols(dpy, XtWindow(toplevel), &wmDeleteWindow, 1);
++ XtOverrideTranslations(toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()"));
+ }
+
+
+@@ -157,9 +183,7 @@
+ * CurrentTime if the event has no time field.
+ */
+
+-Time
+-TimeFromEvent(XEvent *ev)
+-{
++Time TimeFromEvent(XEvent *ev) {
+ switch (ev->type) {
+ case KeyPress:
+ case KeyRelease:
+@@ -192,18 +216,15 @@
+ * generated by SendRFBEvent.
+ */
+
+-void
+-Pause(Widget w, XEvent *event, String *params, Cardinal *num_params)
+-{
+- int msec;
++void Pause(Widget w, XEvent *event, String *params, Cardinal *num_params) {
++ int msec;
+
+- if (*num_params == 0) {
+- msec = 100;
+- } else {
+- msec = atoi(params[0]);
+- }
+-
+- usleep(msec * 1000);
++ if (*num_params == 0) {
++ msec = 100;
++ } else {
++ msec = atoi(params[0]);
++ }
++ usleep(msec * 1000);
+ }
+
+
+@@ -264,11 +285,9 @@
+ * Quit action - called when we get a "delete window" message.
+ */
+
+-void
+-Quit(Widget w, XEvent *event, String *params, Cardinal *num_params)
+-{
+- Cleanup();
+- exit(0);
++void Quit(Widget w, XEvent *event, String *params, Cardinal *num_params) {
++ Cleanup();
++ exit(0);
+ }
+
+
+@@ -276,49 +295,90 @@
+ * Cleanup - perform any cleanup operations prior to exiting.
+ */
+
+-void
+-Cleanup()
+-{
+- if (xloginIconified) {
+- IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", True);
+- XFlush(dpy);
+- }
++void Cleanup() {
++
++ if (appData.chatActive) {
++ appData.chatActive = False;
++ fprintf(stderr,"Sending SendTextChatClose()\n");
++ SendTextChatClose();
++ SendTextChatFinished();
++ }
++
++ if (xloginIconified) {
++ IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", True);
++ XFlush(dpy);
++ }
+ #ifdef MITSHM
+- if (appData.useShm)
+- ShmCleanup();
++ if (appData.useShm) {
++ ShmCleanup();
++ }
#endif
-+ fprintf(stderr,"\nVNC Viewer exiting.\n\n");
++
++ releaseAllPressedModifiers();
++
++ fprintf(stderr,"\nVNC Viewer exiting.\n\n");
++ if (listenSpecified) {
++ if (listenParent != 0 && getenv("SSVNC_LISTEN_ONCE") && listenParent != getpid()) {
++ fprintf(stderr, "SSVNC_LISTEN_ONCE: Trying to kill Listening Parent: %d\n", (int) listenParent);
++ fprintf(stderr, "SSVNC_LISTEN_ONCE: Press Ctrl-C if it continues to Listen.\n\n");
++ kill(listenParent, SIGTERM);
++ } else {
++ fprintf(stderr,"(NOTE: You may need to Press Ctrl-C to make the Viewer Stop Listening.)\n\n");
++ }
++ }
++}
++
++static void check_dbg(void) {
++ if (getenv("SSVNC_EXIT_DEBUG")) {
++ fprintf(stderr, "Press any key to continue: ");
++ getc(stdin);
++ }
+ }
+
+ static int
+ CleanupXErrorHandler(Display *dpy, XErrorEvent *error)
+ {
+- fprintf(stderr,"CleanupXErrorHandler called\n");
+- Cleanup();
+- return (*defaultXErrorHandler)(dpy, error);
++ if (XError_ign) {
++ char str[4096];
++ XError_ign++;
++ fprintf(stderr,"XError_ign called.\n");
++ str[0] = '\0';
++ if (XGetErrorText(dpy, error->error_code, str, 4096)) {
++ fprintf(stderr, "%s", str);
++ }
++ return;
++ }
++ fprintf(stderr,"CleanupXErrorHandler called\n");
++ check_dbg();
++ Cleanup();
++ return (*defaultXErrorHandler)(dpy, error);
}
static int
+ CleanupXIOErrorHandler(Display *dpy)
+ {
+- fprintf(stderr,"CleanupXIOErrorHandler called\n");
+- Cleanup();
+- return (*defaultXIOErrorHandler)(dpy);
++ fprintf(stderr,"CleanupXIOErrorHandler called\n");
++ check_dbg();
++ Cleanup();
++ return (*defaultXIOErrorHandler)(dpy);
+ }
+
+ static void
+ CleanupXtErrorHandler(String message)
+ {
+- fprintf(stderr,"CleanupXtErrorHandler called\n");
+- Cleanup();
+- (*defaultXtErrorHandler)(message);
++ fprintf(stderr,"CleanupXtErrorHandler called\n");
++ check_dbg();
++ Cleanup();
++ (*defaultXtErrorHandler)(message);
+ }
+
+ static void
+ CleanupSignalHandler(int sig)
+ {
+- fprintf(stderr,"CleanupSignalHandler called\n");
+- Cleanup();
+- exit(1);
++ fprintf(stderr,"CleanupSignalHandler called\n");
++ check_dbg();
++ Cleanup();
++ exit(1);
+ }
+
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer/popup.c
--- vnc_unixsrc.orig/vncviewer/popup.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/popup.c 2008-09-14 10:34:39.000000000 -0400
-@@ -25,15 +25,44 @@
++++ vnc_unixsrc/vncviewer/popup.c 2008-10-15 08:26:28.000000000 -0400
+@@ -25,22 +25,55 @@
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
@@ -4613,24 +7721,39 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer
+ XtMoveWidget(wid, x0, y0);
+}
+
++void Noop(Widget w, XEvent *event, String *params, Cardinal *num_params) {
++ //fprintf(stderr, "No-op\n");
++}
++
void
ShowPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
- XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root);
- XtPopup(popup, XtGrabNone);
-+ if (appData.popupFix) {
-+ popupFixer(popup);
-+ } else {
-+ XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root);
-+ XtPopup(popup, XtGrabNone);
-+ }
-+ if (appData.grabAll) {
-+ XRaiseWindow(dpy, XtWindow(popup));
-+ }
- XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1);
+- XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1);
++ if (appData.popupFix) {
++ popupFixer(popup);
++ } else {
++ XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root);
++ XtPopup(popup, XtGrabNone);
++ }
++ if (appData.grabAll) {
++ XSync(dpy, False);
++ XRaiseWindow(dpy, XtWindow(popup));
++ }
++ XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1);
}
-@@ -52,42 +81,464 @@
+ void
+-HidePopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
+-{
+- XtPopdown(popup);
++HidePopup(Widget w, XEvent *event, String *params, Cardinal *num_params) {
++ XtPopdown(popup);
+ }
+
+
+@@ -52,42 +85,541 @@
};
void
@@ -4952,13 +8075,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer
+ if (! chat_visible) {
+ XtPopup(chat, XtGrabNone);
+ chat_visible = 1;
++ wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(dpy, XtWindow(chat), &wmDeleteWindow, 1);
++ if (appData.chatOnly) {
++ XtOverrideTranslations(chat, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()"));
++ } else {
++ XtOverrideTranslations(chat, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideChat()"));
++ }
+ XSync(dpy, False);
+ usleep(200 * 1000);
+ }
+}
+
+void hidechat(void) {
++ appData.chatActive = False;
+ if (appData.termChat) {
+ return;
+ }
@@ -4968,46 +8098,116 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer
+ XSync(dpy, False);
+ usleep(200 * 1000);
+ }
++ if (appData.chatOnly) {
++ Quit(0, NULL, NULL, NULL);
++ }
+}
+
+void HideChat(Widget w, XEvent *event, String *params, Cardinal *num_params) {
+ SendTextChatClose();
++ SendTextChatFinished();
+ hidechat();
+}
+
+void dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) {
+ SendTextChatClose();
++ SendTextChatFinished();
+ hidechat();
+}
+
+extern void printChat(char *, Bool);
+
++static void ChatTextCallback(XtPointer clientData, XtIntervalId *id);
++static XtIntervalId timer;
++static Bool timerSet = False;
++
++void CheckTextInput(void);
++extern double start_time;
++
++static void ChatTextCallback(XtPointer clientData, XtIntervalId *id) {
++ static int db = -1;
++ if (db < 0) {
++ if (getenv("SSVNC_DEBUG_CHAT")) {
++ db = 1;
++ } else {
++ db = 0;
++ }
++ }
++ if (db) fprintf(stderr, "ChatTextCallback: %.4f\n", dnow() - start_time);
++ CheckTextInput();
++}
++
+void CheckTextInput(void) {
+ Arg args[2];
+ String str;
+ int len;
++ static int db = -1;
++
++ if (timerSet) {
++ XtRemoveTimeOut(timer);
++ timerSet = False;
++ }
++ if (appData.chatActive) {
++ timer = XtAppAddTimeOut(appContext, 333, ChatTextCallback, NULL);
++ timerSet = True;
++ }
++ if (appData.chatOnly && !appData.chatActive) {
++ Quit(0, NULL, NULL, NULL);
++ }
+
+ if (appData.termChat) {
+ return;
+ }
++#if 0
++ if (!appData.chatActive) {
++ return;
++ }
++#endif
++
++ if (db < 0) {
++ if (getenv("SSVNC_DEBUG_CHAT")) {
++ db = 1;
++ } else {
++ db = 0;
++ }
++ }
+
+ XtSetArg(args[0], XtNstring, &str);
+ XtGetValues(entry, args, 1);
++
++ if (db) fprintf(stderr, "CheckTextInput\n");
++
+ if (str == NULL || str[0] == '\0') {
+ return;
+ } else {
++ char *q;
+ len = strlen(str);
++ if (db) fprintf(stderr, "CheckTextInput: len: %d '%s'\n", len, str);
+ if (len <= 0) {
+ return;
+ }
-+ if (str[len-1] == '\n') {
-+ char *s = strdup(str);
-+ if (s) {
-+ SendTextChat(s);
++ q = strrchr(str, '\n');
++ if (q) {
++ char *send, save[2];
++ save[0] = *(q+1);
++ *(q+1) = '\0';
++ send = strdup(str);
++ *(q+1) = save[0];
++ if (send) {
++ SendTextChat(send);
+ printChat("Send: ", True);
-+ printChat(s, True);
-+ XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, "", NULL);
-+ free(s);
++ printChat(send, True);
++ free(send);
++ if (save[0] == '\0') {
++ XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, "", NULL);
++ } else {
++ char *leak = strdup(q+1);
++ XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, leak, NULL);
++ if (strlen(leak) > 0) {
++ XSync(dpy, False);
++ XtVaSetValues(entry, XtNinsertPosition, strlen(leak), NULL);
++ }
++ }
+ }
+ }
+ }
@@ -5099,7 +8299,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer
+ XtNuseStringInPlace, False, NULL);
+
+ entry = XtVaCreateManagedWidget("entry", asciiTextWidgetClass, myform,
-+ XtNresize, XawtextResizeWidth, XtNresizable, True, XtNwrap, XawtextWrapWord,
++ XtNresize, XawtextResizeWidth, XtNresizable, True, XtNwrap, XawtextWrapNever,
+ XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollNever,
+ XtNheight, 20, XtNwidth, 400, XtNfromVert, text, XtNeditType, XawtextEdit,
+ XtNdisplayCaret, True, XtNeditType, XawtextEdit, NULL);
@@ -5138,7 +8338,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewe
+}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncviewer/rfbproto.c
--- vnc_unixsrc.orig/vncviewer/rfbproto.c 2008-09-05 19:51:24.000000000 -0400
-+++ vnc_unixsrc/vncviewer/rfbproto.c 2008-09-13 18:00:27.000000000 -0400
++++ vnc_unixsrc/vncviewer/rfbproto.c 2008-10-15 08:00:20.000000000 -0400
@@ -23,6 +23,7 @@
* rfbproto.c - functions to deal with client side of RFB protocol.
*/
@@ -5192,11 +8392,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
static void ReadConnFailedReason(void);
static long ReadCompactLen (void);
-@@ -67,6 +106,11 @@
+@@ -67,6 +106,13 @@
static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData,
int compressedLen);
+extern int currentMsg;
++extern double scale_factor_x;
++extern double scale_factor_y;
+
+int sent_FBU = 0;
+int skip_XtUpdate = 0;
@@ -5204,7 +8406,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
int rfbsock;
char *desktopName;
-@@ -177,6 +221,9 @@
+@@ -177,6 +223,9 @@
sig_rfbEncodingPointerPos, "Pointer position update");
CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor,
sig_rfbEncodingLastRect, "LastRect protocol extension");
@@ -5214,7 +8416,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -187,21 +234,104 @@
+@@ -187,21 +236,117 @@
Bool
ConnectToRFBServer(const char *hostname, int port)
{
@@ -5256,9 +8458,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- }
+ if (cmd != NULL) {
+ int sfd[2];
++ char *q, *cmd2 = strdup(cmd);
+ pid_t pid;
+
-+ fprintf(stderr, "exec-cmd: %s\n", cmd);
++ q = strstr(cmd2, "pw=");
++ if (q) {
++ q += strlen("pw=");
++ while (*q != '\0' && !isspace(*q)) {
++ *q = '*';
++ q++;
++ }
++ }
++
++ fprintf(stderr, "exec-cmd: %s\n", cmd2);
++ free(cmd2);
+
+ if (! SocketPair(sfd)) {
+ return False;
@@ -5300,6 +8513,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ fprintf(stderr,"Unable to connect to exec'd command: %s\n", cmd);
+ return False;
+ }
++ } else if (strstr(hostname, "fd=") == hostname) {
++ rfbsock = atoi(hostname + strlen("fd="));
+ } else if (strchr(hostname, '/') && stat(hostname, &sb) == 0) {
+ /* assume unix domain socket */
+ char *thost = strdup(hostname);
@@ -5332,7 +8547,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -212,211 +342,301 @@
+@@ -212,211 +357,307 @@
Bool
InitialiseRFBConnection(void)
{
@@ -5411,7 +8626,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ fprintf(stderr, "***************************************************************\n");
+ fprintf(stderr, "To work around UltraVNC SC III SSL dropping after a few minutes\n");
+ fprintf(stderr, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n");
-+ fprintf(stderr, "Or select 'UltraVNC Single Click III Bug' in the SSVNC GUI.\n");
+ fprintf(stderr, "***************************************************************\n");
+ fprintf(stderr, "\n");
+ }
@@ -5463,6 +8677,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- return False;
+ if (appData.rfbVersion != NULL && sscanf(appData.rfbVersion, "%d.%d", &viewer_major, &viewer_minor) == 2) {
+ fprintf(stderr,"Setting RFB version to %d.%d from -rfbversion.\n", viewer_major, viewer_minor);
++ } else if (getenv("SSVNC_RFB_VERSION") != NULL && sscanf(getenv("SSVNC_RFB_VERSION"), "%d.%d", &viewer_major, &viewer_minor) == 2) {
++ fprintf(stderr,"Setting RFB version to %d.%d from SSVNC_RFB_VERSION.\n", viewer_major, viewer_minor);
+ } else if (server_major == 3 && (server_minor == 14 || server_minor == 16)) {
+ /* hack for UltraVNC Single Click. They misuse rfb proto version */
+ fprintf(stderr,"Setting RFB version to 3.3 for UltraVNC Single Click.\n");
@@ -5584,6 +8800,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ si.format.blueMax = Swap16IfLE(si.format.blueMax);
+ si.nameLength = Swap32IfLE(si.nameLength);
+
++ if (appData.chatOnly) {
++ si.framebufferWidth = 32;
++ si.framebufferHeight = 32;
++ }
+
+- fprintf(stderr,"VNC server default format:\n");
+- PrintPixelFormat(&si.format);
+ /* FIXME: Check arguments to malloc() calls. */
+ desktopName = malloc(si.nameLength + 1);
+ if (!desktopName) {
@@ -5592,20 +8815,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ return False;
+ }
-- fprintf(stderr,"VNC server default format:\n");
-- PrintPixelFormat(&si.format);
-+ if (!ReadFromRFBServer(desktopName, si.nameLength)) {
-+ return False;
-+ }
-
- if (tightVncProtocol) {
- /* Read interaction capabilities (protocol 3.7t) */
- if (!ReadInteractionCaps())
- return False;
- }
-+ desktopName[si.nameLength] = 0;
++ if (!ReadFromRFBServer(desktopName, si.nameLength)) {
++ return False;
++ }
- return True;
++ desktopName[si.nameLength] = 0;
++
+ fprintf(stderr,"Desktop name \"%s\"\n\n", desktopName);
+
+ fprintf(stderr,"VNC server default format:\n");
@@ -5757,8 +8978,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ return rfbSecTypeTight;
+ }
+ }
-
-- free(secTypes);
++
+ /* Find first supported security type */
+ for (j = 0; j < (int)nSecTypes; j++) {
+ for (i = 0; i < nKnownSecTypes; i++) {
@@ -5775,7 +8995,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ break;
+ }
+ }
-+
+
+- free(secTypes);
+ free(secTypes);
- if (secType == rfbSecTypeInvalid)
@@ -5789,7 +9010,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -451,6 +671,9 @@
+@@ -451,6 +692,9 @@
return True;
}
@@ -5799,7 +9020,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
/*
* Negotiate authentication scheme (protocol version 3.7t)
-@@ -459,56 +682,61 @@
+@@ -459,56 +703,61 @@
static Bool
PerformAuthenticationTight(void)
{
@@ -5903,7 +9124,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -519,80 +747,97 @@
+@@ -519,80 +768,100 @@
static Bool
AuthenticateVNC(void)
{
@@ -5975,6 +9196,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ buffer[len - 1] = '\0';
+ }
+ }
++ } else if (getenv("VNCVIEWER_PASSWORD")) {
++ passwd = strdup(getenv("VNCVIEWER_PASSWORD"));
++ putenv("VNCVIEWER_PASSWORD=none");
+ } else if (appData.passwordDialog) {
+ passwd = DoPasswordDialog();
+ } else {
@@ -6064,7 +9288,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
/*
-@@ -602,68 +847,71 @@
+@@ -602,68 +871,71 @@
static Bool
AuthenticateUnixLogin(void)
{
@@ -6188,7 +9412,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -675,19 +923,20 @@
+@@ -675,19 +947,20 @@
static Bool
ReadInteractionCaps(void)
{
@@ -6221,7 +9445,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -700,17 +949,18 @@
+@@ -700,17 +973,18 @@
static Bool
ReadCapabilityList(CapsContainer *caps, int count)
{
@@ -6249,7 +9473,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -729,6 +979,11 @@
+@@ -729,6 +1003,11 @@
Bool requestCompressLevel = False;
Bool requestQualityLevel = False;
Bool requestLastRectEncoding = False;
@@ -6261,7 +9485,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
spf.type = rfbSetPixelFormat;
spf.format = myFormat;
-@@ -736,12 +991,18 @@
+@@ -736,12 +1015,18 @@
spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
@@ -6280,7 +9504,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
if (appData.encodingsString) {
char *encStr = appData.encodingsString;
int encStrLen;
-@@ -754,11 +1015,17 @@
+@@ -754,11 +1039,17 @@
encStrLen = strlen(encStr);
}
@@ -6299,7 +9523,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
requestLastRectEncoding = True;
if (appData.compressLevel >= 0 && appData.compressLevel <= 9)
-@@ -767,16 +1034,33 @@
+@@ -767,16 +1058,33 @@
requestQualityLevel = True;
} else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
@@ -6335,7 +9559,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
encStr = nextEncStr;
-@@ -797,7 +1081,7 @@
+@@ -797,7 +1105,7 @@
if (appData.useRemoteCursor) {
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
@@ -6344,7 +9568,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
-@@ -806,10 +1090,14 @@
+@@ -806,10 +1114,14 @@
if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
}
@@ -6360,7 +9584,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
fprintf(stderr,"Same machine: preferring raw encoding\n");
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
} else {
-@@ -818,13 +1106,15 @@
+@@ -818,13 +1130,15 @@
}
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
@@ -6380,7 +9604,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel +
rfbEncodingCompressLevel0);
} else if (!tunnelSpecified) {
-@@ -835,7 +1125,7 @@
+@@ -835,7 +1149,7 @@
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1);
}
@@ -6389,7 +9613,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
if (appData.qualityLevel < 0 || appData.qualityLevel > 9)
appData.qualityLevel = 5;
encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel +
-@@ -844,18 +1134,35 @@
+@@ -844,18 +1158,35 @@
if (appData.useRemoteCursor) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
@@ -6428,7 +9652,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
return True;
}
-@@ -868,31 +1175,110 @@
+@@ -868,31 +1199,86 @@
Bool
SendIncrementalFramebufferUpdateRequest()
{
@@ -6436,38 +9660,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- si.framebufferHeight, True);
+ return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
+ si.framebufferHeight, True);
-+}
-+
+ }
+
+time_t last_filexfer = 0;
+int delay_filexfer = 3;
+extern void CheckFileXfer(void);
+extern int rfbsock_is_ready(void);
+
+
-+// fprintf(stderr, "skip SendFramebufferUpdateRequest: %d - %d\n", last_filexfer, time(NULL));
-+#if 0
-+int ready;
-+if (0) {
-+ ready = rfbsock_is_ready();
-+ if (db) fprintf(stderr, "rsir: %d\n", ready);
-+ if (ready) {
-+ int r = (int) HandleRFBServerMessage();
-+ if (db) fprintf(stderr, "hrsm: %d\n", r);
-+
-+ }
-+ if (db) fprintf(stderr, "CFX: C ****\n");
-+ CheckFileXfer();
-+ return True;
-+}
-+if (db) {
-+ ready = rfbsock_is_ready();
-+ fprintf(stderr, "rsir: %d\n", ready);
- }
-+#endif
-+// x = y = 0;
-+// w = h = 1;
-+
-
+static int dyn = -1;
+extern int filexfer_sock;
+extern int filexfer_listen;
@@ -6552,7 +9752,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -903,19 +1289,28 @@
+@@ -903,19 +1289,36 @@
Bool
SendPointerEvent(int x, int y, int buttonMask)
{
@@ -6565,6 +9765,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ return True;
+ }
+ }
++
++ pe.type = rfbPointerEvent;
++ pe.buttonMask = buttonMask;
++
++ if (scale_factor_x > 0.0 && scale_factor_x != 1.0) {
++ x /= scale_factor_x;
++ }
++ if (scale_factor_y > 0.0 && scale_factor_y != 1.0) {
++ y /= scale_factor_y;
++ }
++
++ if (x < 0) x = 0;
++ if (y < 0) y = 0;
++
++ if (!appData.useX11Cursor) {
++ SoftCursorMove(x, y);
++ }
- pe.type = rfbPointerEvent;
- pe.buttonMask = buttonMask;
@@ -6577,15 +9794,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- pe.x = Swap16IfLE(x);
- pe.y = Swap16IfLE(y);
- return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
-+ pe.type = rfbPointerEvent;
-+ pe.buttonMask = buttonMask;
-+ if (x < 0) x = 0;
-+ if (y < 0) y = 0;
-+
-+ if (!appData.useX11Cursor) {
-+ SoftCursorMove(x, y);
-+ }
-+
+ pe.x = Swap16IfLE(x);
+ pe.y = Swap16IfLE(y);
+ currentMsg = rfbPointerEvent;
@@ -6593,7 +9801,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -926,12 +1321,20 @@
+@@ -926,12 +1329,20 @@
Bool
SendKeyEvent(CARD32 key, Bool down)
{
@@ -6619,7 +9827,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -942,281 +1345,860 @@
+@@ -942,281 +1353,943 @@
Bool
SendClientCutText(char *str, int len)
{
@@ -6737,19 +9945,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+Bool
+SendTextChat(char *str)
+{
++ static int db = -1;
+ rfbTextChatMsg chat;
-+ chat.type = rfbTextChat;
-+ chat.pad1 = 0;
-+ chat.pad2 = 0;
-+ chat.length = (unsigned int) strlen(str);
-+ //fprintf(stderr, "SendTextChat: %d '%s'\n", chat.length, str);
-+ chat.length = Swap32IfLE(chat.length);
-+ if (!WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg)) {
-+ return False;
-+ }
-+ currentMsg = rfbTextChat;
-+ return WriteExact(rfbsock, str, strlen(str));
-+}
- for (i = 0; i < msg.scme.nColours; i++) {
- if (!ReadFromRFBServer((char *)rgb, 6))
@@ -6761,20 +9958,31 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- xc.flags = DoRed|DoGreen|DoBlue;
- XStoreColor(dpy, cmap, &xc);
- }
-+extern void raiseme(int force);
++ if (db < 0) {
++ if (getenv("SSVNC_DEBUG_CHAT")) {
++ db = 1;
++ } else {
++ db = 0;
++ }
++ }
++ if (!appData.chatActive) {
++ SendTextChatOpen();
++ appData.chatActive = True;
++ }
- break;
- }
-+Bool
-+SendTextChatOpen(void)
-+{
-+ raiseme(0);
-+ rfbTextChatMsg chat;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
-+ chat.length = Swap32IfLE(rfbTextChatOpen);
-+ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
++ chat.length = (unsigned int) strlen(str);
++ if (db) fprintf(stderr, "SendTextChat: %d '%s'\n", chat.length, str);
++ chat.length = Swap32IfLE(chat.length);
++ if (!WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg)) {
++ return False;
++ }
++ currentMsg = rfbTextChat;
++ return WriteExact(rfbsock, str, strlen(str));
+}
- case rfbFramebufferUpdate:
@@ -6784,6 +9992,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- int bytesPerLine;
- int i;
- int usecs;
++extern void raiseme(int force);
+
+- if (!ReadFromRFBServer(((char *)&msg.fu) + 1,
+- sz_rfbFramebufferUpdateMsg - 1))
+- return False;
++Bool
++SendTextChatOpen(void)
++{
++ raiseme(0);
++ rfbTextChatMsg chat;
++ chat.type = rfbTextChat;
++ chat.pad1 = 0;
++ chat.pad2 = 0;
++ chat.length = Swap32IfLE(rfbTextChatOpen);
++ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
++}
+
+- msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
+Bool
+SendTextChatClose(void)
+{
@@ -6792,12 +10018,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = Swap32IfLE(rfbTextChatClose);
++ appData.chatActive = False;
+ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
+}
-- if (!ReadFromRFBServer(((char *)&msg.fu) + 1,
-- sz_rfbFramebufferUpdateMsg - 1))
-- return False;
+- for (i = 0; i < msg.fu.nRects; i++) {
+- if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader))
+- return False;
+Bool
+SendTextChatFinished(void)
+{
@@ -6806,6 +10033,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = Swap32IfLE(rfbTextChatFinished);
++ appData.chatActive = False;
+ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
+}
+
@@ -6880,9 +10108,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ int rfbCFileDelete = 4; // Request the server to delete the given file
+
+ int rfbRErrorUnknownCmd = 1; // Unknown FileTransfer command.
-+ int rfbRErrorCmd = 0xFFFFFFFF;
++#define rfbRErrorCmd 0xFFFFFFFF
+
-+ int db = 0;
++ static int db = -1;
++ static int guess_x11vnc = 0;
+
+#if 0
+ if (filexfer_sock < 0) {
@@ -6891,20 +10120,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ // instead, we read and discard the ft msg data.
+#endif
-- msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
-+//fprintf(stderr, "In HandleFileXfer\n");
-
-- for (i = 0; i < msg.fu.nRects; i++) {
-- if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader))
-- return False;
-+ last_filexfer = time(NULL);
-+ //fprintf(stderr, "last_filexfer-1: %d\n", last_filexfer);
-
- rect.encoding = Swap32IfLE(rect.encoding);
- if (rect.encoding == rfbEncodingLastRect)
- break;
-+ // load first byte to send to Java be the FT msg number:
-+ hdr[0] = rfbFileTransfer;
++//fprintf(stderr, "In HandleFileXfer\n");
- rect.r.x = Swap16IfLE(rect.r.x);
- rect.r.y = Swap16IfLE(rect.r.y);
@@ -6916,6 +10135,25 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h,
- rect.encoding)) {
- return False;
++ if (db < 0) {
++ if (getenv("DEBUG_HandleFileXfer")) {
++ db = 1;
++ } else {
++ db = 0;
++ }
+ }
+- continue;
+- }
+
+- if (rect.encoding == rfbEncodingPointerPos) {
+- if (!HandleCursorPos(rect.r.x, rect.r.y)) {
+- return False;
++ last_filexfer = time(NULL);
++ //fprintf(stderr, "last_filexfer-1: %d\n", last_filexfer);
++
++ // load first byte to send to Java be the FT msg number:
++ hdr[0] = rfbFileTransfer;
++
+ // this is to avoid XtAppProcessEvent() calls induce by our ReadFromRFBServer calls below:
+ skip_XtUpdateAll = 1;
+ if (!ReadFromRFBServer(&hdr[1], 11)) {
@@ -6942,23 +10180,29 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- continue;
- }
-- if (rect.encoding == rfbEncodingPointerPos) {
-- if (!HandleCursorPos(rect.r.x, rect.r.y)) {
+- if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
+- (rect.r.y + rect.r.h > si.framebufferHeight))
+- {
+- fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n",
+- rect.r.w, rect.r.h, rect.r.x, rect.r.y);
- return False;
+ if (hdr[1] == rfbEndOfFile) {
+ goto read_no_more;
+ } else if (hdr[1] == rfbAbortFileTransfer) {
+ goto read_no_more;
}
+
+- if (rect.r.h * rect.r.w == 0) {
+- fprintf(stderr,"Zero size rect - ignoring\n");
- continue;
- }
++ if (hdr[1] == rfbDirPacket && hdr[3] == rfbADirectory) {
++
++ }
-- if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
-- (rect.r.y + rect.r.h > si.framebufferHeight))
-- {
-- fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n",
-- rect.r.w, rect.r.h, rect.r.x, rect.r.y);
-- return False;
+- /* If RichCursor encoding is used, we should prevent collisions
+- between framebuffer updates and cursor drawing operations. */
+- SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+ len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11];
+ if (db) fprintf(stderr, "Got rfbFileTransfer: len1 %u\n", len);
+ if (len > 0) {
@@ -6967,24 +10211,64 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ return False;
+ }
+ if (db > 1) write(2, fxfer, len);
++ if (len >= 12 && hdr[1] == rfbDirPacket) {
++ /* try to guess if x11vnc or not... */
++ if (db) {
++ int i;
++ fprintf(stderr, "HFX DIR PKT (attr, timeL, timeH):");
++ for (i=0; i < 12; i++) {
++ fprintf(stderr, " %d", (unsigned char) fxfer[i]);
++ }
++ fprintf(stderr, "\n");
++ }
++ if (hdr[2] == 1) {
++ int dattr = (unsigned char) fxfer[0];
++ int timeL1 = (unsigned char) fxfer[4];
++ int timeL2 = (unsigned char) fxfer[5];
++ int timeL3 = (unsigned char) fxfer[6];
++ int timeL4 = (unsigned char) fxfer[7];
++ int timeH1 = (unsigned char) fxfer[8];
++ int timeH2 = (unsigned char) fxfer[9];
++ int timeH3 = (unsigned char) fxfer[10];
++ int timeH4 = (unsigned char) fxfer[11];
++ if (dattr != 0) {
++ if (timeH1 == 0 && timeH2 == 0 && timeH3 == 0 && timeH4 == 0) {
++ if (timeL1 != 0 || timeL2 != 0 && timeL3 != 0 && timeL4 != 0) {
++ if (!guess_x11vnc) fprintf(stderr, "guessed x11vnc server\n");
++ guess_x11vnc = 1;
++ }
++ }
++ }
++ }
++ }
+ if (db && 0) fprintf(stderr, "\n");
+ if (filexfer_sock >= 0) {
+ write(filexfer_sock, fxfer, len);
+ } else {
+ fprintf(stderr, "filexfer_sock closed, discarding %d bytes\n", len);
+ }
- }
++ }
-- if (rect.r.h * rect.r.w == 0) {
-- fprintf(stderr,"Zero size rect - ignoring\n");
-- continue;
-- }
-+ /* not used! */
+- switch (rect.encoding) {
+ len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7];
+ if (db) fprintf(stderr, "Got rfbFileTransfer: len2 %u\n", len);
-+
-+ if (hdr[1] == rfbFileHeader && len != rfbRErrorCmd) {
+
+- case rfbEncodingRaw:
++#if 0
++ if (hdr[1] == rfbFileHeader && len != rfbRErrorCmd)
++#else
++ // the extra 4 bytes get send on rfbRErrorCmd as well.
++ if (hdr[1] == rfbFileHeader) {
++#endif
++ int is_err = 0;
++ if (len == rfbRErrorCmd) {
++ is_err = 1;
++ }
+ if (db) fprintf(stderr, "Got rfbFileTransfer: rfbFileHeader\n");
++ if (is_err && guess_x11vnc) {
++ fprintf(stderr, "rfbRErrorCmd x11vnc skip read 4 bytes.\n");
++ goto read_no_more;
++ }
+ len = 4;
+ if (!ReadFromRFBServer(fxfer, len)) {
+ skip_XtUpdateAll = 0;
@@ -6992,6 +10276,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ }
+ if (db > 1) write(2, fxfer, len);
+ if (db && 0) fprintf(stderr, "\n");
++ if (is_err) {
++ fprintf(stderr, "rfbRErrorCmd skip write 4 bytes.\n");
++ goto read_no_more;
++ }
+ if (filexfer_sock >= 0) {
+ write(filexfer_sock, fxfer, len);
+ } else {
@@ -6999,12 +10287,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ }
+ }
-- /* If RichCursor encoding is used, we should prevent collisions
-- between framebuffer updates and cursor drawing operations. */
-- SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+- bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
+- linesToRead = BUFFER_SIZE / bytesPerLine;
+ read_no_more:
-- switch (rect.encoding) {
+- while (rect.r.h > 0) {
+- if (linesToRead > rect.r.h)
+- linesToRead = rect.r.h;
+ if (filexfer_sock < 0) {
+ int stop = 0;
+ static time_t last_stop = 0;
@@ -7028,58 +10317,34 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ }
+ }
-- case rfbEncodingRaw:
+- if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead))
+- return False;
+ if (db) fprintf(stderr, "Got rfbFileTransfer done.\n");
+ skip_XtUpdateAll = 0;
-- bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
-- linesToRead = BUFFER_SIZE / bytesPerLine;
+- CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w,
+- linesToRead);
+ if (db) fprintf(stderr, "CFX: B\n");
+ CheckFileXfer();
+//fprintf(stderr, "Out HandleFileXfer\n");
+ return True;
+}
-
-- while (rect.r.h > 0) {
-- if (linesToRead > rect.r.h)
-- linesToRead = rect.r.h;
++
+/*
+ * HandleRFBServerMessage.
+ */
-- if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead))
-- return False;
+- rect.r.h -= linesToRead;
+- rect.r.y += linesToRead;
-- CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w,
-- linesToRead);
+- }
+- break;
+Bool
+HandleRFBServerMessage()
+{
+ static int db = -1;
+ rfbServerToClientMsg msg;
-- rect.r.h -= linesToRead;
-- rect.r.y += linesToRead;
-+ if (db < 0) {
-+ if (getenv("DEBUG_RFB_SMSG")) {
-+ db = 1;
-+ } else {
-+ db = 0;
-+ }
-+ }
-
-+ if (!ReadFromRFBServer((char *)&msg, 1)) {
-+ return False;
- }
-- break;
-+ if (appData.ultraDSM) {
-+ if (!ReadFromRFBServer((char *)&msg, 1)) {
-+ return False;
-+ }
-+ }
-+
-+//fprintf(stderr, "msg.type: %d\n", msg.type);
-
- case rfbEncodingCopyRect:
- {
- rfbCopyRect cr;
@@ -7106,21 +10371,28 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- rect.r.w, rect.r.h);
- XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY,
- rect.r.w, rect.r.h);
-+ if (msg.type == rfbFileTransfer) {
-+ return HandleFileXfer();
++ if (db < 0) {
++ if (getenv("DEBUG_RFB_SMSG")) {
++ db = 1;
++ } else {
++ db = 0;
++ }
}
- XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
- rect.r.w, rect.r.h, rect.r.x, rect.r.y);
-+ switch (msg.type) {
++ if (!ReadFromRFBServer((char *)&msg, 1)) {
++ return False;
++ }
++ if (appData.ultraDSM) {
++ if (!ReadFromRFBServer((char *)&msg, 1)) {
++ return False;
++ }
++ }
- break;
- }
-+ case rfbSetColourMapEntries:
-+ {
-+ int i;
-+ CARD16 rgb[3];
-+ XColor xc;
++//fprintf(stderr, "msg.type: %d\n", msg.type);
- case rfbEncodingRRE:
- {
@@ -7137,8 +10409,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
-+ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) {
-+ return False;
++ if (msg.type == rfbFileTransfer) {
++ return HandleFileXfer();
}
- break;
- }
@@ -7158,11 +10430,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
-- }
++ switch (msg.type) {
++
++ case rfbSetColourMapEntries:
++ {
++ int i;
++ CARD16 rgb[3];
++ XColor xc;
++
++ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) {
++ return False;
+ }
- break;
- }
-+ msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
-+ msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
- case rfbEncodingHextile:
- {
@@ -7179,6 +10459,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
- if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
++ msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
++ msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
++
+ for (i = 0; i < msg.scme.nColours; i++) {
+ if (!ReadFromRFBServer((char *)rgb, 6)) {
+ return False;
@@ -7317,6 +10600,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ continue;
+ }
+ if (rect.encoding == rfbEncodingNewFBSize) {
++ if (appData.chatOnly) {
++ continue;
++ }
+ fprintf(stderr,"New Size: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+ si.framebufferWidth = rect.r.w;
+ si.framebufferHeight = rect.r.h;
@@ -7357,9 +10643,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+
+ if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
+ (rect.r.y + rect.r.h > si.framebufferHeight)) {
-+ fprintf(stderr,"Rect too large: %dx%d at (%d, %d) encoding=%d\n",
-+ rect.r.w, rect.r.h, rect.r.x, rect.r.y, rect.encoding);
-+ return False;
++ if (!appData.chatOnly) {
++ fprintf(stderr,"Rect too large: %dx%d at (%d, %d) encoding=%d\n",
++ rect.r.w, rect.r.h, rect.r.x, rect.r.y, rect.encoding);
++ return False;
++ }
+ }
+
+ if (rect.r.h * rect.r.w == 0) {
@@ -7409,6 +10697,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) {
+ return False;
+ }
++ if (appData.chatOnly) {
++ break;
++ }
+
+ cr.srcX = Swap16IfLE(cr.srcX);
+ cr.srcY = Swap16IfLE(cr.srcY);
@@ -7436,9 +10727,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
+ }
+
+ if (db) fprintf(stderr, "FBU-CPA1 %.6f\n", dnow());
-+ if (!appData.useBackingstore) {
++ if (!appData.useXserverBackingStore) {
+ copy_rect(rect.r.x, rect.r.y, rect.r.w, rect.r.h, cr.srcX, cr.srcY);
-+ put_image(rect.r.x, rect.r.y, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
++ put_image(rect.r.x, rect.r.y, rect.r.x, rect.r.y, rect.r.w, rect.r.h, 0);
+ XSync(dpy, False);
+ } else {
+ XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
@@ -7703,7 +10994,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
#ifdef MITSHM
/* if using shared memory PutImage, make sure that the X server has
-@@ -1224,59 +2206,165 @@
+@@ -1224,59 +2297,165 @@
mainly to avoid copyrect using invalid screen contents - not sure
if we'd need it otherwise. */
@@ -7902,7 +11193,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
}
-@@ -1296,26 +2384,47 @@
+@@ -1296,26 +2475,47 @@
#define CONCAT2(a,b) a##b
#define CONCAT2E(a,b) CONCAT2(a,b)
@@ -7950,7 +11241,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
#undef BPP
/*
-@@ -1358,9 +2467,9 @@
+@@ -1358,9 +2558,9 @@
" %s significant bit in each byte is leftmost on the screen.\n",
(format->bigEndian ? "Most" : "Least"));
} else {
@@ -7962,14 +11253,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie
(format->bigEndian ? "Most" : "Least"));
}
if (format->trueColour) {
-@@ -1462,4 +2571,3 @@
+@@ -1462,4 +2662,3 @@
cinfo->src = &jpegSrcManager;
}
-
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/rre.c
--- vnc_unixsrc.orig/vncviewer/rre.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/rre.c 2007-02-17 22:52:24.000000000 -0500
++++ vnc_unixsrc/vncviewer/rre.c 2008-10-05 15:16:30.000000000 -0400
@@ -29,6 +29,18 @@
#define HandleRREBPP CONCAT2E(HandleRRE,BPP)
#define CARDBPP CONCAT2E(CARD,BPP)
@@ -7978,7 +11269,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/r
+ { \
+ XGCValues _gcv; \
+ _gcv.foreground = color; \
-+ if (!appData.useBackingstore) { \
++ if (!appData.useXserverBackingStore) { \
+ FillScreen(x, y, w, h, _gcv.foreground); \
+ } else { \
+ XChangeGC(dpy, gc, GCForeground, &_gcv); \
@@ -8035,8 +11326,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/r
+#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c
--- vnc_unixsrc.orig/vncviewer/shm.c 2000-06-11 08:00:53.000000000 -0400
-+++ vnc_unixsrc/vncviewer/shm.c 2007-03-23 22:20:35.000000000 -0400
-@@ -33,68 +33,80 @@
++++ vnc_unixsrc/vncviewer/shm.c 2008-10-10 12:26:07.000000000 -0400
+@@ -33,68 +33,97 @@
void
ShmCleanup()
{
@@ -8067,6 +11358,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/s
+ return 0;
}
++int scale_round(int len, double fac);
++extern int scale_x, scale_y;
++extern double scale_factor_x, scale_factor_y;
++
XImage *
-CreateShmImage()
+CreateShmImage(int do_ycrop)
@@ -8114,6 +11409,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/s
+ XImage *image;
+ XErrorHandler oldXErrorHandler;
+ int ymax = si.framebufferHeight;
++ int xmax = si.framebufferWidth;
+
+ if (!XShmQueryExtension(dpy)) {
+ return NULL;
@@ -8121,12 +11417,21 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/s
+ if (!appData.useShm) {
+ return NULL;
+ }
++ if (do_ycrop == -1) {
++ /* kludge to test for shm prescence */
++ return (XImage *) 0x1;
++ }
++
+ if (do_ycrop) {
+ ymax = appData.yCrop;
+ }
+
-+ image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
-+ si.framebufferWidth, ymax);
++ if (scale_x > 0) {
++ xmax = scale_round(xmax, scale_factor_x);
++ ymax = scale_round(ymax, scale_factor_y);
++ }
++
++ image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, xmax, ymax);
+ if (!image) {
+ return NULL;
+ }
@@ -8135,6 +11440,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/s
+
+ if (shminfo.shmid == -1) {
+ XDestroyImage(image);
++ //fprintf(stderr, "CreateShmImage: destroyed 'image' (1)\n");
+ return NULL;
+ }
+
@@ -8142,6 +11448,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/s
+
+ if (shminfo.shmaddr == (char *)-1) {
+ XDestroyImage(image);
++ //fprintf(stderr, "CreateShmImage: destroyed 'image' (2)\n");
+ shmctl(shminfo.shmid, IPC_RMID, 0);
+ return NULL;
+ }
@@ -8155,6 +11462,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/s
+
+ if (caughtShmError) {
+ XDestroyImage(image);
++ //fprintf(stderr, "CreateShmImage: destroyed 'image' (3)\n");
+ shmdt(shminfo.shmaddr);
+ shmctl(shminfo.shmid, IPC_RMID, 0);
+ return NULL;
@@ -8164,7 +11472,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/s
+ needShmCleanup = True;
- fprintf(stderr,"Using shared memory PutImage\n");
-+ fprintf(stderr,"Using shared memory (PutImage ycrop=%d)\n", do_ycrop);
++ fprintf(stderr,"Using shared memory (PutImage ycrop=%d, Size %dx%d)\n", do_ycrop, xmax, ymax);
- return image;
+ return image;
@@ -8186,7 +11494,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/smake vnc_unixsrc/vncviewer/s
+fi
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncviewer/sockets.c
--- vnc_unixsrc.orig/vncviewer/sockets.c 2001-01-14 22:54:18.000000000 -0500
-+++ vnc_unixsrc/vncviewer/sockets.c 2008-09-14 10:28:56.000000000 -0400
++++ vnc_unixsrc/vncviewer/sockets.c 2008-10-15 08:30:41.000000000 -0400
@@ -27,6 +27,7 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -8195,7 +11503,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
#include <netdb.h>
#include <fcntl.h>
#include <assert.h>
-@@ -56,22 +57,339 @@
+@@ -56,22 +57,366 @@
*/
static Bool rfbsockReady = False;
@@ -8323,7 +11631,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
+ fprintf(stderr, " %d", (int) fxfer[i]);
+ }
+ fprintf(stderr, " ?\n");
- }
++}
+ if (0 || db) fprintf(stderr, "filexfer read[%d] %d.\n", icnt, rn);
+ if (rn < 0) {
+ fprintf(stderr, "filexfer bad read: %d\n", errno);
@@ -8421,12 +11729,52 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
+ }
+//fprintf(stderr, "Out CheckFileXfer\n");
+ return;
+ }
+
++static void check_term_chat(void) {
++ fd_set fds;
++ struct timeval tv;
++ int i, igot = -1, n = fileno(stdin);
++ char strs[100][512];
++ char buf[rfbTextMaxSize];
++
++ for (i=0; i < 100; i++) {
++ FD_ZERO(&fds);
++ FD_SET(n,&fds);
++ tv.tv_sec = 0;
++ tv.tv_usec = 0;
++ if (select(n+1, &fds, NULL, NULL, &tv) > 0) {
++ if (FD_ISSET(n, &fds)) {
++ fgets(strs[i], 512, stdin);
++ igot = i;
++ } else {
++ break;
++ }
++ } else {
++ break;
++ }
++ }
++ buf[0] = '\0';
++ for (i=0; i <= igot; i++) {
++ if (strlen(buf) + strlen(strs[i]) < rfbTextMaxSize) {
++ strcat(buf, strs[i]);
++ } else {
++ SendTextChat(buf);
++ buf[0] = '0';
++ }
++ }
++ if (buf[0] != '\0') {
++ SendTextChat(buf);
++ }
++ if (igot >= 0) printChat("Send: ");
+}
+
+static time_t time_mark;
+extern int delay_filexfer;
+#include <sys/stat.h>
-
++
++extern double start_time;
++
static void
ProcessXtEvents()
{
@@ -8438,6 +11786,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
- }
+ int y, db = 0;
+ static int dyn = -1;
++ static int chat_was_active = 0;
++ int check_chat = 0;
+
+ if (dyn < 0) {
+ struct stat sb;
@@ -8454,50 +11804,35 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
+ }
+ }
+
++ //if (0) fprintf(stderr, "ProcessXtEvents: %d %.4f\n", skip_XtUpdateAll, dnow() - start_time);
++
+ if (skip_XtUpdateAll) {
+ return;
+ }
-+ if (appData.chatActive) {
-+ fd_set fds;
-+ struct timeval tv;
-+ int i, igot = -1, n = fileno(stdin);
-+ char strs[100][512];
-+ char buf[rfbTextMaxSize];
+
-+ if (appData.termChat) {
-+ for (i=0; i < 100; i++) {
-+ FD_ZERO(&fds);
-+ FD_SET(n,&fds);
-+ tv.tv_sec = 0;
-+ tv.tv_usec = 0;
-+ if (select(n+1, &fds, NULL, NULL, &tv) > 0) {
-+ if (FD_ISSET(n, &fds)) {
-+ fgets(strs[i], 512, stdin);
-+ igot = i;
-+ } else {
-+ break;
-+ }
-+ } else {
-+ break;
-+ }
-+ }
-+ buf[0] = '\0';
-+ for (i=0; i <= igot; i++) {
-+ if (strlen(buf) + strlen(strs[i]) < rfbTextMaxSize) {
-+ strcat(buf, strs[i]);
-+ } else {
-+ SendTextChat(buf);
-+ buf[0] = '0';
-+ }
-+ }
-+ if (buf[0] != '\0') {
-+ SendTextChat(buf);
-+ }
-+ if (igot >= 0) printChat("Send: ");
-+ } else {
++ /* text chat */
++ if (appData.chatActive ) {
++ check_chat = 1;
++ } else if (chat_was_active) {
++ static double last_check = 0.0;
++ double now = dnow();
++ if (now > last_check + 0.75) {
++ //fprintf(stderr, "cwa\n");
++ check_chat = 1;
++ last_check = now;
++ }
++ }
++ if (check_chat) {
++ if (appData.chatActive) {
++ chat_was_active = 1;
++ }
++ if (!appData.termChat) {
+ CheckTextInput();
++ } else {
++ check_term_chat();
+ }
+ }
++
+ if (skip_XtUpdate) {
+ return;
+ }
@@ -8543,7 +11878,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
}
Bool
-@@ -151,6 +469,8 @@
+@@ -151,6 +496,8 @@
}
@@ -8552,7 +11887,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
/*
* Write an exact number of bytes, and don't return until you've sent them.
*/
-@@ -158,37 +478,81 @@
+@@ -158,37 +505,81 @@
Bool
WriteExact(int sock, char *buf, int n)
{
@@ -8663,7 +11998,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
}
-@@ -203,6 +567,8 @@
+@@ -203,6 +594,8 @@
struct sockaddr_in addr;
int one = 1;
@@ -8672,12 +12007,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = host;
-@@ -232,7 +598,22 @@
+@@ -232,7 +625,22 @@
return sock;
}
+Bool SocketPair(int fd[2]) {
-+ if (socketpair(PF_UNIX, SOCK_STREAM, AF_UNIX, fd) == -1) {
++ if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) == -1) {
+ perror("socketpair");
+ return False;
+ }
@@ -8695,7 +12030,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
/*
* FindFreeTcpPort tries to find unused TCP port in the range
-@@ -245,6 +626,8 @@
+@@ -245,6 +653,8 @@
int sock, port;
struct sockaddr_in addr;
@@ -8704,7 +12039,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
-@@ -272,6 +655,8 @@
+@@ -272,6 +682,8 @@
* ListenAtTcpPort starts listening at the given TCP port.
*/
@@ -8713,7 +12048,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
int
ListenAtTcpPort(int port)
{
-@@ -279,10 +664,16 @@
+@@ -279,10 +691,16 @@
struct sockaddr_in addr;
int one = 1;
@@ -8732,7 +12067,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview
fprintf(stderr,programName);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer/tight.c
--- vnc_unixsrc.orig/vncviewer/tight.c 2002-04-30 09:07:31.000000000 -0400
-+++ vnc_unixsrc/vncviewer/tight.c 2007-02-17 22:08:20.000000000 -0500
++++ vnc_unixsrc/vncviewer/tight.c 2008-10-05 15:16:35.000000000 -0400
@@ -129,14 +129,21 @@
#endif
@@ -8750,7 +12085,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer
- XChangeGC(dpy, gc, GCForeground, &gcv);
- XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
-+ if (!appData.useBackingstore) {
++ if (!appData.useXserverBackingStore) {
+ FillScreen(rx, ry, rw, rh, gcv.foreground);
+ } else {
+ XChangeGC(dpy, gc, GCForeground, &gcv);
@@ -8787,7 +12122,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tunnel.c vnc_unixsrc/vncviewe
sprintf(lastArgv, "localhost::%d", localPort);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncviewer/vncviewer.c
--- vnc_unixsrc.orig/vncviewer/vncviewer.c 2004-01-13 09:22:05.000000000 -0500
-+++ vnc_unixsrc/vncviewer/vncviewer.c 2008-09-09 00:08:07.000000000 -0400
++++ vnc_unixsrc/vncviewer/vncviewer.c 2008-10-17 20:36:47.000000000 -0400
@@ -22,6 +22,7 @@
*/
@@ -8796,7 +12131,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
char *programName;
XtAppContext appContext;
-@@ -29,11 +30,179 @@
+@@ -29,11 +30,190 @@
Widget toplevel;
@@ -8957,12 +12292,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ SendKeyEvent(XK_Return, 0);
+}
+
++static void chat_window_only(void) {
++ if (appData.chatOnly) {
++ static double last_time = 0.0;
++ if (dnow() > last_time + 1.5) {
++ XSync(dpy, False);
++ XUnmapWindow(dpy, XtWindow(toplevel));
++ }
++ }
++}
++
int
main(int argc, char **argv)
{
- int i;
- programName = argv[0];
+ int i, save_sbw;
++ char *pw_loc = NULL;
+ programName = argv[0];
+
+ for (i = 1; i < argc; i++) {
@@ -8978,7 +12324,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
/* The -listen option is used to make us a daemon process which listens for
incoming connections from servers, rather than actively connecting to a
-@@ -45,89 +214,1235 @@
+@@ -45,89 +225,1363 @@
listenForIncomingConnections() returns, setting the listenSpecified
flag. */
@@ -8994,6 +12340,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
- }
- }
+ for (i = 1; i < argc; i++) {
++ if (strstr(argv[i], " pw=") != NULL) {
++ pw_loc = strstr(argv[i], " pw=") + 1;
++ }
++ }
++
++ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-listen") == 0) {
+ listenForIncomingConnections(&argc, argv, i);
+ break;
@@ -9085,6 +12437,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ if (save_sbw) {
+ appData.sbWidth = save_sbw;
+ }
++
++ if (appData.chatOnly) {
++ appData.encodingsString = "raw hextile";
++ }
++
++ if (pw_loc != NULL) {
++ char *q = pw_loc;
++ while (*q != '\0' && !isspace(*q)) {
++ *q = ' ';
++ q++;
++ }
++ }
/* Unless we accepted an incoming connection, make a TCP connection to the
given VNC server */
@@ -9136,6 +12500,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
- if (!InitialiseRFBConnection()) exit(1);
+ if (!InitialiseRFBConnection()) {
++ Cleanup();
+ exit(1);
+ }
+ if (appData.unixPW != NULL) {
@@ -9189,6 +12554,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
- SetFormatAndEncodings();
+ SetFormatAndEncodings();
++
++ if (appData.chatOnly) {
++ chat_window_only();
++ ToggleTextChat(0, NULL, NULL, NULL);
++ }
/* Now enter the main loop, processing VNC messages. X events will
automatically be processed whenever the VNC connection is idle. */
@@ -9201,6 +12571,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ if (!HandleRFBServerMessage()) {
+ break;
+ }
++ if (appData.chatOnly) {
++ chat_window_only();
++ }
+ }
+
+ Cleanup();
@@ -9324,6 +12697,21 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ schedule_format_change();
+}
+
++void
++ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (getenv("SSVNC_DEBUG_GRAB")) {
++ fprintf(stderr, "ToggleXGrab, current=%d\n", appData.grabAll);
++ }
++ if (appData.grabAll) {
++ appData.grabAll = False;
++ } else {
++ appData.grabAll = True;
++ }
++ /* always ungrab to be sure, fullscreen will handle the rest */
++ XUngrabServer(dpy);
++}
++
+/*
+ * ToggleNColors
+ */
@@ -9641,7 +13029,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ if (appData.chatActive) {
+ printChat("\n*SentClose*\n\n", False);
+ SendTextChatClose();
-+ HideChat();
++ SendTextChatFinished();
++ HideChat(0, NULL, NULL, NULL);
+ appData.chatActive= False;
+ } else {
+ ShowChat();
@@ -9731,7 +13120,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ char str[100], *s, *q;
+ int n;
+ if (1) {
-+ s = DoScaleDialog();
++ s = DoScaleNDialog();
+ } else {
+ raiseme(1);
+ fprintf(stderr, "\n\n\a\nEnter integer n for 1/n server scaling: ");
@@ -9815,8 +13204,41 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ }
+}
+
-
-- Cleanup();
++extern void rescale_image(void);
++
++void
++SetScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ char *s;
++ s = DoScaleDialog();
++ if (s[0] != '\0') {
++ int w = si.framebufferWidth;
++ int h = si.framebufferHeight;
++ int fs = 0;
++ if (appData.scale != NULL && !strcmp(s, appData.scale)) {
++ return;
++ }
++ if (!strcasecmp(s, "none")) {
++ appData.scale = NULL;
++ } else if (!strcmp(s, "1.0")) {
++ appData.scale = NULL;
++ } else if (!strcmp(s, "1")) {
++ appData.scale = NULL;
++ } else {
++ appData.scale = strdup(s);
++ }
++ if (appData.fullScreen) {
++ fs = 1;
++ FullScreenOff();
++ }
++ rescale_image();
++ if (fs) {
++ FullScreenOn();
++ }
++ }
++}
++
++
+void set_ycrop(int n) {
+ if (n >= 1) {
+ int w = si.framebufferWidth;
@@ -9849,8 +13271,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ set_ycrop(n);
+ }
+}
-
-- return 0;
++
+void set_scbar(int n) {
+ if (n >= 1) {
+ int w = si.framebufferWidth;
@@ -9911,13 +13332,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ set_server_compress(n);
+ }
+}
-+
+
+- Cleanup();
+void
+GotChatText(char *str, int len)
+{
+ static char *b = NULL;
+ static int blen = -1;
-+ int i;
++ int i, k;
+ if (appData.termChat) {
+ printChat("\nChat: ", True);
+ } else {
@@ -9932,9 +13354,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ b = (char *) malloc(blen);
+ }
+
++ k = 0;
+ for (i=0; i < len; i++) {
-+ b[i] = str[i];
++ if (str[i] != '\r') {
++ b[k++] = str[i];
++ }
+ }
++ b[k] = '\0';
+ b[len] = '\0';
+ printChat(b, True);
+
@@ -9946,23 +13372,26 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ }
+ }
+}
-+
+
+- return 0;
+void
+SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.viewOnly)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.viewOnly) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.enableJPEG)
-+ XtVaSetValues(w, XtNstate, False, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, True, NULL);
++ if (appData.enableJPEG) {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ }
+}
+
+void
@@ -10009,8 +13438,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+{
+ if (appData.useBGR233) {
+ XtVaSetValues(w, XtNstate, True, NULL);
-+ if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL);
-+ if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL);
++ if (b16 != NULL) {
++ XtVaSetValues(b16, XtNstate, False, NULL);
++ }
++ if (bfull != NULL) {
++ XtVaSetValues(bfull, XtNstate, False, NULL);
++ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
@@ -10021,8 +13454,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+{
+ if (appData.useBGR565) {
+ XtVaSetValues(w, XtNstate, True, NULL);
-+ if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL);
-+ if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL);
++ if (b8 != NULL) {
++ XtVaSetValues(b8, XtNstate, False, NULL);
++ }
++ if (bfull != NULL) {
++ XtVaSetValues(bfull, XtNstate, False, NULL);
++ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
@@ -10035,8 +13472,22 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ XtVaSetValues(w, XtNstate, False, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, True, NULL);
-+ if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL);
-+ if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL);
++ if (b8 != NULL) {
++ XtVaSetValues(b8, XtNstate, False, NULL);
++ }
++ if (b16 != NULL) {
++ XtVaSetValues(b16, XtNstate, False, NULL);
++ }
++ }
++}
++
++void
++SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
++{
++ if (appData.grabAll) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
@@ -10045,8 +13496,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+{
+ if (appData.useBGR233 == 256) {
+ XtVaSetValues(w, XtNstate, True, NULL);
-+ if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL);
-+ if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL);
++ if (w64 != NULL) {
++ XtVaSetValues(w64 , XtNstate, False, NULL);
++ }
++ if (w8 != NULL) {
++ XtVaSetValues(w8 , XtNstate, False, NULL);
++ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
@@ -10057,8 +13512,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+{
+ if (appData.useBGR233 == 64) {
+ XtVaSetValues(w, XtNstate, True, NULL);
-+ if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL);
-+ if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL);
++ if (w256 != NULL) {
++ XtVaSetValues(w256, XtNstate, False, NULL);
++ }
++ if (w8 != NULL) {
++ XtVaSetValues(w8 , XtNstate, False, NULL);
++ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
@@ -10069,8 +13528,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+{
+ if (appData.useBGR233 == 8) {
+ XtVaSetValues(w, XtNstate, True, NULL);
-+ if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL);
-+ if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL);
++ if (w256 != NULL) {
++ XtVaSetValues(w256, XtNstate, False, NULL);
++ }
++ if (w64 != NULL) {
++ XtVaSetValues(w64 , XtNstate, False, NULL);
++ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
@@ -10155,104 +13618,115 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi
+ }
+ first = 0;
+
-+ if (usingZRLE)
++ if (usingZRLE) {
+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
++ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetZYWRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (usingZYWRLE)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (usingZYWRLE) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.useRemoteCursor)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.useRemoteCursor) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.useCursorAlpha)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.useCursorAlpha) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.useX11Cursor)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.useX11Cursor) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.useBell)
-+ XtVaSetValues(w, XtNstate, False, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, True, NULL);
++ if (appData.useBell) {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ }
+}
+
+void
+SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.useRawLocal)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.useRawLocal) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (!appData.serverInput)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (!appData.serverInput) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.singleWindow)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.singleWindow) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.chatActive)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.chatActive) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
+}
+
+void
+SetFileXferState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
-+ if (appData.fileActive)
-+ XtVaSetValues(w, XtNstate, True, NULL);
-+ else
-+ XtVaSetValues(w, XtNstate, False, NULL);
++ if (appData.fileActive) {
++ XtVaSetValues(w, XtNstate, True, NULL);
++ } else {
++ XtVaSetValues(w, XtNstate, False, NULL);
++ }
}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncviewer/vncviewer.h
--- vnc_unixsrc.orig/vncviewer/vncviewer.h 2004-03-11 13:14:40.000000000 -0500
-+++ vnc_unixsrc/vncviewer/vncviewer.h 2008-09-13 13:54:01.000000000 -0400
++++ vnc_unixsrc/vncviewer/vncviewer.h 2008-10-17 20:31:48.000000000 -0400
@@ -51,7 +51,7 @@
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x000000ff) << 24)) : (l))
@@ -10262,10 +13736,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
#define FLASH_PORT_OFFSET 5400
#define LISTEN_PORT_OFFSET 5500
-@@ -68,51 +68,77 @@
- /* argsresources.c */
+@@ -65,59 +65,93 @@
+ (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20")
- typedef struct {
+
+-/* argsresources.c */
+-
+-typedef struct {
- Bool shareDesktop;
- Bool viewOnly;
- Bool fullScreen;
@@ -10293,20 +13770,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
-
- int rawDelay;
- int copyRectDelay;
--
++/* for debugging width, height, etc */
++//#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues
+
- Bool debug;
--
+
- int popupButtonCount;
--
++/* argsresources.c */
+
- int bumpScrollTime;
- int bumpScrollPixels;
--
-- int compressLevel;
-- int qualityLevel;
-- Bool enableJPEG;
-- Bool useRemoteCursor;
-- Bool useX11Cursor;
-- Bool autoPass;
++typedef struct {
+ Bool shareDesktop;
+ Bool viewOnly;
+ Bool fullScreen;
@@ -10325,7 +13799,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+ Bool useGreyScale;
+
+ Bool grabAll;
-+ Bool useBackingstore;
++ Bool useXserverBackingStore;
+ Bool overrideRedir;
+ Bool popupFix;
+
@@ -10372,8 +13846,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+ Bool singleWindow;
+ int serverScale;
+ Bool chatActive;
++ Bool chatOnly;
+ Bool fileActive;
+- int compressLevel;
+- int qualityLevel;
+- Bool enableJPEG;
+- Bool useRemoteCursor;
+- Bool useX11Cursor;
+- Bool autoPass;
++ char *scale;
+
} AppData;
extern AppData appData;
@@ -10381,7 +13864,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
extern char *fallback_resources[];
extern char vncServerHost[];
-@@ -130,10 +156,11 @@
+ extern int vncServerPort;
+ extern Bool listenSpecified;
++extern pid_t listenParent;
+ extern int listenPort, flashPort;
+
+ extern XrmOptionDescRec cmdLineOptions[];
+@@ -130,10 +164,11 @@
/* colour.c */
extern unsigned long BGR233ToPixel[];
@@ -10394,7 +13883,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
extern void SetVisualAndCmap();
-@@ -157,13 +184,40 @@
+@@ -157,13 +192,48 @@
extern void DesktopInitBeforeRealization();
extern void DesktopInitAfterRealization();
@@ -10407,11 +13896,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+extern void ReDoDesktop();
+extern void DesktopCursorOff();
-+extern void put_image(int x1, int y1, int x2, int y2, int width, int height);
++extern void put_image(int x1, int y1, int x2, int y2, int width, int height, int solid);
+extern void copy_rect(int x, int y, int width, int height, int src_x, int src_y);
+
++extern void releaseAllPressedModifiers(void);
++extern void fs_grab(int check);
++extern void fs_ungrab(int check);
++
/* dialogs.c */
++extern void ScaleDialogDone(Widget w, XEvent *event, String *params,
++ Cardinal *num_params);
++extern char *DoScaleDialog();
++
+extern void YCropDialogDone(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
+extern char *DoYCropDialog();
@@ -10420,9 +13917,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+ Cardinal *num_params);
+extern char *DoScbarDialog();
+
-+extern void ScaleDialogDone(Widget w, XEvent *event, String *params,
++extern void ScaleNDialogDone(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
-+extern char *DoScaleDialog();
++extern char *DoScaleNDialog();
+
+extern void QualityDialogDone(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
@@ -10435,10 +13932,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
extern void ServerDialogDone(Widget w, XEvent *event, String *params,
Cardinal *num_params);
extern char *DoServerDialog();
-@@ -181,6 +235,11 @@
+@@ -181,6 +251,13 @@
extern void FullScreenOn();
extern void FullScreenOff();
++extern int net_wm_supported(void);
++
+extern void JumpLeft(Widget w, XEvent *event, String *params, Cardinal *num_params);
+extern void JumpRight(Widget w, XEvent *event, String *params, Cardinal *num_params);
+extern void JumpUp(Widget w, XEvent *event, String *params, Cardinal *num_params);
@@ -10447,7 +13946,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
/* listen.c */
extern void listenForIncomingConnections();
-@@ -207,6 +266,18 @@
+@@ -196,6 +273,8 @@
+ Cardinal *num_params);
+ extern void Quit(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
++extern void HideChat(Widget w, XEvent *event, String *params,
++ Cardinal *num_params);
+ extern void Cleanup();
+
+ /* popup.c */
+@@ -207,6 +286,20 @@
Cardinal *num_params);
extern void CreatePopup();
@@ -10463,10 +13971,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+ Cardinal *num_params);
+extern void CreateCompress();
+
++extern void Noop(Widget w, XEvent *event, String *params,
++ Cardinal *num_params);
/* rfbproto.c */
extern int rfbsock;
-@@ -229,6 +300,15 @@
+@@ -229,8 +322,19 @@
extern Bool SendClientCutText(char *str, int len);
extern Bool HandleRFBServerMessage();
@@ -10481,8 +13991,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+
extern void PrintPixelFormat(rfbPixelFormat *format);
++extern double dnow(void);
++
/* selection.c */
-@@ -241,8 +321,9 @@
+
+ extern void InitialiseSelection();
+@@ -241,8 +345,9 @@
/* shm.c */
@@ -10493,7 +14007,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
/* sockets.c */
-@@ -253,8 +334,11 @@
+@@ -253,8 +358,11 @@
extern int FindFreeTcpPort(void);
extern int ListenAtTcpPort(int port);
extern int ConnectToTcpAddr(unsigned int host, int port);
@@ -10505,7 +14019,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
extern int StringToIPAddr(const char *str, unsigned int *addr);
extern Bool SameMachine(int sock);
-@@ -271,3 +355,63 @@
+@@ -271,3 +379,66 @@
extern XtAppContext appContext;
extern Display* dpy;
extern Widget toplevel;
@@ -10530,9 +14044,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+extern void ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void DoServerQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void DoServerCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void SetScale(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ShowScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params);
@@ -10569,9 +14085,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi
+extern void SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetTermTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetFileXferState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
++extern void SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vncviewer/vncviewer.man
--- vnc_unixsrc.orig/vncviewer/vncviewer.man 2004-03-11 13:14:40.000000000 -0500
-+++ vnc_unixsrc/vncviewer/vncviewer.man 2008-09-14 14:32:53.000000000 -0400
++++ vnc_unixsrc/vncviewer/vncviewer.man 2008-10-17 22:04:57.000000000 -0400
@@ -5,38 +5,51 @@
.\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de
.\" Copyright (C) 2000,2001 Red Hat, Inc.
@@ -10583,7 +14100,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
.\" TightVNC distribution.
.\"
-.TH vncviewer 1 "January 2003" "" "TightVNC"
-+.TH ssvncviewer 1 "August 2008" "" "SSVNC"
++.TH ssvncviewer 1 "October 2008" "" "SSVNC"
.SH NAME
-vncviewer \- an X viewer client for VNC
+ssvncviewer \- an X viewer client for VNC
@@ -10632,7 +14149,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
You can use F8 to display a pop\-up utility menu. Press F8 twice to
pass single F8 to the remote side.
.SH OPTIONS
-@@ -168,6 +181,227 @@
+@@ -168,6 +181,244 @@
\fB\-autopass\fR
Read a plain-text password from stdin. This option affects only the
standard VNC authentication.
@@ -10701,6 +14218,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
+requires: x11vnc server, both client and server
+must be 32bpp and same endianness.
+.TP
++\fB\-scale\fR \fIstr\fR
++Scale the desktop locally. The string "str" can
++a floating point ratio, e.g. "0.9", or a fraction,
++e.g. "3/4", or WxH, e.g. 1280x1024. Use "fit"
++to fit in the current screen size.
++Use "auto" to fit in the window size.
++Note that scaling is done in software and can be slow
++and requires more memory. "str" can also be set by
++the env. var. SSVNC_SCALE.
++.TP
+\fB\-ycrop\fR n
+Only show the top n rows of the framebuffer. For
+use with x11vnc \fB\-ncache\fR client caching option
@@ -10811,6 +14338,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
+data sent so as to work with the UltraVNC Server. For some
+reason, each RFB msg type must be sent twice under DSM.
+.TP
++\fB\-chatonly\fR
++Try to be a client that only does UltraVNC text chat. This
++mode is used by x11vnc to present a chat window on the physical
++X11 console (i.e. to chat with the person at the display).
++.TP
+\fB-env\fR \fIVAR=VALUE\fR
+To save writing a shell script to set environment
+variables, specify as many as you need on the command line. For example,
@@ -10841,8 +14373,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
+ 256 colors ~ -bgr233 default # of colors.
+ 64 colors ~ -bgr222 / -use64
+ 8 colors ~ -bgr111 / -use8
++ Scale Viewer ~ -scale
+ Set Y Crop (y-max) ~ -ycrop
+ Set Scrollbar Width ~ -sbwidth
++ XGrabServer ~ -graball
+
+ UltraVNC Extensions:
+
@@ -10860,7 +14394,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
.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.
-@@ -238,6 +472,15 @@
+@@ -238,6 +489,15 @@
\-quality and \-nojpeg options above). Tight encoding is usually the
best choice for low\-bandwidth network environments (e.g. slow modem
connections).
@@ -10876,7 +14410,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
.SH RESOURCES
X resources that \fBvncviewer\fR knows about, aside from the
normal Xt resources, are as follows:
-@@ -364,8 +607,8 @@
+@@ -364,8 +624,8 @@
.B %R
remote TCP port number.
.SH SEE ALSO
@@ -10887,7 +14421,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
.SH AUTHORS
Original VNC was developed in AT&T Laboratories Cambridge. TightVNC
additions was implemented by Constantin Kaplinsky. Many other people
-@@ -380,3 +623,5 @@
+@@ -380,3 +640,5 @@
Tim Waugh <twaugh@redhat.com>,
.br
Constantin Kaplinsky <const@ce.cctpu.edu.ru>
@@ -10895,8 +14429,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc
+Karl Runge <runge@karlrunge.com>
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/zrle.c
--- vnc_unixsrc.orig/vncviewer/zrle.c 2007-02-04 18:59:50.000000000 -0500
-+++ vnc_unixsrc/vncviewer/zrle.c 2008-02-17 10:34:45.000000000 -0500
-@@ -0,0 +1,616 @@
++++ vnc_unixsrc/vncviewer/zrle.c 2008-10-08 00:04:43.000000000 -0400
+@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2005 Johannes E. Schindelin. All Rights Reserved.
+ *
@@ -10948,7 +14482,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/
+ { \
+ XGCValues _gcv; \
+ _gcv.foreground = color; \
-+ if (!appData.useBackingstore) { \
++ if (!appData.useXserverBackingStore) { \
+ FillScreen(x, y, w, h, _gcv.foreground); \
+ } else { \
+ XChangeGC(dpy, gc, GCForeground, &_gcv); \
@@ -11163,6 +14697,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/
+#endif
+
+extern XImage *image;
++extern XImage *image_scale;
+extern int skip_maybe_sync;
+
+static int HandleZRLETile(
@@ -11409,6 +14944,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/
+ char *scr, *buf;
+ static CARDBPP *ptmp = NULL;
+ static int ptmp_len = 0;
++ XImage *im = image_scale ? image_scale : image;
+
+ if (w * h > ptmp_len) {
+ ptmp_len = w * h;
@@ -11426,7 +14962,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/
+ // make this CopyDataFromScreen() or something.
+ if (!appData.useBGR565) {
+ scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
-+ scr = image->data + y * scrWidthInBytes + x * myFormat.bitsPerPixel / 8;
++ scr = im->data + y * scrWidthInBytes + x * myFormat.bitsPerPixel / 8;
+ buf = (char *) ptmp;
+
+ for (th = 0; th < h; th++) {
@@ -11436,7 +14972,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/
+ }
+ } else {
+ scrWidthInBytes = si.framebufferWidth * 4;
-+ scr = image->data + y * scrWidthInBytes + x * 4;
++ scr = im->data + y * scrWidthInBytes + x * 4;
+ buf = (char *) ptmp;
+
+ for (th = 0; th < h; th++) {