diff options
author | runge <runge> | 2008-10-19 16:33:22 +0000 |
---|---|---|
committer | runge <runge> | 2008-10-19 16:33:22 +0000 |
commit | 8938cda1e7e09d946475fddaba46194baf7e6388 (patch) | |
tree | 6aacd449c9b71749d4b05d6278011b2615377e36 /x11vnc/misc/enhanced_tightvnc_viewer/src/patches | |
parent | 73f19d71e0dbdf4f5237e89bd431b971dacbca99 (diff) | |
download | libtdevnc-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-x | x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle | 2 | ||||
-rw-r--r-- | x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch | 5474 |
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++) { |