You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vncviewer.cxx 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. //
  19. // All-new VNC viewer for X.
  20. //
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <ctype.h>
  24. #include <stdlib.h>
  25. #include <sys/time.h>
  26. #include <sys/types.h>
  27. #include <sys/wait.h>
  28. #include <unistd.h>
  29. #include <errno.h>
  30. #include <signal.h>
  31. #include <rfb/Logger_stdio.h>
  32. #include <rfb/LogWriter.h>
  33. #include <network/TcpSocket.h>
  34. #include "TXWindow.h"
  35. #include "CConn.h"
  36. #include <intl/gettext.h>
  37. #define _(String) gettext (String)
  38. #define gettext_noop(String) String
  39. #define N_(String) gettext_noop (String)
  40. rfb::LogWriter vlog("main");
  41. using namespace network;
  42. using namespace rfb;
  43. IntParameter pointerEventInterval("PointerEventInterval",
  44. "Time in milliseconds to rate-limit"
  45. " successive pointer events", 0);
  46. IntParameter wmDecorationWidth("WMDecorationWidth", "Width of window manager "
  47. "decoration around a window", 6);
  48. IntParameter wmDecorationHeight("WMDecorationHeight", "Height of window "
  49. "manager decoration around a window", 24);
  50. StringParameter passwordFile("PasswordFile",
  51. "Password file for VNC authentication", "");
  52. AliasParameter rfbauth("passwd", "Alias for PasswordFile", &passwordFile);
  53. BoolParameter useLocalCursor("UseLocalCursor",
  54. "Render the mouse cursor locally", true);
  55. BoolParameter dotWhenNoCursor("DotWhenNoCursor",
  56. "Show the dot cursor when the server sends an "
  57. "invisible cursor", true);
  58. BoolParameter autoSelect("AutoSelect",
  59. "Auto select pixel format and encoding. "
  60. "Default if PreferredEncoding and FullColor are not specified.",
  61. true);
  62. BoolParameter fullColour("FullColor",
  63. "Use full color", true);
  64. AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour);
  65. IntParameter lowColourLevel("LowColorLevel",
  66. "Color level to use on slow connections. "
  67. "0 = Very Low (8 colors), 1 = Low (64 colors), "
  68. "2 = Medium (256 colors)", 2);
  69. AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel);
  70. StringParameter preferredEncoding("PreferredEncoding",
  71. "Preferred encoding to use (Tight, ZRLE, Hextile or"
  72. " Raw)", "Tight");
  73. BoolParameter fullScreen("FullScreen", "Full screen mode", false);
  74. BoolParameter viewOnly("ViewOnly",
  75. "Don't send any mouse or keyboard events to the server",
  76. false);
  77. BoolParameter shared("Shared",
  78. "Don't disconnect other viewers upon connection - "
  79. "share the desktop instead",
  80. false);
  81. BoolParameter acceptClipboard("AcceptClipboard",
  82. "Accept clipboard changes from the server",
  83. true);
  84. BoolParameter sendClipboard("SendClipboard",
  85. "Send clipboard changes to the server", true);
  86. BoolParameter sendPrimary("SendPrimary",
  87. "Send the primary selection and cut buffer to the "
  88. "server as well as the clipboard selection",
  89. true);
  90. BoolParameter listenMode("listen", "Listen for connections from VNC servers",
  91. false);
  92. StringParameter geometry("geometry", "X geometry specification", "");
  93. StringParameter displayname("display", "The X display", "");
  94. BoolParameter customCompressLevel("CustomCompressLevel",
  95. "Use custom compression level. "
  96. "Default if CompressLevel is specified.", false);
  97. IntParameter compressLevel("CompressLevel",
  98. "Use specified compression level"
  99. "0 = Low, 9 = High",
  100. 6);
  101. BoolParameter noJpeg("NoJPEG",
  102. "Disable lossy JPEG compression in Tight encoding.",
  103. false);
  104. IntParameter qualityLevel("QualityLevel",
  105. "JPEG quality level. "
  106. "0 = Low, 9 = High",
  107. 6);
  108. char aboutText[1024];
  109. char* programName;
  110. extern char buildtime[];
  111. static void CleanupSignalHandler(int sig)
  112. {
  113. // CleanupSignalHandler allows C++ object cleanup to happen because it calls
  114. // exit() rather than the default which is to abort.
  115. vlog.info("CleanupSignalHandler called");
  116. exit(1);
  117. }
  118. // XLoginIconifier is a class which iconifies the XDM login window when it has
  119. // grabbed the keyboard, thus releasing the grab, allowing the viewer to use
  120. // the keyboard. It remaps the xlogin window on exit.
  121. class XLoginIconifier {
  122. public:
  123. Display* dpy;
  124. Window xlogin;
  125. XLoginIconifier() : dpy(0), xlogin(0) {}
  126. void iconify(Display* dpy_) {
  127. dpy = dpy_;
  128. if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync,
  129. GrabModeSync, CurrentTime) == GrabSuccess) {
  130. XUngrabKeyboard(dpy, CurrentTime);
  131. } else {
  132. xlogin = TXWindow::windowWithName(dpy, DefaultRootWindow(dpy), "xlogin");
  133. if (xlogin) {
  134. XIconifyWindow(dpy, xlogin, DefaultScreen(dpy));
  135. XSync(dpy, False);
  136. }
  137. }
  138. }
  139. ~XLoginIconifier() {
  140. if (xlogin) {
  141. fprintf(stderr,"~XLoginIconifier remapping xlogin\n");
  142. XMapWindow(dpy, xlogin);
  143. XFlush(dpy);
  144. sleep(1);
  145. }
  146. }
  147. };
  148. static XLoginIconifier xloginIconifier;
  149. static void usage()
  150. {
  151. fprintf(stderr,
  152. "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
  153. " %s [parameters] -listen [port] [parameters]\n",
  154. programName,programName);
  155. fprintf(stderr,"\n"
  156. "Parameters can be turned on with -<param> or off with -<param>=0\n"
  157. "Parameters which take a value can be specified as "
  158. "-<param> <value>\n"
  159. "Other valid forms are <param>=<value> -<param>=<value> "
  160. "--<param>=<value>\n"
  161. "Parameter names are case-insensitive. The parameters are:\n\n");
  162. Configuration::listParams(79, 14);
  163. exit(1);
  164. }
  165. int main(int argc, char** argv)
  166. {
  167. setlocale(LC_ALL, "");
  168. bindtextdomain(PACKAGE, LOCALEDIR);
  169. textdomain(PACKAGE);
  170. snprintf(aboutText, sizeof(aboutText),
  171. _("TightVNC viewer for X version 4.0 - built %s\n"
  172. "Copyright (C) 2002-2004 RealVNC Ltd.\n"
  173. "Copyright (C) 2000-2004 Constantin Kaplinsky.\n"
  174. "Copyright (C) 2004 Peter Astrand, Cendio AB\n"
  175. "See http://www.tightvnc.com for information on TightVNC."),
  176. buildtime);
  177. fprintf(stderr,"\n%s\n", aboutText);
  178. rfb::initStdIOLoggers();
  179. rfb::LogWriter::setLogParams("*:stderr:30");
  180. signal(SIGHUP, CleanupSignalHandler);
  181. signal(SIGINT, CleanupSignalHandler);
  182. signal(SIGTERM, CleanupSignalHandler);
  183. programName = argv[0];
  184. char* vncServerName = 0;
  185. Display* dpy;
  186. for (int i = 1; i < argc; i++) {
  187. if (Configuration::setParam(argv[i]))
  188. continue;
  189. if (argv[i][0] == '-') {
  190. if (i+1 < argc) {
  191. if (Configuration::setParam(&argv[i][1], argv[i+1])) {
  192. i++;
  193. continue;
  194. }
  195. }
  196. usage();
  197. }
  198. if (vncServerName)
  199. usage();
  200. vncServerName = argv[i];
  201. }
  202. if (!::autoSelect.hasBeenSet()) {
  203. // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
  204. ::autoSelect.setParam(!::preferredEncoding.hasBeenSet()
  205. && !::fullColour.hasBeenSet()
  206. && !::fullColourAlias.hasBeenSet());
  207. }
  208. if (!::customCompressLevel.hasBeenSet()) {
  209. // Default to CustomCompressLevel=1 if CompressLevel is used.
  210. ::customCompressLevel.setParam(::compressLevel.hasBeenSet());
  211. }
  212. try {
  213. TcpSocket::initTcpSockets();
  214. Socket* sock = 0;
  215. if (listenMode) {
  216. int port = 5500;
  217. if (vncServerName && isdigit(vncServerName[0]))
  218. port = atoi(vncServerName);
  219. TcpListener listener(port);
  220. vlog.info("Listening on port %d\n",port);
  221. while (true) {
  222. sock = listener.accept();
  223. int pid = fork();
  224. if (pid < 0) { perror("fork"); exit(1); }
  225. if (pid == 0) break; // child
  226. delete sock;
  227. int status;
  228. while (wait3(&status, WNOHANG, 0) > 0) ;
  229. }
  230. }
  231. CharArray displaynameStr(displayname.getData());
  232. if (!(dpy = XOpenDisplay(TXWindow::strEmptyToNull(displaynameStr.buf)))) {
  233. fprintf(stderr,"%s: unable to open display \"%s\"\n",
  234. programName, XDisplayName(displaynameStr.buf));
  235. exit(1);
  236. }
  237. TXWindow::init(dpy, "Vncviewer");
  238. xloginIconifier.iconify(dpy);
  239. CConn cc(dpy, argc, argv, sock, vncServerName);
  240. // X events are processed whenever reading from the socket would block.
  241. while (true) {
  242. cc.getInStream()->check(1);
  243. cc.processMsg();
  244. }
  245. } catch (rdr::Exception &e) {
  246. vlog.error(e.str());
  247. }
  248. return 0;
  249. }