git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4759 3789f03b-4d11-0410-bbf8-ca57d06f2519tags/v1.1.90
@@ -23,9 +23,6 @@ set(VERSION 1.1.80) | |||
# The RC version must always be four comma-separated numbers | |||
set(RCVERSION 1,1,80,0) | |||
# Manual toggle until we can deprecate the old viewers | |||
option(BUILD_NEW_VNCVIEWER "Build the new FLTK based vncviewer instead of the old ones" ON) | |||
# Compatibility variables for the migration from autotools | |||
add_definitions(-DPACKAGE_NAME="${CMAKE_PROJECT_NAME}") | |||
add_definitions(-DPACKAGE_VERSION="${VERSION}") | |||
@@ -270,72 +267,69 @@ if(BUILD_JAVA) | |||
endif() | |||
# Check for FLTK | |||
if(BUILD_NEW_VNCVIEWER) | |||
set(FLTK_SKIP_FLUID TRUE) | |||
set(FLTK_SKIP_OPENGL TRUE) | |||
set(FLTK_SKIP_IMAGES TRUE) | |||
set(FLTK_SKIP_FORMS TRUE) | |||
find_package(FLTK) | |||
if(NOT APPLE) | |||
# No proper handling for extra X11 libs that FLTK might need... | |||
if(X11_Xft_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xft_LIB}) | |||
endif() | |||
if(X11_Xinerama_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xinerama_LIB}) | |||
endif() | |||
if(X11_Xfixes_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xfixes_LIB}) | |||
endif() | |||
if(X11_Xcursor_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xcursor_LIB}) | |||
endif() | |||
set(FLTK_SKIP_FLUID TRUE) | |||
set(FLTK_SKIP_OPENGL TRUE) | |||
set(FLTK_SKIP_IMAGES TRUE) | |||
set(FLTK_SKIP_FORMS TRUE) | |||
find_package(FLTK) | |||
if(NOT APPLE) | |||
# No proper handling for extra X11 libs that FLTK might need... | |||
if(X11_Xft_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xft_LIB}) | |||
endif() | |||
if(X11_Xinerama_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xinerama_LIB}) | |||
endif() | |||
if(X11_Xfixes_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xfixes_LIB}) | |||
endif() | |||
if(X11_Xcursor_FOUND) | |||
set(FLTK_LIBRARIES ${FLTK_LIBRARIES} ${X11_Xcursor_LIB}) | |||
endif() | |||
endif() | |||
if(FLTK_FOUND) | |||
set(CMAKE_REQUIRED_INCLUDES ${FLTK_INCLUDE_DIR}) | |||
set(CMAKE_REQUIRED_LIBRARIES ${FLTK_LIBRARIES}) | |||
if(FLTK_FOUND) | |||
set(CMAKE_REQUIRED_INCLUDES ${FLTK_INCLUDE_DIR}) | |||
set(CMAKE_REQUIRED_LIBRARIES ${FLTK_LIBRARIES}) | |||
# FLTK STR #2599 | |||
check_cxx_source_compiles("#include <FL/Fl_Widget.H>\nint main(int c, char** v) { void (Fl_Widget::*foo)() = &Fl_Widget::set_simple_keyboard; return 0; }" HAVE_FLTK_DEAD_KEYS) | |||
# FLTK STR #2599 | |||
check_cxx_source_compiles("#include <FL/Fl_Widget.H>\nint main(int c, char** v) { void (Fl_Widget::*foo)() = &Fl_Widget::set_simple_keyboard; return 0; }" HAVE_FLTK_DEAD_KEYS) | |||
# FLTK STR #2636 | |||
check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { Fl::add_clipboard_notify(NULL, NULL); return 0; }" HAVE_FLTK_CLIPBOARD) | |||
# FLTK STR #2636 | |||
check_cxx_source_compiles("#include <FL/Fl.H>\nint main(int c, char** v) { Fl::add_clipboard_notify(NULL, NULL); return 0; }" HAVE_FLTK_CLIPBOARD) | |||
# FLTK STR #2638 | |||
check_cxx_source_compiles("#include <FL/Enumerations.H>\nint main(int c, char** v) { return FL_Volume_Down; }" HAVE_FLTK_MEDIAKEYS) | |||
# FLTK STR #2638 | |||
check_cxx_source_compiles("#include <FL/Enumerations.H>\nint main(int c, char** v) { return FL_Volume_Down; }" HAVE_FLTK_MEDIAKEYS) | |||
# FLTK STR #2641 | |||
check_cxx_source_compiles("#include <FL/Enumerations.H>\nint main(int c, char** v) { return FL_FULLSCREEN; }" HAVE_FLTK_FULLSCREEN) | |||
# FLTK STR #2641 | |||
check_cxx_source_compiles("#include <FL/Enumerations.H>\nint main(int c, char** v) { return FL_FULLSCREEN; }" HAVE_FLTK_FULLSCREEN) | |||
# FLTK STR #2660 | |||
check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** v) { void (Fl_Window::*foo)(const Fl_RGB_Image*,int,int) = &Fl_Window::cursor; return 0; }" HAVE_FLTK_CURSOR) | |||
# FLTK STR #2660 | |||
check_cxx_source_compiles("#include <FL/Fl_Window.H>\nint main(int c, char** v) { void (Fl_Window::*foo)(const Fl_RGB_Image*,int,int) = &Fl_Window::cursor; return 0; }" HAVE_FLTK_CURSOR) | |||
set(CMAKE_REQUIRED_INCLUDES) | |||
set(CMAKE_REQUIRED_LIBRARIES) | |||
endif() | |||
set(CMAKE_REQUIRED_INCLUDES) | |||
set(CMAKE_REQUIRED_LIBRARIES) | |||
endif() | |||
option(USE_INCLUDED_FLTK | |||
"Force the use of the FLTK library bundled with the TigerVNC source") | |||
if(NOT FLTK_FOUND OR NOT HAVE_FLTK_DEAD_KEYS OR NOT HAVE_FLTK_CLIPBOARD | |||
OR NOT HAVE_FLTK_MEDIAKEYS OR NOT HAVE_FLTK_FULLSCREEN | |||
OR NOT HAVE_FLTK_CURSOR) | |||
set(USE_INCLUDED_FLTK 1) | |||
endif() | |||
if(USE_INCLUDED_FLTK) | |||
set(FLTK_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/common/fltk) | |||
set(FLTK_LIBRARIES) | |||
if(APPLE) | |||
set(FLTK_LIBRARIES "-framework Carbon -framework Cocoa -framework ApplicationServices") | |||
elseif(NOT WIN32) | |||
set(FLTK_LIBRARIES "-ldl") | |||
endif() | |||
message(STATUS "Using included FLTK library") | |||
option(USE_INCLUDED_FLTK | |||
"Force the use of the FLTK library bundled with the TigerVNC source") | |||
if(NOT FLTK_FOUND OR NOT HAVE_FLTK_DEAD_KEYS OR NOT HAVE_FLTK_CLIPBOARD | |||
OR NOT HAVE_FLTK_MEDIAKEYS OR NOT HAVE_FLTK_FULLSCREEN | |||
OR NOT HAVE_FLTK_CURSOR) | |||
set(USE_INCLUDED_FLTK 1) | |||
endif() | |||
if(USE_INCLUDED_FLTK) | |||
set(FLTK_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/common/fltk) | |||
set(FLTK_LIBRARIES) | |||
if(APPLE) | |||
set(FLTK_LIBRARIES "-framework Carbon -framework Cocoa -framework ApplicationServices") | |||
elseif(NOT WIN32) | |||
set(FLTK_LIBRARIES "-ldl") | |||
endif() | |||
message(STATUS "Using included FLTK library") | |||
endif() | |||
# Check for GNUTLS library | |||
option(ENABLE_GNUTLS "Enable protocol encryption and advanced authentication" ON) | |||
if(ENABLE_GNUTLS) | |||
@@ -421,12 +415,10 @@ else() | |||
endif() | |||
endif() | |||
if(BUILD_NEW_VNCVIEWER) | |||
if(ENABLE_NLS) | |||
add_subdirectory(po) | |||
endif() | |||
add_subdirectory(vncviewer) | |||
if(ENABLE_NLS) | |||
add_subdirectory(po) | |||
endif() | |||
add_subdirectory(vncviewer) | |||
include(cmake/BuildPackages.cmake) | |||
@@ -4,9 +4,5 @@ add_subdirectory(vncconfig) | |||
add_subdirectory(vncpasswd) | |||
add_subdirectory(x0vncserver) | |||
if(NOT BUILD_NEW_VNCVIEWER) | |||
add_subdirectory(vncviewer) | |||
endif() | |||
install(PROGRAMS vncserver DESTINATION bin) | |||
install(FILES vncserver.man DESTINATION man/man1 RENAME vncserver.1) |
@@ -1,42 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// | |||
// AboutDialog.h | |||
// | |||
#ifndef __ABOUTDIALOG_H__ | |||
#define __ABOUTDIALOG_H__ | |||
#include "TXMsgBox.h" | |||
#include "parameters.h" | |||
#include "gettext.h" | |||
#define _(String) gettext (String) | |||
#define gettext_noop(String) String | |||
#define N_(String) gettext_noop (String) | |||
extern char buildtime[]; | |||
class AboutDialog : public TXMsgBox { | |||
public: | |||
AboutDialog(Display* dpy) | |||
: TXMsgBox(dpy, aboutText, MB_OK, _("About TigerVNC Viewer")) { | |||
} | |||
}; | |||
#endif |
@@ -1,141 +0,0 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* Copyright 2009 Pierre Ossman for Cendio AB | |||
* | |||
* 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. | |||
*/ | |||
// | |||
// CConn represents a client connection to a VNC server. | |||
// | |||
#ifndef __CCONN_H__ | |||
#define __CCONN_H__ | |||
#include <rfb/CConnection.h> | |||
#include <rfb/Exception.h> | |||
#include <rfb/UserPasswdGetter.h> | |||
#include <rfb/UserMsgBox.h> | |||
#include <rdr/FdInStream.h> | |||
#include <list> | |||
#include "TXWindow.h" | |||
#include "AboutDialog.h" | |||
#include "InfoDialog.h" | |||
#include "TXMenu.h" | |||
#include "OptionsDialog.h" | |||
class TXWindow; | |||
class TXViewport; | |||
class DesktopWindow; | |||
namespace network { class Socket; } | |||
class CConn : public rfb::CConnection, public rfb::UserPasswdGetter, | |||
public TXDeleteWindowCallback, | |||
public rdr::FdInStreamBlockCallback, | |||
public TXMenuCallback , public OptionsDialogCallback, | |||
public TXEventHandler, public rfb::UserMsgBox | |||
{ | |||
public: | |||
CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, | |||
char* vncServerName, bool reverse=false); | |||
~CConn(); | |||
// TXDeleteWindowCallback methods | |||
void deleteWindow(TXWindow* w); | |||
// FdInStreamBlockCallback methods | |||
void blockCallback(); | |||
// UserPasswdGetter methods | |||
virtual void getUserPasswd(char** user, char** password); | |||
// UserMsgBox methods | |||
virtual bool showMsgBox(int flags, const char* title, const char* text); | |||
// TXMenuCallback methods | |||
void menuSelect(long id, TXMenu* m); | |||
// OptionsDialogCallback methods | |||
virtual void setOptions(); | |||
virtual void getOptions(); | |||
// TXEventHandler callback method | |||
virtual void handleEvent(TXWindow* w, XEvent* ev); | |||
// CConnection callback methods | |||
void serverInit(); | |||
void setDesktopSize(int w, int h); | |||
void setExtendedDesktopSize(int reason, int result, int w, int h, | |||
const rfb::ScreenSet& layout); | |||
void setName(const char* name); | |||
void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); | |||
void bell(); | |||
void serverCutText(const char* str, rdr::U32 len); | |||
void framebufferUpdateStart(); | |||
void framebufferUpdateEnd(); | |||
void beginRect(const rfb::Rect& r, int encoding); | |||
void endRect(const rfb::Rect& r, int encoding); | |||
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(int width, int height, const rfb::Point& hotspot, | |||
void* data, void* mask); | |||
private: | |||
void resizeFramebuffer(); | |||
void recreateViewport(); | |||
void reconfigureViewport(); | |||
void initMenu(); | |||
void showMenu(int x, int y); | |||
void autoSelectFormatAndEncoding(); | |||
void checkEncodings(); | |||
void requestNewUpdate(); | |||
Display* dpy; | |||
int argc; | |||
char** argv; | |||
char* serverHost; | |||
int serverPort; | |||
network::Socket* sock; | |||
rfb::PixelFormat serverPF; | |||
TXViewport* viewport; | |||
DesktopWindow* desktop; | |||
TXEventHandler* desktopEventHandler; | |||
rfb::PixelFormat fullColourPF; | |||
std::list<rfb::Rect> debugRects; | |||
int currentEncoding, lastServerEncoding; | |||
bool fullColour; | |||
bool autoSelect; | |||
bool shared; | |||
bool formatChange; | |||
bool encodingChange; | |||
bool sameMachine; | |||
bool fullScreen; | |||
bool ctrlDown; | |||
bool altDown; | |||
KeySym menuKeysym; | |||
TXMenu menu; | |||
TXEventHandler* menuEventHandler; | |||
OptionsDialog options; | |||
AboutDialog about; | |||
InfoDialog info; | |||
bool reverseConnection; | |||
bool firstUpdate; | |||
bool pendingUpdate; | |||
}; | |||
#endif |
@@ -1,13 +0,0 @@ | |||
include_directories(${X11_INCLUDE_DIR}) | |||
include_directories(${CMAKE_SOURCE_DIR}/common) | |||
include_directories(${CMAKE_SOURCE_DIR}/unix/tx) | |||
include_directories(${CMAKE_SOURCE_DIR}/intl) | |||
add_executable(vncviewer | |||
buildtime.c | |||
CConn.cxx | |||
DesktopWindow.cxx | |||
vncviewer.cxx) | |||
target_link_libraries(vncviewer tx rfb network rdr os ${X11_LIBRARIES}) |
@@ -1,580 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// | |||
// DesktopWindow.cxx | |||
// | |||
#include "DesktopWindow.h" | |||
#include "CConn.h" | |||
#include <rfb/CMsgWriter.h> | |||
#include <rfb/LogWriter.h> | |||
#include <X11/keysym.h> | |||
#include <X11/Xatom.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include "parameters.h" | |||
#ifndef XK_ISO_Left_Tab | |||
#define XK_ISO_Left_Tab 0xFE20 | |||
#endif | |||
static rdr::U8 reverseBits[] = { | |||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, | |||
0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, | |||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, | |||
0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, | |||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, | |||
0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, | |||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, | |||
0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, | |||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, | |||
0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, | |||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, | |||
0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, | |||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, | |||
0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, | |||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, | |||
0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, | |||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, | |||
0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, | |||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, | |||
0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, | |||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, | |||
0x3f, 0xbf, 0x7f, 0xff | |||
}; | |||
using namespace rfb; | |||
static rfb::LogWriter vlog("DesktopWindow"); | |||
DesktopWindow::DesktopWindow(Display* dpy, int w, int h, | |||
const rfb::PixelFormat& serverPF, | |||
CConn* cc_, TXWindow* parent) | |||
: TXWindow(dpy, w, h, parent), cc(cc_), im(0), updateTimer(this), | |||
cursorVisible(false), cursorAvailable(false), currentSelectionTime(0), | |||
newSelection(0), gettingInitialSelectionTime(true), | |||
newServerCutText(false), serverCutText_(0), | |||
setColourMapEntriesTimer(this), viewport(0), | |||
pointerEventTimer(this), | |||
lastButtonMask(0) | |||
{ | |||
setEventHandler(this); | |||
gc = XCreateGC(dpy, win(), 0, 0); | |||
addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask | | |||
PointerMotionMask | KeyPressMask | KeyReleaseMask | | |||
EnterWindowMask | LeaveWindowMask); | |||
createXCursors(); | |||
setNoCursor(); | |||
im = new TXImage(dpy, width(), height()); | |||
if (!serverPF.trueColour) | |||
im->setPF(serverPF); | |||
XConvertSelection(dpy, sendPrimary ? XA_PRIMARY : xaCLIPBOARD, xaTIMESTAMP, | |||
xaSELECTION_TIME, win(), CurrentTime); | |||
memset(downKeysym, 0, 256*4); | |||
} | |||
DesktopWindow::~DesktopWindow() | |||
{ | |||
XFreeGC(dpy, gc); | |||
XFreeCursor(dpy, dotCursor); | |||
XFreeCursor(dpy, noCursor); | |||
if (localXCursor) | |||
XFreeCursor(dpy, localXCursor); | |||
delete im; | |||
} | |||
void DesktopWindow::setViewport(TXViewport* viewport_) | |||
{ | |||
viewport = viewport_; | |||
viewport->setChild(this); | |||
} | |||
// Cursor stuff | |||
void DesktopWindow::createXCursors() | |||
{ | |||
static char dotSource[] = { 0x00, 0x0e, 0x0e, 0x0e, 0x00 }; | |||
static char dotMask[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; | |||
Pixmap source = XCreateBitmapFromData(dpy, win(), dotSource, 5, 5); | |||
Pixmap mask = XCreateBitmapFromData(dpy, win(), dotMask, 5, 5); | |||
XColor fg, bg; | |||
fg.red = fg.green = fg.blue = 0; | |||
bg.red = bg.green = bg.blue = 0xffff; | |||
dotCursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg, 2, 2); | |||
XFreePixmap(dpy, source); | |||
XFreePixmap(dpy, mask); | |||
char zero = 0; | |||
Pixmap empty = XCreateBitmapFromData(dpy, win(), &zero, 1, 1); | |||
noCursor = XCreatePixmapCursor(dpy, empty, empty, &fg, &bg, 0, 0); | |||
XFreePixmap(dpy, empty); | |||
localXCursor = 0; | |||
} | |||
void DesktopWindow::setCursor(int width, int height, const Point& hotspot, | |||
void* data, void* mask) | |||
{ | |||
if (!useLocalCursor) return; | |||
hideLocalCursor(); | |||
int mask_len = ((width+7)/8) * height; | |||
int i; | |||
for (i = 0; i < mask_len; i++) | |||
if (((rdr::U8*)mask)[i]) break; | |||
if (i == mask_len) { | |||
if (dotWhenNoCursor) | |||
vlog.debug("cursor is empty - using dot"); | |||
setNoCursor(); | |||
cursorAvailable = false; | |||
return; | |||
} | |||
cursor.hotspot = hotspot; | |||
cursor.setSize(width, height); | |||
cursor.setPF(getPF()); | |||
cursor.imageRect(cursor.getRect(), data); | |||
cursorBacking.setSize(width, height); | |||
cursorBacking.setPF(getPF()); | |||
delete [] cursor.mask.buf; | |||
cursor.mask.buf = new rdr::U8[mask_len]; | |||
memcpy(cursor.mask.buf, mask, mask_len); | |||
Pixel pix0, pix1; | |||
rdr::U8Array bitmap(cursor.getBitmap(&pix0, &pix1)); | |||
if (bitmap.buf && cursor.getRect().contains(cursor.hotspot)) { | |||
int bytesPerRow = (cursor.width() + 7) / 8; | |||
for (int j = 0; j < cursor.height(); j++) { | |||
for (int i = 0; i < bytesPerRow; i++) { | |||
bitmap.buf[j * bytesPerRow + i] | |||
= reverseBits[bitmap.buf[j * bytesPerRow + i]]; | |||
cursor.mask.buf[j * bytesPerRow + i] | |||
= reverseBits[cursor.mask.buf[j * bytesPerRow + i]]; | |||
} | |||
} | |||
Pixmap source = XCreateBitmapFromData(dpy, win(), (char*)bitmap.buf, | |||
cursor.width(), cursor.height()); | |||
Pixmap mask = XCreateBitmapFromData(dpy, win(), (char*)cursor.mask.buf, | |||
cursor.width(), cursor.height()); | |||
Colour rgb; | |||
XColor fg, bg; | |||
getPF().rgbFromPixel(pix1, im->getColourMap(), &rgb); | |||
fg.red = rgb.r; fg.green = rgb.g; fg.blue = rgb.b; | |||
getPF().rgbFromPixel(pix0, im->getColourMap(), &rgb); | |||
bg.red = rgb.r; bg.green = rgb.g; bg.blue = rgb.b; | |||
if (localXCursor) | |||
XFreeCursor(dpy, localXCursor); | |||
localXCursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg, | |||
cursor.hotspot.x, cursor.hotspot.y); | |||
XDefineCursor(dpy, win(), localXCursor); | |||
XFreePixmap(dpy, source); | |||
XFreePixmap(dpy, mask); | |||
cursorAvailable = false; | |||
return; | |||
} | |||
if (!cursorAvailable) { | |||
XDefineCursor(dpy, win(), noCursor); | |||
cursorAvailable = true; | |||
} | |||
showLocalCursor(); | |||
} | |||
void DesktopWindow::resetLocalCursor() | |||
{ | |||
hideLocalCursor(); | |||
setNoCursor(); | |||
cursorAvailable = false; | |||
} | |||
void DesktopWindow::hideLocalCursor() | |||
{ | |||
// - Blit the cursor backing store over the cursor | |||
if (cursorVisible) { | |||
cursorVisible = false; | |||
im->imageRect(cursorBackingRect, cursorBacking.data); | |||
damageRect(cursorBackingRect); | |||
} | |||
} | |||
void DesktopWindow::showLocalCursor() | |||
{ | |||
if (cursorAvailable && !cursorVisible) { | |||
if (!getPF().equal(cursor.getPF()) || | |||
cursor.getRect().is_empty()) { | |||
vlog.error("attempting to render invalid local cursor"); | |||
setNoCursor(); | |||
cursorAvailable = false; | |||
return; | |||
} | |||
cursorVisible = true; | |||
rfb::Rect cursorRect = (cursor.getRect().translate(cursorPos). | |||
translate(cursor.hotspot.negate())); | |||
cursorBackingRect = cursorRect.intersect(im->getRect()); | |||
im->getImage(cursorBacking.data, cursorBackingRect); | |||
im->maskRect(cursorRect, cursor.data, cursor.mask.buf); | |||
damageRect(cursorBackingRect); | |||
} | |||
} | |||
// setColourMapEntries() changes some of the entries in the colourmap. | |||
// Unfortunately these messages are often sent one at a time, so we delay the | |||
// settings taking effect by 100ms. This is because recalculating the internal | |||
// translation table can be expensive. | |||
void DesktopWindow::setColourMapEntries(int firstColour, int nColours, | |||
rdr::U16* rgbs) | |||
{ | |||
im->setColourMapEntries(firstColour, nColours, rgbs); | |||
if (!setColourMapEntriesTimer.isStarted()) | |||
setColourMapEntriesTimer.start(100); | |||
} | |||
void DesktopWindow::serverCutText(const char* str, rdr::U32 len) | |||
{ | |||
if (acceptClipboard) { | |||
newServerCutText = true; | |||
delete [] serverCutText_; | |||
serverCutText_ = new char[len+1]; | |||
memcpy(serverCutText_, str, len); | |||
serverCutText_[len] = 0; | |||
} | |||
} | |||
// Update the actual window with the changed parts of the framebuffer. | |||
void DesktopWindow::framebufferUpdateEnd() | |||
{ | |||
updateWindow(); | |||
} | |||
// invertRect() flips all the bits in every pixel in the given rectangle | |||
void DesktopWindow::invertRect(const Rect& r) | |||
{ | |||
int stride; | |||
rdr::U8* p = im->getPixelsRW(r, &stride); | |||
for (int y = 0; y < r.height(); y++) { | |||
for (int x = 0; x < r.width(); x++) { | |||
switch (getPF().bpp) { | |||
case 8: ((rdr::U8* )p)[x+y*stride] ^= 0xff; break; | |||
case 16: ((rdr::U16*)p)[x+y*stride] ^= 0xffff; break; | |||
case 32: ((rdr::U32*)p)[x+y*stride] ^= 0xffffffff; break; | |||
} | |||
} | |||
} | |||
damageRect(r); | |||
} | |||
// resize() - resize the window and the image, taking care to remove the local | |||
// cursor first. | |||
void DesktopWindow::resize(int w, int h) | |||
{ | |||
hideLocalCursor(); | |||
TXWindow::resize(w, h); | |||
im->resize(w, h); | |||
} | |||
// Copy the areas of the framebuffer that have been changed (damaged) | |||
// to the displayed window. | |||
void DesktopWindow::updateWindow() | |||
{ | |||
Rect r; | |||
updateTimer.stop(); | |||
r = damage.get_bounding_rect(); | |||
damage.clear(); | |||
im->put(win(), gc, r); | |||
XFlush(dpy); | |||
} | |||
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()->pointerEvent(lastPointerPos, lastButtonMask); | |||
} | |||
} else if (timer == &updateTimer) { | |||
updateWindow(); | |||
} | |||
return false; | |||
} | |||
void DesktopWindow::handlePointerEvent(const Point& pos, int buttonMask) | |||
{ | |||
if (!viewOnly) { | |||
if (pointerEventInterval == 0 || buttonMask != lastButtonMask) { | |||
cc->writer()->pointerEvent(pos, buttonMask); | |||
} else { | |||
if (!pointerEventTimer.isStarted()) | |||
pointerEventTimer.start(pointerEventInterval); | |||
} | |||
lastPointerPos = pos; | |||
lastButtonMask = buttonMask; | |||
} | |||
// - If local cursor rendering is enabled then use it | |||
if (cursorAvailable) { | |||
// - Render the cursor! | |||
if (!pos.equals(cursorPos)) { | |||
hideLocalCursor(); | |||
if (im->getRect().contains(pos)) { | |||
cursorPos = pos; | |||
showLocalCursor(); | |||
} | |||
updateWindow(); | |||
} | |||
} | |||
} | |||
// handleXEvent() handles the various X events on the window | |||
void DesktopWindow::handleEvent(TXWindow* w, XEvent* ev) | |||
{ | |||
switch (ev->type) { | |||
case GraphicsExpose: | |||
case Expose: | |||
im->put(win(), gc, Rect(ev->xexpose.x, ev->xexpose.y, | |||
ev->xexpose.x + ev->xexpose.width, | |||
ev->xexpose.y + ev->xexpose.height)); | |||
break; | |||
case MotionNotify: | |||
while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev)); | |||
if (viewport && viewport->bumpScrollEvent(&ev->xmotion)) break; | |||
handlePointerEvent(Point(ev->xmotion.x, ev->xmotion.y), | |||
(ev->xmotion.state & 0x1f00) >> 8); | |||
break; | |||
case ButtonPress: | |||
handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y), | |||
(((ev->xbutton.state & 0x1f00) >> 8) | | |||
(1 << (ev->xbutton.button-1)))); | |||
break; | |||
case ButtonRelease: | |||
handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y), | |||
(((ev->xbutton.state & 0x1f00) >> 8) & | |||
~(1 << (ev->xbutton.button-1)))); | |||
break; | |||
case KeyPress: | |||
if (!viewOnly) { | |||
KeySym ks; | |||
char keyname[256]; | |||
XLookupString(&ev->xkey, keyname, 256, &ks, NULL); | |||
bool fakeShiftPress = false; | |||
// Turn ISO_Left_Tab into shifted Tab | |||
if (ks == XK_ISO_Left_Tab) { | |||
fakeShiftPress = !(ev->xkey.state & ShiftMask); | |||
ks = XK_Tab; | |||
} | |||
if (fakeShiftPress) | |||
cc->writer()->keyEvent(XK_Shift_L, true); | |||
downKeysym[ev->xkey.keycode] = ks; | |||
cc->writer()->keyEvent(ks, true); | |||
if (fakeShiftPress) | |||
cc->writer()->keyEvent(XK_Shift_L, false); | |||
break; | |||
} | |||
case KeyRelease: | |||
if (!viewOnly) { | |||
if (downKeysym[ev->xkey.keycode]) { | |||
cc->writer()->keyEvent(downKeysym[ev->xkey.keycode], false); | |||
downKeysym[ev->xkey.keycode] = 0; | |||
} | |||
} | |||
break; | |||
case EnterNotify: | |||
newSelection = 0; | |||
if (sendPrimary && !selectionOwner(XA_PRIMARY)) { | |||
XConvertSelection(dpy, XA_PRIMARY, xaTIMESTAMP, xaSELECTION_TIME, | |||
win(), ev->xcrossing.time); | |||
} else if (!selectionOwner(xaCLIPBOARD)) { | |||
XConvertSelection(dpy, xaCLIPBOARD, xaTIMESTAMP, xaSELECTION_TIME, | |||
win(), ev->xcrossing.time); | |||
} | |||
break; | |||
case LeaveNotify: | |||
if (serverCutText_ && newServerCutText) { | |||
newServerCutText = false; | |||
vlog.debug("acquiring primary and clipboard selections"); | |||
XStoreBytes(dpy, serverCutText_, strlen(serverCutText_)); | |||
ownSelection(XA_PRIMARY, ev->xcrossing.time); | |||
ownSelection(xaCLIPBOARD, ev->xcrossing.time); | |||
currentSelectionTime = ev->xcrossing.time; | |||
} | |||
// Release all keys - this should probably done on a FocusOut event, but | |||
// LeaveNotify is near enough... | |||
for (int i = 8; i < 256; i++) { | |||
if (downKeysym[i]) { | |||
cc->writer()->keyEvent(downKeysym[i], false); | |||
downKeysym[i] = 0; | |||
} | |||
} | |||
break; | |||
} | |||
} | |||
// selectionRequest() is called when we are the selection owner and another X | |||
// client has requested the selection. We simply put the server's cut text | |||
// into the requested property. TXWindow will handle the rest. | |||
bool DesktopWindow::selectionRequest(Window requestor, | |||
Atom selection, Atom property) | |||
{ | |||
XChangeProperty(dpy, requestor, property, XA_STRING, 8, | |||
PropModeReplace, (unsigned char*)serverCutText_, | |||
strlen(serverCutText_)); | |||
return true; | |||
} | |||
// selectionNotify() is called when we have requested any information about a | |||
// selection from the selection owner. Note that there are two selections, | |||
// PRIMARY and CLIPBOARD, plus the cut buffer, and we try to use whichever is | |||
// the most recent of the three. | |||
// | |||
// There are two different "targets" for which selectionNotify() is called, the | |||
// timestamp and the actual string value of the selection. We always use the | |||
// timestamp to decide which selection to retrieve. | |||
// | |||
// The first time selectionNotify() is called is when we are trying to find the | |||
// timestamp of the selections at initialisation. This should be called first | |||
// for PRIMARY, then we call XConvertSelection() for CLIPBOARD. The second | |||
// time should be the result for CLIPBOARD. At this stage we've got the | |||
// "currentSelectionTime" so we return. | |||
// | |||
// Subsequently selectionNotify() is called whenever the mouse enters the | |||
// viewer window. Again, the first time it is called should be the timestamp | |||
// for PRIMARY, and we then request the timestamp for CLIPBOARD. When | |||
// selectionNotify() is called again with the timestamp for CLIPBOARD, we now | |||
// know if either selection is "new" i.e. later than the previous value of | |||
// currentSelectionTime. The last thing to check is the timestamp on the cut | |||
// buffer. If the cut buffer is newest we send that to the server, otherwise | |||
// if one of the selections was newer, we request the string value of that | |||
// selection. | |||
// | |||
// Finally, if we get selectionNotify() called for the string value of a | |||
// selection, we sent that to the server. | |||
// | |||
// As a final minor complication, when one of the selections is actually owned | |||
// by us, we don't request the details for it. | |||
// TIME_LATER treats 0 as meaning a long time ago, so a==0 means a cannot be | |||
// later than b. This is different to the usual meaning of CurrentTime. | |||
#define TIME_LATER(a, b) ((a) != 0 && ((b) == 0 || (long)((a) - (b)) > 0)) | |||
void DesktopWindow::selectionNotify(XSelectionEvent* ev, Atom type, int format, | |||
int nitems, void* data) | |||
{ | |||
if (ev->requestor != win()) | |||
return; | |||
if (ev->target == xaTIMESTAMP) { | |||
if (ev->property == xaSELECTION_TIME) { | |||
if (data && format == 32 && nitems == 1) { | |||
Time t = *(rdr::U32 *)data; | |||
vlog.debug("selection (%d) time is %d, later %d", | |||
ev->selection, t, TIME_LATER(t, currentSelectionTime)); | |||
if (TIME_LATER(t, currentSelectionTime)) { | |||
currentSelectionTime = t; | |||
newSelection = ev->selection; | |||
} | |||
} | |||
} else { | |||
vlog.debug("no selection (%d)",ev->selection); | |||
} | |||
if (ev->selection == XA_PRIMARY) { | |||
if (!selectionOwner(xaCLIPBOARD)) { | |||
XConvertSelection(dpy, xaCLIPBOARD, xaTIMESTAMP, xaSELECTION_TIME, | |||
win(), ev->time); | |||
return; | |||
} | |||
} else if (ev->selection != xaCLIPBOARD) { | |||
vlog.error("unknown selection %d",ev->selection); | |||
return; | |||
} | |||
if (gettingInitialSelectionTime) { | |||
gettingInitialSelectionTime = false; | |||
return; | |||
} | |||
if (!sendClipboard) return; | |||
if (sendPrimary) { | |||
vlog.debug("cut buffer time is %d, later %d", cutBufferTime, | |||
TIME_LATER(cutBufferTime, currentSelectionTime)); | |||
if (TIME_LATER(cutBufferTime, currentSelectionTime)) { | |||
currentSelectionTime = cutBufferTime; | |||
int len; | |||
char* str = XFetchBytes(dpy, &len); | |||
if (str) { | |||
if (!viewOnly) { | |||
vlog.debug("sending cut buffer to server"); | |||
cc->writer()->clientCutText(str, len); | |||
} | |||
XFree(str); | |||
return; | |||
} | |||
} | |||
} | |||
if (newSelection) { | |||
XConvertSelection(dpy, newSelection, XA_STRING, xaSELECTION_STRING, | |||
win(), CurrentTime); | |||
} | |||
} else if (ev->target == XA_STRING) { | |||
if (!sendClipboard) return; | |||
if (ev->property == xaSELECTION_STRING) { | |||
if (data && format == 8) { | |||
if (!viewOnly) { | |||
vlog.debug("sending %s selection to server", | |||
ev->selection == XA_PRIMARY ? "primary" : | |||
ev->selection == xaCLIPBOARD ? "clipboard" : "unknown" ); | |||
cc->writer()->clientCutText((char*)data, nitems); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,142 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// | |||
// DesktopWindow is a TXWindow representing a VNC desktop. | |||
// | |||
#ifndef __DESKTOPWINDOW_H__ | |||
#define __DESKTOPWINDOW_H__ | |||
#include <rfb/Cursor.h> | |||
#include <rfb/Rect.h> | |||
#include <rfb/Region.h> | |||
#include <rfb/Timer.h> | |||
#include "TXWindow.h" | |||
#include "TXViewport.h" | |||
#include "TXImage.h" | |||
#include "parameters.h" | |||
class CConn; | |||
class DesktopWindow : public TXWindow, public TXEventHandler, | |||
public rfb::Timer::Callback { | |||
public: | |||
DesktopWindow(Display* dpy, int w, int h, | |||
const rfb::PixelFormat& serverPF, CConn* cc_, | |||
TXWindow* parent=0); | |||
~DesktopWindow(); | |||
void setViewport(TXViewport* viewport); | |||
// getPF() and setPF() get and set the TXImage's pixel format | |||
const rfb::PixelFormat& getPF() { return im->getPF(); } | |||
void setPF(const rfb::PixelFormat& pf) { im->setPF(pf); } | |||
// setCursor() sets the shape of the local cursor | |||
void setCursor(int width, int height, const rfb::Point& hotspot, | |||
void* data, void* mask); | |||
// resetLocalCursor() stops the rendering of the local cursor | |||
void resetLocalCursor(); | |||
// setNoCursor() sets what to display when no cursor is defined - if dot or | |||
// nothing. | |||
inline void setNoCursor() { | |||
XDefineCursor(dpy, win(), dotWhenNoCursor ? dotCursor : noCursor); | |||
} | |||
// Methods forwarded from CConn | |||
void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); | |||
void serverCutText(const char* str, rdr::U32 len); | |||
void framebufferUpdateEnd(); | |||
void fillRect(const rfb::Rect& r, rfb::Pixel pix) { | |||
if (r.overlaps(cursorBackingRect)) hideLocalCursor(); | |||
im->fillRect(r, pix); | |||
damageRect(r); | |||
showLocalCursor(); | |||
} | |||
void imageRect(const rfb::Rect& r, void* pixels) { | |||
if (r.overlaps(cursorBackingRect)) hideLocalCursor(); | |||
im->imageRect(r, pixels); | |||
damageRect(r); | |||
showLocalCursor(); | |||
} | |||
void copyRect(const rfb::Rect& r, int srcX, int srcY) { | |||
if (r.overlaps(cursorBackingRect) || | |||
cursorBackingRect.overlaps(rfb::Rect(srcX, srcY, | |||
srcX+r.width(), srcY+r.height()))) | |||
hideLocalCursor(); | |||
im->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY)); | |||
damageRect(r); | |||
showLocalCursor(); | |||
} | |||
void invertRect(const rfb::Rect& r); | |||
// TXWindow methods | |||
virtual void resize(int w, int h); | |||
virtual bool selectionRequest(Window requestor, | |||
Atom selection, Atom property); | |||
virtual void selectionNotify(XSelectionEvent* ev, Atom type, int format, | |||
int nitems, void* data); | |||
virtual void handleEvent(TXWindow* w, XEvent* ev); | |||
private: | |||
void createXCursors(); | |||
void hideLocalCursor(); | |||
void showLocalCursor(); | |||
void damageRect(const rfb::Rect& r) { | |||
damage.assign_union(rfb::Region(r)); | |||
if (!updateTimer.isStarted()) | |||
updateTimer.start(100); | |||
}; | |||
void updateWindow(); | |||
bool handleTimeout(rfb::Timer* timer); | |||
void handlePointerEvent(const rfb::Point& pos, int buttonMask); | |||
CConn* cc; | |||
TXImage* im; | |||
GC gc; | |||
rfb::Region damage; | |||
rfb::Timer updateTimer; | |||
::Cursor dotCursor, noCursor, localXCursor; | |||
rfb::Cursor cursor; | |||
bool cursorVisible; // Is cursor currently rendered? | |||
bool cursorAvailable; // Is cursor available for rendering? | |||
rfb::Point cursorPos; | |||
rfb::ManagedPixelBuffer cursorBacking; | |||
rfb::Rect cursorBackingRect; | |||
Time currentSelectionTime; | |||
Atom newSelection; | |||
bool gettingInitialSelectionTime; | |||
bool newServerCutText; | |||
char* serverCutText_; | |||
rfb::Timer setColourMapEntriesTimer; | |||
TXViewport* viewport; | |||
rfb::Timer pointerEventTimer; | |||
rfb::Point lastPointerPos; | |||
int lastButtonMask; | |||
rdr::U32 downKeysym[256]; | |||
}; | |||
#endif |
@@ -1,60 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// | |||
// InfoDialog.h | |||
// | |||
#ifndef __INFODIALOG_H__ | |||
#define __INFODIALOG_H__ | |||
#include "TXDialog.h" | |||
#include "TXLabel.h" | |||
#include "TXButton.h" | |||
extern char buildtime[]; | |||
class InfoDialog : public TXDialog, public TXButtonCallback { | |||
public: | |||
InfoDialog(Display* dpy) | |||
: TXDialog(dpy, 1, 1, _("VNC connection info")), | |||
infoLabel(dpy, "", this, 1, 1, TXLabel::left), | |||
okButton(dpy, "OK", this, this, 60) | |||
{ | |||
infoLabel.xPad = 8; | |||
infoLabel.move(0, yPad*4); | |||
setBorderWidth(1); | |||
} | |||
void setText(char* infoText) { | |||
infoLabel.setText(infoText); | |||
resize(infoLabel.width(), | |||
infoLabel.height() + okButton.height() + yPad*12); | |||
okButton.move((width() - okButton.width()) / 2, | |||
height() - yPad*4 - okButton.height()); | |||
} | |||
virtual void buttonActivate(TXButton* b) { | |||
unmap(); | |||
} | |||
TXLabel infoLabel; | |||
TXButton okButton; | |||
}; | |||
#endif |
@@ -1,314 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// | |||
// OptionsDialog.h | |||
// | |||
#ifndef __OPTIONSDIALOG_H__ | |||
#define __OPTIONSDIALOG_H__ | |||
#include "TXDialog.h" | |||
#include "TXLabel.h" | |||
#include "TXEntry.h" | |||
#include "TXButton.h" | |||
#include "TXCheckbox.h" | |||
#include "parameters.h" | |||
#define SECOND_COL_XPAD 350 | |||
class OptionsDialogCallback { | |||
public: | |||
virtual void setOptions() = 0; | |||
virtual void getOptions() = 0; | |||
}; | |||
class OptionsDialog : public TXDialog, public TXButtonCallback, | |||
public TXCheckboxCallback, public TXEntryCallback { | |||
public: | |||
OptionsDialog(Display* dpy, OptionsDialogCallback* cb_) | |||
: TXDialog(dpy, 450, 450, _("VNC Viewer: Connection Options")), cb(cb_), | |||
/* Encoding and color level */ | |||
formatAndEnc(dpy, _("Encoding and Color Level:"), this), | |||
inputs(dpy, _("Inputs:"), this), | |||
misc(dpy, _("Misc:"), this), | |||
autoSelect(dpy, _("Auto select"), this, false, this), | |||
fullColour(dpy, _("Full (all available colors)"), this, true, this), | |||
mediumColour(dpy, _("Medium (256 colors)"), this, true, this), | |||
lowColour(dpy, _("Low (64 colors)"), this, true, this), | |||
veryLowColour(dpy, _("Very low (8 colors)"), this, true, this), | |||
tight(dpy, "Tight", this, true, this), | |||
zrle(dpy, "ZRLE", this, true, this), | |||
hextile(dpy, "Hextile", this, true, this), | |||
raw(dpy, "Raw", this, true, this), | |||
/* Compression */ | |||
customCompressLevel(dpy, _("Custom compression level:"), this, false, this), | |||
compressLevel(dpy, this, this, false, 30), | |||
compressLevelLabel(dpy, _("level (1=fast, 9=best)"), this), | |||
noJpeg(dpy, _("Allow JPEG compression:"), this, false, this), | |||
qualityLevel(dpy, this, this, false, 30), | |||
qualityLevelLabel(dpy, _("quality (1=poor, 9=best)"), this), | |||
/* Inputs */ | |||
viewOnly(dpy, _("View only (ignore mouse & keyboard)"), this, false, this), | |||
acceptClipboard(dpy, _("Accept clipboard from server"), this, false, this), | |||
sendClipboard(dpy, _("Send clipboard to server"), this, false, this), | |||
sendPrimary(dpy, _("Send primary selection & cut buffer as clipboard"), | |||
this, false, this), | |||
/* Misc */ | |||
shared(dpy, _("Shared (don't disconnect other viewers)"), this, false,this), | |||
fullScreen(dpy, _("Full-screen mode"), this, false, this), | |||
useLocalCursor(dpy, _("Render cursor locally"), this, false, this), | |||
dotWhenNoCursor(dpy, _("Show dot when no cursor"), this, false, this), | |||
okButton(dpy, _("OK"), this, this, 60), | |||
cancelButton(dpy, _("Cancel"), this, this, 60) | |||
#ifdef HAVE_GNUTLS | |||
, | |||
/* Security */ | |||
security(dpy, _("Security:"), this), | |||
secVeNCrypt(dpy, _("Extended encryption and authentication methods (VeNCrypt)"), | |||
this, false, this), | |||
/* Encryption */ | |||
encryption(dpy, _("Session encryption:"), this), | |||
encNone(dpy, _("None"), this, false, this), | |||
encTLS(dpy, _("TLS with anonymous certificates"), this, false, this), | |||
encX509(dpy, _("TLS with X509 certificates"), this, false, this), | |||
cacert(dpy, _("Path to X509 CA certificate"), this), | |||
ca(dpy, this, this, false, 350), | |||
crlcert(dpy, _("Path to X509 CRL file"), this), | |||
crl(dpy, this, this, false, 350), | |||
/* Authentication */ | |||
authentication(dpy, _("Authentication:"), this), | |||
secNone(dpy, _("None"), this, false, this), | |||
secVnc(dpy, _("Standard VNC (insecure without encryption)"), | |||
this, false, this), | |||
secPlain(dpy, _("Username and password (insecure without encryption)"), | |||
this, false, this) | |||
#endif | |||
{ | |||
/* Render the first collumn */ | |||
int y = yPad; | |||
formatAndEnc.move(xPad, y); | |||
y += formatAndEnc.height(); | |||
autoSelect.move(xPad, y); | |||
int x2 = xPad + autoSelect.width() + xPad*5; | |||
y += autoSelect.height(); | |||
tight.move(xPad, y); | |||
fullColour.move(x2, y); | |||
y += tight.height(); | |||
zrle.move(xPad, y); | |||
mediumColour.move(x2, y); | |||
y += zrle.height(); | |||
hextile.move(xPad, y); | |||
lowColour.move(x2, y); | |||
y += hextile.height(); | |||
raw.move(xPad, y); | |||
veryLowColour.move(x2, y); | |||
y += raw.height() + yPad*2; | |||
customCompressLevel.move(xPad, y); | |||
y += customCompressLevel.height(); | |||
compressLevel.move(xPad*10, y); | |||
compressLevelLabel.move(xPad*20, y); | |||
y += compressLevel.height(); | |||
noJpeg.move(xPad, y); | |||
y += noJpeg.height(); | |||
qualityLevel.move(xPad*10, y); | |||
qualityLevelLabel.move(xPad*20, y); | |||
y += qualityLevel.height(); | |||
y += yPad*4; | |||
inputs.move(xPad, y); | |||
y += inputs.height(); | |||
viewOnly.move(xPad, y); | |||
y += viewOnly.height(); | |||
acceptClipboard.move(xPad, y); | |||
y += acceptClipboard.height(); | |||
sendClipboard.move(xPad, y); | |||
y += sendClipboard.height(); | |||
sendPrimary.move(xPad, y); | |||
y += sendPrimary.height(); | |||
y += yPad*4; | |||
misc.move(xPad, y); | |||
y += misc.height(); | |||
shared.move(xPad, y); | |||
y += shared.height(); | |||
fullScreen.move(xPad, y); | |||
y += fullScreen.height(); | |||
useLocalCursor.move(xPad, y); | |||
y += useLocalCursor.height(); | |||
dotWhenNoCursor.move(xPad, y); | |||
y += dotWhenNoCursor.height(); | |||
#ifdef HAVE_GNUTLS | |||
/* Render the second collumn */ | |||
y = yPad; | |||
xPad += SECOND_COL_XPAD; | |||
resize(750, height()); | |||
security.move(xPad, y); | |||
y += security.height(); | |||
secVeNCrypt.move(xPad, y); | |||
y += secVeNCrypt.height(); | |||
encryption.move(xPad, y); | |||
y += encryption.height(); | |||
encNone.move(xPad, y); | |||
y += encNone.height(); | |||
encTLS.move(xPad, y); | |||
y += encTLS.height(); | |||
encX509.move(xPad, y); | |||
y += encX509.height(); | |||
cacert.move(xPad, y); | |||
y += cacert.height(); | |||
ca.move(xPad, y); | |||
y += ca.height(); | |||
crlcert.move(xPad, y); | |||
y += crlcert.height(); | |||
crl.move(xPad, y); | |||
y += crl.height(); | |||
authentication.move(xPad, y); | |||
y += authentication.height(); | |||
secNone.move(xPad, y); | |||
y += secNone.height(); | |||
secVnc.move(xPad, y); | |||
y += secVnc.height(); | |||
secPlain.move(xPad, y); | |||
y += secPlain.height(); | |||
xPad -= SECOND_COL_XPAD; | |||
#endif | |||
/* Render "OK" and "Cancel" buttons */ | |||
okButton.move(width() - xPad*12 - cancelButton.width() - okButton.width(), | |||
height() - yPad*4 - okButton.height()); | |||
cancelButton.move(width() - xPad*6 - cancelButton.width(), | |||
height() - yPad*4 - cancelButton.height()); | |||
setBorderWidth(1); | |||
} | |||
virtual void initDialog() { | |||
if (cb) cb->setOptions(); | |||
tight.disabled(autoSelect.checked()); | |||
zrle.disabled(autoSelect.checked()); | |||
hextile.disabled(autoSelect.checked()); | |||
raw.disabled(autoSelect.checked()); | |||
fullColour.disabled(autoSelect.checked()); | |||
mediumColour.disabled(autoSelect.checked()); | |||
lowColour.disabled(autoSelect.checked()); | |||
veryLowColour.disabled(autoSelect.checked()); | |||
sendPrimary.disabled(!sendClipboard.checked()); | |||
dotWhenNoCursor.disabled(!useLocalCursor.checked()); | |||
compressLevel.disabled(!customCompressLevel.checked()); | |||
qualityLevel.disabled(autoSelect.checked() || !noJpeg.checked()); | |||
} | |||
virtual void takeFocus(Time time) { | |||
//XSetInputFocus(dpy, entry.win, RevertToParent, time); | |||
} | |||
virtual void buttonActivate(TXButton* b) { | |||
if (b == &okButton) { | |||
if (cb) cb->getOptions(); | |||
unmap(); | |||
} else if (b == &cancelButton) { | |||
unmap(); | |||
} | |||
} | |||
virtual void checkboxSelect(TXCheckbox* checkbox) { | |||
if (checkbox == &autoSelect) { | |||
tight.disabled(autoSelect.checked()); | |||
zrle.disabled(autoSelect.checked()); | |||
hextile.disabled(autoSelect.checked()); | |||
raw.disabled(autoSelect.checked()); | |||
fullColour.disabled(autoSelect.checked()); | |||
mediumColour.disabled(autoSelect.checked()); | |||
lowColour.disabled(autoSelect.checked()); | |||
veryLowColour.disabled(autoSelect.checked()); | |||
qualityLevel.disabled(autoSelect.checked() || !noJpeg.checked()); | |||
} else if (checkbox == &fullColour || checkbox == &mediumColour || | |||
checkbox == &lowColour || checkbox == &veryLowColour) { | |||
fullColour.checked(checkbox == &fullColour); | |||
mediumColour.checked(checkbox == &mediumColour); | |||
lowColour.checked(checkbox == &lowColour); | |||
veryLowColour.checked(checkbox == &veryLowColour); | |||
} else if (checkbox == &tight || checkbox == &zrle || checkbox == &hextile || checkbox == &raw) { | |||
tight.checked(checkbox == &tight); | |||
zrle.checked(checkbox == &zrle); | |||
hextile.checked(checkbox == &hextile); | |||
raw.checked(checkbox == &raw); | |||
} else if (checkbox == &sendClipboard) { | |||
sendPrimary.disabled(!sendClipboard.checked()); | |||
} else if (checkbox == &useLocalCursor) { | |||
dotWhenNoCursor.disabled(!useLocalCursor.checked()); | |||
} else if (checkbox == &customCompressLevel) { | |||
compressLevel.disabled(!customCompressLevel.checked()); | |||
} else if (checkbox == &noJpeg) { | |||
qualityLevel.disabled(autoSelect.checked() || !noJpeg.checked()); | |||
#ifdef HAVE_GNUTLS | |||
} else if (checkbox == &secVeNCrypt) { | |||
encTLS.checked(false); | |||
encTLS.disabled(!secVeNCrypt.checked()); | |||
encX509.checked(false); | |||
encX509.disabled(!secVeNCrypt.checked()); | |||
secPlain.checked(false); | |||
secPlain.disabled(!secVeNCrypt.checked()); | |||
#endif | |||
} | |||
} | |||
virtual void entryCallback(TXEntry* e, Detail detail, Time time) { | |||
} | |||
OptionsDialogCallback* cb; | |||
TXLabel formatAndEnc, inputs, misc; | |||
TXCheckbox autoSelect; | |||
TXCheckbox fullColour, mediumColour, lowColour, veryLowColour; | |||
TXCheckbox tight, zrle, hextile, raw; | |||
TXCheckbox customCompressLevel; TXEntry compressLevel; TXLabel compressLevelLabel; | |||
TXCheckbox noJpeg; TXEntry qualityLevel; TXLabel qualityLevelLabel; | |||
TXCheckbox viewOnly, acceptClipboard, sendClipboard, sendPrimary; | |||
TXCheckbox shared, fullScreen, useLocalCursor, dotWhenNoCursor; | |||
TXButton okButton, cancelButton; | |||
#ifdef HAVE_GNUTLS | |||
TXLabel security; | |||
TXCheckbox secVeNCrypt; | |||
TXLabel encryption; | |||
TXCheckbox encNone, encTLS, encX509; | |||
TXLabel cacert; TXEntry ca; TXLabel crlcert; TXEntry crl; | |||
TXLabel authentication; | |||
TXCheckbox secNone, secVnc, secPlain; | |||
#endif | |||
}; | |||
#endif |
@@ -1,72 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// | |||
// PasswdDialog.h | |||
// | |||
#ifndef __PASSWDDIALOG_H__ | |||
#define __PASSWDDIALOG_H__ | |||
#include "TXDialog.h" | |||
#include "TXLabel.h" | |||
#include "TXEntry.h" | |||
class PasswdDialog : public TXDialog, public TXEntryCallback { | |||
public: | |||
PasswdDialog(Display* dpy, const char* title, bool userDisabled) | |||
: TXDialog(dpy, 320, 100, title, true), | |||
userLabel(dpy, _("Username:"), this, 120), | |||
userEntry(dpy, this, this, false, 180), | |||
passwdLabel(dpy, _("Password:"), this, 120), | |||
passwdEntry(dpy, this, this, true, 180) | |||
{ | |||
userLabel.move(0, 20); | |||
userEntry.move(userLabel.width(), 18); | |||
userEntry.disabled(userDisabled); | |||
passwdLabel.move(0, 60); | |||
passwdEntry.move(passwdLabel.width(), 58); | |||
} | |||
void takeFocus(Time time) { | |||
if (!userEntry.disabled()) | |||
XSetInputFocus(dpy, userEntry.win(), RevertToParent, time); | |||
else | |||
XSetInputFocus(dpy, passwdEntry.win(), RevertToParent, time); | |||
} | |||
void entryCallback(TXEntry* e, Detail detail, Time time) { | |||
if (e == &userEntry) { | |||
if (detail == ENTER || detail == NEXT_FOCUS || detail == PREV_FOCUS) | |||
XSetInputFocus(dpy, passwdEntry.win(), RevertToParent, time); | |||
} else if (e == &passwdEntry) { | |||
if (detail == ENTER) { | |||
ok = true; | |||
done = true; | |||
} else if (detail == NEXT_FOCUS || detail == PREV_FOCUS) { | |||
XSetInputFocus(dpy, userEntry.win(), RevertToParent, time); | |||
} | |||
} | |||
} | |||
TXLabel userLabel; | |||
TXEntry userEntry; | |||
TXLabel passwdLabel; | |||
TXEntry passwdEntry; | |||
}; | |||
#endif |
@@ -1,91 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// | |||
// ServerDialog.h | |||
// | |||
#ifndef __SERVERDIALOG_H__ | |||
#define __SERVERDIALOG_H__ | |||
#include "TXDialog.h" | |||
#include "TXLabel.h" | |||
#include "TXEntry.h" | |||
#include "TXButton.h" | |||
#include "OptionsDialog.h" | |||
#include "AboutDialog.h" | |||
class ServerDialog : public TXDialog, public TXEntryCallback, | |||
public TXButtonCallback { | |||
public: | |||
ServerDialog(Display* dpy, OptionsDialog* options_, AboutDialog* about_) | |||
: TXDialog(dpy, 355, 120, _("VNC Viewer: Connection Details"), true), | |||
label(dpy, _("VNC server:"), this, 100), | |||
entry(dpy, this, this, false, 180), | |||
aboutButton(dpy, _("About..."), this, this, 70), | |||
optionsButton(dpy, _("Options..."), this, this, 70), | |||
okButton(dpy, _("OK"), this, this, 70), | |||
cancelButton(dpy, _("Cancel"), this, this, 70), | |||
options(options_), about(about_) | |||
{ | |||
label.move(0, 30); | |||
entry.move(label.width(), 28); | |||
int x = width(); | |||
int y = height() - yPad*4 - cancelButton.height(); | |||
x -= cancelButton.width() + xPad*4; | |||
cancelButton.move(x, y); | |||
x -= okButton.width() + xPad*4; | |||
okButton.move(x, y); | |||
x -= optionsButton.width() + xPad*4; | |||
optionsButton.move(x, y); | |||
x -= aboutButton.width() + xPad*4; | |||
aboutButton.move(x, y); | |||
} | |||
virtual void takeFocus(Time time) { | |||
XSetInputFocus(dpy, entry.win(), RevertToParent, time); | |||
} | |||
virtual void entryCallback(TXEntry* e, Detail detail, Time time) { | |||
if (detail == ENTER) { | |||
ok = true; | |||
done = true; | |||
} | |||
} | |||
virtual void buttonActivate(TXButton* b) { | |||
if (b == &okButton) { | |||
ok = true; | |||
done = true; | |||
} else if (b == &cancelButton) { | |||
ok = false; | |||
done = true; | |||
} else if (b == &optionsButton) { | |||
options->show(); | |||
} else if (b == &aboutButton) { | |||
about->show(); | |||
} | |||
} | |||
TXLabel label; | |||
TXEntry entry; | |||
TXButton aboutButton, optionsButton, okButton, cancelButton; | |||
OptionsDialog* options; | |||
AboutDialog* about; | |||
}; | |||
#endif |
@@ -1,18 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
char buildtime[] = __DATE__ " " __TIME__; |
@@ -1,271 +0,0 @@ | |||
/* Convenience header for conditional use of GNU <libintl.h>. | |||
Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc. | |||
This program 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, or (at your option) | |||
any later version. | |||
This program 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 | |||
Library General Public License for more details. | |||
You should have received a copy of the GNU General Public | |||
License along with this program; if not, write to the Free Software | |||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | |||
USA. */ | |||
#ifndef _LIBGETTEXT_H | |||
#define _LIBGETTEXT_H 1 | |||
/* NLS can be disabled through the configure --disable-nls option. */ | |||
#if ENABLE_NLS | |||
/* Get declarations of GNU message catalog functions. */ | |||
# include <libintl.h> | |||
/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by | |||
the gettext() and ngettext() macros. This is an alternative to calling | |||
textdomain(), and is useful for libraries. */ | |||
# ifdef DEFAULT_TEXT_DOMAIN | |||
# undef gettext | |||
# define gettext(Msgid) \ | |||
dgettext (DEFAULT_TEXT_DOMAIN, Msgid) | |||
# undef ngettext | |||
# define ngettext(Msgid1, Msgid2, N) \ | |||
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) | |||
# endif | |||
#else | |||
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which | |||
chokes if dcgettext is defined as a macro. So include it now, to make | |||
later inclusions of <locale.h> a NOP. We don't include <libintl.h> | |||
as well because people using "gettext.h" will not include <libintl.h>, | |||
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> | |||
is OK. */ | |||
#if defined(__sun) | |||
# include <locale.h> | |||
#endif | |||
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include | |||
<libintl.h>, which chokes if dcgettext is defined as a macro. So include | |||
it now, to make later inclusions of <libintl.h> a NOP. */ | |||
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) | |||
# include <cstdlib> | |||
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H | |||
# include <libintl.h> | |||
# endif | |||
#endif | |||
/* Disabled NLS. | |||
The casts to 'const char *' serve the purpose of producing warnings | |||
for invalid uses of the value returned from these functions. | |||
On pre-ANSI systems without 'const', the config.h file is supposed to | |||
contain "#define const". */ | |||
# define gettext(Msgid) ((const char *) (Msgid)) | |||
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) | |||
# define dcgettext(Domainname, Msgid, Category) \ | |||
((void) (Category), dgettext (Domainname, Msgid)) | |||
# define ngettext(Msgid1, Msgid2, N) \ | |||
((N) == 1 \ | |||
? ((void) (Msgid2), (const char *) (Msgid1)) \ | |||
: ((void) (Msgid1), (const char *) (Msgid2))) | |||
# define dngettext(Domainname, Msgid1, Msgid2, N) \ | |||
((void) (Domainname), ngettext (Msgid1, Msgid2, N)) | |||
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ | |||
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) | |||
# define textdomain(Domainname) ((const char *) (Domainname)) | |||
# define bindtextdomain(Domainname, Dirname) \ | |||
((void) (Domainname), (const char *) (Dirname)) | |||
# define bind_textdomain_codeset(Domainname, Codeset) \ | |||
((void) (Domainname), (const char *) (Codeset)) | |||
#endif | |||
/* A pseudo function call that serves as a marker for the automated | |||
extraction of messages, but does not call gettext(). The run-time | |||
translation is done at a different place in the code. | |||
The argument, String, should be a literal string. Concatenated strings | |||
and other string expressions won't work. | |||
The macro's expansion is not parenthesized, so that it is suitable as | |||
initializer for static 'char[]' or 'const char[]' variables. */ | |||
#define gettext_noop(String) String | |||
/* The separator between msgctxt and msgid in a .mo file. */ | |||
#define GETTEXT_CONTEXT_GLUE "\004" | |||
/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a | |||
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be | |||
short and rarely need to change. | |||
The letter 'p' stands for 'particular' or 'special'. */ | |||
#ifdef DEFAULT_TEXT_DOMAIN | |||
# define pgettext(Msgctxt, Msgid) \ | |||
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) | |||
#else | |||
# define pgettext(Msgctxt, Msgid) \ | |||
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) | |||
#endif | |||
#define dpgettext(Domainname, Msgctxt, Msgid) \ | |||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) | |||
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ | |||
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) | |||
#ifdef DEFAULT_TEXT_DOMAIN | |||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ | |||
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) | |||
#else | |||
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ | |||
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) | |||
#endif | |||
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ | |||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) | |||
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ | |||
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) | |||
#ifdef __GNUC__ | |||
__inline | |||
#else | |||
#ifdef __cplusplus | |||
inline | |||
#endif | |||
#endif | |||
static const char * | |||
pgettext_aux (const char *domain, | |||
const char *msg_ctxt_id, const char *msgid, | |||
int category) | |||
{ | |||
const char *translation = dcgettext (domain, msg_ctxt_id, category); | |||
if (translation == msg_ctxt_id) | |||
return msgid; | |||
else | |||
return translation; | |||
} | |||
#ifdef __GNUC__ | |||
__inline | |||
#else | |||
#ifdef __cplusplus | |||
inline | |||
#endif | |||
#endif | |||
static const char * | |||
npgettext_aux (const char *domain, | |||
const char *msg_ctxt_id, const char *msgid, | |||
const char *msgid_plural, unsigned long int n, | |||
int category) | |||
{ | |||
const char *translation = | |||
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); | |||
if (translation == msg_ctxt_id || translation == msgid_plural) | |||
return (n == 1 ? msgid : msgid_plural); | |||
else | |||
return translation; | |||
} | |||
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID | |||
can be arbitrary expressions. But for string literals these macros are | |||
less efficient than those above. */ | |||
#include <string.h> | |||
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ | |||
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ | |||
/* || __STDC_VERSION__ >= 199901L */ ) | |||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | |||
#include <stdlib.h> | |||
#endif | |||
#define pgettext_expr(Msgctxt, Msgid) \ | |||
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) | |||
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ | |||
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) | |||
#ifdef __GNUC__ | |||
__inline | |||
#else | |||
#ifdef __cplusplus | |||
inline | |||
#endif | |||
#endif | |||
static const char * | |||
dcpgettext_expr (const char *domain, | |||
const char *msgctxt, const char *msgid, | |||
int category) | |||
{ | |||
size_t msgctxt_len = strlen (msgctxt) + 1; | |||
size_t msgid_len = strlen (msgid) + 1; | |||
const char *translation; | |||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | |||
char msg_ctxt_id[msgctxt_len + msgid_len]; | |||
#else | |||
char buf[1024]; | |||
char *msg_ctxt_id = | |||
(msgctxt_len + msgid_len <= sizeof (buf) | |||
? buf | |||
: (char *) malloc (msgctxt_len + msgid_len)); | |||
if (msg_ctxt_id != NULL) | |||
#endif | |||
{ | |||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); | |||
msg_ctxt_id[msgctxt_len - 1] = '\004'; | |||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); | |||
translation = dcgettext (domain, msg_ctxt_id, category); | |||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | |||
if (msg_ctxt_id != buf) | |||
free (msg_ctxt_id); | |||
#endif | |||
if (translation != msg_ctxt_id) | |||
return translation; | |||
} | |||
return msgid; | |||
} | |||
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ | |||
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) | |||
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ | |||
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) | |||
#ifdef __GNUC__ | |||
__inline | |||
#else | |||
#ifdef __cplusplus | |||
inline | |||
#endif | |||
#endif | |||
static const char * | |||
dcnpgettext_expr (const char *domain, | |||
const char *msgctxt, const char *msgid, | |||
const char *msgid_plural, unsigned long int n, | |||
int category) | |||
{ | |||
size_t msgctxt_len = strlen (msgctxt) + 1; | |||
size_t msgid_len = strlen (msgid) + 1; | |||
const char *translation; | |||
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | |||
char msg_ctxt_id[msgctxt_len + msgid_len]; | |||
#else | |||
char buf[1024]; | |||
char *msg_ctxt_id = | |||
(msgctxt_len + msgid_len <= sizeof (buf) | |||
? buf | |||
: (char *) malloc (msgctxt_len + msgid_len)); | |||
if (msg_ctxt_id != NULL) | |||
#endif | |||
{ | |||
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); | |||
msg_ctxt_id[msgctxt_len - 1] = '\004'; | |||
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); | |||
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); | |||
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS | |||
if (msg_ctxt_id != buf) | |||
free (msg_ctxt_id); | |||
#endif | |||
if (!(translation == msg_ctxt_id || translation == msgid_plural)) | |||
return translation; | |||
} | |||
return (n == 1 ? msgid : msgid_plural); | |||
} | |||
#endif /* _LIBGETTEXT_H */ |
@@ -1,49 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#ifndef __PARAMETERS_H__ | |||
#define __PARAMETERS_H__ | |||
#include <rfb/Configuration.h> | |||
extern rfb::IntParameter pointerEventInterval; | |||
extern rfb::IntParameter wmDecorationWidth; | |||
extern rfb::IntParameter wmDecorationHeight; | |||
extern rfb::StringParameter passwordFile; | |||
extern rfb::BoolParameter useLocalCursor; | |||
extern rfb::BoolParameter dotWhenNoCursor; | |||
extern rfb::BoolParameter autoSelect; | |||
extern rfb::BoolParameter fullColour; | |||
extern rfb::IntParameter lowColourLevel; | |||
extern rfb::StringParameter preferredEncoding; | |||
extern rfb::BoolParameter viewOnly; | |||
extern rfb::BoolParameter shared; | |||
extern rfb::BoolParameter acceptClipboard; | |||
extern rfb::BoolParameter sendClipboard; | |||
extern rfb::BoolParameter sendPrimary; | |||
extern rfb::StringParameter desktopSize; | |||
extern rfb::BoolParameter fullScreen; | |||
extern rfb::StringParameter geometry; | |||
extern rfb::BoolParameter customCompressLevel; | |||
extern rfb::IntParameter compressLevel; | |||
extern rfb::BoolParameter noJpeg; | |||
extern rfb::IntParameter qualityLevel; | |||
extern char aboutText[]; | |||
extern char* programName; | |||
#endif |
@@ -1,423 +0,0 @@ | |||
/* 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 | |||
* (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/stat.h> | |||
#include <sys/wait.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
#include <signal.h> | |||
#include <locale.h> | |||
#include <os/os.h> | |||
#include <rfb/Logger_stdio.h> | |||
#include <rfb/SecurityClient.h> | |||
#include <rfb/LogWriter.h> | |||
#include <network/TcpSocket.h> | |||
#include "TXWindow.h" | |||
#include "TXMsgBox.h" | |||
#include "CConn.h" | |||
#include "gettext.h" | |||
#define _(String) gettext (String) | |||
#define gettext_noop(String) String | |||
#define N_(String) gettext_noop (String) | |||
rfb::LogWriter vlog("main"); | |||
using namespace network; | |||
using namespace rfb; | |||
using namespace std; | |||
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 passwd("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. " | |||
"Default if PreferredEncoding and FullColor are not specified.", | |||
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 (Tight, ZRLE, Hextile or" | |||
" Raw)", "Tight"); | |||
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); | |||
StringParameter desktopSize("DesktopSize", | |||
"Reconfigure desktop size on the server on " | |||
"connect (if possible)", ""); | |||
BoolParameter listenMode("listen", "Listen for connections from VNC servers", | |||
false); | |||
StringParameter geometry("geometry", "X geometry specification", ""); | |||
StringParameter displayname("display", "The X display", ""); | |||
StringParameter via("via", "Gateway to tunnel via", ""); | |||
BoolParameter customCompressLevel("CustomCompressLevel", | |||
"Use custom compression level. " | |||
"Default if CompressLevel is specified.", 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", | |||
8); | |||
char aboutText[1024]; | |||
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); | |||
} | |||
/* Tunnelling support. */ | |||
static void | |||
interpretViaParam (char **gatewayHost, char **remoteHost, | |||
int *remotePort, char **vncServerName, | |||
int localPort) | |||
{ | |||
const int SERVER_PORT_OFFSET = 5900; | |||
char *pos = strchr (*vncServerName, ':'); | |||
if (pos == NULL) | |||
*remotePort = SERVER_PORT_OFFSET; | |||
else { | |||
int portOffset = SERVER_PORT_OFFSET; | |||
size_t len; | |||
*pos++ = '\0'; | |||
len = strlen (pos); | |||
if (*pos == ':') { | |||
/* Two colons is an absolute port number, not an offset. */ | |||
pos++; | |||
len--; | |||
portOffset = 0; | |||
} | |||
if (!len || strspn (pos, "-0123456789") != len ) | |||
usage (); | |||
*remotePort = atoi (pos) + portOffset; | |||
} | |||
if (**vncServerName != '\0') | |||
*remoteHost = *vncServerName; | |||
*gatewayHost = strDup (via.getValueStr ()); | |||
*vncServerName = new char[50]; | |||
sprintf (*vncServerName, "localhost::%d", localPort); | |||
} | |||
#ifndef HAVE_SETENV | |||
int | |||
setenv(const char *envname, const char * envval, int overwrite) | |||
{ | |||
if (envname && envval) { | |||
char * envp = NULL; | |||
envp = (char*)malloc(strlen(envname) + strlen(envval) + 2); | |||
if (envp) { | |||
// The putenv API guarantees memory leaks when | |||
// changing environment variables repeatedly. | |||
sprintf(envp, "%s=%s", envname, envval); | |||
// Cannot free envp | |||
putenv(envp); | |||
return(0); | |||
} | |||
} | |||
return(-1); | |||
} | |||
#endif | |||
static void | |||
createTunnel (const char *gatewayHost, const char *remoteHost, | |||
int remotePort, int localPort) | |||
{ | |||
char *cmd = getenv ("VNC_VIA_CMD"); | |||
char *percent; | |||
char lport[10], rport[10]; | |||
sprintf (lport, "%d", localPort); | |||
sprintf (rport, "%d", remotePort); | |||
setenv ("G", gatewayHost, 1); | |||
setenv ("H", remoteHost, 1); | |||
setenv ("R", rport, 1); | |||
setenv ("L", lport, 1); | |||
if (!cmd) | |||
cmd = "/usr/bin/ssh -f -L \"$L\":\"$H\":\"$R\" \"$G\" sleep 20"; | |||
/* Compatibility with TigerVNC's method. */ | |||
while ((percent = strchr (cmd, '%')) != NULL) | |||
*percent = '$'; | |||
system (cmd); | |||
} | |||
int main(int argc, char** argv) | |||
{ | |||
setlocale(LC_ALL, ""); | |||
bindtextdomain(PACKAGE_NAME, LOCALEDIR); | |||
textdomain(PACKAGE_NAME); | |||
const char englishAbout[] = N_("TigerVNC Viewer for X version %s - built %s\n" | |||
"Copyright (C) 1999-2011 TigerVNC Team and many others (see README.txt)\n" | |||
"See http://www.tigervnc.org for information on TigerVNC."); | |||
rfb::SecurityClient::setDefaults(); | |||
// Write about text to console, still using normal locale codeset | |||
snprintf(aboutText, sizeof(aboutText), | |||
gettext(englishAbout), PACKAGE_VERSION, buildtime); | |||
fprintf(stderr,"\n%s\n", aboutText); | |||
// Set gettext codeset to what our GUI toolkit uses. Since we are | |||
// passing strings from strerror/gai_strerror to the GUI, these must | |||
// be in GUI codeset as well. | |||
bind_textdomain_codeset(PACKAGE_NAME, "iso-8859-1"); | |||
bind_textdomain_codeset("libc", "iso-8859-1"); | |||
// Re-create the aboutText for the GUI, now using GUI codeset | |||
snprintf(aboutText, sizeof(aboutText), | |||
gettext(englishAbout), PACKAGE_VERSION, buildtime); | |||
rfb::initStdIOLoggers(); | |||
rfb::LogWriter::setLogParams("*:stderr:30"); | |||
signal(SIGHUP, CleanupSignalHandler); | |||
signal(SIGINT, CleanupSignalHandler); | |||
signal(SIGTERM, CleanupSignalHandler); | |||
programName = argv[0]; | |||
char* vncServerName = 0; | |||
Display* dpy = 0; | |||
Configuration::enableViewerParams(); | |||
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(); | |||
} | |||
vncServerName = argv[i]; | |||
} | |||
// Create .vnc in the user's home directory if it doesn't already exist | |||
char* homeDir = NULL; | |||
if (getvnchomedir(&homeDir) == -1) { | |||
vlog.error("Could not create VNC home directory: can't obtain home " | |||
"directory path."); | |||
} else { | |||
int result = mkdir(homeDir, 0755); | |||
if (result == -1 && errno != EEXIST) | |||
vlog.error("Could not create VNC home directory: %s.", strerror(errno)); | |||
delete [] homeDir; | |||
} | |||
if (!::autoSelect.hasBeenSet()) { | |||
// Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used | |||
::autoSelect.setParam(!::preferredEncoding.hasBeenSet() | |||
&& !::fullColour.hasBeenSet() | |||
&& !::fullColourAlias.hasBeenSet()); | |||
} | |||
if (!::fullColour.hasBeenSet() && !::fullColourAlias.hasBeenSet()) { | |||
// Default to FullColor=0 if AutoSelect=0 && LowColorLevel is set | |||
if (!::autoSelect && (::lowColourLevel.hasBeenSet() || | |||
::lowColourLevelAlias.hasBeenSet())) { | |||
::fullColour.setParam(false); | |||
} | |||
} | |||
if (!::customCompressLevel.hasBeenSet()) { | |||
// Default to CustomCompressLevel=1 if CompressLevel is used. | |||
::customCompressLevel.setParam(::compressLevel.hasBeenSet()); | |||
} | |||
try { | |||
/* Tunnelling support. */ | |||
if (strlen (via.getValueStr ()) > 0) { | |||
char *gatewayHost = ""; | |||
char *remoteHost = "localhost"; | |||
int localPort = findFreeTcpPort (); | |||
int remotePort; | |||
if (!vncServerName) | |||
usage(); | |||
interpretViaParam (&gatewayHost, &remoteHost, &remotePort, | |||
&vncServerName, localPort); | |||
createTunnel (gatewayHost, remoteHost, remotePort, localPort); | |||
} | |||
Socket* sock = 0; | |||
if (listenMode) { | |||
int port = 5500; | |||
if (vncServerName && isdigit(vncServerName[0])) | |||
port = atoi(vncServerName); | |||
TcpListener listener(NULL, 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, listenMode); | |||
// X events are processed whenever reading from the socket would block. | |||
while (true) { | |||
cc.getInStream()->check(1); | |||
cc.processMsg(); | |||
} | |||
} 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; | |||
} |
@@ -1,224 +0,0 @@ | |||
.TH vncviewer 1 "05 May 2004" "TigerVNC" "Virtual Network Computing" | |||
.SH NAME | |||
vncviewer \- VNC viewer for X | |||
.SH SYNOPSIS | |||
.B vncviewer | |||
.RI [ options ] | |||
.RI [ host ][: display# ] | |||
.br | |||
.B vncviewer | |||
.RI [ options ] | |||
.RI [ host ][:: port ] | |||
.br | |||
.B vncviewer | |||
.RI [ options ] | |||
.B \-listen | |||
.RI [ port ] | |||
.SH DESCRIPTION | |||
.B vncviewer | |||
is a viewer (client) for Virtual Network Computing. This manual page documents | |||
version 4 for the X window system. | |||
If you run the viewer with no arguments it will prompt you for a VNC server to | |||
connect to. Alternatively, specify the VNC server as an argument, e.g.: | |||
.RS | |||
vncviewer snoopy:2 | |||
.RE | |||
where 'snoopy' is the name of the machine, and '2' is the display number of the | |||
VNC server on that machine. Either the machine name or display number can be | |||
omitted. So for example ":1" means display number 1 on the same machine, and | |||
"snoopy" means "snoopy:0" i.e. display 0 on machine "snoopy". | |||
If the VNC server is successfully contacted, you will be prompted for a | |||
password to authenticate you. If the password is correct, a window will appear | |||
showing the desktop of the VNC server. | |||
.SH AUTOMATIC PROTOCOL SELECTION | |||
The viewer tests the speed of the connection to the server and chooses the | |||
encoding and pixel format (color level) appropriately. This makes it much | |||
easier to use than previous versions where the user had to specify arcane | |||
command line arguments. | |||
The viewer normally starts out assuming the link is slow, using the | |||
encoding with the best compression. If it turns out that the link is | |||
fast enough it switches to an encoding which compresses less but is | |||
faster to generate, thus improving the interactive feel. | |||
The viewer normally starts in full-color mode, but switches to | |||
low-color mode if the bandwidth is insufficient. However, this only | |||
occurs when communicating with servers supporting protocol 3.8 or | |||
newer, since many old servers does not support color mode changes | |||
safely. | |||
Automatic selection can be turned off by setting the | |||
\fBAutoSelect\fP parameter to false, or from the options dialog. | |||
.SH POPUP MENU | |||
The viewer has a popup menu containing entries which perform various actions. | |||
It is usually brought up by pressing F8, but this can be configured with the | |||
MenuKey parameter. Actions which the popup menu can perform include: | |||
.RS 2 | |||
.IP * 2 | |||
switching in and out of full-screen mode | |||
.IP * | |||
quitting the viewer | |||
.IP * | |||
generating key events, e.g. sending ctrl-alt-del | |||
.IP * | |||
accessing the options dialog and various other dialogs | |||
.RE | |||
.PP | |||
By default, key presses in the popup menu get sent to the VNC server and | |||
dismiss the popup. So to get an F8 through to the VNC server simply press it | |||
twice. | |||
.SH FULL SCREEN MODE | |||
A full-screen mode is supported. This is particularly useful when connecting | |||
to a remote screen which is the same size as your local one. If the remote | |||
screen is bigger, you can scroll by bumping the mouse against the edge of the | |||
screen. | |||
Unfortunately this mode doesn't work completely with all window managers, since | |||
it breaks the X window management conventions. | |||
.SH OPTIONS (PARAMETERS) | |||
You can get a list of parameters by giving \fB\-h\fP as a command-line option | |||
to vncviewer. Parameters can be turned on with -\fIparam\fP or off with | |||
-\fIparam\fP=0. Parameters which take a value can be specified as | |||
-\fIparam\fP \fIvalue\fP. Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP | |||
-\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP. Parameter names are | |||
case-insensitive. | |||
Many of the parameters can also be set graphically via the options dialog box. | |||
This can be accessed from the popup menu or from the "Connection details" | |||
dialog box. | |||
.TP | |||
.B \-display \fIXdisplay\fP | |||
Specifies the X display on which the VNC viewer window should appear. | |||
.TP | |||
.B \-geometry \fIgeometry\fP | |||
Standard X position and sizing specification. | |||
.TP | |||
.B \-listen \fI[port]\fP | |||
Causes vncviewer to listen on the given port (default 5500) for reverse | |||
connections from a VNC server. WinVNC supports reverse connections initiated | |||
using the 'Add New Client' menu option or the '\-connect' command-line option. | |||
Xvnc supports reverse connections with a helper program called | |||
.B vncconfig. | |||
.TP | |||
.B \-passwd \fIpassword-file\fP | |||
If you are on a filesystem which gives you access to the password file used by | |||
the server, you can specify it here to avoid typing it in. It will usually be | |||
"~/.vnc/passwd". | |||
.TP | |||
.B \-Shared | |||
When you make a connection to a VNC server, all other existing connections are | |||
normally closed. This option requests that they be left open, allowing you to | |||
share the desktop with someone already using it. | |||
.TP | |||
.B \-ViewOnly | |||
Specifies that no keyboard or mouse events should be sent to the server. | |||
Useful if you want to view a desktop without interfering; often needs to be | |||
combined with | |||
.B \-Shared. | |||
.TP | |||
.B \-FullScreen | |||
Start in full-screen mode. | |||
.TP | |||
.B \-DesktopSize \fIwidth\fPx\fIheight\fP | |||
Instead of keeping the existing remote screen size, the client will attempt to | |||
switch to the specified since when connecting. If the server does not support | |||
the SetDesktopSize message then the screen will retain the original size. | |||
.TP | |||
.B \-AutoSelect | |||
Use automatic selection of encoding and pixel format (default is on). Normally | |||
the viewer tests the speed of the connection to the server and chooses the | |||
encoding and pixel format appropriately. Turn it off with \fB-AutoSelect=0\fP. | |||
.TP | |||
.B \-FullColor, \-FullColour | |||
Tells the VNC server to send full-color pixels in the best format for this | |||
display. This is default. | |||
.TP | |||
.B \-LowColorLevel, \-LowColourLevel \fIlevel\fP | |||
Selects the reduced color level to use on slow links. \fIlevel\fP can range | |||
from 0 to 2, 0 meaning 8 colors, 1 meaning 64 colors (the default), 2 meaning | |||
256 colors. Note that decision if reduced color level is used is made by | |||
vncviewer. If you would like to force vncviewer to use reduced color level | |||
use \fB-AutoSelect=0\fP parameter. | |||
.TP | |||
.B \-PreferredEncoding \fIencoding\fP | |||
This option specifies the preferred encoding to use from one of "Tight", "ZRLE", | |||
"hextile" or "raw". | |||
.TP | |||
.B -UseLocalCursor | |||
Render the mouse cursor locally if the server supports it (default is on). | |||
This can make the interactive performance feel much better over slow links. | |||
.TP | |||
.B \-WMDecorationWidth \fIw\fP, \-WMDecorationHeight \fIh\fP | |||
The total width and height taken up by window manager decorations. This is | |||
used to calculate the maximum size of the VNC viewer window. Default is | |||
width 6, height 24. | |||
.TP | |||
.B \-log \fIlogname\fP:\fIdest\fP:\fIlevel\fP | |||
Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP or | |||
\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose | |||
output. \fIlogname\fP is usually \fB*\fP meaning all, but you can target a | |||
specific source file if you know the name of its "LogWriter". Default is | |||
\fB*:stderr:30\fP. | |||
.TP | |||
.B \-MenuKey \fIkeysym-name\fP | |||
This option specifies the key which brings up the popup menu. The key is | |||
specified as an X11 keysym name (these can be obtained by removing the XK_ | |||
prefix from the entries in "/usr/include/X11/keysymdef.h"). Default is F8. | |||
.TP | |||
\fB\-via\fR \fIgateway\fR | |||
Automatically create encrypted TCP tunnel to the \fIgateway\fR machine | |||
before connection, connect to the \fIhost\fR through that tunnel | |||
(TigerVNC\-specific). By default, this option invokes SSH local port | |||
forwarding, assuming that SSH client binary can be accessed as | |||
/usr/bin/ssh. Note that when using the \fB\-via\fR option, the host | |||
machine name should be specified as known to the gateway machine, e.g. | |||
"localhost" denotes the \fIgateway\fR, not the machine where vncviewer | |||
was launched. The environment variable \fIVNC_VIA_CMD\fR can override | |||
the default tunnel command of | |||
\fB/usr/bin/ssh\ -f\ -L\ "$L":"$H":"$R"\ "$G"\ sleep\ 20\fR. The tunnel | |||
command is executed with the environment variables \fIL\fR, \fIH\fR, | |||
\fIR\fR, and \fIG\fR taken the values of the local port number, the remote | |||
host, the port number on the remote host, and the gateway machine | |||
respectively. | |||
.SH SEE ALSO | |||
.BR Xvnc (1), | |||
.BR vncpasswd (1), | |||
.BR vncconfig (1), | |||
.BR vncserver (1) | |||
.br | |||
http://www.tigervnc.org | |||
.SH AUTHOR | |||
Tristan Richardson, RealVNC Ltd. | |||
VNC was originally developed by the RealVNC team while at Olivetti | |||
Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were | |||
implemented by Constantin Kaplinsky. Many other people participated in | |||
development, testing and support. |
@@ -4,10 +4,6 @@ configure_file(resdefs.h.in ${CMAKE_CURRENT_BINARY_DIR}/resdefs.h) | |||
add_subdirectory(rfb_win32) | |||
if(NOT BUILD_NEW_VNCVIEWER) | |||
add_subdirectory(vncviewer) | |||
endif() | |||
if(BUILD_WINVNC) | |||
add_subdirectory(vncconfig) | |||
add_subdirectory(winvnc) |
@@ -1,863 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#ifdef HAVE_CONFIG_H | |||
#include <config.h> | |||
#endif | |||
#include <winsock2.h> | |||
#include <vncviewer/UserPasswdDialog.h> | |||
#include <vncviewer/CConn.h> | |||
#include <vncviewer/CConnThread.h> | |||
#include <vncviewer/resource.h> | |||
#include <rfb/encodings.h> | |||
#include <rfb/Security.h> | |||
#include <rfb/CMsgWriter.h> | |||
#include <rfb/Configuration.h> | |||
#ifdef HAVE_GNUTLS | |||
#include <rfb/CSecurityTLS.h> | |||
#endif | |||
#include <rfb/LogWriter.h> | |||
#include <rfb_win32/AboutDialog.h> | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
using namespace rdr; | |||
// - Statics & consts | |||
static LogWriter vlog("CConn"); | |||
const int IDM_FULLSCREEN = ID_FULLSCREEN; | |||
const int IDM_SEND_MENU_KEY = ID_SEND_MENU_KEY; | |||
const int IDM_SEND_CAD = ID_SEND_CAD; | |||
const int IDM_SEND_CTLESC = ID_SEND_CTLESC; | |||
const int IDM_ABOUT = ID_ABOUT; | |||
const int IDM_OPTIONS = ID_OPTIONS; | |||
const int IDM_INFO = ID_INFO; | |||
const int IDM_NEWCONN = ID_NEW_CONNECTION; | |||
const int IDM_REQUEST_REFRESH = ID_REQUEST_REFRESH; | |||
const int IDM_CTRL_KEY = ID_CTRL_KEY; | |||
const int IDM_ALT_KEY = ID_ALT_KEY; | |||
const int IDM_CONN_SAVE_AS = ID_CONN_SAVE_AS; | |||
const int IDM_ZOOM_IN = ID_ZOOM_IN; | |||
const int IDM_ZOOM_OUT = ID_ZOOM_OUT; | |||
const int IDM_ACTUAL_SIZE = ID_ACTUAL_SIZE; | |||
const int IDM_AUTO_SIZE = ID_AUTO_SIZE; | |||
static IntParameter debugDelay("DebugDelay","Milliseconds to display inverted " | |||
"pixel data - a debugging feature", 0); | |||
const int scaleValues[9] = {10, 25, 50, 75, 90, 100, 125, 150, 200}; | |||
const int scaleCount = 9; | |||
// | |||
// -=- CConn implementation | |||
// | |||
RegKey CConn::userConfigKey; | |||
CConn::CConn() | |||
: window(0), sameMachine(false), encodingChange(false), formatChange(false), | |||
lastUsedEncoding_(encodingRaw), sock(0), sockEvent(CreateEvent(0, TRUE, FALSE, 0)), | |||
reverseConnection(false), requestUpdate(false), firstUpdate(true), | |||
pendingUpdate(false), isClosed_(false) { | |||
} | |||
CConn::~CConn() { | |||
delete window; | |||
} | |||
bool CConn::initialise(network::Socket* s, bool reverse) { | |||
// Set the server's name for MRU purposes | |||
CharArray endpoint(s->getPeerEndpoint()); | |||
if (!options.host.buf) | |||
options.setHost(endpoint.buf); | |||
setServerName(options.host.buf); | |||
// Initialise the underlying CConnection | |||
setStreams(&s->inStream(), &s->outStream()); | |||
// Enable processing of window messages while blocked on I/O | |||
s->inStream().setBlockCallback(this); | |||
// Initialise the viewer options | |||
applyOptions(options); | |||
CSecurity::upg = this; | |||
#ifdef HAVE_GNUTLS | |||
CSecurityTLS::msg = this; | |||
#endif | |||
// Start the RFB protocol | |||
sock = s; | |||
reverseConnection = reverse; | |||
initialiseProtocol(); | |||
return true; | |||
} | |||
void | |||
CConn::applyOptions(CConnOptions& opt) { | |||
// - If any encoding-related settings have changed then we must | |||
// notify the server of the new settings | |||
encodingChange |= ((options.useLocalCursor != opt.useLocalCursor) || | |||
(options.useDesktopResize != opt.useDesktopResize) || | |||
(options.customCompressLevel != opt.customCompressLevel) || | |||
(options.compressLevel != opt.compressLevel) || | |||
(options.noJpeg != opt.noJpeg) || | |||
(options.qualityLevel != opt.qualityLevel) || | |||
(options.preferredEncoding != opt.preferredEncoding)); | |||
// - If the preferred pixel format has changed then notify the server | |||
formatChange |= (options.fullColour != opt.fullColour); | |||
if (!opt.fullColour) | |||
formatChange |= (options.lowColourLevel != opt.lowColourLevel); | |||
// - Save the new set of options | |||
options = opt; | |||
// - Set optional features in ConnParams | |||
cp.supportsLocalCursor = options.useLocalCursor; | |||
cp.supportsDesktopResize = options.useDesktopResize; | |||
cp.supportsExtendedDesktopSize = options.useDesktopResize; | |||
cp.supportsDesktopRename = true; | |||
cp.customCompressLevel = options.customCompressLevel; | |||
cp.compressLevel = options.compressLevel; | |||
cp.noJpeg = options.noJpeg; | |||
cp.qualityLevel = options.qualityLevel; | |||
// - Configure connection sharing on/off | |||
setShared(options.shared); | |||
// - Whether to use protocol 3.3 for legacy compatibility | |||
setProtocol3_3(options.protocol3_3); | |||
// - Apply settings that affect the window, if it is visible | |||
if (window) { | |||
window->setMonitor(options.monitor.buf); | |||
window->setFullscreen(options.fullScreen); | |||
window->setEmulate3(options.emulate3); | |||
window->setPointerEventInterval(options.pointerEventInterval); | |||
window->setMenuKey(options.menuKey); | |||
window->setDisableWinKeys(options.disableWinKeys); | |||
window->setShowToolbar(options.showToolbar); | |||
window->printScale(); | |||
if (options.autoScaling) { | |||
window->setAutoScaling(true); | |||
} else { | |||
window->setAutoScaling(false); | |||
window->setDesktopScale(options.scale); | |||
} | |||
if (!options.useLocalCursor) | |||
window->setCursor(0, 0, Point(), 0, 0); | |||
} | |||
security->SetSecTypes(options.secTypes); | |||
} | |||
void | |||
CConn::displayChanged() { | |||
// Display format has changed - recalculate the full-colour pixel format | |||
calculateFullColourPF(); | |||
} | |||
bool | |||
CConn::sysCommand(WPARAM wParam, LPARAM lParam) { | |||
// - If it's one of our (F8 Menu) messages | |||
switch (wParam) { | |||
case IDM_FULLSCREEN: | |||
options.fullScreen = !window->isFullscreen(); | |||
window->setFullscreen(options.fullScreen); | |||
return true; | |||
case IDM_ZOOM_IN: | |||
case IDM_ZOOM_OUT: | |||
{ | |||
if (options.autoScaling) { | |||
options.scale = window->getDesktopScale(); | |||
options.autoScaling = false; | |||
window->setAutoScaling(false); | |||
} | |||
if (wParam == (unsigned)IDM_ZOOM_IN) { | |||
for (int i = 0; i < scaleCount; i++) | |||
if (options.scale < scaleValues[i]) { | |||
options.scale = scaleValues[i]; | |||
break; | |||
} | |||
} else { | |||
for (int i = scaleCount-1; i >= 0; i--) | |||
if (options.scale > scaleValues[i]) { | |||
options.scale = scaleValues[i]; | |||
break; | |||
} | |||
} | |||
if (options.scale != window->getDesktopScale()) | |||
window->setDesktopScale(options.scale); | |||
} | |||
return true; | |||
case IDM_ACTUAL_SIZE: | |||
if (options.autoScaling) { | |||
options.autoScaling = false; | |||
window->setAutoScaling(false); | |||
} | |||
options.scale = 100; | |||
window->setDesktopScale(100); | |||
return true; | |||
case IDM_AUTO_SIZE: | |||
options.autoScaling = !options.autoScaling; | |||
window->setAutoScaling(options.autoScaling); | |||
if (!options.autoScaling) options.scale = window->getDesktopScale(); | |||
return true; | |||
case IDM_SHOW_TOOLBAR: | |||
options.showToolbar = !window->isToolbarEnabled(); | |||
window->setShowToolbar(options.showToolbar); | |||
return true; | |||
case IDM_CTRL_KEY: | |||
window->kbd.keyEvent(this, VK_CONTROL, 0, !window->kbd.keyPressed(VK_CONTROL)); | |||
return true; | |||
case IDM_ALT_KEY: | |||
window->kbd.keyEvent(this, VK_MENU, 0, !window->kbd.keyPressed(VK_MENU)); | |||
return true; | |||
case IDM_SEND_MENU_KEY: | |||
window->kbd.keyEvent(this, options.menuKey, 0, true); | |||
window->kbd.keyEvent(this, options.menuKey, 0, false); | |||
return true; | |||
case IDM_SEND_CAD: | |||
window->kbd.keyEvent(this, VK_CONTROL, 0, true); | |||
window->kbd.keyEvent(this, VK_MENU, 0, true); | |||
window->kbd.keyEvent(this, VK_DELETE, 0x1000000, true); | |||
window->kbd.keyEvent(this, VK_DELETE, 0x1000000, false); | |||
window->kbd.keyEvent(this, VK_MENU, 0, false); | |||
window->kbd.keyEvent(this, VK_CONTROL, 0, false); | |||
return true; | |||
case IDM_SEND_CTLESC: | |||
window->kbd.keyEvent(this, VK_CONTROL, 0, true); | |||
window->kbd.keyEvent(this, VK_ESCAPE, 0, true); | |||
window->kbd.keyEvent(this, VK_ESCAPE, 0, false); | |||
window->kbd.keyEvent(this, VK_CONTROL, 0, false); | |||
return true; | |||
case IDM_REQUEST_REFRESH: | |||
try { | |||
writer()->writeFramebufferUpdateRequest(Rect(0,0,cp.width,cp.height), false); | |||
requestUpdate = false; | |||
} catch (rdr::Exception& e) { | |||
close(e.str()); | |||
} | |||
return true; | |||
case IDM_NEWCONN: | |||
{ | |||
new CConnThread; | |||
} | |||
return true; | |||
case IDM_OPTIONS: | |||
// Update the monitor device name in the CConnOptions instance | |||
options.monitor.replaceBuf(window->getMonitor()); | |||
showOptionsDialog(); | |||
return true; | |||
case IDM_INFO: | |||
infoDialog.showDialog(this); | |||
return true; | |||
case IDM_ABOUT: | |||
AboutDialog::instance.showDialog(); | |||
return true; | |||
case IDM_CONN_SAVE_AS: | |||
return true; | |||
}; | |||
return false; | |||
} | |||
void | |||
CConn::closeWindow() { | |||
vlog.info("window closed"); | |||
close(); | |||
} | |||
void | |||
CConn::refreshMenu(bool enableSysItems) { | |||
HMENU menu = GetSystemMenu(window->getHandle(), FALSE); | |||
if (!enableSysItems) { | |||
// Gray out menu items that might cause a World Of Pain | |||
EnableMenuItem(menu, SC_SIZE, MF_BYCOMMAND | MF_GRAYED); | |||
EnableMenuItem(menu, SC_MOVE, MF_BYCOMMAND | MF_GRAYED); | |||
EnableMenuItem(menu, SC_RESTORE, MF_BYCOMMAND | MF_ENABLED); | |||
EnableMenuItem(menu, SC_MINIMIZE, MF_BYCOMMAND | MF_ENABLED); | |||
EnableMenuItem(menu, SC_MAXIMIZE, MF_BYCOMMAND | MF_ENABLED); | |||
} | |||
// Update the modifier key menu items | |||
UINT ctrlCheckFlags = window->kbd.keyPressed(VK_CONTROL) ? MF_CHECKED : MF_UNCHECKED; | |||
UINT altCheckFlags = window->kbd.keyPressed(VK_MENU) ? MF_CHECKED : MF_UNCHECKED; | |||
CheckMenuItem(menu, IDM_CTRL_KEY, MF_BYCOMMAND | ctrlCheckFlags); | |||
CheckMenuItem(menu, IDM_ALT_KEY, MF_BYCOMMAND | altCheckFlags); | |||
// Ensure that the Send <MenuKey> menu item has the correct text | |||
if (options.menuKey) { | |||
TCharArray menuKeyStr(options.menuKeyName()); | |||
TCharArray tmp(_tcslen(menuKeyStr.buf) + 6); | |||
_stprintf(tmp.buf, _T("Send %s"), menuKeyStr.buf); | |||
if (!ModifyMenu(menu, IDM_SEND_MENU_KEY, MF_BYCOMMAND | MF_STRING, IDM_SEND_MENU_KEY, tmp.buf)) | |||
InsertMenu(menu, IDM_SEND_CAD, MF_BYCOMMAND | MF_STRING, IDM_SEND_MENU_KEY, tmp.buf); | |||
} else { | |||
RemoveMenu(menu, IDM_SEND_MENU_KEY, MF_BYCOMMAND); | |||
} | |||
// Set the menu fullscreen option tick | |||
CheckMenuItem(menu, IDM_FULLSCREEN, (window->isFullscreen() ? MF_CHECKED : 0) | MF_BYCOMMAND); | |||
// Set the menu toolbar option tick | |||
int toolbarFlags = window->isToolbarEnabled() ? MF_CHECKED : 0; | |||
CheckMenuItem(menu, IDM_SHOW_TOOLBAR, MF_BYCOMMAND | toolbarFlags); | |||
// In the full-screen mode, "Show toolbar" should be grayed. | |||
toolbarFlags = window->isFullscreen() ? MF_GRAYED : MF_ENABLED; | |||
EnableMenuItem(menu, IDM_SHOW_TOOLBAR, MF_BYCOMMAND | toolbarFlags); | |||
} | |||
void | |||
CConn::blockCallback() { | |||
// - An InStream has blocked on I/O while processing an RFB message | |||
// We re-enable socket event notifications, so we'll know when more | |||
// data is available, then we sit and dispatch window events until | |||
// the notification arrives. | |||
if (!isClosed()) { | |||
if (WSAEventSelect(sock->getFd(), sockEvent, FD_READ | FD_CLOSE) == SOCKET_ERROR) | |||
throw rdr::SystemException("Unable to wait for sokcet data", WSAGetLastError()); | |||
} | |||
while (true) { | |||
// If we have closed then we can't block waiting for data | |||
if (isClosed()) | |||
throw rdr::EndOfStream(); | |||
// Wait for socket data, or a message to process | |||
DWORD result = MsgWaitForMultipleObjects(1, &sockEvent.h, FALSE, INFINITE, QS_ALLINPUT); | |||
if (result == WAIT_FAILED) { | |||
// - The wait operation failed - raise an exception | |||
throw rdr::SystemException("blockCallback wait error", GetLastError()); | |||
} | |||
// - There should be a message in the message queue | |||
MSG msg; | |||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { | |||
// IMPORTANT: We mustn't call TranslateMessage() here, because instead we | |||
// call ToAscii() in CKeyboard::keyEvent(). ToAscii() stores dead key | |||
// state from one call to the next, which would be messed up by calls to | |||
// TranslateMessage() (actually it looks like TranslateMessage() calls | |||
// ToAscii() internally). | |||
DispatchMessage(&msg); | |||
} | |||
if (result == WAIT_OBJECT_0) | |||
// - Network event notification. Return control to I/O routine. | |||
break; | |||
} | |||
// Before we return control to the InStream, reset the network event | |||
WSAEventSelect(sock->getFd(), sockEvent, 0); | |||
ResetEvent(sockEvent); | |||
} | |||
void CConn::keyEvent(rdr::U32 key, bool down) { | |||
if (!options.sendKeyEvents) return; | |||
try { | |||
writer()->keyEvent(key, down); | |||
} catch (rdr::Exception& e) { | |||
close(e.str()); | |||
} | |||
} | |||
void CConn::pointerEvent(const Point& pos, int buttonMask) { | |||
if (!options.sendPtrEvents) return; | |||
try { | |||
writer()->pointerEvent(pos, buttonMask); | |||
} catch (rdr::Exception& e) { | |||
close(e.str()); | |||
} | |||
} | |||
void CConn::clientCutText(const char* str, int len) { | |||
if (!options.clientCutText) return; | |||
if (state() != RFBSTATE_NORMAL) return; | |||
try { | |||
writer()->clientCutText(str, len); | |||
} catch (rdr::Exception& e) { | |||
close(e.str()); | |||
} | |||
} | |||
void | |||
CConn::setColourMapEntries(int first, int count, U16* rgbs) { | |||
vlog.debug("setColourMapEntries: first=%d, count=%d", first, count); | |||
int i; | |||
for (i=0;i<count;i++) | |||
window->setColour(i+first, rgbs[i*3], rgbs[i*3+1], rgbs[i*3+2]); | |||
// *** change to 0, 256? | |||
window->refreshWindowPalette(first, count); | |||
} | |||
void | |||
CConn::bell() { | |||
if (options.acceptBell) | |||
MessageBeep((UINT)-1); | |||
} | |||
void | |||
CConn::setDesktopSize(int w, int h) { | |||
vlog.debug("setDesktopSize %dx%d", w, h); | |||
// Resize the window's buffer | |||
if (window) | |||
window->setSize(w, h); | |||
// Tell the underlying CConnection | |||
CConnection::setDesktopSize(w, h); | |||
} | |||
void | |||
CConn::setExtendedDesktopSize(int reason, int result, int w, int h, | |||
const rfb::ScreenSet& layout) { | |||
if ((reason == (signed)reasonClient) && (result != (signed)resultSuccess)) { | |||
vlog.error("SetDesktopSize failed: %d", result); | |||
return; | |||
} | |||
// Resize the window's buffer | |||
if (window) | |||
window->setSize(w, h); | |||
// Tell the underlying CConnection | |||
CConnection::setExtendedDesktopSize(reason, result, w, h, layout); | |||
} | |||
void | |||
CConn::setCursor(int w, int h, const Point& hotspot, void* data, void* mask) { | |||
if (!options.useLocalCursor) return; | |||
// Set the window to use the new cursor | |||
window->setCursor(w, h, hotspot, data, mask); | |||
} | |||
void | |||
CConn::close(const char* reason) { | |||
// If already closed then ignore this | |||
if (isClosed()) | |||
return; | |||
// Hide the window, if it exists | |||
if (window) | |||
ShowWindow(window->getHandle(), SW_HIDE); | |||
// Save the reason & flag that we're closed & shutdown the socket | |||
isClosed_ = true; | |||
closeReason_.replaceBuf(strDup(reason)); | |||
sock->shutdown(); | |||
} | |||
bool CConn::showMsgBox(int flags, const char* title, const char* text) | |||
{ | |||
UINT winflags = 0; | |||
int ret; | |||
/* Translate flags */ | |||
if ((flags & M_OK) != 0) | |||
winflags |= MB_OK; | |||
if ((flags & M_OKCANCEL) != 0) | |||
winflags |= MB_OKCANCEL; | |||
if ((flags & M_YESNO) != 0) | |||
winflags |= MB_YESNO; | |||
if ((flags & M_ICONERROR) != 0) | |||
winflags |= MB_ICONERROR; | |||
if ((flags & M_ICONQUESTION) != 0) | |||
winflags |= MB_ICONQUESTION; | |||
if ((flags & M_ICONWARNING) != 0) | |||
winflags |= MB_ICONWARNING; | |||
if ((flags & M_ICONINFORMATION) != 0) | |||
winflags |= MB_ICONINFORMATION; | |||
if ((flags & M_DEFBUTTON1) != 0) | |||
winflags |= MB_DEFBUTTON1; | |||
if ((flags & M_DEFBUTTON2) != 0) | |||
winflags |= MB_DEFBUTTON2; | |||
ret = MessageBox(NULL, text, title, flags); | |||
return (ret == IDOK || ret == IDYES) ? true : false; | |||
} | |||
void | |||
CConn::showOptionsDialog() { | |||
optionsDialog.showDialog(this); | |||
} | |||
void | |||
CConn::framebufferUpdateStart() { | |||
if (!formatChange) { | |||
requestUpdate = pendingUpdate = true; | |||
requestNewUpdate(); | |||
} else | |||
pendingUpdate = false; | |||
} | |||
void | |||
CConn::framebufferUpdateEnd() { | |||
if (debugDelay != 0) { | |||
vlog.debug("debug delay %d",(int)debugDelay); | |||
UpdateWindow(window->getHandle()); | |||
Sleep(debugDelay); | |||
std::list<rfb::Rect>::iterator i; | |||
for (i = debugRects.begin(); i != debugRects.end(); i++) { | |||
window->invertRect(*i); | |||
} | |||
debugRects.clear(); | |||
} | |||
window->framebufferUpdateEnd(); | |||
if (firstUpdate) { | |||
int width, height; | |||
if (cp.supportsSetDesktopSize && | |||
sscanf(options.desktopSize.buf, "%dx%d", &width, &height) == 2) { | |||
ScreenSet layout; | |||
layout = cp.screenLayout; | |||
if (layout.num_screens() == 0) | |||
layout.add_screen(rfb::Screen()); | |||
else if (layout.num_screens() != 1) { | |||
ScreenSet::iterator iter; | |||
while (true) { | |||
iter = layout.begin(); | |||
++iter; | |||
if (iter == layout.end()) | |||
break; | |||
layout.remove_screen(iter->id); | |||
} | |||
} | |||
layout.begin()->dimensions.tl.x = 0; | |||
layout.begin()->dimensions.tl.y = 0; | |||
layout.begin()->dimensions.br.x = width; | |||
layout.begin()->dimensions.br.y = height; | |||
writer()->writeSetDesktopSize(width, height, layout); | |||
} | |||
firstUpdate = false; | |||
} | |||
// Always request the next update | |||
requestUpdate = true; | |||
// A format change prevented us from sending this before the update, | |||
// so make sure to send it now. | |||
if (formatChange && !pendingUpdate) | |||
requestNewUpdate(); | |||
if (options.autoSelect) | |||
autoSelectFormatAndEncoding(); | |||
// Check that at least part of the window has changed | |||
if (!GetUpdateRect(window->getHandle(), 0, FALSE)) { | |||
if (!(GetWindowLong(window->getHandle(), GWL_STYLE) & WS_MINIMIZE)) | |||
requestNewUpdate(); | |||
} | |||
// Make sure the local cursor is shown | |||
window->showCursor(); | |||
} | |||
// Note: The method below is duplicated in win/vncviewer/CConn.cxx! | |||
// autoSelectFormatAndEncoding() chooses the format and encoding appropriate | |||
// to the connection speed: | |||
// | |||
// First we wait for at least one second of bandwidth measurement. | |||
// | |||
// Above 16Mbps (i.e. LAN), we choose the second highest JPEG quality, | |||
// which should be perceptually lossless. | |||
// | |||
// If the bandwidth is below that, we choose a more lossy JPEG quality. | |||
// | |||
// If the bandwidth drops below 256 Kbps, we switch to palette mode. | |||
// | |||
// Note: The system here is fairly arbitrary and should be replaced | |||
// with something more intelligent at the server end. | |||
// | |||
void CConn::autoSelectFormatAndEncoding() | |||
{ | |||
int kbitsPerSecond = sock->inStream().kbitsPerSecond(); | |||
unsigned int timeWaited = sock->inStream().timeWaited(); | |||
bool newFullColour = options.fullColour; | |||
int newQualityLevel = options.qualityLevel; | |||
// Always use Tight | |||
options.preferredEncoding = encodingTight; | |||
// Check that we have a decent bandwidth measurement | |||
if ((kbitsPerSecond == 0) || (timeWaited < 10000)) | |||
return; | |||
// Select appropriate quality level | |||
if (!options.noJpeg) { | |||
if (kbitsPerSecond > 16000) | |||
newQualityLevel = 8; | |||
else | |||
newQualityLevel = 6; | |||
if (newQualityLevel != options.qualityLevel) { | |||
vlog.info("Throughput %d kbit/s - changing to quality %d ", | |||
kbitsPerSecond, newQualityLevel); | |||
cp.qualityLevel = newQualityLevel; | |||
options.qualityLevel = newQualityLevel; | |||
encodingChange = true; | |||
} | |||
} | |||
if (cp.beforeVersion(3, 8)) { | |||
// Xvnc from TightVNC 1.2.9 sends out FramebufferUpdates with | |||
// cursors "asynchronously". If this happens in the middle of a | |||
// pixel format change, the server will encode the cursor with | |||
// the old format, but the client will try to decode it | |||
// according to the new format. This will lead to a | |||
// crash. Therefore, we do not allow automatic format change for | |||
// old servers. | |||
return; | |||
} | |||
// Select best color level | |||
newFullColour = (kbitsPerSecond > 256); | |||
if (newFullColour != options.fullColour) { | |||
vlog.info("Throughput %d kbit/s - full color is now %s", | |||
kbitsPerSecond, | |||
newFullColour ? "enabled" : "disabled"); | |||
options.fullColour = newFullColour; | |||
formatChange = true; | |||
} | |||
} | |||
void | |||
CConn::requestNewUpdate() { | |||
if (!requestUpdate) return; | |||
if (formatChange) { | |||
/* Catch incorrect requestNewUpdate calls */ | |||
assert(pendingUpdate == false); | |||
// Select the required pixel format | |||
if (options.fullColour) { | |||
window->setPF(fullColourPF); | |||
} else { | |||
switch (options.lowColourLevel) { | |||
case 0: | |||
window->setPF(PixelFormat(8,3,0,1,1,1,1,2,1,0)); | |||
break; | |||
case 1: | |||
window->setPF(PixelFormat(8,6,0,1,3,3,3,4,2,0)); | |||
break; | |||
case 2: | |||
window->setPF(PixelFormat(8,8,0,0,0,0,0,0,0,0)); | |||
break; | |||
} | |||
} | |||
// Print the current pixel format | |||
char str[256]; | |||
window->getPF().print(str, 256); | |||
vlog.info("Using pixel format %s",str); | |||
// Save the connection pixel format and tell server to use it | |||
cp.setPF(window->getPF()); | |||
writer()->writeSetPixelFormat(cp.pf()); | |||
// Correct the local window's palette | |||
if (!window->getNativePF().trueColour) | |||
window->refreshWindowPalette(0, 1 << cp.pf().depth); | |||
} | |||
if (encodingChange) { | |||
vlog.info("Using %s encoding",encodingName(options.preferredEncoding)); | |||
writer()->writeSetEncodings(options.preferredEncoding, true); | |||
} | |||
writer()->writeFramebufferUpdateRequest(Rect(0, 0, cp.width, cp.height), | |||
!formatChange); | |||
encodingChange = formatChange = requestUpdate = false; | |||
} | |||
void | |||
CConn::calculateFullColourPF() { | |||
// If the server is palette based then use palette locally | |||
// Also, don't bother doing bgr222 | |||
if (!serverDefaultPF.trueColour || (serverDefaultPF.depth < 6)) { | |||
fullColourPF = serverDefaultPF; | |||
options.fullColour = true; | |||
} else { | |||
// If server is trueColour, use lowest depth PF | |||
PixelFormat native = window->getNativePF(); | |||
if ((serverDefaultPF.bpp < native.bpp) || | |||
((serverDefaultPF.bpp == native.bpp) && | |||
(serverDefaultPF.depth < native.depth))) | |||
fullColourPF = serverDefaultPF; | |||
else | |||
fullColourPF = window->getNativePF(); | |||
} | |||
formatChange = true; | |||
} | |||
void | |||
CConn::setName(const char* name) { | |||
if (window) | |||
window->setName(name); | |||
CConnection::setName(name); | |||
} | |||
void CConn::serverInit() { | |||
CConnection::serverInit(); | |||
// If using AutoSelect with old servers, start in FullColor | |||
// mode. See comment in autoSelectFormatAndEncoding. | |||
if (cp.beforeVersion(3, 8) && options.autoSelect) { | |||
options.fullColour = true; | |||
} | |||
// Show the window | |||
window = new DesktopWindow(this); | |||
// Update the window menu | |||
HMENU wndmenu = GetSystemMenu(window->getHandle(), FALSE); | |||
int toolbarChecked = options.showToolbar ? MF_CHECKED : 0; | |||
AppendMenu(wndmenu, MF_SEPARATOR, 0, 0); | |||
AppendMenu(wndmenu, MF_STRING, IDM_FULLSCREEN, _T("&Full screen")); | |||
AppendMenu(wndmenu, MF_STRING | toolbarChecked, IDM_SHOW_TOOLBAR, | |||
_T("Show tool&bar")); | |||
AppendMenu(wndmenu, MF_SEPARATOR, 0, 0); | |||
AppendMenu(wndmenu, MF_STRING, IDM_CTRL_KEY, _T("Ctr&l")); | |||
AppendMenu(wndmenu, MF_STRING, IDM_ALT_KEY, _T("Al&t")); | |||
AppendMenu(wndmenu, MF_STRING, IDM_SEND_CAD, _T("Send Ctrl-Alt-&Del")); | |||
AppendMenu(wndmenu, MF_STRING, IDM_SEND_CTLESC, _T("Send Ctrl-&Esc")); | |||
AppendMenu(wndmenu, MF_STRING, IDM_REQUEST_REFRESH, _T("Refres&h Screen")); | |||
AppendMenu(wndmenu, MF_SEPARATOR, 0, 0); | |||
AppendMenu(wndmenu, MF_STRING, IDM_NEWCONN, _T("Ne&w Connection...")); | |||
AppendMenu(wndmenu, MF_STRING, IDM_OPTIONS, _T("&Options...")); | |||
AppendMenu(wndmenu, MF_STRING, IDM_INFO, _T("Connection &Info...")); | |||
AppendMenu(wndmenu, MF_STRING, IDM_ABOUT, _T("&About...")); | |||
// Set window attributes | |||
window->setName(cp.name()); | |||
window->setShowToolbar(options.showToolbar); | |||
window->setSize(cp.width, cp.height); | |||
applyOptions(options); | |||
// Save the server's current format | |||
serverDefaultPF = cp.pf(); | |||
// Calculate the full-colour format to use | |||
calculateFullColourPF(); | |||
// Request the initial update | |||
vlog.info("requesting initial update"); | |||
formatChange = encodingChange = requestUpdate = true; | |||
requestNewUpdate(); | |||
} | |||
void | |||
CConn::serverCutText(const char* str, rdr::U32 len) { | |||
if (!options.serverCutText) return; | |||
window->serverCutText(str, len); | |||
} | |||
void CConn::beginRect(const Rect& r, int encoding) { | |||
sock->inStream().startTiming(); | |||
} | |||
void CConn::endRect(const Rect& r, int encoding) { | |||
sock->inStream().stopTiming(); | |||
lastUsedEncoding_ = encoding; | |||
if (debugDelay != 0) { | |||
window->invertRect(r); | |||
debugRects.push_back(r); | |||
} | |||
} | |||
void CConn::fillRect(const Rect& r, Pixel pix) { | |||
window->fillRect(r, pix); | |||
} | |||
void CConn::imageRect(const Rect& r, void* pixels) { | |||
window->imageRect(r, pixels); | |||
} | |||
void CConn::copyRect(const Rect& r, int srcX, int srcY) { | |||
window->copyRect(r, srcX, srcY); | |||
} | |||
void CConn::getUserPasswd(char** user, char** password) { | |||
if (!user && options.passwordFile.buf[0]) { | |||
FILE* fp = fopen(options.passwordFile.buf, "rb"); | |||
if (fp) { | |||
char data[256]; | |||
int datalen = fread(data, 1, 256, fp); | |||
fclose(fp); | |||
if (datalen == 8) { | |||
ObfuscatedPasswd obfPwd; | |||
obfPwd.buf = data; | |||
obfPwd.length = datalen; | |||
PlainPasswd passwd(obfPwd); | |||
obfPwd.takeBuf(); | |||
*password = strDup(passwd.buf); | |||
memset(data, 0, sizeof(data)); | |||
} | |||
} | |||
} | |||
if (user && options.userName.buf) | |||
*user = strDup(options.userName.buf); | |||
if (password && options.password.buf) | |||
*password = strDup(options.password.buf); | |||
if ((user && !*user) || (password && !*password)) { | |||
// Missing username or password - prompt the user | |||
UserPasswdDialog userPasswdDialog; | |||
userPasswdDialog.setCSecurity(csecurity); | |||
userPasswdDialog.getUserPasswd(user, password); | |||
} | |||
if (user) options.setUserName(*user); | |||
if (password) options.setPassword(*password); | |||
} | |||
@@ -1,169 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- CConn.h | |||
// Windows-specific implementation of CConnection | |||
#ifndef __RFB_WIN32_CCONN_H__ | |||
#define __RFB_WIN32_CCONN_H__ | |||
#include <network/Socket.h> | |||
#include <rfb/CConnection.h> | |||
#include <rfb/Cursor.h> | |||
#include <rfb/UserMsgBox.h> | |||
#include <rfb/UserPasswdGetter.h> | |||
#include <rfb_win32/Registry.h> | |||
#include <rfb_win32/Handle.h> | |||
#include <vncviewer/InfoDialog.h> | |||
#include <vncviewer/OptionsDialog.h> | |||
#include <vncviewer/CConnOptions.h> | |||
#include <vncviewer/DesktopWindow.h> | |||
#include <list> | |||
namespace rfb { | |||
namespace win32 { | |||
class CConn : public CConnection, | |||
UserPasswdGetter, | |||
DesktopWindow::Callback, | |||
rdr::FdInStreamBlockCallback, | |||
UserMsgBox | |||
{ | |||
public: | |||
CConn(); | |||
~CConn(); | |||
// - Start the VNC session on the supplied socket | |||
// The socket must already be connected to a host | |||
bool initialise(network::Socket* s, bool reverse=false); | |||
// - Set/get the session options | |||
void applyOptions(CConnOptions& opt); | |||
const CConnOptions& getOptions() const { return options; }; | |||
// - Show the options dialog for the connection | |||
void showOptionsDialog(); | |||
// - Close the socket & set the reason for closure | |||
void close(const char* reason=0); | |||
bool isClosed() const { return isClosed_; } | |||
const char* closeReason() const { return closeReason_.buf; } | |||
// - Last received encoding, for the Info dialog | |||
int lastUsedEncoding() const { return lastUsedEncoding_; } | |||
// - Get at the DesktopWindow, if any | |||
DesktopWindow* getWindow() { return window; } | |||
// - Get at the underlying Socket | |||
network::Socket* getSocket() { return sock; } | |||
// - Get the server's preferred format | |||
const PixelFormat& getServerDefaultPF() const { return serverDefaultPF; } | |||
// - Display message box | |||
virtual bool showMsgBox(int flags, const char* title, const char* text); | |||
// Global user-config registry key | |||
static RegKey userConfigKey; | |||
protected: | |||
// InputHandler interface (via DesktopWindow::Callback) | |||
void keyEvent(rdr::U32 key, bool down); | |||
void pointerEvent(const Point& pos, int buttonMask); | |||
void clientCutText(const char* str, int len); | |||
// DesktopWindow::Callback interface | |||
void displayChanged(); | |||
void paintCompleted() {} | |||
bool sysCommand(WPARAM wParam, LPARAM lParam); | |||
void closeWindow(); | |||
void refreshMenu(bool enableSysCommands); | |||
// CConnection interface | |||
void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); | |||
void bell(); | |||
void framebufferUpdateStart(); | |||
void framebufferUpdateEnd(); | |||
void setDesktopSize(int w, int h); | |||
void setExtendedDesktopSize(int reason, int result, int w, int h, | |||
const rfb::ScreenSet& layout); | |||
void setCursor(int w, int h, const Point& hotspot, void* data, void* mask); | |||
void setName(const char* name); | |||
void serverInit(); | |||
void serverCutText(const char* str, rdr::U32 len); | |||
void beginRect(const Rect& r, int encoding); | |||
void endRect(const Rect& r, int encoding); | |||
void fillRect(const Rect& r, Pixel pix); | |||
void imageRect(const Rect& r, void* pixels); | |||
void copyRect(const Rect& r, int srcX, int srcY); | |||
// rdr::FdInStreamBlockCallback interface | |||
void blockCallback(); | |||
// UserPasswdGetter interface | |||
// (overridden to allow a pre-supplied username & password) | |||
void getUserPasswd(char** user, char** password); | |||
// CConn-specific internal interface | |||
void autoSelectFormatAndEncoding(); | |||
void requestNewUpdate(); | |||
void calculateFullColourPF(); | |||
// The desktop window | |||
DesktopWindow* window; | |||
// Info and Options dialogs | |||
OptionsDialog optionsDialog; | |||
InfoDialog infoDialog; | |||
// VNC Viewer options | |||
CConnOptions options; | |||
// Pixel format and encoding | |||
PixelFormat serverDefaultPF; | |||
PixelFormat fullColourPF; | |||
bool sameMachine; | |||
bool encodingChange; | |||
bool formatChange; | |||
int lastUsedEncoding_; | |||
// Networking and RFB protocol | |||
network::Socket* sock; | |||
Handle sockEvent; | |||
bool reverseConnection; | |||
bool requestUpdate; | |||
bool firstUpdate; | |||
bool pendingUpdate; | |||
// Debugging/logging | |||
std::list<Rect> debugRects; | |||
CharArray closeReason_; | |||
bool isClosed_; | |||
}; | |||
}; | |||
}; | |||
#endif | |||
@@ -1,507 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#include <vncviewer/CConnOptions.h> | |||
#include <rfb/Configuration.h> | |||
#include <rfb/encodings.h> | |||
#include <rfb/LogWriter.h> | |||
#include <rfb/ScaleFilters.h> | |||
#include <rfb_win32/MsgBox.h> | |||
#include <rfb_win32/Registry.h> | |||
#include <rfb/SecurityClient.h> | |||
#include <rdr/HexInStream.h> | |||
#include <rdr/HexOutStream.h> | |||
#include <stdlib.h> | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
static StringParameter passwordFile("PasswordFile", | |||
"Password file for VNC authentication", ""); | |||
// - Settings stored in the registry & in .vnc files, by Save Defaults and | |||
// Save Configuration respectively. | |||
static BoolParameter useLocalCursor("UseLocalCursor", "Render the mouse cursor locally", true); | |||
static BoolParameter useDesktopResize("UseDesktopResize", "Support dynamic desktop resizing", true); | |||
static BoolParameter fullColour("FullColor", | |||
"Use full color", true); | |||
static AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour); | |||
static IntParameter lowColourLevel("LowColorLevel", | |||
"Color level to use on slow connections. " | |||
"0 = Very Low (8 colors), 1 = Low (64 colors), 2 = Medium (256 colors)", | |||
2); | |||
static AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel); | |||
static BoolParameter fullScreen("FullScreen", | |||
"Use the whole display to show the remote desktop." | |||
"(Press F8 to access the viewer menu)", | |||
false); | |||
static StringParameter preferredEncoding("PreferredEncoding", | |||
"Preferred encoding to use (Tight, ZRLE, Hextile or" | |||
" Raw)", "Tight"); | |||
static BoolParameter autoSelect("AutoSelect", | |||
"Auto select pixel format and encoding. " | |||
"Default if PreferredEncoding and FullColor are not specified.", | |||
true); | |||
static BoolParameter sharedConnection("Shared", | |||
"Allow existing connections to the server to continue." | |||
"(Default is to disconnect all other clients)", | |||
false); | |||
StringParameter desktopSize("DesktopSize", | |||
"Reconfigure desktop size on the server on " | |||
"connect (if possible)", ""); | |||
static BoolParameter sendPtrEvents("SendPointerEvents", | |||
"Send pointer (mouse) events to the server.", true); | |||
static BoolParameter sendKeyEvents("SendKeyEvents", | |||
"Send key presses (and releases) to the server.", true); | |||
static BoolParameter clientCutText("ClientCutText", | |||
"Send clipboard changes to the server.", true); | |||
static BoolParameter serverCutText("ServerCutText", | |||
"Accept clipboard changes from the server.", true); | |||
static BoolParameter disableWinKeys("DisableWinKeys", | |||
"Pass special Windows keys directly to the server.", true); | |||
static BoolParameter protocol3_3("Protocol3.3", | |||
"Only use protocol version 3.3", false); | |||
static IntParameter ptrEventInterval("PointerEventInterval", | |||
"The interval to delay between sending one pointer event " | |||
"and the next.", 0); | |||
static BoolParameter emulate3("Emulate3", | |||
"Emulate middle mouse button when left and right buttons " | |||
"are used simulatenously.", false); | |||
static BoolParameter acceptBell("AcceptBell", | |||
"Produce a system beep when requested to by the server.", | |||
true); | |||
static BoolParameter showToolbar("ShowToolbar", "Show toolbar by default.", true); | |||
static StringParameter monitor("Monitor", "The monitor to open the VNC Viewer window on, if available.", ""); | |||
static StringParameter menuKey("MenuKey", "The key which brings up the popup menu", "F8"); | |||
static BoolParameter autoReconnect("AutoReconnect", "Offer to reconnect to the remote server if the connection" | |||
"is dropped because an error occurs.", true); | |||
static BoolParameter customCompressLevel("CustomCompressLevel", | |||
"Use custom compression level. " | |||
"Default if CompressLevel is specified.", false); | |||
static IntParameter compressLevel("CompressLevel", | |||
"Use specified compression level" | |||
"0 = Low, 9 = High", | |||
6); | |||
static BoolParameter noJpeg("NoJPEG", | |||
"Disable lossy JPEG compression in Tight encoding.", | |||
false); | |||
static IntParameter qualityLevel("QualityLevel", | |||
"JPEG quality level. " | |||
"0 = Low, 9 = High", | |||
8); | |||
static BoolParameter autoScaling("AutoScaling", | |||
"Auto rescale local copy of the remote desktop to the client window.", | |||
false); | |||
static IntParameter scale("Scale", | |||
"Scale local copy of the remote desktop, in percent", | |||
100); | |||
CConnOptions::CConnOptions() | |||
: useLocalCursor (::useLocalCursor), | |||
useDesktopResize(::useDesktopResize), | |||
fullScreen(::fullScreen), | |||
fullColour(::fullColour), | |||
lowColourLevel(::lowColourLevel), | |||
preferredEncoding(encodingTight), | |||
autoSelect(::autoSelect), | |||
shared(::sharedConnection), | |||
desktopSize(::desktopSize.getData()), | |||
sendPtrEvents(::sendPtrEvents), | |||
sendKeyEvents(::sendKeyEvents), | |||
showToolbar(::showToolbar), | |||
clientCutText(::clientCutText), | |||
serverCutText(::serverCutText), | |||
disableWinKeys(::disableWinKeys), | |||
emulate3(::emulate3), | |||
pointerEventInterval(ptrEventInterval), | |||
protocol3_3(::protocol3_3), | |||
acceptBell(::acceptBell), | |||
autoScaling(::autoScaling), | |||
scale(::scale), | |||
monitor(::monitor.getData()), | |||
autoReconnect(::autoReconnect), | |||
customCompressLevel(::customCompressLevel), | |||
compressLevel(::compressLevel), | |||
noJpeg(::noJpeg), | |||
qualityLevel(::qualityLevel), | |||
passwordFile(::passwordFile.getData()) | |||
{ | |||
char *sectypes; | |||
if (autoSelect) { | |||
preferredEncoding = encodingTight; | |||
} else { | |||
CharArray encodingName(::preferredEncoding.getData()); | |||
preferredEncoding = encodingNum(encodingName.buf); | |||
} | |||
setMenuKey(CharArray(::menuKey.getData()).buf); | |||
if (!::autoSelect.hasBeenSet()) { | |||
// Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used | |||
autoSelect = (!::preferredEncoding.hasBeenSet() | |||
&& !::fullColour.hasBeenSet() | |||
&& !::fullColourAlias.hasBeenSet()); | |||
} | |||
if (!::customCompressLevel.hasBeenSet()) { | |||
// Default to CustomCompressLevel=1 if CompressLevel is used. | |||
customCompressLevel = ::compressLevel.hasBeenSet(); | |||
} | |||
sectypes = SecurityClient::secTypes.getDefaultStr(); | |||
secTypes = parseSecTypes(sectypes); | |||
delete [] sectypes; | |||
} | |||
void CConnOptions::readFromFile(const char* filename) { | |||
FILE* f = fopen(filename, "r"); | |||
if (!f) | |||
throw rdr::Exception("Failed to read configuration file"); | |||
try { | |||
char line[4096]; | |||
CharArray section; | |||
CharArray hostTmp; | |||
int portTmp = 0; | |||
while (!feof(f)) { | |||
// Read the next line | |||
if (!fgets(line, sizeof(line), f)) { | |||
if (feof(f)) | |||
break; | |||
throw rdr::SystemException("fgets", ferror(f)); | |||
} | |||
int len=strlen(line); | |||
if (line[len-1] == '\n') { | |||
line[len-1] = 0; | |||
len--; | |||
} | |||
// Process the line | |||
if (line[0] == ';') { | |||
// Comment | |||
} else if (line[0] == '[') { | |||
// Entering a new section | |||
if (!strSplit(&line[1], ']', §ion.buf, 0)) | |||
throw rdr::Exception("bad Section"); | |||
} else { | |||
// Reading an option | |||
CharArray name; | |||
CharArray value; | |||
if (!strSplit(line, '=', &name.buf, &value.buf)) | |||
throw rdr::Exception("bad Name/Value pair"); | |||
if (stricmp(section.buf, "Connection") == 0) { | |||
if (stricmp(name.buf, "Host") == 0) { | |||
hostTmp.replaceBuf(value.takeBuf()); | |||
} else if (stricmp(name.buf, "Port") == 0) { | |||
portTmp = atoi(value.buf); | |||
} else if (stricmp(name.buf, "UserName") == 0) { | |||
userName.replaceBuf(value.takeBuf()); | |||
} else if (stricmp(name.buf, "Password") == 0) { | |||
ObfuscatedPasswd obfPwd; | |||
rdr::HexInStream::hexStrToBin(value.buf, (char**)&obfPwd.buf, &obfPwd.length); | |||
PlainPasswd passwd(obfPwd); | |||
password.replaceBuf(passwd.takeBuf()); | |||
} | |||
} else if (stricmp(section.buf, "Options") == 0) { | |||
// V4 options | |||
if (stricmp(name.buf, "UseLocalCursor") == 0) { | |||
useLocalCursor = atoi(value.buf); | |||
} else if (stricmp(name.buf, "UseDesktopResize") == 0) { | |||
useDesktopResize = atoi(value.buf); | |||
} else if (stricmp(name.buf, "FullScreen") == 0) { | |||
fullScreen = atoi(value.buf); | |||
} else if (stricmp(name.buf, "FullColour") == 0) { | |||
fullColour = atoi(value.buf); | |||
} else if (stricmp(name.buf, "LowColourLevel") == 0) { | |||
lowColourLevel = atoi(value.buf); | |||
} else if (stricmp(name.buf, "PreferredEncoding") == 0) { | |||
preferredEncoding = encodingNum(value.buf); | |||
} else if ((stricmp(name.buf, "AutoDetect") == 0) || | |||
(stricmp(name.buf, "AutoSelect") == 0)) { | |||
autoSelect = atoi(value.buf); | |||
} else if (stricmp(name.buf, "Shared") == 0) { | |||
shared = atoi(value.buf); | |||
} else if (stricmp(name.buf, "SendPtrEvents") == 0) { | |||
sendPtrEvents = atoi(value.buf); | |||
} else if (stricmp(name.buf, "SendKeyEvents") == 0) { | |||
sendKeyEvents = atoi(value.buf); | |||
} else if (stricmp(name.buf, "SendCutText") == 0) { | |||
clientCutText = atoi(value.buf); | |||
} else if (stricmp(name.buf, "AcceptCutText") == 0) { | |||
serverCutText = atoi(value.buf); | |||
} else if (stricmp(name.buf, "DisableWinKeys") == 0) { | |||
disableWinKeys = atoi(value.buf); | |||
} else if (stricmp(name.buf, "AcceptBell") == 0) { | |||
acceptBell = atoi(value.buf); | |||
} else if (stricmp(name.buf, "Emulate3") == 0) { | |||
emulate3 = atoi(value.buf); | |||
} else if (stricmp(name.buf, "ShowToolbar") == 0) { | |||
showToolbar = atoi(value.buf); | |||
} else if (stricmp(name.buf, "PointerEventInterval") == 0) { | |||
pointerEventInterval = atoi(value.buf); | |||
} else if (stricmp(name.buf, "Monitor") == 0) { | |||
monitor.replaceBuf(value.takeBuf()); | |||
} else if (stricmp(name.buf, "MenuKey") == 0) { | |||
setMenuKey(value.buf); | |||
} else if (stricmp(name.buf, "AutoReconnect") == 0) { | |||
autoReconnect = atoi(value.buf); | |||
} else if (stricmp(name.buf, "CustomCompressLevel") == 0) { | |||
customCompressLevel = atoi(value.buf); | |||
} else if (stricmp(name.buf, "CompressLevel") == 0) { | |||
compressLevel = atoi(value.buf); | |||
} else if (stricmp(name.buf, "NoJPEG") == 0) { | |||
noJpeg = atoi(value.buf); | |||
} else if (stricmp(name.buf, "QualityLevel") == 0) { | |||
qualityLevel = atoi(value.buf); | |||
// Legacy options | |||
} else if (stricmp(name.buf, "Preferred_Encoding") == 0) { | |||
preferredEncoding = atoi(value.buf); | |||
} else if (stricmp(name.buf, "8bit") == 0) { | |||
fullColour = !atoi(value.buf); | |||
} else if (stricmp(name.buf, "FullScreen") == 0) { | |||
fullScreen = atoi(value.buf); | |||
} else if (stricmp(name.buf, "ViewOnly") == 0) { | |||
sendPtrEvents = sendKeyEvents = !atoi(value.buf); | |||
} else if (stricmp(name.buf, "DisableClipboard") == 0) { | |||
clientCutText = serverCutText = !atoi(value.buf); | |||
} else if (stricmp(name.buf, "AutoScaling") == 0) { | |||
autoScaling = atoi(value.buf); | |||
} else if (stricmp(name.buf, "Scale") == 0) { | |||
scale = atoi(value.buf); | |||
} else if (stricmp(name.buf, "SecurityTypes") == 0) { | |||
secTypes = parseSecTypes(value.buf); | |||
} | |||
} | |||
} | |||
} | |||
fclose(f); f=0; | |||
// Process the Host and Port | |||
if (hostTmp.buf) { | |||
int hostLen = strlen(hostTmp.buf) + 2 + 17; | |||
host.replaceBuf(new char[hostLen]); | |||
strCopy(host.buf, hostTmp.buf, hostLen); | |||
if (portTmp) { | |||
strncat(host.buf, "::", hostLen-1); | |||
char tmp[16]; | |||
sprintf(tmp, "%d", portTmp); | |||
strncat(host.buf, tmp, hostLen-1); | |||
} | |||
} | |||
// If AutoSelect is enabled then override the preferred encoding | |||
if (autoSelect) | |||
preferredEncoding = encodingZRLE; | |||
setConfigFileName(filename); | |||
} catch (rdr::Exception&) { | |||
if (f) fclose(f); | |||
throw; | |||
} | |||
} | |||
void CConnOptions::writeToFile(const char* filename) { | |||
FILE* f = fopen(filename, "w"); | |||
if (!f) | |||
throw rdr::Exception("Failed to write configuration file"); | |||
try { | |||
// - Split server into host and port and save | |||
fprintf(f, "[Connection]\n"); | |||
fprintf(f, "Host=%s\n", host.buf); | |||
if (userName.buf) | |||
fprintf(f, "UserName=%s\n", userName.buf); | |||
if (password.buf) { | |||
// - Warn the user before saving the password | |||
if (MsgBox(0, _T("Do you want to include the VNC Password in this configuration file?\n") | |||
_T("Storing the password is more convenient but poses a security risk."), | |||
MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDYES) { | |||
ObfuscatedPasswd obfPwd(password); | |||
CharArray obfuscatedHex(rdr::HexOutStream::binToHexStr(obfPwd.buf, obfPwd.length)); | |||
fprintf(f, "Password=%s\n", obfuscatedHex.buf); | |||
} | |||
} | |||
// - Save the other options | |||
fprintf(f, "[Options]\n"); | |||
fprintf(f, "UseLocalCursor=%d\n", (int)useLocalCursor); | |||
fprintf(f, "UseDesktopResize=%d\n", (int)useDesktopResize); | |||
fprintf(f, "FullScreen=%d\n", (int)fullScreen); | |||
fprintf(f, "FullColour=%d\n", (int)fullColour); | |||
fprintf(f, "LowColourLevel=%d\n", lowColourLevel); | |||
fprintf(f, "PreferredEncoding=%s\n", encodingName(preferredEncoding)); | |||
fprintf(f, "AutoSelect=%d\n", (int)autoSelect); | |||
fprintf(f, "Shared=%d\n", (int)shared); | |||
fprintf(f, "SendPtrEvents=%d\n", (int)sendPtrEvents); | |||
fprintf(f, "SendKeyEvents=%d\n", (int)sendKeyEvents); | |||
fprintf(f, "SendCutText=%d\n", (int)clientCutText); | |||
fprintf(f, "AcceptCutText=%d\n", (int)serverCutText); | |||
fprintf(f, "DisableWinKeys=%d\n", (int)disableWinKeys); | |||
fprintf(f, "AcceptBell=%d\n", (int)acceptBell); | |||
fprintf(f, "Emulate3=%d\n", (int)emulate3); | |||
fprintf(f, "ShowToolbar=%d\n", (int)showToolbar); | |||
fprintf(f, "PointerEventInterval=%d\n", pointerEventInterval); | |||
if (monitor.buf) | |||
fprintf(f, "Monitor=%s\n", monitor.buf); | |||
fprintf(f, "MenuKey=%s\n", CharArray(menuKeyName()).buf); | |||
fprintf(f, "AutoReconnect=%d\n", (int)autoReconnect); | |||
fprintf(f, "CustomCompressLevel=%d\n", customCompressLevel); | |||
fprintf(f, "CompressLevel=%d\n", compressLevel); | |||
fprintf(f, "NoJPEG=%d\n", noJpeg); | |||
fprintf(f, "QualityLevel=%d\n", qualityLevel); | |||
fprintf(f, "AutoScaling=%d\n", (int)autoScaling); | |||
fprintf(f, "Scale=%d\n", scale); | |||
fprintf(f, "SecurityTypes="); | |||
std::list<rdr::U32>::iterator i; | |||
for (i = secTypes.begin(); i != secTypes.end(); i++) | |||
fprintf(f, "%s,", secTypeName(*i)); | |||
fprintf(f, "\n"); | |||
fclose(f); f=0; | |||
setConfigFileName(filename); | |||
} catch (rdr::Exception&) { | |||
if (f) fclose(f); | |||
throw; | |||
} | |||
} | |||
void CConnOptions::writeDefaults() { | |||
RegKey key; | |||
key.createKey(HKEY_CURRENT_USER, _T("Software\\TigerVNC\\VNCviewer4")); | |||
key.setBool(_T("UseLocalCursor"), useLocalCursor); | |||
key.setBool(_T("UseDesktopResize"), useDesktopResize); | |||
key.setBool(_T("FullScreen"), fullScreen); | |||
key.setBool(_T("FullColour"), fullColour); | |||
key.setInt(_T("LowColourLevel"), lowColourLevel); | |||
key.setString(_T("PreferredEncoding"), TStr(encodingName(preferredEncoding))); | |||
key.setBool(_T("AutoSelect"), autoSelect); | |||
key.setBool(_T("Shared"), shared); | |||
key.setBool(_T("SendPointerEvents"), sendPtrEvents); | |||
key.setBool(_T("SendKeyEvents"), sendKeyEvents); | |||
key.setBool(_T("ClientCutText"), clientCutText); | |||
key.setBool(_T("ServerCutText"), serverCutText); | |||
key.setBool(_T("DisableWinKeys"), disableWinKeys); | |||
key.setBool(_T("Protocol3.3"), protocol3_3); | |||
key.setBool(_T("AcceptBell"), acceptBell); | |||
key.setBool(_T("ShowToolbar"), showToolbar); | |||
key.setBool(_T("Emulate3"), emulate3); | |||
key.setInt(_T("PointerEventInterval"), pointerEventInterval); | |||
if (monitor.buf) | |||
key.setString(_T("Monitor"), TStr(monitor.buf)); | |||
key.setString(_T("MenuKey"), TCharArray(menuKeyName()).buf); | |||
key.setBool(_T("AutoReconnect"), autoReconnect); | |||
key.setInt(_T("CustomCompressLevel"), customCompressLevel); | |||
key.setInt(_T("CompressLevel"), compressLevel); | |||
key.setInt(_T("NoJPEG"), noJpeg); | |||
key.setInt(_T("QualityLevel"), qualityLevel); | |||
key.setBool(_T("AutoScaling"), autoScaling); | |||
key.setInt(_T("Scale"), scale); | |||
} | |||
void CConnOptions::setUserName(const char* user) {userName.replaceBuf(strDup(user));} | |||
void CConnOptions::setPassword(const char* pwd) {password.replaceBuf(strDup(pwd));} | |||
void CConnOptions::setConfigFileName(const char* cfn) {configFileName.replaceBuf(strDup(cfn));} | |||
void CConnOptions::setHost(const char* h) {host.replaceBuf(strDup(h));} | |||
void CConnOptions::setMonitor(const char* m) {monitor.replaceBuf(strDup(m));} | |||
void CConnOptions::setMenuKey(const char* keyName) { | |||
if (!keyName[0]) { | |||
menuKey = 0; | |||
} else { | |||
menuKey = VK_F8; | |||
if (keyName[0] == 'F') { | |||
UINT fKey = atoi(&keyName[1]); | |||
if (fKey >= 1 && fKey <= 12) | |||
menuKey = fKey-1 + VK_F1; | |||
} | |||
} | |||
} | |||
char* CConnOptions::menuKeyName() { | |||
int fNum = (menuKey-VK_F1)+1; | |||
if (fNum<1 || fNum>12) | |||
return strDup(""); | |||
CharArray menuKeyStr(4); | |||
sprintf(menuKeyStr.buf, "F%d", fNum); | |||
return menuKeyStr.takeBuf(); | |||
} | |||
CConnOptions& CConnOptions::operator=(const CConnOptions& o) { | |||
useLocalCursor = o.useLocalCursor; | |||
useDesktopResize = o.useDesktopResize; | |||
fullScreen = o.fullScreen; | |||
fullColour = o.fullColour; | |||
lowColourLevel = o.lowColourLevel; | |||
preferredEncoding = o.preferredEncoding; | |||
autoSelect = o.autoSelect; | |||
shared = o.shared; | |||
sendPtrEvents = o.sendPtrEvents; | |||
sendKeyEvents = o.sendKeyEvents; | |||
clientCutText = o.clientCutText; | |||
serverCutText = o.serverCutText; | |||
disableWinKeys = o.disableWinKeys; | |||
emulate3 = o.emulate3; | |||
pointerEventInterval = o.pointerEventInterval; | |||
protocol3_3 = o.protocol3_3; | |||
acceptBell = o.acceptBell; | |||
showToolbar = o.showToolbar; | |||
setUserName(o.userName.buf); | |||
setPassword(o.password.buf); | |||
setConfigFileName(o.configFileName.buf); | |||
setHost(o.host.buf); | |||
setMonitor(o.monitor.buf); | |||
menuKey = o.menuKey; | |||
autoReconnect = o.autoReconnect; | |||
customCompressLevel = o.customCompressLevel; | |||
compressLevel = o.compressLevel; | |||
noJpeg = o.noJpeg; | |||
qualityLevel = o.qualityLevel; | |||
autoScaling = o.autoScaling; | |||
scale = o.scale; | |||
secTypes = o.secTypes; | |||
return *this; | |||
} |
@@ -1,104 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- CConnOptions.h | |||
// Definition of the CConnOptions class, responsible for storing the | |||
// current & requested VNC Viewer options. | |||
#ifndef __RFB_WIN32_CCONN_OPTIONS_H__ | |||
#define __RFB_WIN32_CCONN_OPTIONS_H__ | |||
#include <rdr/types.h> | |||
#include <rfb/Password.h> | |||
#include <list> | |||
namespace rfb { | |||
namespace win32 { | |||
// | |||
// -=- Options structure. Each viewer option has a corresponding | |||
// entry in CConnOptions. The viewer options are set by calling | |||
// CConn::applyOptions(...) | |||
// The CConnOptions structure automatically picks up the default | |||
// value of each option from the Configuration system | |||
// The readFromFile and writeFromFile methods can be used to load | |||
// and save VNC configuration files. readFromFile is backwards | |||
// compatible with 3.3 releases, while writeToFile is not. | |||
class CConnOptions { | |||
public: | |||
CConnOptions(); | |||
CConnOptions(const CConnOptions& o) {operator=(o);} | |||
CConnOptions& operator=(const CConnOptions& o); | |||
void readFromFile(const char* filename_); | |||
void writeToFile(const char* filename_); | |||
void writeDefaults(); | |||
bool useLocalCursor; | |||
bool useDesktopResize; | |||
bool fullScreen; | |||
bool fullColour; | |||
int lowColourLevel; | |||
int preferredEncoding; | |||
bool autoSelect; | |||
bool shared; | |||
CharArray desktopSize; | |||
bool sendPtrEvents; | |||
bool sendKeyEvents; | |||
bool showToolbar; | |||
bool clientCutText; | |||
bool serverCutText; | |||
bool disableWinKeys; | |||
bool emulate3; | |||
int pointerEventInterval; | |||
bool protocol3_3; | |||
bool acceptBell; | |||
bool autoScaling; | |||
int scale; | |||
std::list<rdr::U32> secTypes; | |||
CharArray userName; | |||
void setUserName(const char* user); | |||
PlainPasswd password; | |||
void setPassword(const char* pwd); | |||
CharArray configFileName; | |||
void setConfigFileName(const char* cfn); | |||
CharArray host; | |||
void setHost(const char* h); | |||
CharArray monitor; | |||
void setMonitor(const char* m); | |||
unsigned int menuKey; | |||
void setMenuKey(const char* keyName); | |||
char* menuKeyName(); | |||
bool autoReconnect; | |||
bool customCompressLevel; | |||
int compressLevel; | |||
bool noJpeg; | |||
int qualityLevel; | |||
CharArray passwordFile; | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,197 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- CConnThread.cxx | |||
// A CConnThread instance is created for each new connection. | |||
// The CConnThread creates the corresponding CConn instance | |||
// and manages it. | |||
#include <stdlib.h> | |||
#include <rfb/LogWriter.h> | |||
#include <rfb_win32/MsgBox.h> | |||
#include <network/TcpSocket.h> | |||
#include <vncviewer/CConnThread.h> | |||
#include <vncviewer/CConn.h> | |||
#include <vncviewer/ConnectionDialog.h> | |||
#include <vncviewer/ConnectingDialog.h> | |||
#include <vncviewer/UserPasswdDialog.h> | |||
#include <set> | |||
using namespace rfb; | |||
using namespace win32; | |||
static LogWriter vlog("CConnThread"); | |||
static std::set<CConnThread*> threads; | |||
static Mutex threadsLock; | |||
static Handle noMoreThreads(CreateEvent(0, TRUE, FALSE, 0)); | |||
CConnThread::CConnThread() : Thread("CConnThread"), isConfig(false), | |||
sock(0), reverse(false) { | |||
vlog.info("CConnThread (dialog)"); | |||
setDeleteAfterRun(); | |||
Lock l(threadsLock); | |||
threads.insert(this); | |||
start(); | |||
} | |||
CConnThread::CConnThread(const char* hostOrConfig_, bool isConfig_) | |||
: Thread("CConnThread"), hostOrConfig(strDup(hostOrConfig_)), | |||
isConfig(isConfig_), sock(0), reverse(false) { | |||
vlog.info("CConnThread (host/port)"); | |||
setDeleteAfterRun(); | |||
Lock l(threadsLock); | |||
threads.insert(this); | |||
start(); | |||
} | |||
CConnThread::CConnThread(network::Socket* sock_, bool reverse_) | |||
: Thread("CConnThread"), isConfig(false), sock(sock_), reverse(reverse_) { | |||
vlog.info("CConnThread (reverse connection)"); | |||
setDeleteAfterRun(); | |||
Lock l(threadsLock); | |||
threads.insert(this); | |||
start(); | |||
} | |||
CConnThread::~CConnThread() { | |||
Lock l(threadsLock); | |||
threads.erase(this); | |||
if (threads.empty()) | |||
SetEvent(noMoreThreads); | |||
delete sock; | |||
} | |||
void CConnThread::run() { | |||
CConnOptions options; | |||
bool reconnect; | |||
do { | |||
{ | |||
CConn conn; | |||
reconnect = false; | |||
// If there is no socket object then set the host & port info | |||
if (!sock && !options.host.buf) { | |||
try { | |||
if (isConfig) { | |||
// A configuration file name was specified - load it | |||
CharArray filename(hostOrConfig.takeBuf()); | |||
options.readFromFile(filename.buf); | |||
} else { | |||
// An actual hostname (and possibly port) was specified | |||
options.host.replaceBuf(hostOrConfig.takeBuf()); | |||
} | |||
if (!options.host.buf) { | |||
// No host was specified - prompt for one | |||
ConnectionDialog connDlg(&conn); | |||
if (!connDlg.showDialog()) | |||
return; | |||
options = conn.getOptions(); | |||
options.setHost(CStr(connDlg.hostname.buf)); | |||
} | |||
} catch (rdr::Exception& e) { | |||
MsgBox(0, TStr(e.str()), MB_ICONERROR | MB_OK); | |||
return; | |||
} | |||
} | |||
// Apply the connection options to the CConn | |||
conn.applyOptions(options); | |||
if (!sock) { | |||
// There is no existing connection - better make one | |||
const char* hostAndPort = conn.getOptions().host.buf; | |||
try { | |||
ConnectingDialog dlg; | |||
sock = dlg.connect(hostAndPort); | |||
// If the connection was cancelled by the user, just quit | |||
if (!sock) | |||
return; | |||
} catch(rdr::Exception& e) { | |||
MsgBox(NULL, TStr(e.str()), MB_ICONERROR | MB_OK); | |||
return; | |||
} | |||
// Try to add the caller to the MRU | |||
MRU::addToMRU(hostAndPort); | |||
} | |||
// Run the RFB protocol over the connected socket | |||
conn.initialise(sock, reverse); | |||
while (!conn.isClosed()) { | |||
try { | |||
conn.getInStream()->check(1,1); | |||
conn.processMsg(); | |||
} catch (rdr::EndOfStream) { | |||
if (conn.state() == CConnection::RFBSTATE_NORMAL) | |||
conn.close(); | |||
else | |||
conn.close("The connection closed unexpectedly"); | |||
} catch (rfb::AuthCancelledException) { | |||
conn.close(); | |||
} catch (rfb::AuthFailureException& e) { | |||
// Clear the password, in case we auto-reconnect | |||
options = conn.getOptions(); | |||
options.password.replaceBuf(0); | |||
conn.applyOptions(options); | |||
conn.close(e.str()); | |||
} catch (rdr::Exception& e) { | |||
conn.close(e.str()); | |||
} | |||
} | |||
// If there is a cause for closing the connection logged then display it | |||
if (conn.closeReason()) { | |||
reconnect = !reverse && conn.getOptions().autoReconnect; | |||
if (!reconnect) { | |||
MsgBox(0, TStr(conn.closeReason()), MB_ICONINFORMATION | MB_OK); | |||
} else { | |||
options = conn.getOptions(); | |||
const char* format = "%s\nDo you wish to attempt to reconnect to %s?"; | |||
CharArray message(strlen(conn.closeReason()) + strlen(format) + | |||
strlen(conn.getOptions().host.buf)); | |||
sprintf(message.buf, format, conn.closeReason(), conn.getOptions().host.buf); | |||
if (MsgBox(0, TStr(message.buf), MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) != IDYES) | |||
reconnect = false; | |||
} | |||
} | |||
} // Exit the CConn's scope, implicitly destroying it & making it safe to delete the TcpSocket | |||
// Clean up the old socket, if any | |||
delete sock; sock = 0; | |||
} while (reconnect); | |||
} | |||
BOOL CConnThread::getMessage(MSG* msg, HWND hwnd, UINT minMsg, UINT maxMsg) { | |||
while (!PeekMessage(msg, hwnd, minMsg, maxMsg, PM_REMOVE)) { | |||
DWORD result = MsgWaitForMultipleObjects(1, &noMoreThreads.h, FALSE, INFINITE, QS_ALLINPUT); | |||
if (result == WAIT_OBJECT_0) | |||
return FALSE; | |||
else if (result == WAIT_FAILED) | |||
throw rdr::SystemException("CConnThread::getMessage wait failed", GetLastError()); | |||
} | |||
return msg->message != WM_QUIT; | |||
} |
@@ -1,57 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- CConnThread.h | |||
// CConn-managing Thread implementation. | |||
#ifndef __RFB_WIN32_CCONN_THREAD_H__ | |||
#define __RFB_WIN32_CCONN_THREAD_H__ | |||
#include <network/Socket.h> | |||
#include <rfb/Threading.h> | |||
#include <rfb/util.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class CConnThread : public Thread { | |||
public: | |||
CConnThread(); | |||
CConnThread(const char* hostOrConfig, bool isConfig=false); | |||
CConnThread(network::Socket* sock, bool reverse=false); | |||
~CConnThread(); | |||
void run(); | |||
// Special getMessage call that returns FALSE if message is WM_QUIT, | |||
// OR if there are no more CConnThreads running. | |||
static BOOL getMessage(MSG* msg, HWND hwnd, UINT minMsg, UINT maxMsg); | |||
protected: | |||
CharArray hostOrConfig; | |||
bool isConfig; | |||
network::Socket* sock; | |||
bool reverse; | |||
}; | |||
}; | |||
}; | |||
#endif // __RFB_WIN32_CCONN_THREAD_H__ |
@@ -1,36 +0,0 @@ | |||
include_directories(${CMAKE_BINARY_DIR}/win) | |||
# Disable auto-generated manifests, since we have our own | |||
if(MSVC) | |||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") | |||
endif() | |||
add_executable(vncviewer WIN32 | |||
buildTime.cxx | |||
CConn.cxx | |||
CConnOptions.cxx | |||
CConnThread.cxx | |||
ConnectingDialog.cxx | |||
ConnectionDialog.cxx | |||
DesktopWindow.cxx | |||
InfoDialog.cxx | |||
OptionsDialog.cxx | |||
UserPasswdDialog.cxx | |||
ViewerToolBar.cxx | |||
vncviewer.cxx | |||
vncviewer.rc) | |||
set(VNCVIEWER_LIBRARIES rfb rfb_win32 Xregion network rdr) | |||
# When building with GnuTLS, librdr depends on ws2_32, so in order to make | |||
# MinGW happy, we need to put ws2_32 in librdr's target_link_libraries string, | |||
# not here. | |||
if(NOT GNUTLS_FOUND) | |||
set(VNCVIEWER_LIBRARIES ${VNCVIEWER_LIBRARIES} ws2_32) | |||
endif() | |||
target_link_libraries(vncviewer ${VNCVIEWER_LIBRARIES}) | |||
install(TARGETS vncviewer | |||
RUNTIME DESTINATION . | |||
) |
@@ -1,161 +0,0 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* Copyright (C) 2010 D. R. Commander. 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. | |||
*/ | |||
// -=- ConnectingDialog.cxx | |||
#include <stdlib.h> | |||
#include <vncviewer/ConnectingDialog.h> | |||
#include <vncviewer/resource.h> | |||
#include <network/TcpSocket.h> | |||
#include <rfb/Threading.h> | |||
#include <rfb/Hostname.h> | |||
#include <map> | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
// ConnectingDialog callback | |||
static INT_PTR CALLBACK ConnectingDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { | |||
bool* activePtr = (bool*)GetWindowLongPtr(hwnd, GWLP_USERDATA); | |||
switch (uMsg) { | |||
case WM_INITDIALOG: | |||
SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); | |||
return TRUE; | |||
case WM_COMMAND: | |||
switch (LOWORD(wParam)) { | |||
case IDCANCEL: | |||
if (activePtr) | |||
*activePtr = false; | |||
return TRUE; | |||
} | |||
break; | |||
case WM_DESTROY: | |||
if (activePtr) | |||
*activePtr = false; | |||
return TRUE; | |||
} | |||
return 0; | |||
} | |||
// Global map, used by ConnectingDialog::Threads to call back to their owning | |||
// ConnectingDialogs, while coping with the fact that the owner may already have quit. | |||
static std::map<int, ConnectingDialog*> dialogs; | |||
static int nextDialogId = 0; | |||
static Mutex dialogsLock; | |||
// ConnectingDialog::Thread | |||
// Attempts to connect to the specified host. If the connection succeeds, the | |||
// socket is saved in the owning ConnectingDialog, if still available, and the | |||
// event is signalled. If the connection fails, the Exception text is returned | |||
// to the dialog. If the dialog is already gone, the Exception/socket are discarded. | |||
// NB: This thread class cleans itself up on exit - DO NOT join()! | |||
class ConnectingDialog::Thread : public rfb::Thread { | |||
public: | |||
Thread(int dialogId_, const char* hostAndPort) : dialogId(dialogId_) { | |||
setDeleteAfterRun(); | |||
getHostAndPort(hostAndPort, &host.buf, &port); | |||
} | |||
virtual void run() { | |||
try { | |||
returnSock(new network::TcpSocket(host.buf, port)); | |||
} catch (rdr::Exception& e) { | |||
returnException(e); | |||
} | |||
} | |||
void returnSock(network::Socket* s) { | |||
Lock l(dialogsLock); | |||
if (dialogs.count(dialogId)) { | |||
dialogs[dialogId]->newSocket = s; | |||
SetEvent(dialogs[dialogId]->readyEvent); | |||
} else { | |||
delete s; | |||
} | |||
} | |||
void returnException(const rdr::Exception& e) { | |||
Lock l(dialogsLock); | |||
if (dialogs.count(dialogId)) { | |||
dialogs[dialogId]->errMsg.replaceBuf(strDup(e.str())); | |||
SetEvent(dialogs[dialogId]->readyEvent); | |||
} | |||
}; | |||
CharArray host; | |||
int port; | |||
int dialogId; | |||
}; | |||
ConnectingDialog::ConnectingDialog() : dialog(0), newSocket(0), | |||
readyEvent(CreateEvent(0, TRUE, FALSE, 0)), dialogId(0) { | |||
} | |||
network::Socket* ConnectingDialog::connect(const char* hostAndPort) { | |||
Thread* connectThread = 0; | |||
bool active = true; | |||
errMsg.replaceBuf(0); | |||
newSocket = 0; | |||
// Get a unique dialog identifier and create the dialog window | |||
{ | |||
Lock l(dialogsLock); | |||
dialogId = ++nextDialogId; | |||
dialogs[dialogId] = this; | |||
dialog = CreateDialogParam(GetModuleHandle(0), | |||
MAKEINTRESOURCE(IDD_CONNECTING_DLG), 0, &ConnectingDlgProc, (LONG_PTR)&active); | |||
ShowWindow(dialog, SW_SHOW); | |||
ResetEvent(readyEvent); | |||
} | |||
// Create and start the connection thread | |||
try { | |||
connectThread = new Thread(dialogId, hostAndPort); | |||
connectThread->start(); | |||
} catch (rdr::Exception& e) { | |||
errMsg.replaceBuf(strDup(e.str())); | |||
active = false; | |||
} | |||
// Process window messages until the connection thread signals readyEvent, or the dialog is cancelled | |||
while (active && (MsgWaitForMultipleObjects(1, &readyEvent.h, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)) { | |||
MSG msg; | |||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) | |||
DispatchMessage(&msg); | |||
} | |||
// Remove this dialog from the table | |||
// NB: If the dialog was cancelled then the thread is still running, and will only | |||
// discover that we're gone when it looks up our unique Id in the dialog table. | |||
{ | |||
Lock l(dialogsLock); | |||
dialogs.erase(dialogId); | |||
} | |||
// Close the dialog window | |||
DestroyWindow(dialog); dialog=0; | |||
// Throw the exception, if there was one | |||
if (errMsg.buf) | |||
throw rdr::Exception(errMsg.buf); | |||
// Otherwise, return the socket | |||
// NB: The socket will be null if the dialog was cancelled | |||
return newSocket; | |||
} |
@@ -1,65 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- ConnectingDialog.h | |||
// ConnectingDialog instances are used to display a status dialog while a | |||
// connection attempt is in progress. The connection attempt is performed | |||
// in a background thread by the ConnectingDialog, to allow the status dialog | |||
// to remain interactive. If the dialog is cancelled then it will close and | |||
// the connection dialog will eventually tidy itself up. | |||
#ifndef __RFB_WIN32_CONNECTING_DLG_H__ | |||
#define __RFB_WIN32_CONNECTING_DLG_H__ | |||
#include <windows.h> | |||
#include <network/Socket.h> | |||
#include <rfb/util.h> | |||
#include <rfb_win32/Handle.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class ConnectingDialog { | |||
public: | |||
ConnectingDialog(); | |||
// connect | |||
// Show a Connecting dialog and attempt to connect to the specified host | |||
// in the background. | |||
// If the connection succeeds then the Socket is returned. | |||
// If an error occurs, an Exception is thrown. | |||
// If the dialog is cancelled then null is returned. | |||
network::Socket* connect(const char* hostAndPort); | |||
protected: | |||
HWND dialog; | |||
network::Socket* newSocket; | |||
CharArray errMsg; | |||
Handle readyEvent; | |||
int dialogId; | |||
class Thread; | |||
friend class Thread; | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,72 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#include <vncviewer/ConnectionDialog.h> | |||
#include <vncviewer/CConn.h> | |||
#include <vncviewer/resource.h> | |||
#include <rfb_win32/AboutDialog.h> | |||
#include <tchar.h> | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
ConnectionDialog::ConnectionDialog(CConn* conn_) : Dialog(GetModuleHandle(0)), conn(conn_) { | |||
} | |||
bool ConnectionDialog::showDialog() { | |||
return Dialog::showDialog(MAKEINTRESOURCE(IDD_CONNECTION_DLG)); | |||
} | |||
void ConnectionDialog::initDialog() { | |||
HWND box = GetDlgItem(handle, IDC_SERVER_EDIT); | |||
std::list<char*> mru = MRU::getEntries(); | |||
std::list<char*>::iterator i; | |||
// Locate the combo-box | |||
// NB: TCharArray converts the supplied char* and assumes ownership! | |||
for (i=mru.begin(); i!=mru.end(); i++) { | |||
SendMessage(box, CB_ADDSTRING, 0, (LPARAM)TCharArray(*i).buf); | |||
} | |||
// Select the first item in the list | |||
SendMessage(box, CB_SETCURSEL, 0, 0); | |||
} | |||
bool ConnectionDialog::onOk() { | |||
delete [] hostname.buf; | |||
hostname.buf = 0; | |||
hostname.buf = getItemString(IDC_SERVER_EDIT); | |||
return hostname.buf[0] != 0; | |||
} | |||
bool ConnectionDialog::onCommand(int id, int cmd) { | |||
switch (id) { | |||
case IDC_ABOUT: | |||
AboutDialog::instance.showDialog(); | |||
return true; | |||
case IDC_OPTIONS: | |||
conn->showOptionsDialog(); | |||
return true; | |||
}; | |||
return false; | |||
} |
@@ -1,52 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- ConnectionDialog.h | |||
// Connection dialog for VNC Viewer 4.0 | |||
#ifndef __RFB_WIN32_CONN_DIALOG_H__ | |||
#define __RFB_WIN32_CONN_DIALOG_H__ | |||
#include <rfb_win32/Dialog.h> | |||
#include <vncviewer/MRU.h> | |||
#include <rfb/util.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class CConn; | |||
class ConnectionDialog : Dialog { | |||
public: | |||
ConnectionDialog(CConn* view); | |||
virtual bool showDialog(); | |||
virtual void initDialog(); | |||
virtual bool onOk(); | |||
virtual bool onCommand(int id, int cmd); | |||
TCharArray hostname; | |||
protected: | |||
CConn* conn; | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,294 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- DesktopWindow.h | |||
// Each VNC connection instance (CConn) creates a DesktopWindow the | |||
// server initialisation message has been received. The CConn is | |||
// responsible for all RFB-specific and network issues. The | |||
// DesktopWindow is responsible for all GUI management issues. | |||
// | |||
// DesktopWindow provides a FullFramePixelBuffer interface for the | |||
// CConn to render updates into. It also requires a callback object | |||
// to be supplied, which will be notified when various events occur. | |||
#ifndef __RFB_WIN32_DESKTOP_WINDOW_H__ | |||
#define __RFB_WIN32_DESKTOP_WINDOW_H__ | |||
#include <rfb/Cursor.h> | |||
#include <rfb_win32/CKeyboard.h> | |||
#include <rfb_win32/CPointer.h> | |||
#include <rfb_win32/Clipboard.h> | |||
#include <rfb_win32/ScaledDIBSectionBuffer.h> | |||
#include <rfb_win32/LogicalPalette.h> | |||
#include <vncviewer/ViewerToolBar.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class DesktopWindow : rfb::win32::Clipboard::Notifier { | |||
public: | |||
class Callback; | |||
DesktopWindow(Callback* cb_); | |||
~DesktopWindow(); | |||
// - Window message handling procedure | |||
LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam); | |||
// - Window message handling procedure for the framebuffer window | |||
LRESULT processFrameMessage(UINT msg, WPARAM wParam, LPARAM lParam); | |||
// - Separate message handling procedure for mouse events | |||
// It's called from both processMessage() and processFrameMessage() | |||
void processMouseMessage(UINT msg, WPARAM wParam, LPARAM lParam); | |||
// - Determine the native pixel format of the window | |||
// This can (and often will) differ from the PixelBuffer format | |||
PixelFormat getNativePF() const; | |||
// - Get the underlying window handle | |||
// This is used by F8Menu to modify the window's menu | |||
HWND getHandle() const {return handle;} | |||
// - Get the framebuffer window handle | |||
HWND getFrameHandle() const {return frameHandle;} | |||
// - Set the window title | |||
void setName(const char* name); | |||
// - Set the key that causes the system/F8 menu to be displayed | |||
void setMenuKey(rdr::U8 key) { menuKey = key; } | |||
// - Pointer event handling | |||
void setEmulate3(bool em3) { ptr.enableEmulate3(em3); } | |||
void setPointerEventInterval(int interval) { ptr.enableInterval(interval); } | |||
// - Set the pixel format, size etc of the underlying PixelBuffer | |||
void setPF(const PixelFormat& pf); | |||
PixelFormat getPF() const { return buffer->getPixelFormat(); } | |||
void setSize(int w, int h); | |||
void setColour(int i, int r, int g, int b) {buffer->setColour(i, r, g, b);} | |||
void setAutoScaling(bool as); | |||
bool isAutoScaling() const { return autoScaling; } | |||
void setDesktopScale(int scale); | |||
int getDesktopScale() const { return buffer->getScale(); } | |||
void setDesktopScaleFilter(unsigned int scaleFilterID); | |||
unsigned int getDesktopScaleFilterID() const { return buffer->getScaleFilterID(); } | |||
void fitBufferToWindow(bool repaint = true); | |||
void printScale(); | |||
// - Set the cursor to render when the pointer is within the desktop buffer | |||
void setCursor(int w, int h, const Point& hotspot, void* data, void* mask); | |||
void showCursor() { showLocalCursor(); } | |||
void convertCursorToBuffer(); | |||
// - Set the window fullscreen / determine whether it is fullscreen | |||
void setFullscreen(bool fs); | |||
bool isFullscreen() { return fullscreenActive; } | |||
// - Set/get the toolbar's state | |||
void setShowToolbar(bool st); | |||
bool isToolbarEnabled() { return showToolbar; } | |||
void refreshToolbarButtons(); | |||
// - Set whether to disable special Windows keys & pass them straight to server | |||
void setDisableWinKeys(bool dwk); | |||
// - Set/get which monitor the window should be displayed on | |||
void setMonitor(const char* monitor); | |||
char* getMonitor() const; | |||
// - Set the local clipboard | |||
void serverCutText(const char* str, rdr::U32 len); | |||
// - Completion of one FramebufferUpdate | |||
void framebufferUpdateEnd(); | |||
// - Draw into the desktop buffer & update the window | |||
void fillRect(const Rect& r, Pixel pix); | |||
void imageRect(const Rect& r, void* pixels); | |||
void copyRect(const Rect& r, int srcX, int srcY); | |||
void invertRect(const Rect& r); | |||
// - Update the window palette if the display is palette-based. | |||
// Colours are pulled from the desktop buffer's ColourMap. | |||
// Only the specified range of indexes is dealt with. | |||
// After the update, the entire window is redrawn. | |||
void refreshWindowPalette(int start, int count); | |||
// Clipboard::Notifier interface | |||
void notifyClipboardChanged(const char* text, int len); | |||
// DesktopWindow Callback interface | |||
class Callback : public InputHandler { | |||
public: | |||
virtual ~Callback() {} | |||
virtual void displayChanged() = 0; | |||
virtual void paintCompleted() = 0; | |||
virtual bool sysCommand(WPARAM wParam, LPARAM lParam) = 0; | |||
virtual void closeWindow() = 0; | |||
virtual void refreshMenu(bool enableSysItems) = 0; | |||
}; | |||
Callback *getCallback() const { return callback; } | |||
// Currently accessible so that the CConn can releaseAllKeys & check | |||
// whether Ctrl and Alt are down... | |||
rfb::win32::CKeyboard kbd; | |||
protected: | |||
// Routines to convert between Desktop and client (window) coordinates | |||
Point desktopToClient(const Point& p) { | |||
Point pos = p; | |||
if (client_size.width() > buffer->width()) | |||
pos.x += (client_size.width() - buffer->width()) / 2; | |||
else if (client_size.width() < buffer->width()) | |||
pos.x -= scrolloffset.x; | |||
if (client_size.height() > buffer->height()) | |||
pos.y += (client_size.height() - buffer->height()) / 2; | |||
else if (client_size.height() < buffer->height()) | |||
pos.y -= scrolloffset.y; | |||
return pos; | |||
} | |||
Rect desktopToClient(const Rect& r) { | |||
return Rect(desktopToClient(r.tl), desktopToClient(r.br)); | |||
} | |||
Point clientToDesktop(const Point& p) { | |||
Point pos = p; | |||
if (client_size.width() > buffer->width()) | |||
pos.x -= (client_size.width() - buffer->width()) / 2; | |||
else if (client_size.width() < buffer->width()) | |||
pos.x += scrolloffset.x; | |||
if (client_size.height() > buffer->height()) | |||
pos.y -= (client_size.height() - buffer->height()) / 2; | |||
else if (client_size.height() < buffer->height()) | |||
pos.y += scrolloffset.y; | |||
return pos; | |||
} | |||
Rect clientToDesktop(const Rect& r) { | |||
return Rect(clientToDesktop(r.tl), clientToDesktop(r.br)); | |||
} | |||
// Internal routine used by the scrollbars & bump scroller to select | |||
// the portion of the Desktop to display | |||
bool setViewportOffset(const Point& tl); | |||
// Bump scroll handling. Bump scrolling is used if the window is | |||
// in fullscreen mode and the Desktop is larger than the window | |||
bool processBumpScroll(const Point& cursorPos); | |||
void setBumpScroll(bool on); | |||
bool bumpScroll; | |||
Point bumpScrollDelta; | |||
IntervalTimer bumpScrollTimer; | |||
// Track modified areas of the framebuffer | |||
void updateWindow(); | |||
// Locally-rendered VNC cursor | |||
void hideLocalCursor(); | |||
void showLocalCursor(); | |||
void renderLocalCursor(); | |||
// The system-rendered cursor | |||
void hideSystemCursor(); | |||
void showSystemCursor(); | |||
// cursorOutsideBuffer() is called whenever we detect that the mouse has | |||
// moved outside the desktop. It restores the system arrow cursor. | |||
void cursorOutsideBuffer(); | |||
// Returns true if part of the supplied rect is visible, false otherwise | |||
bool invalidateDesktopRect(const Rect& crect, bool scaling=true); | |||
// Determine whether or not we need to enable/disable scrollbars and set the | |||
// window style accordingly | |||
void calculateScrollBars(); | |||
// Resizes the main window against the pixel buffer size | |||
void resizeDesktopWindowToBuffer(); | |||
// Win32-specific input handling | |||
rfb::win32::CPointer ptr; | |||
Point oldpos; | |||
rfb::win32::Clipboard clipboard; | |||
// Palette handling | |||
LogicalPalette windowPalette; | |||
bool palette_changed; | |||
// - Full-screen mode | |||
RECT fullscreenOldRect; | |||
DWORD fullscreenOldFlags; | |||
bool fullscreenActive; | |||
bool fullscreenRestore; | |||
// Damage tracking | |||
rfb::Region damage; | |||
IntervalTimer updateTimer; | |||
// Cursor handling | |||
Cursor cursor; | |||
bool systemCursorVisible; // Should system-cursor be drawn? | |||
bool trackingMouseLeave; | |||
bool cursorInBuffer; // Is cursor position within server buffer? (ONLY for LocalCursor) | |||
bool cursorVisible; // Is cursor currently rendered? | |||
bool cursorAvailable; // Is cursor available for rendering? | |||
bool internalSetCursor; | |||
Point cursorPos; | |||
ManagedPixelBuffer cursorBacking; | |||
Rect cursorBackingRect; | |||
U8 *cursorImage; | |||
U8 *cursorMask; | |||
int cursorWidth; | |||
int cursorHeight; | |||
Point cursorHotspot; | |||
// ToolBar handling | |||
ViewerToolBar tb; | |||
bool showToolbar; | |||
// Remote desktop name | |||
char desktopName[255]; | |||
// Local window state | |||
win32::ScaledDIBSectionBuffer* buffer; | |||
double aspect_corr; | |||
bool has_focus; | |||
bool autoScaling; | |||
Rect window_size; | |||
Rect client_size; | |||
Point scrolloffset; | |||
Point maxscrolloffset; | |||
HWND handle; | |||
HWND frameHandle; | |||
rdr::U8 menuKey; | |||
Callback* callback; | |||
}; | |||
}; | |||
}; | |||
#endif // __RFB_WIN32_DESKTOP_WINDOW_H__ | |||
@@ -1,65 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#include <vncviewer/InfoDialog.h> | |||
#include <vncviewer/resource.h> | |||
#include <vncviewer/CConn.h> | |||
#include <rfb/Security.h> | |||
#include <rfb/encodings.h> | |||
#include <rfb/CSecurity.h> | |||
#include <rfb/LogWriter.h> | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
static LogWriter vlog("Info"); | |||
bool InfoDialog::showDialog(CConn* cc) { | |||
conn = cc; | |||
return Dialog::showDialog(MAKEINTRESOURCE(IDD_CONNECTION_INFO)); | |||
} | |||
void InfoDialog::initDialog() { | |||
char buf[256]; | |||
setItemString(IDC_INFO_NAME, TStr(conn->cp.name())); | |||
setItemString(IDC_INFO_HOST, TCharArray(conn->getSocket()->getPeerAddress()).buf); | |||
sprintf(buf, "%dx%d", conn->cp.width, conn->cp.height); | |||
setItemString(IDC_INFO_SIZE, TStr(buf)); | |||
conn->cp.pf().print(buf, 256); | |||
setItemString(IDC_INFO_PF, TStr(buf)); | |||
conn->getServerDefaultPF().print(buf, 256); | |||
setItemString(IDC_INFO_DEF_PF, TStr(buf)); | |||
setItemString(IDC_REQUESTED_ENCODING, TStr(encodingName(conn->getOptions().preferredEncoding))); | |||
setItemString(IDC_LAST_ENCODING, TStr(encodingName(conn->lastUsedEncoding()))); | |||
sprintf(buf, "%d kbits/s", conn->getSocket()->inStream().kbitsPerSecond()); | |||
setItemString(IDC_INFO_LINESPEED, TStr(buf)); | |||
sprintf(buf, "%d.%d", conn->cp.majorVersion, conn->cp.minorVersion); | |||
setItemString(IDC_INFO_VERSION, TStr(buf)); | |||
const CSecurity* cSec = conn->csecurity; | |||
setItemString(IDC_INFO_SECURITY, TStr(secTypeName(cSec->getType()))); | |||
setItemString(IDC_INFO_ENCRYPTION, TStr(cSec->description())); | |||
} |
@@ -1,48 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- InfoDialog.h | |||
// Info dialog for VNC Viewer 4.0 | |||
#ifndef __RFB_WIN32_INFO_DIALOG_H__ | |||
#define __RFB_WIN32_INFO_DIALOG_H__ | |||
#include <rfb_win32/Dialog.h> | |||
#include <rfb/util.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class CConn; | |||
class InfoDialog : Dialog { | |||
public: | |||
InfoDialog() : Dialog(GetModuleHandle(0)), conn(0) {} | |||
virtual bool showDialog(CConn* vw); | |||
virtual void initDialog(); | |||
protected: | |||
CConn* conn; | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,55 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- ListenServer.h | |||
#ifndef __RFB_WIN32_LISTEN_SERVER_H__ | |||
#define __RFB_WIN32_LISTEN_SERVER_H__ | |||
#include <winsock2.h> | |||
#include <network/Socket.h> | |||
#include <rfb_win32/MsgWindow.h> | |||
#include <vncviewer/CConnThread.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class ListenServer : MsgWindow { | |||
public: | |||
ListenServer(network::SocketListener* l) : MsgWindow(_T("rfb::win32::ListenServer")), sock(l) { | |||
if (WSAAsyncSelect(l->getFd(), getHandle(), WM_USER, FD_ACCEPT) == SOCKET_ERROR) | |||
throw rdr::SystemException("unable to monitor listen socket", WSAGetLastError()); | |||
} | |||
LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) { | |||
if (msg == WM_USER) { | |||
network::Socket* newConn = sock->accept(); | |||
new CConnThread(newConn, true); | |||
return 0; | |||
} | |||
return MsgWindow::processMessage(msg, wParam, lParam); | |||
} | |||
protected: | |||
network::SocketListener* sock; | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,95 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- ListenTrayIcon.h | |||
#ifndef __RFB_WIN32_LISTEN_TRAY_ICON_H__ | |||
#define __RFB_WIN32_LISTEN_TRAY_ICON_H__ | |||
#include <rfb_win32/TrayIcon.h> | |||
#include <rfb_win32/AboutDialog.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class ListenTrayIcon : public TrayIcon { | |||
public: | |||
ListenTrayIcon() { | |||
setIcon(IDI_ICON); | |||
setToolTip(_T("VNC Viewer")); | |||
} | |||
virtual LRESULT processMessage(UINT msg, WPARAM wParam, LPARAM lParam) { | |||
switch(msg) { | |||
case WM_USER: | |||
switch (lParam) { | |||
case WM_LBUTTONDBLCLK: | |||
SendMessage(getHandle(), WM_COMMAND, ID_NEW_CONNECTION, 0); | |||
break; | |||
case WM_RBUTTONUP: | |||
HMENU menu = LoadMenu(GetModuleHandle(0), MAKEINTRESOURCE(IDR_TRAY)); | |||
HMENU trayMenu = GetSubMenu(menu, 0); | |||
// First item is New Connection, the default | |||
SetMenuDefaultItem(trayMenu, ID_NEW_CONNECTION, FALSE); | |||
// SetForegroundWindow is required, otherwise Windows ignores the | |||
// TrackPopupMenu because the window isn't the foreground one, on | |||
// some older Windows versions... | |||
SetForegroundWindow(getHandle()); | |||
// Display the menu | |||
POINT pos; | |||
GetCursorPos(&pos); | |||
TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, getHandle(), 0); | |||
break; | |||
} | |||
return 0; | |||
case WM_COMMAND: | |||
switch (LOWORD(wParam)) { | |||
case ID_NEW_CONNECTION: | |||
{ | |||
new CConnThread(); | |||
break; | |||
} | |||
case ID_OPTIONS: | |||
OptionsDialog::global.showDialog(0); | |||
break; | |||
case ID_ABOUT: | |||
AboutDialog::instance.showDialog(); | |||
break; | |||
case ID_CLOSE: | |||
SendMessage(getHandle(), WM_CLOSE, 0, 0); | |||
break; | |||
} | |||
return 0; | |||
case WM_CLOSE: | |||
PostQuitMessage(0); | |||
return 0; | |||
} | |||
return TrayIcon::processMessage(msg, wParam, lParam); | |||
} | |||
}; | |||
}; | |||
}; | |||
#endif // __RFB_WIN32_LISTEN_TRAY_ICON_H__ |
@@ -1,133 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#ifndef __VIEWER_MRU_H__ | |||
#define __VIEWER_MRU_H__ | |||
#include <windows.h> | |||
#include <list> | |||
#include <set> | |||
#include <rfb_win32/Registry.h> | |||
#include <rfb/util.h> | |||
#include <rdr/HexOutStream.h> | |||
namespace rfb { | |||
namespace win32 { | |||
namespace MRU { | |||
static const RegKey RegRoot = HKEY_CURRENT_USER; | |||
static const TCHAR* RegPath = _T("Software\\TigerVNC\\VNCViewer4\\MRU"); | |||
static const int MaxMRUEntries = 256; | |||
static const int MRUEntries = 10; | |||
static std::list<char*> getEntries() { | |||
std::list<char*> mru; | |||
try { | |||
RegKey key; | |||
key.openKey(RegRoot, RegPath); | |||
CharArray order; | |||
int length; | |||
key.getBinary(_T("Order"), (void**)&order.buf, &length); | |||
for (int i=0; i<length; i++) { | |||
TCharArray keyname(rdr::HexOutStream::binToHexStr(&order.buf[i], 1)); | |||
try { | |||
TCharArray entry(key.getString(keyname.buf)); | |||
mru.push_back(strDup(entry.buf)); | |||
} catch (rdr::Exception) { | |||
} | |||
} | |||
} catch (rdr::Exception) { | |||
} | |||
return mru; | |||
} | |||
static void addToMRU(const char* name) { | |||
RegKey key; | |||
key.createKey(RegRoot, RegPath); | |||
BYTE keycode; | |||
CharArray old_order; | |||
char order[MaxMRUEntries]; | |||
int orderlen; | |||
try { | |||
key.getBinary(_T("Order"), (void**)&old_order.buf, &orderlen); | |||
if (orderlen) | |||
memcpy(order, old_order.buf, orderlen); | |||
std::set<int> ordercodes; | |||
keycode = 0; | |||
bool found = false; | |||
for (int i=0; i<orderlen; i++) { | |||
TCharArray keyname(rdr::HexOutStream::binToHexStr(&order[i], 1)); | |||
try { | |||
TCharArray hostname(key.getString(keyname.buf)); | |||
if (stricmp(name, CStr(hostname.buf)) == 0) { | |||
keycode = order[i]; | |||
found = true; | |||
break; | |||
} | |||
} catch (rdr::Exception) { | |||
} | |||
ordercodes.insert(order[i]); | |||
} | |||
if (!found) { | |||
if (orderlen <= MRUEntries) { | |||
while (ordercodes.find(keycode) != ordercodes.end()) keycode++; | |||
} else { | |||
keycode = order[orderlen-1]; | |||
orderlen--; | |||
} | |||
} | |||
} catch (rdr::Exception) { | |||
keycode = 0; | |||
orderlen = 0; | |||
} | |||
orderlen++; | |||
int i, j=orderlen-1; | |||
for (i=0; i<orderlen-1; i++) { | |||
if (order[i] == keycode) { | |||
j = i; | |||
orderlen--; | |||
break; | |||
} | |||
} | |||
for (i=j; i>0; i--) | |||
order[i] = order[i-1]; | |||
order[0] = keycode; | |||
TCharArray keyname(rdr::HexOutStream::binToHexStr((char*)&keycode, 1)); | |||
key.setString(keyname.buf, TStr(name)); | |||
key.setBinary(_T("Order"), order, orderlen); | |||
} | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,420 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#include <vncviewer/OptionsDialog.h> | |||
#include <vncviewer/CConn.h> | |||
#include <vncviewer/resource.h> | |||
#include <rfb_win32/Registry.h> | |||
#include <rfb_win32/MsgBox.h> | |||
#include <rfb_win32/OSVersion.h> | |||
#include <rfb_win32/SecurityPage.h> | |||
#include <rfb/encodings.h> | |||
#include <rfb/CConnection.h> | |||
#include <commdlg.h> | |||
#include <rfb/LogWriter.h> | |||
#include <rfb/Security.h> | |||
#include <list> | |||
using namespace rdr; | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
using namespace std; | |||
static LogWriter vlog("Options"); | |||
struct OptionsInfo { | |||
CConn* view; | |||
CConnOptions options; | |||
}; | |||
OptionsDialog rfb::win32::OptionsDialog::global; | |||
class ViewerOptions : public PropSheet { | |||
public: | |||
ViewerOptions(OptionsInfo& info_, std::list<PropSheetPage*> pages) | |||
: PropSheet(GetModuleHandle(0), | |||
info_.view ? _T("VNC Viewer Options") : _T("VNC Viewer Defaults"), pages), | |||
changed(false), info(info_) { | |||
} | |||
~ViewerOptions() { | |||
if (changed) { | |||
if (info.view) | |||
// Apply the settings to the supplied session object | |||
info.view->applyOptions(info.options); | |||
else { | |||
// Commit the settings to the user's registry area | |||
info.options.writeDefaults(); | |||
} | |||
} | |||
} | |||
void setChanged() {changed = true;} | |||
bool changed; | |||
OptionsInfo& info; | |||
}; | |||
class FormatPage : public PropSheetPage { | |||
public: | |||
FormatPage(OptionsInfo* dlg_) | |||
: PropSheetPage(GetModuleHandle(0), MAKEINTRESOURCE(IDD_FORMAT)), dlg(dlg_) { | |||
} | |||
virtual void initDialog() { | |||
setItemChecked(IDC_ENCODING_AUTO, dlg->options.autoSelect); | |||
setItemChecked(IDC_FORMAT_FULLCOLOUR, dlg->options.fullColour); | |||
if (!dlg->options.fullColour) { | |||
switch (dlg->options.lowColourLevel) { | |||
case 0: setItemChecked(IDC_FORMAT_VERYLOWCOLOUR, true); break; | |||
case 1: setItemChecked(IDC_FORMAT_LOWCOLOUR, true); break; | |||
case 2: setItemChecked(IDC_FORMAT_MEDIUMCOLOUR, true); break; | |||
} | |||
} | |||
switch (dlg->options.preferredEncoding) { | |||
case encodingTight: setItemChecked(IDC_ENCODING_TIGHT, true); break; | |||
case encodingZRLE: setItemChecked(IDC_ENCODING_ZRLE, true); break; | |||
case encodingHextile: setItemChecked(IDC_ENCODING_HEXTILE, true); break; | |||
case encodingRaw: setItemChecked(IDC_ENCODING_RAW, true); break; | |||
} | |||
setItemChecked(IDC_CUSTOM_COMPRESSLEVEL, dlg->options.customCompressLevel); | |||
setItemInt(IDC_COMPRESSLEVEL, dlg->options.compressLevel); | |||
setItemChecked(IDC_ALLOW_JPEG, !dlg->options.noJpeg); | |||
setItemInt(IDC_QUALITYLEVEL, dlg->options.qualityLevel); | |||
onCommand(IDC_ENCODING_AUTO, 0 /* ? */); // Force enableItem status to refresh | |||
onCommand(IDC_CUSTOM_COMPRESSLEVEL, 0 /* ? */); // Force enableItem status to refresh | |||
onCommand(IDC_ALLOW_JPEG, 0 /* ? */); // Force enableItem status to refresh | |||
} | |||
virtual bool onOk() { | |||
dlg->options.autoSelect = isItemChecked(IDC_ENCODING_AUTO); | |||
dlg->options.fullColour = isItemChecked(IDC_FORMAT_FULLCOLOUR); | |||
dlg->options.customCompressLevel = isItemChecked(IDC_CUSTOM_COMPRESSLEVEL); | |||
dlg->options.compressLevel = getItemInt(IDC_COMPRESSLEVEL); | |||
dlg->options.noJpeg = !isItemChecked(IDC_ALLOW_JPEG); | |||
dlg->options.qualityLevel = getItemInt(IDC_QUALITYLEVEL); | |||
if (isItemChecked(IDC_FORMAT_VERYLOWCOLOUR)) | |||
dlg->options.lowColourLevel = 0; | |||
if (isItemChecked(IDC_FORMAT_LOWCOLOUR)) | |||
dlg->options.lowColourLevel = 1; | |||
if (isItemChecked(IDC_FORMAT_MEDIUMCOLOUR)) | |||
dlg->options.lowColourLevel = 2; | |||
dlg->options.preferredEncoding = encodingTight; | |||
if (isItemChecked(IDC_ENCODING_ZRLE)) | |||
dlg->options.preferredEncoding = encodingZRLE; | |||
if (isItemChecked(IDC_ENCODING_HEXTILE)) | |||
dlg->options.preferredEncoding = encodingHextile; | |||
if (isItemChecked(IDC_ENCODING_RAW)) | |||
dlg->options.preferredEncoding = encodingRaw; | |||
((ViewerOptions*)propSheet)->setChanged(); | |||
return true; | |||
} | |||
virtual bool onCommand(int id, int cmd) { | |||
bool aut = isItemChecked(IDC_ENCODING_AUTO); | |||
bool jpeg = isItemChecked(IDC_ALLOW_JPEG); | |||
bool custom_comp = isItemChecked(IDC_CUSTOM_COMPRESSLEVEL); | |||
if (id == IDC_ENCODING_AUTO) { | |||
enableItem(IDC_ENCODING_TIGHT, !aut); | |||
enableItem(IDC_ENCODING_ZRLE, !aut); | |||
enableItem(IDC_ENCODING_HEXTILE, !aut); | |||
enableItem(IDC_ENCODING_RAW, !aut); | |||
enableItem(IDC_FORMAT_FULLCOLOUR, !aut); | |||
enableItem(IDC_FORMAT_MEDIUMCOLOUR, !aut); | |||
enableItem(IDC_FORMAT_LOWCOLOUR, !aut); | |||
enableItem(IDC_FORMAT_VERYLOWCOLOUR, !aut); | |||
enableItem(IDC_QUALITYLEVEL, !aut && jpeg); | |||
return true; | |||
} | |||
if (id == IDC_CUSTOM_COMPRESSLEVEL) { | |||
enableItem(IDC_COMPRESSLEVEL, custom_comp); | |||
return true; | |||
} | |||
if (id == IDC_ALLOW_JPEG) { | |||
enableItem(IDC_QUALITYLEVEL, !aut && jpeg); | |||
return true; | |||
} | |||
return false; | |||
} | |||
protected: | |||
OptionsInfo* dlg; | |||
}; | |||
class MiscPage : public PropSheetPage { | |||
public: | |||
MiscPage(OptionsInfo* dlg_) | |||
: PropSheetPage(GetModuleHandle(0), MAKEINTRESOURCE(IDD_MISC)), dlg(dlg_) { | |||
} | |||
virtual void initDialog() { | |||
setItemChecked(IDC_CONN_SHARED, dlg->options.shared); | |||
enableItem(IDC_CONN_SHARED, (!dlg->view) || (dlg->view->state() != CConnection::RFBSTATE_NORMAL)); | |||
setItemChecked(IDC_FULL_SCREEN, dlg->options.fullScreen); | |||
setItemChecked(IDC_LOCAL_CURSOR, dlg->options.useLocalCursor); | |||
setItemChecked(IDC_DESKTOP_RESIZE, dlg->options.useDesktopResize); | |||
enableItem(IDC_PROTOCOL_3_3, (!dlg->view) || (dlg->view->state() != CConnection::RFBSTATE_NORMAL)); | |||
setItemChecked(IDC_PROTOCOL_3_3, dlg->options.protocol3_3); | |||
setItemChecked(IDC_ACCEPT_BELL, dlg->options.acceptBell); | |||
setItemChecked(IDC_AUTO_RECONNECT, dlg->options.autoReconnect); | |||
setItemChecked(IDC_SHOW_TOOLBAR, dlg->options.showToolbar); | |||
char scale_values[10][20] = { | |||
"10","25","50","75","90","100","125","150","200","Auto" | |||
}; | |||
HWND hScaleCombo = GetDlgItem(handle, IDC_COMBO_SCALE); | |||
for (int i = 0; i <= 9; i++) { | |||
SendMessage(hScaleCombo, CB_INSERTSTRING, | |||
(WPARAM)i, (LPARAM)(int FAR*)scale_values[i]); | |||
} | |||
if (dlg->options.autoScaling) { | |||
SetDlgItemText(handle, IDC_COMBO_SCALE, (LPCTSTR) "Auto"); | |||
} else { | |||
SetDlgItemInt(handle, IDC_COMBO_SCALE, dlg->options.scale, FALSE); | |||
} | |||
} | |||
virtual bool onOk() { | |||
dlg->options.shared = isItemChecked(IDC_CONN_SHARED); | |||
dlg->options.fullScreen = isItemChecked(IDC_FULL_SCREEN); | |||
dlg->options.useLocalCursor = isItemChecked(IDC_LOCAL_CURSOR); | |||
dlg->options.useDesktopResize = isItemChecked(IDC_DESKTOP_RESIZE); | |||
dlg->options.protocol3_3 = isItemChecked(IDC_PROTOCOL_3_3); | |||
dlg->options.acceptBell = isItemChecked(IDC_ACCEPT_BELL); | |||
dlg->options.autoReconnect = isItemChecked(IDC_AUTO_RECONNECT); | |||
dlg->options.showToolbar = isItemChecked(IDC_SHOW_TOOLBAR); | |||
int s = GetDlgItemInt(handle, IDC_COMBO_SCALE, NULL, FALSE); | |||
if (s > 0) { | |||
dlg->options.scale = s; | |||
dlg->options.autoScaling = false; | |||
} else { | |||
char scaleStr[20]; | |||
GetDlgItemText(handle, IDC_COMBO_SCALE, (LPTSTR) scaleStr, 20); | |||
if (strcmp(scaleStr, (const char *) "Auto") == 0) { | |||
dlg->options.autoScaling = true; | |||
} | |||
} | |||
((ViewerOptions*)propSheet)->setChanged(); | |||
return true; | |||
} | |||
virtual bool onCommand(int id, int cmd) { | |||
if (id == IDC_COMBO_SCALE) { | |||
if (cmd == CBN_SELENDOK || cmd == CBN_EDITCHANGE) { | |||
char scaleStr[20]; | |||
if (cmd == CBN_SELENDOK) { | |||
HWND handleComboScale = GetDlgItem(handle, IDC_COMBO_SCALE); | |||
int index = SendMessage(handleComboScale, CB_GETCURSEL, 0, 0); | |||
SendMessage(handleComboScale, CB_GETLBTEXT, (WPARAM)index, (LPARAM)scaleStr); | |||
} else { | |||
GetDlgItemText(handle, IDC_COMBO_SCALE, (LPTSTR) scaleStr, 20); | |||
} | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
protected: | |||
OptionsInfo* dlg; | |||
}; | |||
class InputsPage : public PropSheetPage { | |||
public: | |||
InputsPage(OptionsInfo* dlg_) | |||
: PropSheetPage(GetModuleHandle(0), MAKEINTRESOURCE(IDD_INPUTS)), dlg(dlg_) { | |||
} | |||
virtual void initDialog() { | |||
setItemChecked(IDC_SEND_POINTER, dlg->options.sendPtrEvents); | |||
setItemChecked(IDC_SEND_KEYS, dlg->options.sendKeyEvents); | |||
setItemChecked(IDC_CLIENT_CUTTEXT, dlg->options.clientCutText); | |||
setItemChecked(IDC_SERVER_CUTTEXT, dlg->options.serverCutText); | |||
setItemChecked(IDC_DISABLE_WINKEYS, dlg->options.disableWinKeys && !osVersion.isPlatformWindows); | |||
enableItem(IDC_DISABLE_WINKEYS, !osVersion.isPlatformWindows); | |||
setItemChecked(IDC_EMULATE3, dlg->options.emulate3); | |||
setItemChecked(IDC_POINTER_INTERVAL, dlg->options.pointerEventInterval != 0); | |||
// Populate the Menu Key tab | |||
HWND menuKey = GetDlgItem(handle, IDC_MENU_KEY); | |||
SendMessage(menuKey, CB_RESETCONTENT, 0, 0); | |||
SendMessage(menuKey, CB_ADDSTRING, 0, (LPARAM)_T("none")); | |||
if (!dlg->options.menuKey) | |||
SendMessage(menuKey, CB_SETCURSEL, 0, 0); | |||
for (unsigned int i=0; i<12; i++) { | |||
TCHAR buf[4]; | |||
_stprintf(buf, _T("F%d"), i+1); | |||
int index = SendMessage(menuKey, CB_ADDSTRING, 0, (LPARAM)buf); | |||
if (i == (dlg->options.menuKey - VK_F1)) | |||
SendMessage(menuKey, CB_SETCURSEL, index, 0); | |||
} | |||
} | |||
virtual bool onOk() { | |||
dlg->options.sendPtrEvents = isItemChecked(IDC_SEND_POINTER); | |||
dlg->options.sendKeyEvents = isItemChecked(IDC_SEND_KEYS); | |||
dlg->options.clientCutText = isItemChecked(IDC_CLIENT_CUTTEXT); | |||
dlg->options.serverCutText = isItemChecked(IDC_SERVER_CUTTEXT); | |||
dlg->options.disableWinKeys = isItemChecked(IDC_DISABLE_WINKEYS); | |||
dlg->options.emulate3 = isItemChecked(IDC_EMULATE3); | |||
dlg->options.pointerEventInterval = | |||
isItemChecked(IDC_POINTER_INTERVAL) ? 200 : 0; | |||
HWND mkHwnd = GetDlgItem(handle, IDC_MENU_KEY); | |||
int index = SendMessage(mkHwnd, CB_GETCURSEL, 0, 0); | |||
TCharArray keyName(SendMessage(mkHwnd, CB_GETLBTEXTLEN, index, 0)+1); | |||
SendMessage(mkHwnd, CB_GETLBTEXT, index, (LPARAM)keyName.buf); | |||
if (_tcscmp(keyName.buf, _T("none")) == 0) | |||
dlg->options.setMenuKey(""); | |||
else | |||
dlg->options.setMenuKey(CStr(keyName.buf)); | |||
((ViewerOptions*)propSheet)->setChanged(); | |||
return true; | |||
} | |||
protected: | |||
OptionsInfo* dlg; | |||
}; | |||
class DefaultsPage : public PropSheetPage { | |||
public: | |||
DefaultsPage(OptionsInfo* dlg_) | |||
: PropSheetPage(GetModuleHandle(0), MAKEINTRESOURCE(IDD_DEFAULTS)), dlg(dlg_) { | |||
} | |||
virtual void initDialog() { | |||
enableItem(IDC_LOAD_CONFIG, dlg->options.configFileName.buf); | |||
enableItem(IDC_SAVE_CONFIG, dlg->options.configFileName.buf); | |||
} | |||
virtual bool onCommand(int id, int cmd) { | |||
switch (id) { | |||
case IDC_LOAD_DEFAULTS: | |||
dlg->options = CConnOptions(); | |||
break; | |||
case IDC_SAVE_DEFAULTS: | |||
propSheet->commitPages(); | |||
dlg->options.writeDefaults(); | |||
break; | |||
case IDC_LOAD_CONFIG: | |||
dlg->options.readFromFile(dlg->options.configFileName.buf); | |||
break; | |||
case IDC_SAVE_CONFIG: | |||
propSheet->commitPages(); | |||
dlg->options.writeToFile(dlg->options.configFileName.buf); | |||
MsgBox(handle, _T("Options saved successfully"), | |||
MB_OK | MB_ICONINFORMATION); | |||
return 0; | |||
case IDC_SAVE_CONFIG_AS: | |||
propSheet->commitPages(); | |||
// Get a filename to save to | |||
TCHAR newFilename[4096]; | |||
TCHAR currentDir[4096]; | |||
if (dlg->options.configFileName.buf) | |||
_tcscpy(newFilename, TStr(dlg->options.configFileName.buf)); | |||
else | |||
newFilename[0] = 0; | |||
OPENFILENAME ofn; | |||
memset(&ofn, 0, sizeof(ofn)); | |||
#ifdef OPENFILENAME_SIZE_VERSION_400 | |||
ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; | |||
#else | |||
ofn.lStructSize = sizeof(ofn); | |||
#endif | |||
ofn.hwndOwner = handle; | |||
ofn.lpstrFilter = _T("VNC Connection Options\000*.vnc\000"); | |||
ofn.lpstrFile = newFilename; | |||
currentDir[0] = 0; | |||
GetCurrentDirectory(4096, currentDir); | |||
ofn.lpstrInitialDir = currentDir; | |||
ofn.nMaxFile = 4096; | |||
ofn.lpstrDefExt = _T(".vnc"); | |||
ofn.Flags = OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; | |||
if (!GetSaveFileName(&ofn)) { | |||
if (CommDlgExtendedError()) | |||
throw rdr::Exception("GetSaveFileName failed"); | |||
return 0; | |||
} | |||
// Save the Options | |||
dlg->options.writeToFile(CStr(newFilename)); | |||
MsgBox(handle, _T("Options saved successfully"), | |||
MB_OK | MB_ICONINFORMATION); | |||
return 0; | |||
}; | |||
propSheet->reInitPages(); | |||
return true; | |||
} | |||
protected: | |||
OptionsInfo* dlg; | |||
}; | |||
class SecPage : public SecurityPage { | |||
public: | |||
SecPage(Security *security_, OptionsInfo *dlg_) | |||
: SecurityPage(security_), dlg(dlg_) { | |||
} | |||
virtual void enableX509Dialogs() { | |||
enableItem(IDC_LOAD_CACERT, true); | |||
enableItem(IDC_LOAD_CRLCERT, true); | |||
} | |||
virtual void disableX509Dialogs() { | |||
enableItem(IDC_LOAD_CACERT, false); | |||
enableItem(IDC_LOAD_CRLCERT, false); | |||
} | |||
virtual bool onOk() { | |||
SecurityPage::onOk(); | |||
dlg->options.secTypes = security->GetEnabledExtSecTypes(); | |||
if (isItemChecked(IDC_VENCRYPT)) | |||
dlg->options.secTypes.push_front(secTypeVeNCrypt); | |||
return true; | |||
} | |||
virtual void loadX509Certs() {} | |||
virtual void loadVncPasswd() {} | |||
protected: | |||
OptionsInfo* dlg; | |||
}; | |||
OptionsDialog::OptionsDialog() : visible(false) { | |||
} | |||
bool OptionsDialog::showDialog(CConn* view, bool capture) { | |||
if (visible) return false; | |||
visible = true; | |||
// Grab the current properties | |||
OptionsInfo info; | |||
if (view) | |||
info.options = view->getOptions(); | |||
info.view = view; | |||
// Build a list of pages to display | |||
std::list<PropSheetPage*> pages; | |||
FormatPage formatPage(&info); pages.push_back(&formatPage); | |||
InputsPage inputsPage(&info); pages.push_back(&inputsPage); | |||
MiscPage miscPage(&info); pages.push_back(&miscPage); | |||
DefaultsPage defPage(&info); if (view) pages.push_back(&defPage); | |||
SecPage secPage(view->security, &info); pages.push_back(&secPage); | |||
// Show the property sheet | |||
ViewerOptions dialog(info, pages); | |||
dialog.showPropSheet(view && view->getWindow() ? view->getWindow()->getHandle() : 0, | |||
false, false, capture); | |||
visible = false; | |||
return dialog.changed; | |||
} |
@@ -1,48 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- OptionsDialog.h | |||
// Options dialog for VNC Viewer 4.0 | |||
#ifndef __RFB_WIN32_OPTIONS_DIALOG_H__ | |||
#define __RFB_WIN32_OPTIONS_DIALOG_H__ | |||
#include <rfb_win32/Dialog.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class CConn; | |||
class OptionsDialog { | |||
public: | |||
OptionsDialog(); | |||
virtual bool showDialog(CConn* cfg, bool capture=false); | |||
static OptionsDialog global; | |||
protected: | |||
bool visible; | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,85 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
#include <vncviewer/UserPasswdDialog.h> | |||
#include <vncviewer/resource.h> | |||
#include <rfb/Exception.h> | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
UserPasswdDialog::UserPasswdDialog() : Dialog(GetModuleHandle(0)), | |||
showUsername(false), showPassword(false) { | |||
} | |||
void UserPasswdDialog::setCSecurity(const CSecurity* cs) { | |||
description.replaceBuf(tstrDup(cs->description())); | |||
} | |||
bool UserPasswdDialog::showDialog() { | |||
return Dialog::showDialog(MAKEINTRESOURCE(IDD_VNC_AUTH_DLG)); | |||
} | |||
void UserPasswdDialog::initDialog() { | |||
if (username.buf) | |||
setItemString(IDC_USERNAME, username.buf); | |||
if (password.buf) | |||
setItemString(IDC_PASSWORD, password.buf); | |||
if (!showUsername) { | |||
setItemString(IDC_USERNAME, _T("")); | |||
enableItem(IDC_USERNAME, false); | |||
} | |||
if (!showPassword) { | |||
setItemString(IDC_PASSWORD, _T("")); | |||
enableItem(IDC_PASSWORD, false); | |||
} | |||
if (description.buf) { | |||
TCharArray title(128); | |||
GetWindowText(handle, title.buf, 128); | |||
_tcsncat(title.buf, _T(" ["), 128); | |||
_tcsncat(title.buf, description.buf, 128); | |||
_tcsncat(title.buf, _T("]"), 128); | |||
SetWindowText(handle, title.buf); | |||
} | |||
} | |||
bool UserPasswdDialog::onOk() { | |||
username.replaceBuf(getItemString(IDC_USERNAME)); | |||
password.replaceBuf(getItemString(IDC_PASSWORD)); | |||
return true; | |||
} | |||
void UserPasswdDialog::getUserPasswd(char** user, char** passwd) { | |||
showUsername = user != 0; | |||
showPassword = passwd != 0; | |||
if (user && *user) | |||
username.replaceBuf(tstrDup(*user)); | |||
if (passwd && *passwd) | |||
password.replaceBuf(tstrDup(*passwd)); | |||
if (!showDialog()) | |||
throw rfb::AuthCancelledException(); | |||
if (user) | |||
*user = strDup(username.buf); | |||
if (passwd) | |||
*passwd = strDup(password.buf); | |||
} |
@@ -1,58 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- UserPasswdDialog.h | |||
// Username and password dialog for VNC Viewer 4.0 | |||
// Note that the password and username fields are only freed | |||
// when the dialog instance is deleted - it is important to | |||
// ensure that the instance is deleted as early as possible, to | |||
// avoid the password being retained in memory for too long. | |||
#ifndef __RFB_WIN32_USERPASSWD_DIALOG_H__ | |||
#define __RFB_WIN32_USERPASSWD_DIALOG_H__ | |||
#include <rfb_win32/Dialog.h> | |||
#include <rfb_win32/TCharArray.h> | |||
#include <rfb/CSecurity.h> | |||
#include <rfb/UserPasswdGetter.h> | |||
namespace rfb { | |||
namespace win32 { | |||
class UserPasswdDialog : Dialog, public UserPasswdGetter { | |||
public: | |||
UserPasswdDialog(); | |||
virtual bool showDialog(); | |||
virtual void initDialog(); | |||
virtual bool onOk(); | |||
virtual void getUserPasswd(char** user, char** passwd); | |||
void setCSecurity(const CSecurity* cs); | |||
protected: | |||
TCharArray username; | |||
TPlainPasswd password; | |||
bool showUsername, showPassword; | |||
TCharArray description; | |||
}; | |||
}; | |||
}; | |||
#endif |
@@ -1,104 +0,0 @@ | |||
/* Copyright (C) 2005 TightVNC Team. 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. | |||
*/ | |||
// -=- ViewerToolBar.cxx | |||
#include <vncviewer/ViewerToolBar.h> | |||
#include <vncviewer/resource.h> | |||
void ViewerToolBar::create(HWND parentHwnd) { | |||
// Create the toolbar panel | |||
ToolBar::create(ID_TOOLBAR, parentHwnd, WS_CHILD | | |||
TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_NORESIZE); | |||
addBitmap(4, IDB_TOOLBAR); | |||
// Create the control buttons | |||
addButton(0, ID_OPTIONS); | |||
addButton(1, ID_INFO); | |||
addButton(0, 0, TBSTATE_ENABLED, TBSTYLE_SEP); | |||
addButton(2, ID_FULLSCREEN); | |||
addButton(3, ID_REQUEST_REFRESH); | |||
addButton(0, 0, TBSTATE_ENABLED, TBSTYLE_SEP); | |||
addButton(4, ID_ZOOM_IN); | |||
addButton(5, ID_ZOOM_OUT); | |||
addButton(6, ID_ACTUAL_SIZE); | |||
addButton(7, ID_AUTO_SIZE); | |||
addButton(0, 0, TBSTATE_ENABLED, TBSTYLE_SEP); | |||
addButton(8, ID_SEND_CAD); | |||
addButton(9, ID_SEND_CTLESC); | |||
addButton(10, ID_CTRL_KEY); | |||
addButton(11, ID_ALT_KEY); | |||
addButton(0, 0, TBSTATE_ENABLED, TBSTYLE_SEP); | |||
addButton(0, 0, TBSTATE_ENABLED, TBSTYLE_SEP); | |||
addButton(13, ID_NEW_CONNECTION); | |||
addButton(14, ID_CONN_SAVE_AS); | |||
// Resize the toolbar window | |||
autoSize(); | |||
} | |||
LRESULT ViewerToolBar::processWM_NOTIFY(WPARAM wParam, LPARAM lParam) { | |||
switch (((LPNMHDR)lParam)->code) { | |||
// Process tooltips text | |||
case TTN_NEEDTEXT: | |||
{ | |||
LPTOOLTIPTEXT TTStr = (LPTOOLTIPTEXT)lParam; | |||
if (TTStr->hdr.code != TTN_NEEDTEXT) | |||
return 0; | |||
switch (TTStr->hdr.idFrom) { | |||
case ID_OPTIONS: | |||
TTStr->lpszText = (LPTSTR) "Connection options..."; | |||
break; | |||
case ID_INFO: | |||
TTStr->lpszText = (LPTSTR) "Connection info"; | |||
break; | |||
case ID_FULLSCREEN: | |||
TTStr->lpszText = (LPTSTR) "Full screen"; | |||
break; | |||
case ID_REQUEST_REFRESH: | |||
TTStr->lpszText = (LPTSTR) "Request screen refresh"; | |||
break; | |||
case ID_SEND_CAD: | |||
TTStr->lpszText = (LPTSTR) "Send Ctrl-Alt-Del"; | |||
break; | |||
case ID_SEND_CTLESC: | |||
TTStr->lpszText = (LPTSTR) "Send Ctrl-Esc"; | |||
break; | |||
case ID_CTRL_KEY: | |||
TTStr->lpszText = (LPTSTR) "Send Ctrl key press/release"; | |||
break; | |||
case ID_ALT_KEY: | |||
TTStr->lpszText = (LPTSTR) "Send Alt key press/release"; | |||
break; | |||
case ID_NEW_CONNECTION: | |||
TTStr->lpszText = (LPTSTR) "New connection..."; | |||
break; | |||
case ID_CONN_SAVE_AS: | |||
TTStr->lpszText = (LPTSTR) "Save connection info as..."; | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
default: | |||
break; | |||
} | |||
return 0; | |||
} |
@@ -1,35 +0,0 @@ | |||
/* Copyright (C) 2005 TightVNC Team. 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. | |||
*/ | |||
// -=- ViewerToolBar.h | |||
// ToolBar for the Vnc Viewer | |||
#include <rfb_win32/ToolBar.h> | |||
using namespace rfb::win32; | |||
class ViewerToolBar : public ToolBar { | |||
public: | |||
ViewerToolBar() {} | |||
~ViewerToolBar() {} | |||
void create(HWND parentHwnd); | |||
LRESULT processWM_NOTIFY(WPARAM wParam, LPARAM lParam); | |||
}; |
@@ -1,18 +0,0 @@ | |||
/* Copyright (C) 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 | |||
* (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. | |||
*/ | |||
const char* buildTime = "Built on " __DATE__ " at " __TIME__; |
@@ -1,119 +0,0 @@ | |||
// Used by vncviewer.rc | |||
#include <rfb_win32/resource.h> | |||
#define IDR_MANIFEST 1 | |||
#define IDI_ICON 101 | |||
#define IDD_VNC_AUTH_DLG 102 | |||
#define IDD_CONNECTING_DLG 103 | |||
#define IDD_CONNECTION_DLG 104 | |||
#define IDC_DOT_CURSOR 105 | |||
#define IDD_ABOUT 107 | |||
#define IDD_FORMAT 108 | |||
#define IDD_MISC 109 | |||
#define IDD_INPUTS 110 | |||
#define IDD_SERVER_KEYS 111 | |||
#define IDR_TRAY 112 | |||
#define IDD_CONNECTION_INFO 113 | |||
#define IDD_DEFAULTS 116 | |||
#define IDB_BITMAP 120 | |||
#define IDB_TOOLBAR 122 | |||
#define IDC_PASSWORD 1000 | |||
#define IDC_CONNECTING_TEXT 1001 | |||
#define IDC_SERVER_EDIT 1002 | |||
#define IDC_USERNAME 1005 | |||
#define IDC_VERSION 1008 | |||
#define IDC_BUILDTIME 1009 | |||
#define IDC_ENCODING_AUTO 1010 | |||
#define IDC_FORMAT_FULLCOLOUR 1011 | |||
#define IDC_ENCODING_ZRLE 1012 | |||
#define IDC_ENCODING_HEXTILE 1013 | |||
#define IDC_CONN_SHARED 1013 | |||
#define IDC_ENCODING_RAW 1014 | |||
#define IDC_FULL_SCREEN 1014 | |||
#define IDC_SEND_POINTER 1015 | |||
#define IDC_SEND_KEYS 1016 | |||
#define IDC_CLIENT_CUTTEXT 1017 | |||
#define IDC_SERVER_CUTTEXT 1018 | |||
#define IDC_LOCAL_CURSOR 1019 | |||
#define IDC_DESKTOP_RESIZE 1020 | |||
#define IDC_COPYRIGHT 1021 | |||
#define IDC_DESCRIPTION 1022 | |||
#define IDC_OPTIONS 1023 | |||
#define IDC_ABOUT 1024 | |||
#define IDC_LIST1 1025 | |||
#define IDC_FTLOCALLIST 1025 | |||
#define IDC_INFO_NAME 1026 | |||
#define IDC_INFO_HOST 1027 | |||
#define IDC_INFO_SIZE 1028 | |||
#define IDC_INFO_PF 1029 | |||
#define IDC_INFO_DEF_PF 1030 | |||
#define IDC_INFO_LINESPEED 1031 | |||
#define IDC_INFO_VERSION 1032 | |||
#define IDC_PROTOCOL_3_3 1034 | |||
#define IDC_ACCEPT_BELL 1035 | |||
#define IDC_FORMAT_VERYLOWCOLOUR 1036 | |||
#define IDC_SHOW_TOOLBAR 1036 | |||
#define IDC_FORMAT_LOWCOLOUR 1037 | |||
#define IDC_FORMAT_MEDIUMCOLOUR 1038 | |||
#define IDC_LOAD_DEFAULTS 1040 | |||
#define IDC_SAVE_DEFAULTS 1041 | |||
#define IDC_LOAD_CONFIG 1042 | |||
#define IDC_EMULATE3 1043 | |||
#define IDC_POINTER_INTERVAL 1044 | |||
#define IDC_SAVE_CONFIG 1045 | |||
#define IDC_INFO_SECURITY 1046 | |||
#define IDC_SAVE_CONFIG_AS 1048 | |||
#define IDC_MENU_KEY 1051 | |||
#define IDC_REQUESTED_ENCODING 1052 | |||
#define IDC_LAST_ENCODING 1053 | |||
#define IDC_INFO_ENCRYPTION 1055 | |||
#define IDC_AUTO_RECONNECT 1056 | |||
#define IDC_DISABLE_WINKEYS 1057 | |||
#define IDC_QUALITYLEVEL 1058 | |||
#define IDC_SEND_SYSKEYS 1059 | |||
#define IDC_PROGRESS 1064 | |||
#define IDC_CONFIRM_YESTOALL 1079 | |||
#define IDC_CONFIRM_TEXT 1080 | |||
#define IDC_EDIT2 1082 | |||
#define IDC_TYPE 1088 | |||
#define IDC_ENCODING_TIGHT 1089 | |||
#define IDC_CUSTOM_COMPRESSLEVEL 1091 | |||
#define IDC_COMPRESSLEVEL 1093 | |||
#define IDC_ALLOW_JPEG 1095 | |||
#define IDC_FTLOCALRELOAD 1096 | |||
#define IDC_STATIC_SCALE 1097 | |||
#define IDC_COMBO_SCALE 1098 | |||
#define IDC_STATIC_PERCENT 1099 | |||
#define IDC_LOAD_CACERT 1100 | |||
#define IDC_LOAD_CRLCERT 1101 | |||
#define ID_TOOLBAR 4002 | |||
#define ID_CLOSE 4003 | |||
#define ID_OPTIONS 4004 | |||
#define ID_NEW_CONNECTION 4005 | |||
#define ID_ABOUT 4006 | |||
#define ID_FULLSCREEN 4007 | |||
#define ID_SEND_CAD 4008 | |||
#define ID_INFO 4009 | |||
#define ID_REQUEST_REFRESH 4010 | |||
#define ID_CTRL_KEY 4011 | |||
#define ID_ALT_KEY 4012 | |||
#define ID_SEND_MENU_KEY 4013 | |||
#define ID_SEND_CTLESC 4014 | |||
#define ID_CONN_SAVE_AS 4015 | |||
#define ID_ZOOM_IN 4017 | |||
#define ID_ZOOM_OUT 4018 | |||
#define ID_ACTUAL_SIZE 4019 | |||
#define ID_AUTO_SIZE 4020 | |||
#define IDM_SHOW_TOOLBAR 4027 | |||
// Next default values for new objects | |||
// | |||
#ifdef APSTUDIO_INVOKED | |||
#ifndef APSTUDIO_READONLY_SYMBOLS | |||
#define _APS_NEXT_RESOURCE_VALUE 134 | |||
#define _APS_NEXT_COMMAND_VALUE 40028 | |||
#define _APS_NEXT_CONTROL_VALUE 1102 | |||
#define _APS_NEXT_SYMED_VALUE 101 | |||
#endif | |||
#endif |
@@ -1,310 +0,0 @@ | |||
/* 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 | |||
* (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. | |||
*/ | |||
// -=- VNC Viewer for Win32 | |||
#include <string.h> | |||
#ifdef WIN32 | |||
#define strcasecmp _stricmp | |||
#endif | |||
#include <list> | |||
#include <vncviewer/ListenServer.h> | |||
#include <vncviewer/resource.h> | |||
#include <vncviewer/CConn.h> | |||
#include <vncviewer/CConnThread.h> | |||
#include <vncviewer/OptionsDialog.h> | |||
#include <vncviewer/ListenTrayIcon.h> | |||
#include <network/TcpSocket.h> | |||
#include <os/os.h> | |||
#include <rfb/Logger_stdio.h> | |||
#include <rfb/Logger_file.h> | |||
#include <rfb/LogWriter.h> | |||
#include <rfb/Exception.h> | |||
#include <rfb_win32/RegConfig.h> | |||
#include <rfb_win32/MsgBox.h> | |||
#ifdef _DIALOG_CAPTURE | |||
#include <extra/LoadBMP.h> | |||
#endif | |||
using namespace rfb; | |||
using namespace rfb::win32; | |||
using namespace rdr; | |||
using namespace network; | |||
static LogWriter vlog("main"); | |||
TStr rfb::win32::AppName("VNC Viewer"); | |||
#ifdef _DIALOG_CAPTURE | |||
BoolParameter captureDialogs("CaptureDialogs", "", false); | |||
#endif | |||
// | |||
// -=- Listener | |||
// Class to handle listening on a particular port for incoming connections | |||
// from servers, and spawning of clients | |||
// | |||
static BoolParameter acceptIncoming("Listen", "Accept incoming connections from VNC servers.", false); | |||
// | |||
// -=- AboutDialog global values | |||
// | |||
const WORD rfb::win32::AboutDialog::DialogId = IDD_ABOUT; | |||
const WORD rfb::win32::AboutDialog::Copyright = IDC_COPYRIGHT; | |||
const WORD rfb::win32::AboutDialog::Version = IDC_VERSION; | |||
const WORD rfb::win32::AboutDialog::BuildTime = IDC_BUILDTIME; | |||
const WORD rfb::win32::AboutDialog::Description = IDC_DESCRIPTION; | |||
// | |||
// -=- processParams | |||
// Read in the command-line parameters and interpret them. | |||
// | |||
void | |||
programInfo() { | |||
win32::FileVersionInfo inf; | |||
_tprintf(_T("%s - %s, Version %s\n"), | |||
inf.getVerString(_T("ProductName")), | |||
inf.getVerString(_T("FileDescription")), | |||
inf.getVerString(_T("FileVersion"))); | |||
printf("%s\n", buildTime); | |||
_tprintf(_T("%s\n\n"), inf.getVerString(_T("LegalCopyright"))); | |||
} | |||
void | |||
programUsage() { | |||
printf("usage: vncviewer <options> <hostname>[:<display>]\n"); | |||
printf("Command-line options:\n"); | |||
printf(" -help - Provide usage information.\n"); | |||
printf(" -config <file> - Load connection settings from VNC Viewer 3.3 settings file\n"); | |||
printf(" -console - Run with a console window visible.\n"); | |||
printf(" <setting>=<value> - Set the named configuration parameter.\n"); | |||
printf(" (Parameter values specified on the command-line override those specified by other configuration methods.)\n"); | |||
printf("\nLog names:\n"); | |||
LogWriter::listLogWriters(); | |||
printf("\nLog destinations:\n"); | |||
Logger::listLoggers(); | |||
printf("\nParameters:\n"); | |||
Configuration::listParams(ConfViewer); | |||
printf("Press Enter/Return key to continue\n"); | |||
getchar(); | |||
exit(1); | |||
} | |||
bool print_usage = false; | |||
bool close_console = true; | |||
std::list<char*> hosts; | |||
std::list<char*> configFiles; | |||
void | |||
processParams(int argc, char* argv[]) { | |||
Configuration::enableViewerParams(); | |||
for (int i=1; i<argc; i++) { | |||
try { | |||
if (strcasecmp(argv[i], "-console") == 0) { | |||
close_console = false; | |||
} else if (((strcasecmp(argv[i], "-config") == 0) || | |||
(strcasecmp(argv[i], "/config") == 0)) && (i < argc-1)) { | |||
configFiles.push_back(strDup(argv[i+1])); | |||
i++; | |||
} else if ((strcasecmp(argv[i], "-help") == 0) || | |||
(strcasecmp(argv[i], "--help") == 0) || | |||
(strcasecmp(argv[i], "-h") == 0) || | |||
(strcasecmp(argv[i], "/?") == 0)) { | |||
print_usage = true; | |||
close_console = false; | |||
break; | |||
} else { | |||
// Try to process <option>=<value>, or -<bool> | |||
if (Configuration::setParam(argv[i], true)) | |||
continue; | |||
// Try to process -<option> <value> | |||
if ((argv[i][0] == '-') && (i+1 < argc)) { | |||
if (Configuration::setParam(&argv[i][1], argv[i+1], true)) { | |||
i++; | |||
continue; | |||
} | |||
} | |||
// If it's -<option> then it's not recognised - error | |||
// If it's <host> then add it to the list to connect to. | |||
if ((argv[i][0] == '-') || (argv[i][0] == '/')) { | |||
const char* fmt = "The option %s was not recognized. Use -help to see VNC Viewer usage"; | |||
CharArray tmp(strlen(argv[i])+strlen(fmt)+1); | |||
sprintf(tmp.buf, fmt, argv[i]); | |||
MsgBox(0, TStr(tmp.buf), MB_ICONSTOP | MB_OK); | |||
exit(1); | |||
} else if (strContains(argv[i], '\\')) { | |||
configFiles.push_back(strDup(argv[i])); | |||
} else { | |||
hosts.push_back(strDup(argv[i])); | |||
} | |||
} | |||
} catch (rdr::Exception& e) { | |||
vlog.error(e.str()); | |||
} | |||
} | |||
} | |||
// | |||
// -=- main | |||
// | |||
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, char* cmdLine, int cmdShow) { | |||
try { | |||
// - Initialise the available loggers | |||
initStdIOLoggers(); | |||
initFileLogger("C:\\temp\\vncviewer4.log"); | |||
// - By default, just log errors to stderr | |||
logParams.setDefault("*:stderr:0"); | |||
// - Process the command-line | |||
int argc = __argc; | |||
char** argv = __argv; | |||
processParams(argc, argv); | |||
// - By default the console will be closed | |||
if (close_console) { | |||
if (!FreeConsole()) | |||
vlog.info("unable to close console:%u", GetLastError()); | |||
} else { | |||
AllocConsole(); | |||
freopen("CONIN$","rb",stdin); | |||
freopen("CONOUT$","wb",stdout); | |||
freopen("CONOUT$","wb",stderr); | |||
setbuf(stderr, 0); | |||
} | |||
#ifdef _DIALOG_CAPTURE | |||
if (captureDialogs) { | |||
CConn::userConfigKey.openKey(HKEY_CURRENT_USER, _T("Software\\TigerVNC\\VNCViewer4")); | |||
OptionsDialog::global.showDialog(0, true); | |||
return 0; | |||
} | |||
#endif | |||
// - If no clients are specified, bring up a connection dialog | |||
if (configFiles.empty() && hosts.empty() && !acceptIncoming && !print_usage) | |||
hosts.push_back(0); | |||
programInfo(); | |||
// Create vnc in the user's home directory if it doesn't already exist | |||
char* homeDir = NULL; | |||
if (getvnchomedir(&homeDir) == -1) | |||
vlog.error("Could not create vnc directory: can't obtain home directory path"); | |||
else { | |||
int result = CreateDirectory(homeDir, NULL); | |||
if (result <= 0 && GetLastError() != ERROR_ALREADY_EXISTS) | |||
vlog.error("Could not create vnc directory: %u", GetLastError()); | |||
delete [] homeDir; | |||
} | |||
// - Connect to the clients | |||
if (!configFiles.empty() || !hosts.empty() || acceptIncoming) { | |||
// - Configure the registry configuration reader | |||
win32::RegConfigThread config; | |||
config.start(HKEY_CURRENT_USER, _T("Software\\TigerVNC\\VNCViewer4")); | |||
// - Tell the rest of VNC Viewer where to write config data to | |||
CConn::userConfigKey.createKey(HKEY_CURRENT_USER, _T("Software\\TigerVNC\\VNCViewer4")); | |||
if (acceptIncoming) { | |||
int port = 5500; | |||
// Listening viewer | |||
if (hosts.size() > 1) | |||
programUsage(); | |||
if (!hosts.empty()) | |||
port = atoi(hosts.front()); | |||
// Show the tray icon & menu | |||
ListenTrayIcon tray; | |||
// Listen for reverse connections | |||
network::TcpListener sock(NULL, port); | |||
ListenServer listener(&sock); | |||
// Run the view manager | |||
// Also processes the tray icon if necessary | |||
MSG msg; | |||
while (GetMessage(&msg, NULL, 0, 0) > 0) { | |||
TranslateMessage(&msg); | |||
DispatchMessage(&msg); | |||
} | |||
} else { | |||
// Read each config file in turn | |||
while (!configFiles.empty()) { | |||
char* filename = configFiles.front(); | |||
new CConnThread(filename, true); | |||
strFree(filename); | |||
configFiles.pop_front(); | |||
} | |||
// Connect to each client in turn | |||
while (!hosts.empty()) { | |||
char* hostinfo = hosts.front(); | |||
new CConnThread(hostinfo); | |||
strFree(hostinfo); | |||
hosts.pop_front(); | |||
} | |||
// Run the view manager | |||
MSG msg; | |||
while (CConnThread::getMessage(&msg, NULL, 0, 0) > 0) { | |||
TranslateMessage(&msg); | |||
DispatchMessage(&msg); | |||
} | |||
vlog.debug("quitting viewer"); | |||
} | |||
} | |||
// - If necessary, print the program's usage info | |||
if (print_usage) | |||
programUsage(); | |||
if (!close_console) { | |||
printf("Press Enter/Return key to continue\n"); | |||
getchar(); | |||
} | |||
} catch (rdr::Exception& e) { | |||
MsgBox(0, TStr(e.str()), MB_ICONSTOP | MB_OK); | |||
} | |||
return 0; | |||
} |
@@ -1,22 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | |||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | |||
<assemblyIdentity | |||
version="4.0.0.26" | |||
processorArchitecture="X86" | |||
name="TigerVNC.vncviewer.exe" | |||
type="win32" | |||
/> | |||
<description>.NET control deployment tool</description> | |||
<dependency> | |||
<dependentAssembly> | |||
<assemblyIdentity | |||
type="win32" | |||
name="Microsoft.Windows.Common-Controls" | |||
version="6.0.0.0" | |||
processorArchitecture="X86" | |||
publicKeyToken="6595b64144ccf1df" | |||
language="*" | |||
/> | |||
</dependentAssembly> | |||
</dependency> | |||
</assembly> |
@@ -1,22 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | |||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | |||
<assemblyIdentity | |||
version="4.0.0.26" | |||
processorArchitecture="AMD64" | |||
name="TigerVNC.vncviewer.exe" | |||
type="win32" | |||
/> | |||
<description>.NET control deployment tool</description> | |||
<dependency> | |||
<dependentAssembly> | |||
<assemblyIdentity | |||
type="win32" | |||
name="Microsoft.Windows.Common-Controls" | |||
version="6.0.0.0" | |||
processorArchitecture="AMD64" | |||
publicKeyToken="6595b64144ccf1df" | |||
language="*" | |||
/> | |||
</dependentAssembly> | |||
</dependency> | |||
</assembly> |
@@ -1,594 +0,0 @@ | |||
//Microsoft Developer Studio generated resource script. | |||
// | |||
#include "resource.h" | |||
#include "resdefs.h" | |||
#define APSTUDIO_READONLY_SYMBOLS | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Generated from the TEXTINCLUDE 2 resource. | |||
// | |||
#include "windows.h" | |||
#ifndef IDC_STATIC | |||
#define IDC_STATIC -1 | |||
#endif | |||
///////////////////////////////////////////////////////////////////////////// | |||
#undef APSTUDIO_READONLY_SYMBOLS | |||
///////////////////////////////////////////////////////////////////////////// | |||
// English (U.K.) resources | |||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) | |||
#ifdef _WIN32 | |||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK | |||
#pragma code_page(1252) | |||
#endif //_WIN32 | |||
#ifdef APSTUDIO_INVOKED | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// TEXTINCLUDE | |||
// | |||
1 TEXTINCLUDE DISCARDABLE | |||
BEGIN | |||
"resource.h\0" | |||
END | |||
2 TEXTINCLUDE DISCARDABLE | |||
BEGIN | |||
"#include ""windows.h""\r\n" | |||
"\0" | |||
END | |||
3 TEXTINCLUDE DISCARDABLE | |||
BEGIN | |||
"\r\n" | |||
"\0" | |||
END | |||
#endif // APSTUDIO_INVOKED | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Icon | |||
// | |||
// Icon with lowest ID value placed first to ensure application icon | |||
// remains consistent on all systems. | |||
IDI_ICON ICON DISCARDABLE "vncviewer.ico" | |||
#ifndef _MAC | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Version | |||
// | |||
VS_VERSION_INFO VERSIONINFO | |||
FILEVERSION __RCVERSION | |||
PRODUCTVERSION __RCVERSION | |||
FILEFLAGSMASK 0x3fL | |||
#ifdef _DEBUG | |||
FILEFLAGS 0x1L | |||
#else | |||
FILEFLAGS 0x0L | |||
#endif | |||
FILEOS 0x40004L | |||
FILETYPE 0x1L | |||
FILESUBTYPE 0x0L | |||
BEGIN | |||
BLOCK "StringFileInfo" | |||
BEGIN | |||
BLOCK "080904b0" | |||
BEGIN | |||
VALUE "Comments", "\0" | |||
VALUE "CompanyName", "TigerVNC Project\0" | |||
#ifdef WIN64 | |||
VALUE "FileDescription", "TigerVNC Viewer for Win64\0" | |||
VALUE "ProductName", "TigerVNC Viewer for Win64\0" | |||
#else | |||
VALUE "FileDescription", "TigerVNC Viewer for Win32\0" | |||
VALUE "ProductName", "TigerVNC Viewer for Win32\0" | |||
#endif | |||
VALUE "FileVersion", __RCVERSIONSTR | |||
VALUE "InternalName", "free4/vncviewer/win\0" | |||
VALUE "LegalCopyright", "Copyright (C) 1999-2011 TigerVNC Team and many others (see README.txt)\0" | |||
VALUE "LegalTrademarks", "TigerVNC\0" | |||
VALUE "OriginalFilename", "vncviewer.exe\0" | |||
VALUE "PrivateBuild", "\0" | |||
VALUE "ProductVersion", __VERSIONSTR | |||
VALUE "SpecialBuild", "\0" | |||
END | |||
END | |||
BLOCK "VarFileInfo" | |||
BEGIN | |||
VALUE "Translation", 0x809, 1200 | |||
END | |||
END | |||
#endif // !_MAC | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Dialog | |||
// | |||
IDD_VNC_AUTH_DLG DIALOG DISCARDABLE 0, 0, 241, 46 | |||
STYLE DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | |||
CAPTION "VNC Viewer : Authentication" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
EDITTEXT IDC_USERNAME,85,6,100,14,ES_AUTOHSCROLL | |||
EDITTEXT IDC_PASSWORD,85,25,100,15,ES_PASSWORD | ES_AUTOHSCROLL | | |||
ES_WANTRETURN | |||
DEFPUSHBUTTON "OK",IDOK,190,6,45,14 | |||
PUSHBUTTON "Cancel",IDCANCEL,190,25,45,15 | |||
CONTROL 120,IDI_ICON,"Static",SS_BITMAP,7,6,21,20 | |||
LTEXT "Username:",IDC_STATIC,45,6,35,14 | |||
LTEXT "Password:",IDC_STATIC,45,25,35,15 | |||
END | |||
IDD_CONNECTING_DLG DIALOG DISCARDABLE 0, 0, 185, 47 | |||
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | |||
CAPTION "VNC Viewer : Connecting" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
PUSHBUTTON "Cancel",IDCANCEL,128,26,50,14 | |||
CTEXT "Attempting to connect to host...",IDC_CONNECTING_TEXT,7, | |||
7,171,14,SS_CENTERIMAGE | |||
END | |||
IDD_CONNECTION_DLG DIALOG DISCARDABLE 0, 0, 224, 66 | |||
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | | |||
WS_SYSMENU | |||
CAPTION "VNC Viewer : Connection Details" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
COMBOBOX IDC_SERVER_EDIT,85,15,105,234,CBS_DROPDOWN | | |||
CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP | |||
PUSHBUTTON "&About...",IDC_ABOUT,5,45,50,14 | |||
PUSHBUTTON "&Options...",IDC_OPTIONS,60,45,50,14 | |||
DEFPUSHBUTTON "OK",IDOK,115,45,50,14 | |||
PUSHBUTTON "Cancel",IDCANCEL,170,45,48,14 | |||
CONTROL 120,IDI_ICON,"Static",SS_BITMAP | SS_REALSIZEIMAGE,5,6, | |||
20,20 | |||
RTEXT "Server:",IDC_STATIC,43,15,37,13,SS_CENTERIMAGE | |||
END | |||
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 300, 92 | |||
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | | |||
WS_SYSMENU | |||
CAPTION "About TigerVNC Viewer for Windows" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
DEFPUSHBUTTON "OK",IDOK,245,70,47,15 | |||
CONTROL 120,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,7, | |||
10,33,31 | |||
LTEXT ">appname<",IDC_DESCRIPTION,46,10,119,15 | |||
LTEXT ">version<",IDC_VERSION,165,10,77,15 | |||
LTEXT ">buildtime<",IDC_BUILDTIME,46,25,196,15 | |||
LTEXT ">copyright<",IDC_COPYRIGHT,46,40,250,15 | |||
LTEXT "Visit www.tigervnc.org for more information on TigerVNC.", | |||
IDC_STATIC,46,55,196,15 | |||
END | |||
IDD_FORMAT DIALOG DISCARDABLE 0, 0, 201, 161 | |||
STYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU | |||
CAPTION "Colour && Encoding" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
CONTROL "&Auto select",IDC_ENCODING_AUTO,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,7,7,88,13 | |||
GROUPBOX "Preferred encoding",IDC_STATIC,7,20,83,75 | |||
CONTROL "Tight",IDC_ENCODING_TIGHT,"Button",BS_AUTORADIOBUTTON | | |||
WS_GROUP,10,30,75,14 | |||
CONTROL "ZRLE",IDC_ENCODING_ZRLE,"Button",BS_AUTORADIOBUTTON,10, | |||
45,75,14 | |||
CONTROL "Hextile",IDC_ENCODING_HEXTILE,"Button", | |||
BS_AUTORADIOBUTTON,10,60,75,16 | |||
CONTROL "Raw",IDC_ENCODING_RAW,"Button",BS_AUTORADIOBUTTON,10,75, | |||
75,15 | |||
GROUPBOX "Color level",IDC_STATIC,95,20,99,75 | |||
CONTROL "&Full (all available colors)",IDC_FORMAT_FULLCOLOUR, | |||
"Button",BS_AUTORADIOBUTTON | WS_GROUP,100,30,90,15 | |||
CONTROL "&Medium (256 colors)",IDC_FORMAT_MEDIUMCOLOUR,"Button", | |||
BS_AUTORADIOBUTTON,100,45,90,14 | |||
CONTROL "&Low (64 colors)",IDC_FORMAT_LOWCOLOUR,"Button", | |||
BS_AUTORADIOBUTTON,100,60,90,16 | |||
CONTROL "&Very low (8 colors)",IDC_FORMAT_VERYLOWCOLOUR,"Button", | |||
BS_AUTORADIOBUTTON,100,75,90,15 | |||
CONTROL "Custom compression level:",IDC_CUSTOM_COMPRESSLEVEL, | |||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,100,99,10 | |||
EDITTEXT IDC_COMPRESSLEVEL,25,111,15,12,ES_AUTOHSCROLL | | |||
ES_NUMBER | |||
LTEXT "level (1=fast, 9=best)",IDC_STATIC,44,114,81,9,NOT | |||
WS_GROUP | |||
CONTROL "Allow JPEG compression:",IDC_ALLOW_JPEG,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,10,126,96,10 | |||
EDITTEXT IDC_QUALITYLEVEL,25,137,15,12,ES_AUTOHSCROLL | ES_NUMBER | |||
LTEXT "quality (1=poor, 9=best)",IDC_STATIC,44,140,81,9 | |||
END | |||
IDD_MISC DIALOG DISCARDABLE 0, 0, 216, 138 | |||
STYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU | |||
CAPTION "Misc" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
CONTROL "Shared connection (do not disconnect other viewers)", | |||
IDC_CONN_SHARED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, | |||
10,202,15 | |||
CONTROL "Full-screen mode",IDC_FULL_SCREEN,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,7,25,99,15 | |||
CONTROL "Render cursor locally",IDC_LOCAL_CURSOR,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,7,40,99,15 | |||
CONTROL "Allow dynamic desktop resizing",IDC_DESKTOP_RESIZE, | |||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,55,112,15 | |||
CONTROL "Only use protocol version 3.3",IDC_PROTOCOL_3_3,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,7,70,111,15 | |||
CONTROL "Beep when requested to by the server",IDC_ACCEPT_BELL, | |||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,85,202,15 | |||
CONTROL "Offer to automatically reconnect",IDC_AUTO_RECONNECT, | |||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,100,202,15 | |||
CONTROL "Show toolbar",IDC_SHOW_TOOLBAR,"Button",BS_AUTOCHECKBOX | | |||
WS_TABSTOP,106,25,103,15 | |||
COMBOBOX IDC_COMBO_SCALE,138,40,42,134,CBS_DROPDOWN | CBS_SORT | | |||
WS_VSCROLL | WS_TABSTOP | |||
LTEXT "Scale by:",IDC_STATIC_SCALE,106,40,32,15,SS_CENTERIMAGE | |||
LTEXT "%",IDC_STATIC_PERCENT,185,40,24,15,SS_CENTERIMAGE | |||
END | |||
IDD_INPUTS DIALOG DISCARDABLE 0, 0, 186, 162 | |||
STYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU | |||
CAPTION "Inputs" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
CONTROL "Send pointer events to server",IDC_SEND_POINTER,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,7,10,172,15 | |||
CONTROL "Send keyboard events to server",IDC_SEND_KEYS,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,7,25,172,15 | |||
CONTROL "Send clipboard changes to server",IDC_CLIENT_CUTTEXT, | |||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,172,15 | |||
CONTROL "Accept clipboard changes from server", | |||
IDC_SERVER_CUTTEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, | |||
7,55,172,15 | |||
CONTROL "Enable 3-button mouse emulation",IDC_EMULATE3,"Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP,7,70,172,15 | |||
CONTROL "Rate-limit mouse move events",IDC_POINTER_INTERVAL, | |||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,86,172,14 | |||
LTEXT "Menu key",IDC_STATIC,7,100,98,15,SS_CENTERIMAGE | |||
COMBOBOX IDC_MENU_KEY,105,100,74,105,CBS_DROPDOWNLIST | CBS_SORT | | |||
WS_VSCROLL | WS_TABSTOP | |||
CONTROL "Pass special keys directly to server", | |||
IDC_DISABLE_WINKEYS,"Button",BS_AUTOCHECKBOX | | |||
WS_TABSTOP,7,115,172,15 | |||
END | |||
IDD_CONNECTION_INFO DIALOG DISCARDABLE 0, 0, 239, 199 | |||
STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | | |||
WS_SYSMENU | |||
CAPTION "VNC Connection Info" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
DEFPUSHBUTTON "OK",IDOK,182,178,50,14 | |||
LTEXT "Desktop Name:",IDC_STATIC,7,10,73,15 | |||
LTEXT "Host:",IDC_STATIC,7,25,73,15 | |||
LTEXT "Size:",IDC_STATIC,7,40,73,15 | |||
LTEXT "Pixel Format:",IDC_STATIC,7,55,73,15 | |||
LTEXT "Server Default:",IDC_STATIC,7,70,73,15 | |||
LTEXT "Line Speed Estimate:",IDC_STATIC,7,115,73,15 | |||
LTEXT "Protocol Version:",IDC_STATIC,7,130,73,15 | |||
LTEXT "",IDC_INFO_NAME,80,10,152,15 | |||
LTEXT "",IDC_INFO_HOST,80,25,152,15 | |||
LTEXT "",IDC_INFO_SIZE,80,40,152,15 | |||
LTEXT "",IDC_INFO_PF,80,55,152,15 | |||
LTEXT "",IDC_INFO_DEF_PF,80,70,152,15 | |||
LTEXT "",IDC_INFO_LINESPEED,80,115,152,15 | |||
LTEXT "",IDC_INFO_VERSION,80,130,152,15 | |||
LTEXT "Security Method:",IDC_STATIC,7,145,73,15 | |||
LTEXT "",IDC_INFO_SECURITY,80,145,152,15 | |||
LTEXT "Requested Encoding:",IDC_STATIC,7,85,73,15 | |||
LTEXT "Last Used Encoding:",IDC_STATIC,7,100,73,15 | |||
LTEXT "",IDC_REQUESTED_ENCODING,80,86,152,15 | |||
LTEXT "",IDC_LAST_ENCODING,80,100,152,15 | |||
LTEXT "Static",IDC_INFO_ENCRYPTION,80,160,152,15 | |||
LTEXT "Encryption:",IDC_STATIC,7,160,73,15 | |||
END | |||
IDD_DEFAULTS DIALOG DISCARDABLE 0, 0, 217, 87 | |||
STYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU | |||
CAPTION "Load / Save" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
PUSHBUTTON "&Reload",IDC_LOAD_CONFIG,15,20,85,15 | |||
PUSHBUTTON "&Save",IDC_SAVE_CONFIG,15,40,85,15 | |||
PUSHBUTTON "Save &As ...",IDC_SAVE_CONFIG_AS,15,60,85,15 | |||
PUSHBUTTON "R&eload",IDC_LOAD_DEFAULTS,120,20,85,15 | |||
PUSHBUTTON "S&ave",IDC_SAVE_DEFAULTS,120,40,85,15 | |||
GROUPBOX "Configuration File",IDC_STATIC,7,7,100,74 | |||
GROUPBOX "Defaults",IDC_STATIC,113,7,97,53 | |||
END | |||
IDD_SECURITY DIALOG DISCARDABLE 0, 0, 200, 200 | |||
STYLE DS_MODALFRAME | DS_CONTROL | WS_POPUP | WS_CAPTION | WS_SYSMENU | |||
CAPTION "Security" | |||
FONT 8, "MS Sans Serif" | |||
BEGIN | |||
CONTROL "Extended encryption and authentication methods (VeNCrypt)", | |||
IDC_VENCRYPT, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, | |||
7,10,200,15 | |||
GROUPBOX "Session encryption", IDC_STATIC, 7,25,120,60 | |||
CONTROL "None", IDC_ENC_NONE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, | |||
10,35,50,15 | |||
CONTROL "Anonymous TLS", IDC_ENC_TLS, "Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP, 10,50,80,15 | |||
CONTROL "TLS with X.509 certificates", IDC_ENC_X509, "Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP, 10,65,110,15 | |||
GROUPBOX "X.509 certificates", IDC_STATIC, 7,90,170,30 | |||
PUSHBUTTON "Load CA certificate", IDC_LOAD_CACERT, 10,100,80,15 | |||
PUSHBUTTON "Load CRL certificate", IDC_LOAD_CRLCERT, 90,100,80,15 | |||
GROUPBOX "Authentication", IDC_STATIC, 7,125,100,60 | |||
CONTROL "None", IDC_AUTH_NONE, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, | |||
10,135,50,15 | |||
CONTROL "Standard VNC", IDC_AUTH_VNC, "Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP, 10,150,80,15 | |||
CONTROL "Plaintext", IDC_AUTH_PLAIN, "Button", | |||
BS_AUTOCHECKBOX | WS_TABSTOP, 10,165,70,15 | |||
END | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// DESIGNINFO | |||
// | |||
#ifdef APSTUDIO_INVOKED | |||
GUIDELINES DESIGNINFO DISCARDABLE | |||
BEGIN | |||
IDD_VNC_AUTH_DLG, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 235 | |||
VERTGUIDE, 45 | |||
VERTGUIDE, 80 | |||
VERTGUIDE, 85 | |||
VERTGUIDE, 185 | |||
VERTGUIDE, 190 | |||
TOPMARGIN, 6 | |||
BOTTOMMARGIN, 40 | |||
HORZGUIDE, 20 | |||
HORZGUIDE, 25 | |||
HORZGUIDE, 40 | |||
END | |||
IDD_CONNECTING_DLG, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 178 | |||
TOPMARGIN, 7 | |||
BOTTOMMARGIN, 40 | |||
HORZGUIDE, 21 | |||
HORZGUIDE, 26 | |||
END | |||
IDD_CONNECTION_DLG, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 5 | |||
RIGHTMARGIN, 218 | |||
VERTGUIDE, 30 | |||
VERTGUIDE, 43 | |||
VERTGUIDE, 55 | |||
VERTGUIDE, 60 | |||
VERTGUIDE, 80 | |||
VERTGUIDE, 85 | |||
VERTGUIDE, 110 | |||
VERTGUIDE, 115 | |||
VERTGUIDE, 165 | |||
VERTGUIDE, 170 | |||
VERTGUIDE, 190 | |||
TOPMARGIN, 6 | |||
BOTTOMMARGIN, 59 | |||
HORZGUIDE, 19 | |||
HORZGUIDE, 24 | |||
HORZGUIDE, 36 | |||
HORZGUIDE, 45 | |||
END | |||
IDD_ABOUT, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 242 | |||
VERTGUIDE, 46 | |||
VERTGUIDE, 165 | |||
VERTGUIDE, 195 | |||
TOPMARGIN, 7 | |||
BOTTOMMARGIN, 85 | |||
HORZGUIDE, 10 | |||
HORZGUIDE, 25 | |||
HORZGUIDE, 40 | |||
HORZGUIDE, 55 | |||
HORZGUIDE, 70 | |||
END | |||
IDD_FORMAT, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 194 | |||
VERTGUIDE, 10 | |||
VERTGUIDE, 85 | |||
VERTGUIDE, 90 | |||
VERTGUIDE, 95 | |||
VERTGUIDE, 100 | |||
VERTGUIDE, 105 | |||
VERTGUIDE, 190 | |||
TOPMARGIN, 7 | |||
BOTTOMMARGIN, 154 | |||
HORZGUIDE, 10 | |||
HORZGUIDE, 20 | |||
HORZGUIDE, 25 | |||
HORZGUIDE, 35 | |||
HORZGUIDE, 49 | |||
HORZGUIDE, 65 | |||
HORZGUIDE, 80 | |||
HORZGUIDE, 85 | |||
END | |||
IDD_MISC, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 209 | |||
VERTGUIDE, 106 | |||
VERTGUIDE, 138 | |||
VERTGUIDE, 180 | |||
VERTGUIDE, 185 | |||
TOPMARGIN, 7 | |||
BOTTOMMARGIN, 131 | |||
HORZGUIDE, 10 | |||
HORZGUIDE, 25 | |||
HORZGUIDE, 40 | |||
HORZGUIDE, 55 | |||
HORZGUIDE, 70 | |||
HORZGUIDE, 85 | |||
HORZGUIDE, 100 | |||
HORZGUIDE, 115 | |||
HORZGUIDE, 130 | |||
END | |||
IDD_INPUTS, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 179 | |||
VERTGUIDE, 105 | |||
TOPMARGIN, 7 | |||
BOTTOMMARGIN, 155 | |||
HORZGUIDE, 10 | |||
HORZGUIDE, 25 | |||
HORZGUIDE, 40 | |||
HORZGUIDE, 55 | |||
HORZGUIDE, 70 | |||
HORZGUIDE, 85 | |||
HORZGUIDE, 100 | |||
HORZGUIDE, 115 | |||
HORZGUIDE, 130 | |||
HORZGUIDE, 145 | |||
END | |||
IDD_CONNECTION_INFO, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 232 | |||
VERTGUIDE, 80 | |||
TOPMARGIN, 7 | |||
BOTTOMMARGIN, 192 | |||
HORZGUIDE, 10 | |||
HORZGUIDE, 25 | |||
HORZGUIDE, 40 | |||
HORZGUIDE, 55 | |||
HORZGUIDE, 70 | |||
HORZGUIDE, 85 | |||
HORZGUIDE, 100 | |||
HORZGUIDE, 115 | |||
HORZGUIDE, 130 | |||
HORZGUIDE, 145 | |||
HORZGUIDE, 160 | |||
HORZGUIDE, 175 | |||
END | |||
IDD_DEFAULTS, DIALOG | |||
BEGIN | |||
LEFTMARGIN, 7 | |||
RIGHTMARGIN, 210 | |||
VERTGUIDE, 15 | |||
VERTGUIDE, 100 | |||
VERTGUIDE, 107 | |||
VERTGUIDE, 113 | |||
VERTGUIDE, 120 | |||
VERTGUIDE, 205 | |||
TOPMARGIN, 7 | |||
BOTTOMMARGIN, 80 | |||
HORZGUIDE, 20 | |||
HORZGUIDE, 35 | |||
HORZGUIDE, 40 | |||
HORZGUIDE, 55 | |||
HORZGUIDE, 60 | |||
HORZGUIDE, 75 | |||
END | |||
END | |||
#endif // APSTUDIO_INVOKED | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Cursor | |||
// | |||
IDC_DOT_CURSOR CURSOR DISCARDABLE "cursor1.cur" | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Dialog Info | |||
// | |||
IDD_CONNECTION_DLG DLGINIT | |||
BEGIN | |||
IDC_SERVER_EDIT, 0x403, 16, 0, | |||
0x796d, 0x616d, 0x6863, 0x6e69, 0x2e65, 0x726f, 0x3a67, 0x0031, | |||
0 | |||
END | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Menu | |||
// | |||
IDR_TRAY MENU DISCARDABLE | |||
BEGIN | |||
POPUP "Tray Menu" | |||
BEGIN | |||
MENUITEM "&New Connection...", ID_NEW_CONNECTION | |||
MENUITEM SEPARATOR | |||
MENUITEM "Default &Options...", ID_OPTIONS | |||
MENUITEM SEPARATOR | |||
MENUITEM "&Close Daemon", ID_CLOSE | |||
MENUITEM "&About...", ID_ABOUT | |||
END | |||
END | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// 24 | |||
// | |||
#ifdef WIN64 | |||
IDR_MANIFEST 24 DISCARDABLE "vncviewer.exe.manifest64" | |||
#else | |||
IDR_MANIFEST 24 DISCARDABLE "vncviewer.exe.manifest" | |||
#endif | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Bitmap | |||
// | |||
IDB_BITMAP BITMAP DISCARDABLE "vncviewer.bmp" | |||
IDB_TOOLBAR BITMAP DISCARDABLE "toolbar.bmp" | |||
#endif // English (U.K.) resources | |||
///////////////////////////////////////////////////////////////////////////// | |||
#ifndef APSTUDIO_INVOKED | |||
///////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Generated from the TEXTINCLUDE 3 resource. | |||
// | |||
///////////////////////////////////////////////////////////////////////////// | |||
#endif // not APSTUDIO_INVOKED | |||