-/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
-/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
#include <rfb/Hostname.h>
#include <rfb/LogWriter.h>
#include <rfb/util.h>
+#include <rfb/Password.h>
#include <network/TcpSocket.h>
#include "TXViewport.h"
StringParameter windowName("name", "The X window name", "");
CConn::CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_,
- char* vncServerName)
+ char* vncServerName, bool reverse)
: dpy(dpy_), argc(argc_),
argv(argv_), serverHost(0), serverPort(0), sock(sock_), viewport(0),
desktop(0), desktopEventHandler(0),
autoSelect(::autoSelect), shared(::shared), formatChange(false),
encodingChange(false), sameMachine(false), fullScreen(::fullScreen),
ctrlDown(false), altDown(false),
- menuKeysym(0), menu(dpy, this), options(dpy, this), about(dpy), info(dpy)
+ menuKeysym(0), menu(dpy, this), options(dpy, this), about(dpy), info(dpy),
+ reverseConnection(reverse)
{
CharArray menuKeyStr(menuKey.getData());
menuKeysym = XStringToKeysym(menuKeyStr.buf);
void CConn::blockCallback() {
fd_set rfds;
do {
- TXWindow::handleXEvents(dpy);
struct timeval tv;
- struct timeval* tvp;
- if (Timer::getTimeout(&tv))
+ struct timeval* tvp = 0;
+
+ // Process any incoming X events
+ TXWindow::handleXEvents(dpy);
+
+ // Process expired timers and get the time until the next one
+ int timeoutMs = Timer::checkTimeouts();
+ if (timeoutMs) {
+ tv.tv_sec = timeoutMs / 1000;
+ tv.tv_usec = (timeoutMs % 1000) * 1000;
tvp = &tv;
- else
- tvp = 0;
+ }
+
+ // If there are X requests pending then poll, don't wait!
+ if (XPending(dpy)) {
+ tv.tv_usec = tv.tv_sec = 0;
+ tvp = &tv;
+ }
+
+ // Wait for X events, VNC traffic, or the next timer expiry
FD_ZERO(&rfds);
FD_SET(ConnectionNumber(dpy), &rfds);
FD_SET(sock->getFd(), &rfds);
int n = select(FD_SETSIZE, &rfds, 0, 0, tvp);
if (n < 0) throw rdr::SystemException("select",errno);
- Timer::callTimers();
} while (!(FD_ISSET(sock->getFd(), &rfds)));
}
// getPasswd() is called by the CSecurity object when it needs us to read a
// password from the user.
-bool CConn::getUserPasswd(char** user, char** password)
+void CConn::getUserPasswd(char** user, char** password)
{
CharArray passwordFileStr(passwordFile.getData());
if (!user && passwordFileStr.buf[0]) {
FILE* fp = fopen(passwordFileStr.buf, "r");
- if (!fp) return false;
- char data[256];
- int datalen = fread(data, 1, 256, fp);
+ if (!fp) throw rfb::Exception("Opening password file failed");
+ ObfuscatedPasswd obfPwd(256);
+ obfPwd.length = fread(obfPwd.buf, 1, obfPwd.length, fp);
fclose(fp);
- if (datalen != 8) return false;
- vncAuthUnobfuscatePasswd(data);
- *password = strDup(data);
- memset(data, 0, strlen(data));
- return true;
+ PlainPasswd passwd(obfPwd);
+ *password = passwd.takeBuf();
+ return;
}
const char* secType = secTypeName(getCurrentCSecurity()->getType());
CharArray title(titleLen);
snprintf(title.buf, titleLen, "%s [%s]", titlePrefix, secType);
PasswdDialog dlg(dpy, title.buf, !user);
- if (!dlg.show()) return false;
+ if (!dlg.show()) throw rfb::Exception("Authentication cancelled");
if (user)
*user = strDup(dlg.userEntry.getText());
*password = strDup(dlg.passwdEntry.getText());
- return true;
}
void CConn::copyRect(const rfb::Rect& r, int sx, int sy) {
desktop->copyRect(r,sx,sy);
}
-void CConn::setCursor(const Point& hotspot, const Point& size,
+void CConn::setCursor(int width, int height, const Point& hotspot,
void* data, void* mask) {
- desktop->setCursor(hotspot, size, data, mask);
+ desktop->setCursor(width, height, hotspot, data, mask);
}
case ID_F8:
menu.unmap();
if (!viewOnly) {
- writer()->writeKeyEvent(menuKeysym, true);
- writer()->writeKeyEvent(menuKeysym, false);
+ writer()->keyEvent(menuKeysym, true);
+ writer()->keyEvent(menuKeysym, false);
}
break;
case ID_CTRLALTDEL:
menu.unmap();
if (!viewOnly) {
- writer()->writeKeyEvent(XK_Control_L, true);
- writer()->writeKeyEvent(XK_Alt_L, true);
- writer()->writeKeyEvent(XK_Delete, true);
- writer()->writeKeyEvent(XK_Delete, false);
- writer()->writeKeyEvent(XK_Alt_L, false);
- writer()->writeKeyEvent(XK_Control_L, false);
+ writer()->keyEvent(XK_Control_L, true);
+ writer()->keyEvent(XK_Alt_L, true);
+ writer()->keyEvent(XK_Delete, true);
+ writer()->keyEvent(XK_Delete, false);
+ writer()->keyEvent(XK_Alt_L, false);
+ writer()->keyEvent(XK_Control_L, false);
}
break;
case ID_CTRL:
menu.unmap();
if (!viewOnly) {
ctrlDown = !ctrlDown;
- writer()->writeKeyEvent(XK_Control_L, ctrlDown);
+ writer()->keyEvent(XK_Control_L, ctrlDown);
menu.check(ID_CTRL, ctrlDown);
}
break;
menu.unmap();
if (!viewOnly) {
altDown = !altDown;
- writer()->writeKeyEvent(XK_Alt_L, altDown);
+ writer()->keyEvent(XK_Alt_L, altDown);
menu.check(ID_ALT, altDown);
}
break;
-/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
public:
CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_,
- char* vncServerName);
+ char* vncServerName, bool reverse=false);
~CConn();
// TXDeleteWindowCallback methods
void blockCallback();
// UserPasswdGetter methods
- virtual bool getUserPasswd(char** user, char** password);
+ virtual void getUserPasswd(char** user, char** password);
// TXMenuCallback methods
void menuSelect(long id, TXMenu* m);
// TXEventHandler callback method
virtual void handleEvent(TXWindow* w, XEvent* ev);
-
+
// CConnection callback methods
rfb::CSecurity* getCSecurity(int secType);
void serverInit();
void fillRect(const rfb::Rect& r, rfb::Pixel p);
void imageRect(const rfb::Rect& r, void* p);
void copyRect(const rfb::Rect& r, int sx, int sy);
- void setCursor(const rfb::Point& hotspot, const rfb::Point& size,
+ void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask);
private:
OptionsDialog options;
AboutDialog about;
InfoDialog info;
+ bool reverseConnection;
};
#endif
-/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
newSelection(0), gettingInitialSelectionTime(true),
newServerCutText(false), serverCutText_(0),
setColourMapEntriesTimer(this), viewport(0),
- pointerEventTimer(this), lastPointerX(0), lastPointerY(0),
+ pointerEventTimer(this),
lastButtonMask(0)
{
setEventHandler(this);
localXCursor = 0;
}
-void DesktopWindow::setCursor(const Point& hotspot, const Point& size,
+void DesktopWindow::setCursor(int width, int height, const Point& hotspot,
void* data, void* mask)
{
if (!useLocalCursor) return;
hideLocalCursor();
- int mask_len = ((size.x+7)/8) * size.y;
+ int mask_len = ((width+7)/8) * height;
int i;
for (i = 0; i < mask_len; i++)
cursor.hotspot = hotspot;
- cursor.setSize(size.x, size.y);
+ cursor.setSize(width, height);
cursor.setPF(getPF());
cursor.imageRect(cursor.getRect(), data);
- cursorBacking.setSize(size.x, size.y);
+ cursorBacking.setSize(width, height);
cursorBacking.setPF(getPF());
delete [] cursor.mask.buf;
rdr::U16* rgbs)
{
im->setColourMapEntries(firstColour, nColours, rgbs);
- if (!setColourMapEntriesTimer.isSet())
- setColourMapEntriesTimer.reset(100);
+ if (!setColourMapEntriesTimer.isStarted())
+ setColourMapEntriesTimer.start(100);
}
void DesktopWindow::serverCutText(const char* str, int len)
}
-void DesktopWindow::timerCallback(Timer* timer)
+bool DesktopWindow::handleTimeout(rfb::Timer* timer)
{
if (timer == &setColourMapEntriesTimer) {
im->updateColourMap();
im->put(win(), gc, im->getRect());
} else if (timer == &pointerEventTimer) {
if (!viewOnly) {
- cc->writer()->writePointerEvent(lastPointerX, lastPointerY,
- lastButtonMask);
+ cc->writer()->pointerEvent(lastPointerPos, lastButtonMask);
}
}
+ return false;
}
-void DesktopWindow::handlePointerEvent(int x, int y, int buttonMask)
+void DesktopWindow::handlePointerEvent(const Point& pos, int buttonMask)
{
if (!viewOnly) {
if (pointerEventInterval == 0 || buttonMask != lastButtonMask) {
- cc->writer()->writePointerEvent(x, y, buttonMask);
+ cc->writer()->pointerEvent(pos, buttonMask);
} else {
- if (!pointerEventTimer.isSet())
- pointerEventTimer.reset(pointerEventInterval);
+ if (!pointerEventTimer.isStarted())
+ pointerEventTimer.start(pointerEventInterval);
}
- lastPointerX = x;
- lastPointerY = y;
+ lastPointerPos = pos;
lastButtonMask = buttonMask;
}
// - If local cursor rendering is enabled then use it
if (cursorAvailable) {
// - Render the cursor!
- Point p(x, y);
- if (!p.equals(cursorPos)) {
+ if (!pos.equals(cursorPos)) {
hideLocalCursor();
- if (im->getRect().contains(p)) {
- cursorPos = p;
+ if (im->getRect().contains(pos)) {
+ cursorPos = pos;
showLocalCursor();
}
}
case MotionNotify:
while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev));
if (viewport && viewport->bumpScrollEvent(&ev->xmotion)) break;
- handlePointerEvent(ev->xmotion.x, ev->xmotion.y,
+ handlePointerEvent(Point(ev->xmotion.x, ev->xmotion.y),
(ev->xmotion.state & 0x1f00) >> 8);
break;
case ButtonPress:
- handlePointerEvent(ev->xbutton.x, ev->xbutton.y,
+ handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y),
(((ev->xbutton.state & 0x1f00) >> 8) |
(1 << (ev->xbutton.button-1))));
break;
case ButtonRelease:
- handlePointerEvent(ev->xbutton.x, ev->xbutton.y,
+ handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y),
(((ev->xbutton.state & 0x1f00) >> 8) &
~(1 << (ev->xbutton.button-1))));
break;
}
if (fakeShiftPress)
- cc->writer()->writeKeyEvent(XK_Shift_L, true);
+ cc->writer()->keyEvent(XK_Shift_L, true);
downKeysym[ev->xkey.keycode] = ks;
- cc->writer()->writeKeyEvent(ks, true);
+ cc->writer()->keyEvent(ks, true);
if (fakeShiftPress)
- cc->writer()->writeKeyEvent(XK_Shift_L, false);
+ cc->writer()->keyEvent(XK_Shift_L, false);
break;
}
case KeyRelease:
if (!viewOnly) {
if (downKeysym[ev->xkey.keycode]) {
- cc->writer()->writeKeyEvent(downKeysym[ev->xkey.keycode], false);
+ cc->writer()->keyEvent(downKeysym[ev->xkey.keycode], false);
downKeysym[ev->xkey.keycode] = 0;
}
}
// LeaveNotify is near enough...
for (int i = 8; i < 256; i++) {
if (downKeysym[i]) {
- cc->writer()->writeKeyEvent(downKeysym[i], false);
+ cc->writer()->keyEvent(downKeysym[i], false);
downKeysym[i] = 0;
}
}
if (str) {
if (!viewOnly) {
vlog.debug("sending cut buffer to server");
- cc->writer()->writeClientCutText(str, len);
+ cc->writer()->clientCutText(str, len);
}
XFree(str);
return;
vlog.debug("sending %s selection to server",
ev->selection == XA_PRIMARY ? "primary" :
ev->selection == xaCLIPBOARD ? "clipboard" : "unknown" );
- cc->writer()->writeClientCutText((char*)data, nitems);
+ cc->writer()->clientCutText((char*)data, nitems);
}
}
}
-/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
#include <rfb/Cursor.h>
#include <rfb/Rect.h>
+#include <rfb/Timer.h>
#include "TXWindow.h"
#include "TXViewport.h"
#include "TXImage.h"
-#include "Timer.h"
class CConn;
class DesktopWindow : public TXWindow, public TXEventHandler,
- public TimerCallback {
+ public rfb::Timer::Callback {
public:
DesktopWindow(Display* dpy, int w, int h,
void setPF(const rfb::PixelFormat& pf) { im->setPF(pf); }
// setCursor() sets the shape of the local cursor
- void setCursor(const rfb::Point& hotspot, const rfb::Point& size,
+ void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask);
// resetLocalCursor() stops the rendering of the local cursor
void createXCursors();
void hideLocalCursor();
void showLocalCursor();
- void timerCallback(Timer* timer);
- void handlePointerEvent(int x, int y, int buttonMask);
+ bool handleTimeout(rfb::Timer* timer);
+ void handlePointerEvent(const rfb::Point& pos, int buttonMask);
CConn* cc;
TXImage* im;
bool newServerCutText;
char* serverCutText_;
- Timer setColourMapEntriesTimer;
+ rfb::Timer setColourMapEntriesTimer;
TXViewport* viewport;
- Timer pointerEventTimer;
- int lastPointerX, lastPointerY, lastButtonMask;
+ rfb::Timer pointerEventTimer;
+ rfb::Point lastPointerPos;
+ int lastButtonMask;
rdr::U32 downKeysym[256];
};
-/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
-/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
-/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
-/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
-/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
-/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
-/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
- *
+/* Copyright (C) 2002-2005 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
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <rfb/LogWriter.h>
#include <network/TcpSocket.h>
#include "TXWindow.h"
+#include "TXMsgBox.h"
#include "CConn.h"
#include <intl/gettext.h>
textdomain(PACKAGE);
snprintf(aboutText, sizeof(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-2005 Peter Astrand, Cendio AB\n"
- "See http://www.tightvnc.com for information on TightVNC."),
- buildtime);
+ _("TightVNC viewer for X version 1.5 - built %s\n"
+ "Copyright (C) 2002-2005 RealVNC Ltd.\n"
+ "Copyright (C) 2000-2004 Constantin Kaplinsky\n"
+ "Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n"
+ "See http://www.tightvnc.com for information on TightVNC."),
+ buildtime);
fprintf(stderr,"\n%s\n", aboutText);
bind_textdomain_codeset(PACKAGE, "iso-8859-1");
programName = argv[0];
char* vncServerName = 0;
- Display* dpy;
+ Display* dpy = 0;
for (int i = 1; i < argc; i++) {
if (Configuration::setParam(argv[i]))
vncServerName = argv[i];
}
+ // Create .vnc in the user's home directory if it doesn't already exist
+ char* homeDir = getenv("HOME");
+ if (homeDir) {
+ CharArray vncDir(strlen(homeDir)+6);
+ sprintf(vncDir.buf, "%s/.vnc", homeDir);
+ int result = mkdir(vncDir.buf, 0755);
+ if (result == -1 && errno != EEXIST)
+ vlog.error("Could not create .vnc directory: %s.", strerror(errno));
+ } else
+ vlog.error("Could not create .vnc directory: environment variable $HOME not set.");
+
if (!::autoSelect.hasBeenSet()) {
// Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
::autoSelect.setParam(!::preferredEncoding.hasBeenSet()
}
try {
- TcpSocket::initTcpSockets();
-
/* Tunnelling support. */
if (strlen (via.getValueStr ()) > 0) {
char *gatewayHost = "";
TXWindow::init(dpy, "Vncviewer");
xloginIconifier.iconify(dpy);
- CConn cc(dpy, argc, argv, sock, vncServerName);
+ CConn cc(dpy, argc, argv, sock, vncServerName, listenMode);
// X events are processed whenever reading from the socket would block.
cc.processMsg();
}
- } catch (rdr::Exception &e) {
+ } catch (rdr::EndOfStream& e) {
+ vlog.info(e.str());
+ } catch (rdr::Exception& e) {
vlog.error(e.str());
+ if (dpy) {
+ TXMsgBox msgBox(dpy, e.str(), MB_OK, "VNC Viewer: Information");
+ msgBox.show();
+ }
+ return 1;
}
return 0;
-.TH vncviewer 1 "30 December 2004" "TightVNC" "Virtual Network Computing"
+.TH vncviewer 1 "05 May 2004" "TightVNC" "Virtual Network Computing"
.SH NAME
vncviewer \- VNC viewer for X
.SH SYNOPSIS
respectively.
.SH SEE ALSO
-.BR Xvnc (1)
+.BR Xvnc (1),
+.BR vncpasswd (1),
.BR vncconfig (1),
-.BR vncserver (1),
+.BR vncserver (1)
.br
http://www.tightvnc.com