mirror of
https://github.com/TigerVNC/tigervnc.git
synced 2024-08-21 17:54:34 +02:00
![Peter Åstrand](/assets/img/avatar_default.png)
Also, the Windows viewer now accepts arguments with both spellings. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@69 3789f03b-4d11-0410-bbf8-ca57d06f2519
264 lines
8.6 KiB
C++
264 lines
8.6 KiB
C++
/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
|
|
*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This software is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this software; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
* USA.
|
|
*/
|
|
//
|
|
// All-new VNC viewer for X.
|
|
//
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <rfb/Logger_stdio.h>
|
|
#include <rfb/LogWriter.h>
|
|
#include <network/TcpSocket.h>
|
|
#include "TXWindow.h"
|
|
#include "CConn.h"
|
|
|
|
rfb::LogWriter vlog("main");
|
|
|
|
using namespace network;
|
|
using namespace rfb;
|
|
|
|
IntParameter pointerEventInterval("PointerEventInterval",
|
|
"Time in milliseconds to rate-limit"
|
|
" successive pointer events", 0);
|
|
IntParameter wmDecorationWidth("WMDecorationWidth", "Width of window manager "
|
|
"decoration around a window", 6);
|
|
IntParameter wmDecorationHeight("WMDecorationHeight", "Height of window "
|
|
"manager decoration around a window", 24);
|
|
StringParameter passwordFile("PasswordFile",
|
|
"Password file for VNC authentication", "");
|
|
AliasParameter rfbauth("passwd", "Alias for PasswordFile", &passwordFile);
|
|
|
|
BoolParameter useLocalCursor("UseLocalCursor",
|
|
"Render the mouse cursor locally", true);
|
|
BoolParameter dotWhenNoCursor("DotWhenNoCursor",
|
|
"Show the dot cursor when the server sends an "
|
|
"invisible cursor", true);
|
|
BoolParameter autoSelect("AutoSelect",
|
|
"Auto select pixel format and encoding", true);
|
|
BoolParameter fullColour("FullColor",
|
|
"Use full color", true);
|
|
AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour);
|
|
IntParameter lowColourLevel("LowColorLevel",
|
|
"Color level to use on slow connections. "
|
|
"0 = Very Low (8 colors), 1 = Low (64 colors), "
|
|
"2 = Medium (256 colors)", 2);
|
|
AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel);
|
|
StringParameter preferredEncoding("PreferredEncoding",
|
|
"Preferred encoding to use (ZRLE, hextile or"
|
|
" raw) - implies AutoSelect=0", "");
|
|
BoolParameter fullScreen("FullScreen", "Full screen mode", false);
|
|
BoolParameter viewOnly("ViewOnly",
|
|
"Don't send any mouse or keyboard events to the server",
|
|
false);
|
|
BoolParameter shared("Shared",
|
|
"Don't disconnect other viewers upon connection - "
|
|
"share the desktop instead",
|
|
false);
|
|
BoolParameter acceptClipboard("AcceptClipboard",
|
|
"Accept clipboard changes from the server",
|
|
true);
|
|
BoolParameter sendClipboard("SendClipboard",
|
|
"Send clipboard changes to the server", true);
|
|
BoolParameter sendPrimary("SendPrimary",
|
|
"Send the primary selection and cut buffer to the "
|
|
"server as well as the clipboard selection",
|
|
true);
|
|
|
|
BoolParameter listenMode("listen", "Listen for connections from VNC servers",
|
|
false);
|
|
StringParameter geometry("geometry", "X geometry specification", "");
|
|
StringParameter displayname("display", "The X display", "");
|
|
|
|
BoolParameter customCompressLevel("CustomCompressLevel",
|
|
"Use custom compression level",
|
|
false);
|
|
|
|
IntParameter compressLevel("CompressLevel",
|
|
"Use specified compression level"
|
|
"0 = Low, 9 = High",
|
|
6);
|
|
|
|
BoolParameter noJpeg("NoJPEG",
|
|
"Disable lossy JPEG compression in Tight encoding.",
|
|
false);
|
|
|
|
IntParameter qualityLevel("QualityLevel",
|
|
"JPEG quality level. "
|
|
"0 = Low, 9 = High",
|
|
6);
|
|
|
|
char aboutText[256];
|
|
char* programName;
|
|
extern char buildtime[];
|
|
|
|
static void CleanupSignalHandler(int sig)
|
|
{
|
|
// CleanupSignalHandler allows C++ object cleanup to happen because it calls
|
|
// exit() rather than the default which is to abort.
|
|
vlog.info("CleanupSignalHandler called");
|
|
exit(1);
|
|
}
|
|
|
|
// XLoginIconifier is a class which iconifies the XDM login window when it has
|
|
// grabbed the keyboard, thus releasing the grab, allowing the viewer to use
|
|
// the keyboard. It remaps the xlogin window on exit.
|
|
class XLoginIconifier {
|
|
public:
|
|
Display* dpy;
|
|
Window xlogin;
|
|
XLoginIconifier() : dpy(0), xlogin(0) {}
|
|
void iconify(Display* dpy_) {
|
|
dpy = dpy_;
|
|
if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync,
|
|
GrabModeSync, CurrentTime) == GrabSuccess) {
|
|
XUngrabKeyboard(dpy, CurrentTime);
|
|
} else {
|
|
xlogin = TXWindow::windowWithName(dpy, DefaultRootWindow(dpy), "xlogin");
|
|
if (xlogin) {
|
|
XIconifyWindow(dpy, xlogin, DefaultScreen(dpy));
|
|
XSync(dpy, False);
|
|
}
|
|
}
|
|
}
|
|
~XLoginIconifier() {
|
|
if (xlogin) {
|
|
fprintf(stderr,"~XLoginIconifier remapping xlogin\n");
|
|
XMapWindow(dpy, xlogin);
|
|
XFlush(dpy);
|
|
sleep(1);
|
|
}
|
|
}
|
|
};
|
|
|
|
static XLoginIconifier xloginIconifier;
|
|
|
|
static void usage()
|
|
{
|
|
fprintf(stderr,
|
|
"\nusage: %s [parameters] [host:displayNum] [parameters]\n"
|
|
" %s [parameters] -listen [port] [parameters]\n",
|
|
programName,programName);
|
|
fprintf(stderr,"\n"
|
|
"Parameters can be turned on with -<param> or off with -<param>=0\n"
|
|
"Parameters which take a value can be specified as "
|
|
"-<param> <value>\n"
|
|
"Other valid forms are <param>=<value> -<param>=<value> "
|
|
"--<param>=<value>\n"
|
|
"Parameter names are case-insensitive. The parameters are:\n\n");
|
|
Configuration::listParams(79, 14);
|
|
exit(1);
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
sprintf(aboutText, "TightVNC viewer for X version 4.0 - built %s\n"
|
|
"Copyright (C) 2002-2004 RealVNC Ltd.\n"
|
|
"Copyright (C) 2000-2004 Constantin Kaplinsky.\n"
|
|
"Copyright (C) 2004 Peter Astrand, Cendio AB\n"
|
|
"See http://www.tightvnc.com for information on TightVNC.",
|
|
buildtime);
|
|
fprintf(stderr,"\n%s\n", aboutText);
|
|
|
|
rfb::initStdIOLoggers();
|
|
rfb::LogWriter::setLogParams("*:stderr:30");
|
|
|
|
signal(SIGHUP, CleanupSignalHandler);
|
|
signal(SIGINT, CleanupSignalHandler);
|
|
signal(SIGTERM, CleanupSignalHandler);
|
|
|
|
programName = argv[0];
|
|
char* vncServerName = 0;
|
|
Display* dpy;
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
if (Configuration::setParam(argv[i]))
|
|
continue;
|
|
|
|
if (argv[i][0] == '-') {
|
|
if (i+1 < argc) {
|
|
if (Configuration::setParam(&argv[i][1], argv[i+1])) {
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
usage();
|
|
}
|
|
|
|
if (vncServerName)
|
|
usage();
|
|
vncServerName = argv[i];
|
|
}
|
|
|
|
try {
|
|
TcpSocket::initTcpSockets();
|
|
|
|
Socket* sock = 0;
|
|
|
|
if (listenMode) {
|
|
int port = 5500;
|
|
if (vncServerName && isdigit(vncServerName[0]))
|
|
port = atoi(vncServerName);
|
|
|
|
TcpListener listener(port);
|
|
|
|
vlog.info("Listening on port %d\n",port);
|
|
|
|
while (true) {
|
|
sock = listener.accept();
|
|
int pid = fork();
|
|
if (pid < 0) { perror("fork"); exit(1); }
|
|
if (pid == 0) break; // child
|
|
delete sock;
|
|
int status;
|
|
while (wait3(&status, WNOHANG, 0) > 0) ;
|
|
}
|
|
}
|
|
|
|
CharArray displaynameStr(displayname.getData());
|
|
if (!(dpy = XOpenDisplay(TXWindow::strEmptyToNull(displaynameStr.buf)))) {
|
|
fprintf(stderr,"%s: unable to open display \"%s\"\n",
|
|
programName, XDisplayName(displaynameStr.buf));
|
|
exit(1);
|
|
}
|
|
|
|
TXWindow::init(dpy, "Vncviewer");
|
|
xloginIconifier.iconify(dpy);
|
|
CConn cc(dpy, argc, argv, sock, vncServerName);
|
|
|
|
// X events are processed whenever reading from the socket would block.
|
|
|
|
while (true) {
|
|
cc.getInStream()->check(1);
|
|
cc.processMsg();
|
|
}
|
|
|
|
} catch (rdr::Exception &e) {
|
|
vlog.error(e.str());
|
|
}
|
|
|
|
return 0;
|
|
}
|