git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/merge-with-vnc-4.1.1@545 3789f03b-4d11-0410-bbf8-ca57d06f2519tags/v0.0.90
/* 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * the Free Software Foundation; either version 2 of the License, or | ||||
#include <rfb/Hostname.h> | #include <rfb/Hostname.h> | ||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <rfb/util.h> | #include <rfb/util.h> | ||||
#include <rfb/Password.h> | |||||
#include <network/TcpSocket.h> | #include <network/TcpSocket.h> | ||||
#include "TXViewport.h" | #include "TXViewport.h" | ||||
StringParameter windowName("name", "The X window name", ""); | StringParameter windowName("name", "The X window name", ""); | ||||
CConn::CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, | CConn::CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, | ||||
char* vncServerName) | |||||
char* vncServerName, bool reverse) | |||||
: dpy(dpy_), argc(argc_), | : dpy(dpy_), argc(argc_), | ||||
argv(argv_), serverHost(0), serverPort(0), sock(sock_), viewport(0), | argv(argv_), serverHost(0), serverPort(0), sock(sock_), viewport(0), | ||||
desktop(0), desktopEventHandler(0), | desktop(0), desktopEventHandler(0), | ||||
autoSelect(::autoSelect), shared(::shared), formatChange(false), | autoSelect(::autoSelect), shared(::shared), formatChange(false), | ||||
encodingChange(false), sameMachine(false), fullScreen(::fullScreen), | encodingChange(false), sameMachine(false), fullScreen(::fullScreen), | ||||
ctrlDown(false), altDown(false), | 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()); | CharArray menuKeyStr(menuKey.getData()); | ||||
menuKeysym = XStringToKeysym(menuKeyStr.buf); | menuKeysym = XStringToKeysym(menuKeyStr.buf); | ||||
void CConn::blockCallback() { | void CConn::blockCallback() { | ||||
fd_set rfds; | fd_set rfds; | ||||
do { | do { | ||||
TXWindow::handleXEvents(dpy); | |||||
struct timeval tv; | 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; | 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_ZERO(&rfds); | ||||
FD_SET(ConnectionNumber(dpy), &rfds); | FD_SET(ConnectionNumber(dpy), &rfds); | ||||
FD_SET(sock->getFd(), &rfds); | FD_SET(sock->getFd(), &rfds); | ||||
int n = select(FD_SETSIZE, &rfds, 0, 0, tvp); | int n = select(FD_SETSIZE, &rfds, 0, 0, tvp); | ||||
if (n < 0) throw rdr::SystemException("select",errno); | if (n < 0) throw rdr::SystemException("select",errno); | ||||
Timer::callTimers(); | |||||
} while (!(FD_ISSET(sock->getFd(), &rfds))); | } while (!(FD_ISSET(sock->getFd(), &rfds))); | ||||
} | } | ||||
// getPasswd() is called by the CSecurity object when it needs us to read a | // getPasswd() is called by the CSecurity object when it needs us to read a | ||||
// password from the user. | // password from the user. | ||||
bool CConn::getUserPasswd(char** user, char** password) | |||||
void CConn::getUserPasswd(char** user, char** password) | |||||
{ | { | ||||
CharArray passwordFileStr(passwordFile.getData()); | CharArray passwordFileStr(passwordFile.getData()); | ||||
if (!user && passwordFileStr.buf[0]) { | if (!user && passwordFileStr.buf[0]) { | ||||
FILE* fp = fopen(passwordFileStr.buf, "r"); | 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); | 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()); | const char* secType = secTypeName(getCurrentCSecurity()->getType()); | ||||
CharArray title(titleLen); | CharArray title(titleLen); | ||||
snprintf(title.buf, titleLen, "%s [%s]", titlePrefix, secType); | snprintf(title.buf, titleLen, "%s [%s]", titlePrefix, secType); | ||||
PasswdDialog dlg(dpy, title.buf, !user); | PasswdDialog dlg(dpy, title.buf, !user); | ||||
if (!dlg.show()) return false; | |||||
if (!dlg.show()) throw rfb::Exception("Authentication cancelled"); | |||||
if (user) | if (user) | ||||
*user = strDup(dlg.userEntry.getText()); | *user = strDup(dlg.userEntry.getText()); | ||||
*password = strDup(dlg.passwdEntry.getText()); | *password = strDup(dlg.passwdEntry.getText()); | ||||
return true; | |||||
} | } | ||||
void CConn::copyRect(const rfb::Rect& r, int sx, int sy) { | void CConn::copyRect(const rfb::Rect& r, int sx, int sy) { | ||||
desktop->copyRect(r,sx,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) { | void* data, void* mask) { | ||||
desktop->setCursor(hotspot, size, data, mask); | |||||
desktop->setCursor(width, height, hotspot, data, mask); | |||||
} | } | ||||
case ID_F8: | case ID_F8: | ||||
menu.unmap(); | menu.unmap(); | ||||
if (!viewOnly) { | if (!viewOnly) { | ||||
writer()->writeKeyEvent(menuKeysym, true); | |||||
writer()->writeKeyEvent(menuKeysym, false); | |||||
writer()->keyEvent(menuKeysym, true); | |||||
writer()->keyEvent(menuKeysym, false); | |||||
} | } | ||||
break; | break; | ||||
case ID_CTRLALTDEL: | case ID_CTRLALTDEL: | ||||
menu.unmap(); | menu.unmap(); | ||||
if (!viewOnly) { | 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; | break; | ||||
case ID_CTRL: | case ID_CTRL: | ||||
menu.unmap(); | menu.unmap(); | ||||
if (!viewOnly) { | if (!viewOnly) { | ||||
ctrlDown = !ctrlDown; | ctrlDown = !ctrlDown; | ||||
writer()->writeKeyEvent(XK_Control_L, ctrlDown); | |||||
writer()->keyEvent(XK_Control_L, ctrlDown); | |||||
menu.check(ID_CTRL, ctrlDown); | menu.check(ID_CTRL, ctrlDown); | ||||
} | } | ||||
break; | break; | ||||
menu.unmap(); | menu.unmap(); | ||||
if (!viewOnly) { | if (!viewOnly) { | ||||
altDown = !altDown; | altDown = !altDown; | ||||
writer()->writeKeyEvent(XK_Alt_L, altDown); | |||||
writer()->keyEvent(XK_Alt_L, altDown); | |||||
menu.check(ID_ALT, altDown); | menu.check(ID_ALT, altDown); | ||||
} | } | ||||
break; | 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * the Free Software Foundation; either version 2 of the License, or | ||||
public: | public: | ||||
CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, | CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, | ||||
char* vncServerName); | |||||
char* vncServerName, bool reverse=false); | |||||
~CConn(); | ~CConn(); | ||||
// TXDeleteWindowCallback methods | // TXDeleteWindowCallback methods | ||||
void blockCallback(); | void blockCallback(); | ||||
// UserPasswdGetter methods | // UserPasswdGetter methods | ||||
virtual bool getUserPasswd(char** user, char** password); | |||||
virtual void getUserPasswd(char** user, char** password); | |||||
// TXMenuCallback methods | // TXMenuCallback methods | ||||
void menuSelect(long id, TXMenu* m); | void menuSelect(long id, TXMenu* m); | ||||
// TXEventHandler callback method | // TXEventHandler callback method | ||||
virtual void handleEvent(TXWindow* w, XEvent* ev); | virtual void handleEvent(TXWindow* w, XEvent* ev); | ||||
// CConnection callback methods | // CConnection callback methods | ||||
rfb::CSecurity* getCSecurity(int secType); | rfb::CSecurity* getCSecurity(int secType); | ||||
void serverInit(); | void serverInit(); | ||||
void fillRect(const rfb::Rect& r, rfb::Pixel p); | void fillRect(const rfb::Rect& r, rfb::Pixel p); | ||||
void imageRect(const rfb::Rect& r, void* p); | void imageRect(const rfb::Rect& r, void* p); | ||||
void copyRect(const rfb::Rect& r, int sx, int sy); | 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); | void* data, void* mask); | ||||
private: | private: | ||||
OptionsDialog options; | OptionsDialog options; | ||||
AboutDialog about; | AboutDialog about; | ||||
InfoDialog info; | InfoDialog info; | ||||
bool reverseConnection; | |||||
}; | }; | ||||
#endif | #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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * the Free Software Foundation; either version 2 of the License, or | ||||
newSelection(0), gettingInitialSelectionTime(true), | newSelection(0), gettingInitialSelectionTime(true), | ||||
newServerCutText(false), serverCutText_(0), | newServerCutText(false), serverCutText_(0), | ||||
setColourMapEntriesTimer(this), viewport(0), | setColourMapEntriesTimer(this), viewport(0), | ||||
pointerEventTimer(this), lastPointerX(0), lastPointerY(0), | |||||
pointerEventTimer(this), | |||||
lastButtonMask(0) | lastButtonMask(0) | ||||
{ | { | ||||
setEventHandler(this); | setEventHandler(this); | ||||
localXCursor = 0; | 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) | void* data, void* mask) | ||||
{ | { | ||||
if (!useLocalCursor) return; | if (!useLocalCursor) return; | ||||
hideLocalCursor(); | hideLocalCursor(); | ||||
int mask_len = ((size.x+7)/8) * size.y; | |||||
int mask_len = ((width+7)/8) * height; | |||||
int i; | int i; | ||||
for (i = 0; i < mask_len; i++) | for (i = 0; i < mask_len; i++) | ||||
cursor.hotspot = hotspot; | cursor.hotspot = hotspot; | ||||
cursor.setSize(size.x, size.y); | |||||
cursor.setSize(width, height); | |||||
cursor.setPF(getPF()); | cursor.setPF(getPF()); | ||||
cursor.imageRect(cursor.getRect(), data); | cursor.imageRect(cursor.getRect(), data); | ||||
cursorBacking.setSize(size.x, size.y); | |||||
cursorBacking.setSize(width, height); | |||||
cursorBacking.setPF(getPF()); | cursorBacking.setPF(getPF()); | ||||
delete [] cursor.mask.buf; | delete [] cursor.mask.buf; | ||||
rdr::U16* rgbs) | rdr::U16* rgbs) | ||||
{ | { | ||||
im->setColourMapEntries(firstColour, nColours, 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::serverCutText(const char* str, int len) | ||||
} | } | ||||
void DesktopWindow::timerCallback(Timer* timer) | |||||
bool DesktopWindow::handleTimeout(rfb::Timer* timer) | |||||
{ | { | ||||
if (timer == &setColourMapEntriesTimer) { | if (timer == &setColourMapEntriesTimer) { | ||||
im->updateColourMap(); | im->updateColourMap(); | ||||
im->put(win(), gc, im->getRect()); | im->put(win(), gc, im->getRect()); | ||||
} else if (timer == &pointerEventTimer) { | } else if (timer == &pointerEventTimer) { | ||||
if (!viewOnly) { | 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 (!viewOnly) { | ||||
if (pointerEventInterval == 0 || buttonMask != lastButtonMask) { | if (pointerEventInterval == 0 || buttonMask != lastButtonMask) { | ||||
cc->writer()->writePointerEvent(x, y, buttonMask); | |||||
cc->writer()->pointerEvent(pos, buttonMask); | |||||
} else { | } else { | ||||
if (!pointerEventTimer.isSet()) | |||||
pointerEventTimer.reset(pointerEventInterval); | |||||
if (!pointerEventTimer.isStarted()) | |||||
pointerEventTimer.start(pointerEventInterval); | |||||
} | } | ||||
lastPointerX = x; | |||||
lastPointerY = y; | |||||
lastPointerPos = pos; | |||||
lastButtonMask = buttonMask; | lastButtonMask = buttonMask; | ||||
} | } | ||||
// - If local cursor rendering is enabled then use it | // - If local cursor rendering is enabled then use it | ||||
if (cursorAvailable) { | if (cursorAvailable) { | ||||
// - Render the cursor! | // - Render the cursor! | ||||
Point p(x, y); | |||||
if (!p.equals(cursorPos)) { | |||||
if (!pos.equals(cursorPos)) { | |||||
hideLocalCursor(); | hideLocalCursor(); | ||||
if (im->getRect().contains(p)) { | |||||
cursorPos = p; | |||||
if (im->getRect().contains(pos)) { | |||||
cursorPos = pos; | |||||
showLocalCursor(); | showLocalCursor(); | ||||
} | } | ||||
} | } | ||||
case MotionNotify: | case MotionNotify: | ||||
while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev)); | while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev)); | ||||
if (viewport && viewport->bumpScrollEvent(&ev->xmotion)) break; | 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); | (ev->xmotion.state & 0x1f00) >> 8); | ||||
break; | break; | ||||
case ButtonPress: | case ButtonPress: | ||||
handlePointerEvent(ev->xbutton.x, ev->xbutton.y, | |||||
handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y), | |||||
(((ev->xbutton.state & 0x1f00) >> 8) | | (((ev->xbutton.state & 0x1f00) >> 8) | | ||||
(1 << (ev->xbutton.button-1)))); | (1 << (ev->xbutton.button-1)))); | ||||
break; | break; | ||||
case ButtonRelease: | case ButtonRelease: | ||||
handlePointerEvent(ev->xbutton.x, ev->xbutton.y, | |||||
handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y), | |||||
(((ev->xbutton.state & 0x1f00) >> 8) & | (((ev->xbutton.state & 0x1f00) >> 8) & | ||||
~(1 << (ev->xbutton.button-1)))); | ~(1 << (ev->xbutton.button-1)))); | ||||
break; | break; | ||||
} | } | ||||
if (fakeShiftPress) | if (fakeShiftPress) | ||||
cc->writer()->writeKeyEvent(XK_Shift_L, true); | |||||
cc->writer()->keyEvent(XK_Shift_L, true); | |||||
downKeysym[ev->xkey.keycode] = ks; | downKeysym[ev->xkey.keycode] = ks; | ||||
cc->writer()->writeKeyEvent(ks, true); | |||||
cc->writer()->keyEvent(ks, true); | |||||
if (fakeShiftPress) | if (fakeShiftPress) | ||||
cc->writer()->writeKeyEvent(XK_Shift_L, false); | |||||
cc->writer()->keyEvent(XK_Shift_L, false); | |||||
break; | break; | ||||
} | } | ||||
case KeyRelease: | case KeyRelease: | ||||
if (!viewOnly) { | if (!viewOnly) { | ||||
if (downKeysym[ev->xkey.keycode]) { | 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; | downKeysym[ev->xkey.keycode] = 0; | ||||
} | } | ||||
} | } | ||||
// LeaveNotify is near enough... | // LeaveNotify is near enough... | ||||
for (int i = 8; i < 256; i++) { | for (int i = 8; i < 256; i++) { | ||||
if (downKeysym[i]) { | if (downKeysym[i]) { | ||||
cc->writer()->writeKeyEvent(downKeysym[i], false); | |||||
cc->writer()->keyEvent(downKeysym[i], false); | |||||
downKeysym[i] = 0; | downKeysym[i] = 0; | ||||
} | } | ||||
} | } | ||||
if (str) { | if (str) { | ||||
if (!viewOnly) { | if (!viewOnly) { | ||||
vlog.debug("sending cut buffer to server"); | vlog.debug("sending cut buffer to server"); | ||||
cc->writer()->writeClientCutText(str, len); | |||||
cc->writer()->clientCutText(str, len); | |||||
} | } | ||||
XFree(str); | XFree(str); | ||||
return; | return; | ||||
vlog.debug("sending %s selection to server", | vlog.debug("sending %s selection to server", | ||||
ev->selection == XA_PRIMARY ? "primary" : | ev->selection == XA_PRIMARY ? "primary" : | ||||
ev->selection == xaCLIPBOARD ? "clipboard" : "unknown" ); | 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * the Free Software Foundation; either version 2 of the License, or | ||||
#include <rfb/Cursor.h> | #include <rfb/Cursor.h> | ||||
#include <rfb/Rect.h> | #include <rfb/Rect.h> | ||||
#include <rfb/Timer.h> | |||||
#include "TXWindow.h" | #include "TXWindow.h" | ||||
#include "TXViewport.h" | #include "TXViewport.h" | ||||
#include "TXImage.h" | #include "TXImage.h" | ||||
#include "Timer.h" | |||||
class CConn; | class CConn; | ||||
class DesktopWindow : public TXWindow, public TXEventHandler, | class DesktopWindow : public TXWindow, public TXEventHandler, | ||||
public TimerCallback { | |||||
public rfb::Timer::Callback { | |||||
public: | public: | ||||
DesktopWindow(Display* dpy, int w, int h, | DesktopWindow(Display* dpy, int w, int h, | ||||
void setPF(const rfb::PixelFormat& pf) { im->setPF(pf); } | void setPF(const rfb::PixelFormat& pf) { im->setPF(pf); } | ||||
// setCursor() sets the shape of the local cursor | // 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); | void* data, void* mask); | ||||
// resetLocalCursor() stops the rendering of the local cursor | // resetLocalCursor() stops the rendering of the local cursor | ||||
void createXCursors(); | void createXCursors(); | ||||
void hideLocalCursor(); | void hideLocalCursor(); | ||||
void showLocalCursor(); | 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; | CConn* cc; | ||||
TXImage* im; | TXImage* im; | ||||
bool newServerCutText; | bool newServerCutText; | ||||
char* serverCutText_; | char* serverCutText_; | ||||
Timer setColourMapEntriesTimer; | |||||
rfb::Timer setColourMapEntriesTimer; | |||||
TXViewport* viewport; | TXViewport* viewport; | ||||
Timer pointerEventTimer; | |||||
int lastPointerX, lastPointerY, lastButtonMask; | |||||
rfb::Timer pointerEventTimer; | |||||
rfb::Point lastPointerPos; | |||||
int lastButtonMask; | |||||
rdr::U32 downKeysym[256]; | 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * 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 | * This is free software; you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation; either version 2 of the License, or | * the Free Software Foundation; either version 2 of the License, or | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/stat.h> | |||||
#include <sys/wait.h> | #include <sys/wait.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <rfb/LogWriter.h> | #include <rfb/LogWriter.h> | ||||
#include <network/TcpSocket.h> | #include <network/TcpSocket.h> | ||||
#include "TXWindow.h" | #include "TXWindow.h" | ||||
#include "TXMsgBox.h" | |||||
#include "CConn.h" | #include "CConn.h" | ||||
#include <intl/gettext.h> | #include <intl/gettext.h> | ||||
textdomain(PACKAGE); | textdomain(PACKAGE); | ||||
snprintf(aboutText, sizeof(aboutText), | 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); | fprintf(stderr,"\n%s\n", aboutText); | ||||
bind_textdomain_codeset(PACKAGE, "iso-8859-1"); | bind_textdomain_codeset(PACKAGE, "iso-8859-1"); | ||||
programName = argv[0]; | programName = argv[0]; | ||||
char* vncServerName = 0; | char* vncServerName = 0; | ||||
Display* dpy; | |||||
Display* dpy = 0; | |||||
for (int i = 1; i < argc; i++) { | for (int i = 1; i < argc; i++) { | ||||
if (Configuration::setParam(argv[i])) | if (Configuration::setParam(argv[i])) | ||||
vncServerName = 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()) { | if (!::autoSelect.hasBeenSet()) { | ||||
// Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used | // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used | ||||
::autoSelect.setParam(!::preferredEncoding.hasBeenSet() | ::autoSelect.setParam(!::preferredEncoding.hasBeenSet() | ||||
} | } | ||||
try { | try { | ||||
TcpSocket::initTcpSockets(); | |||||
/* Tunnelling support. */ | /* Tunnelling support. */ | ||||
if (strlen (via.getValueStr ()) > 0) { | if (strlen (via.getValueStr ()) > 0) { | ||||
char *gatewayHost = ""; | char *gatewayHost = ""; | ||||
TXWindow::init(dpy, "Vncviewer"); | TXWindow::init(dpy, "Vncviewer"); | ||||
xloginIconifier.iconify(dpy); | 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. | // X events are processed whenever reading from the socket would block. | ||||
cc.processMsg(); | cc.processMsg(); | ||||
} | } | ||||
} catch (rdr::Exception &e) { | |||||
} catch (rdr::EndOfStream& e) { | |||||
vlog.info(e.str()); | |||||
} catch (rdr::Exception& e) { | |||||
vlog.error(e.str()); | vlog.error(e.str()); | ||||
if (dpy) { | |||||
TXMsgBox msgBox(dpy, e.str(), MB_OK, "VNC Viewer: Information"); | |||||
msgBox.show(); | |||||
} | |||||
return 1; | |||||
} | } | ||||
return 0; | return 0; |
.TH vncviewer 1 "30 December 2004" "TightVNC" "Virtual Network Computing" | |||||
.TH vncviewer 1 "05 May 2004" "TightVNC" "Virtual Network Computing" | |||||
.SH NAME | .SH NAME | ||||
vncviewer \- VNC viewer for X | vncviewer \- VNC viewer for X | ||||
.SH SYNOPSIS | .SH SYNOPSIS | ||||
respectively. | respectively. | ||||
.SH SEE ALSO | .SH SEE ALSO | ||||
.BR Xvnc (1) | |||||
.BR Xvnc (1), | |||||
.BR vncpasswd (1), | |||||
.BR vncconfig (1), | .BR vncconfig (1), | ||||
.BR vncserver (1), | |||||
.BR vncserver (1) | |||||
.br | .br | ||||
http://www.tightvnc.com | http://www.tightvnc.com | ||||