# The RC version must always be four comma-separated numbers
set(RCVERSION 1,0,90,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")
+
# Compatibility variables for the migration from autotools
add_definitions(-DPACKAGE_NAME="${CMAKE_PROJECT_NAME}")
add_definitions(-DPACKAGE_VERSION="${VERSION}")
message(STATUS "WARNING: You are not using libjpeg-turbo. Performance will suffer.")
endif()
+# Check for FLTK
+if(BUILD_NEW_VNCVIEWER)
+ set(FLTK_SKIP_FLUID TRUE)
+ set(FLTK_SKIP_OPENGL TRUE)
+ find_package(FLTK COMPONENTS REQUIRED)
+endif()
+
# Check for GNUTLS library
find_package(GnuTLS)
if(GNUTLS_FOUND)
else()
add_subdirectory(unix)
endif()
+
+if(BUILD_NEW_VNCVIEWER)
+ add_subdirectory(vncviewer)
+endif()
add_subdirectory(vncconfig)
add_subdirectory(vncpasswd)
+
+if(NOT BUILD_NEW_VNCVIEWER)
add_subdirectory(vncviewer)
+endif()
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#include <assert.h>
+#include <unistd.h>
+
+#include <rfb/CMsgWriter.h>
+#include <rfb/encodings.h>
+#include <rfb/Hostname.h>
+#include <rfb/LogWriter.h>
+#include <rfb/util.h>
+#include <rfb/screenTypes.h>
+#include <rfb/Timer.h>
+#include <network/TcpSocket.h>
+
+#include <FL/Fl.H>
+#include <FL/fl_ask.H>
+
+#include "CConn.h"
+#include "i18n.h"
+#include "parameters.h"
+
+using namespace rdr;
+using namespace rfb;
+using namespace std;
+
+extern void exit_vncviewer();
+
+static rfb::LogWriter vlog("CConn");
+
+CConn::CConn(const char* vncServerName)
+ : serverHost(0), serverPort(0), sock(NULL), desktop(NULL),
+ currentEncoding(encodingTight), lastServerEncoding((unsigned int)-1),
+ formatChange(false), encodingChange(false),
+ firstUpdate(true), pendingUpdate(false)
+{
+ setShared(::shared);
+
+ int encNum = encodingNum(preferredEncoding);
+ if (encNum != -1)
+ currentEncoding = encNum;
+
+ cp.supportsDesktopResize = true;
+ cp.supportsExtendedDesktopSize = true;
+ cp.supportsDesktopRename = true;
+ cp.supportsLocalCursor = useLocalCursor;
+
+ cp.customCompressLevel = customCompressLevel;
+ cp.compressLevel = compressLevel;
+
+ cp.noJpeg = noJpeg;
+ cp.qualityLevel = qualityLevel;
+
+ try {
+ getHostAndPort(vncServerName, &serverHost, &serverPort);
+
+ sock = new network::TcpSocket(serverHost, serverPort);
+ vlog.info(_("connected to host %s port %d"), serverHost, serverPort);
+ } catch (rdr::Exception& e) {
+ vlog.error(e.str());
+ fl_alert(e.str());
+ exit_vncviewer();
+ return;
+ }
+
+ Fl::add_fd(sock->getFd(), FL_READ | FL_EXCEPT, socketEvent, this);
+
+ // See callback below
+ sock->inStream().setBlockCallback(this);
+
+ setServerName(serverHost);
+ setStreams(&sock->inStream(), &sock->outStream());
+
+ initialiseProtocol();
+}
+
+CConn::~CConn()
+{
+ free(serverHost);
+ if (sock)
+ Fl::remove_fd(sock->getFd());
+ delete sock;
+}
+
+// The RFB core is not properly asynchronous, so it calls this callback
+// whenever it needs to block to wait for more data. Since FLTK is
+// monitoring the socket, we just make sure FLTK gets to run.
+
+void CConn::blockCallback()
+{
+ int next_timer;
+
+ next_timer = Timer::checkTimeouts();
+ if (next_timer == 0)
+ next_timer = INT_MAX;
+
+ Fl::wait((double)next_timer / 1000.0);
+}
+
+void CConn::socketEvent(int fd, void *data)
+{
+ CConn *cc;
+ static bool recursing = false;
+
+ assert(data);
+ cc = (CConn*)data;
+
+ // I don't think processMsg() is recursion safe, so add this check
+ if (recursing)
+ return;
+
+ recursing = true;
+
+ try {
+ // processMsg() only processes one message, so we need to loop
+ // until the buffers are empty or things will stall.
+ do {
+ cc->processMsg();
+ } while (cc->sock->inStream().checkNoWait(1));
+ } catch (rdr::EndOfStream& e) {
+ vlog.info(e.str());
+ exit_vncviewer();
+ } catch (rdr::Exception& e) {
+ vlog.error(e.str());
+ fl_alert(e.str());
+ exit_vncviewer();
+ }
+
+ recursing = false;
+}
+
+////////////////////// CConnection callback methods //////////////////////
+
+// serverInit() is called when the serverInit message has been received. At
+// this point we create the desktop window and display it. We also tell the
+// server the pixel format and encodings to use and request the first update.
+void CConn::serverInit()
+{
+ CConnection::serverInit();
+
+ // If using AutoSelect with old servers, start in FullColor
+ // mode. See comment in autoSelectFormatAndEncoding.
+ if (cp.beforeVersion(3, 8) && autoSelect)
+ fullColour.setParam(true);
+
+ serverPF = cp.pf();
+
+ desktop = new DesktopWindow(cp.width, cp.height, cp.name(), serverPF, this);
+ fullColourPF = desktop->getPreferredPF();
+
+ formatChange = encodingChange = true;
+ requestNewUpdate();
+}
+
+// setDesktopSize() is called when the desktop size changes (including when
+// it is set initially).
+void CConn::setDesktopSize(int w, int h)
+{
+ CConnection::setDesktopSize(w,h);
+ resizeFramebuffer();
+}
+
+// setExtendedDesktopSize() is a more advanced version of setDesktopSize()
+void CConn::setExtendedDesktopSize(int reason, int result, int w, int h,
+ const rfb::ScreenSet& layout)
+{
+ CConnection::setExtendedDesktopSize(reason, result, w, h, layout);
+
+ if ((reason == reasonClient) && (result != resultSuccess)) {
+ vlog.error(_("SetDesktopSize failed: %d"), result);
+ return;
+ }
+
+ resizeFramebuffer();
+}
+
+// setName() is called when the desktop name changes
+void CConn::setName(const char* name)
+{
+ CConnection::setName(name);
+ if (desktop)
+ desktop->setName(name);
+}
+
+// framebufferUpdateStart() is called at the beginning of an update.
+// Here we try to send out a new framebuffer update request so that the
+// next update can be sent out in parallel with us decoding the current
+// one. We cannot do this if we're in the middle of a format change
+// though.
+void CConn::framebufferUpdateStart()
+{
+ if (!formatChange) {
+ pendingUpdate = true;
+ requestNewUpdate();
+ } else
+ pendingUpdate = false;
+}
+
+// framebufferUpdateEnd() is called at the end of an update.
+// For each rectangle, the FdInStream will have timed the speed
+// of the connection, allowing us to select format and encoding
+// appropriately, and then request another incremental update.
+void CConn::framebufferUpdateEnd()
+{
+ desktop->updateWindow();
+
+ if (firstUpdate) {
+ int width, height;
+
+ if (cp.supportsSetDesktopSize &&
+ sscanf(desktopSize.getValueStr(), "%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;
+ }
+
+ // A format change prevented us from sending this before the update,
+ // so make sure to send it now.
+ if (formatChange && !pendingUpdate)
+ requestNewUpdate();
+
+ // Compute new settings based on updated bandwidth values
+ if (autoSelect)
+ autoSelectFormatAndEncoding();
+
+ // Make sure that the FLTK handling and the timers gets some CPU time
+ // in case of back to back framebuffer updates.
+ Fl::check();
+ Timer::checkTimeouts();
+}
+
+// The rest of the callbacks are fairly self-explanatory...
+
+void CConn::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs)
+{
+ desktop->setColourMapEntries(firstColour, nColours, rgbs);
+}
+
+void CConn::bell()
+{
+ fl_beep();
+}
+
+void CConn::serverCutText(const char* str, rdr::U32 len)
+{
+// desktop->serverCutText(str,len);
+}
+
+// We start timing on beginRect and stop timing on endRect, to
+// avoid skewing the bandwidth estimation as a result of the server
+// being slow or the network having high latency
+void CConn::beginRect(const Rect& r, int encoding)
+{
+ sock->inStream().startTiming();
+ if (encoding != encodingCopyRect) {
+ lastServerEncoding = encoding;
+ }
+}
+
+void CConn::endRect(const Rect& r, int encoding)
+{
+ sock->inStream().stopTiming();
+}
+
+void CConn::fillRect(const rfb::Rect& r, rfb::Pixel p)
+{
+ desktop->fillRect(r,p);
+}
+void CConn::imageRect(const rfb::Rect& r, void* p)
+{
+ desktop->imageRect(r,p);
+}
+void CConn::copyRect(const rfb::Rect& r, int sx, int sy)
+{
+ desktop->copyRect(r,sx,sy);
+}
+void CConn::setCursor(int width, int height, const Point& hotspot,
+ void* data, void* mask)
+{
+// desktop->setCursor(width, height, hotspot, data, mask);
+}
+
+////////////////////// Internal methods //////////////////////
+
+void CConn::resizeFramebuffer()
+{
+/*
+ if (!desktop)
+ return;
+ if ((desktop->width() == cp.width) && (desktop->height() == cp.height))
+ return;
+
+ desktop->resize(cp.width, cp.height);
+*/
+}
+
+// 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 = fullColour;
+ int newQualityLevel = qualityLevel;
+
+ // Always use Tight
+ if (currentEncoding != encodingTight) {
+ currentEncoding = encodingTight;
+ encodingChange = true;
+ }
+
+ // Check that we have a decent bandwidth measurement
+ if ((kbitsPerSecond == 0) || (timeWaited < 10000))
+ return;
+
+ // Select appropriate quality level
+ if (!noJpeg) {
+ if (kbitsPerSecond > 16000)
+ newQualityLevel = 8;
+ else
+ newQualityLevel = 6;
+
+ if (newQualityLevel != qualityLevel) {
+ vlog.info(_("Throughput %d kbit/s - changing to quality %d"),
+ kbitsPerSecond, newQualityLevel);
+ cp.qualityLevel = newQualityLevel;
+ qualityLevel.setParam(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 != fullColour) {
+ vlog.info(_("Throughput %d kbit/s - full color is now %s"),
+ kbitsPerSecond,
+ newFullColour ? _("enabled") : _("disabled"));
+ fullColour.setParam(newFullColour);
+ formatChange = true;
+ }
+}
+
+// checkEncodings() sends a setEncodings message if one is needed.
+void CConn::checkEncodings()
+{
+ if (encodingChange && writer()) {
+ vlog.info(_("Using %s encoding"),encodingName(currentEncoding));
+ writer()->writeSetEncodings(currentEncoding, true);
+ encodingChange = false;
+ }
+}
+
+// requestNewUpdate() requests an update from the server, having set the
+// format and encoding appropriately.
+void CConn::requestNewUpdate()
+{
+ if (formatChange) {
+ PixelFormat pf;
+
+ /* Catch incorrect requestNewUpdate calls */
+ assert(pendingUpdate == false);
+
+ if (fullColour) {
+ pf = fullColourPF;
+ } else {
+ if (lowColourLevel == 0)
+ pf = PixelFormat(8,3,0,1,1,1,1,2,1,0);
+ else if (lowColourLevel == 1)
+ pf = PixelFormat(8,6,0,1,3,3,3,4,2,0);
+ else
+ pf = PixelFormat(8,8,0,0);
+ }
+ char str[256];
+ pf.print(str, 256);
+ vlog.info(_("Using pixel format %s"),str);
+ desktop->setServerPF(pf);
+ cp.setPF(pf);
+ writer()->writeSetPixelFormat(pf);
+ }
+ checkEncodings();
+ writer()->writeFramebufferUpdateRequest(Rect(0, 0, cp.width, cp.height),
+ !formatChange);
+ formatChange = false;
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2009-2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#ifndef __CCONN_H__
+#define __CCONN_H__
+
+#include <rfb/CConnection.h>
+#include <network/Socket.h>
+
+#include "DesktopWindow.h"
+
+class CConn : public rfb::CConnection,
+ public rdr::FdInStreamBlockCallback
+{
+public:
+ CConn(const char* vncServerName);
+ ~CConn();
+
+ // FdInStreamBlockCallback methods
+ void blockCallback();
+
+ // Callback when socket is ready (or broken)
+ static void socketEvent(int fd, void *data);
+
+ // 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 autoSelectFormatAndEncoding();
+ void checkEncodings();
+ void requestNewUpdate();
+
+private:
+ char* serverHost;
+ int serverPort;
+ network::Socket* sock;
+
+ DesktopWindow *desktop;
+
+ rfb::PixelFormat serverPF;
+ rfb::PixelFormat fullColourPF;
+
+ int currentEncoding, lastServerEncoding;
+
+ bool formatChange;
+ bool encodingChange;
+
+ bool firstUpdate;
+ bool pendingUpdate;
+};
+
+#endif
--- /dev/null
+include_directories(${FLTK_INCLUDE_DIR})
+
+include_directories(${CMAKE_SOURCE_DIR}/common)
+
+add_executable(vncviewer
+ CConn.cxx
+ DesktopWindow.cxx
+ UserDialog.cxx
+ parameters.cxx
+ vncviewer.cxx)
+
+target_link_libraries(vncviewer rfb network rdr os Xregion ${FLTK_LIBRARIES})
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <FL/fl_draw.H>
+
+#include <rfb/CMsgWriter.h>
+#include <rfb/LogWriter.h>
+
+#include "DesktopWindow.h"
+#include "CConn.h"
+#include "i18n.h"
+#include "parameters.h"
+
+using namespace rfb;
+
+extern void exit_vncviewer();
+
+static rfb::LogWriter vlog("DesktopWindow");
+
+DesktopWindow::DesktopWindow(int w, int h, const char *name,
+ const rfb::PixelFormat& serverPF,
+ CConn* cc_)
+ : Fl_Window(w, h), cc(cc_), frameBuffer(NULL), pixelTrans(NULL)
+{
+ callback(handleClose, this);
+
+ setName(name);
+
+ frameBuffer = new ManagedPixelBuffer(getPreferredPF(), w, h);
+ assert(frameBuffer);
+
+ setServerPF(serverPF);
+
+ show();
+}
+
+
+DesktopWindow::~DesktopWindow()
+{
+ delete frameBuffer;
+
+ if (pixelTrans)
+ delete pixelTrans;
+}
+
+
+void DesktopWindow::setServerPF(const rfb::PixelFormat& pf)
+{
+ if (pixelTrans)
+ delete pixelTrans;
+ pixelTrans = NULL;
+
+ if (pf.equal(getPreferredPF()))
+ return;
+
+ pixelTrans = new PixelTransformer();
+ pixelTrans->init(pf, &colourMap, getPreferredPF());
+}
+
+
+const rfb::PixelFormat &DesktopWindow::getPreferredPF()
+{
+ static PixelFormat prefPF(32, 24, false, true, 255, 255, 255, 0, 8, 16);
+
+ return prefPF;
+}
+
+
+// Cursor stuff
+
+void DesktopWindow::setCursor(int width, int height, const Point& hotspot,
+ void* data, void* mask)
+{
+}
+
+
+void DesktopWindow::setName(const char *name)
+{
+ CharArray windowNameStr;
+ windowNameStr.replaceBuf(new char[256]);
+
+ snprintf(windowNameStr.buf, 256, _("TigerVNC: %.240s"), name);
+
+ copy_label(windowNameStr.buf);
+}
+
+// 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)
+{
+ for (int i = 0; i < nColours; i++)
+ colourMap.set(firstColour+i, rgbs[i*3], rgbs[i*3+1], rgbs[i*3+2]);
+
+ if (!Fl::has_timeout(handleColourMap, this))
+ Fl::add_timeout(0.100, handleColourMap, this);
+}
+
+
+// Copy the areas of the framebuffer that have been changed (damaged)
+// to the displayed window.
+
+void DesktopWindow::updateWindow()
+{
+ Rect r;
+
+ Fl::remove_timeout(handleUpdateTimeout, this);
+
+ r = damage.get_bounding_rect();
+ Fl_Window::damage(FL_DAMAGE_USER1, r.tl.x, r.tl.y, r.width(), r.height());
+
+ damage.clear();
+}
+
+
+void DesktopWindow::draw()
+{
+ int X, Y, W, H;
+
+ int pixel_bytes, stride_bytes;
+ const uchar *buf_start;
+
+ // Check what actually needs updating
+ fl_clip_box(0, 0, w(), h(), X, Y, W, H);
+ if ((W == 0) || (H == 0))
+ return;
+
+ pixel_bytes = frameBuffer->getPF().bpp/8;
+ stride_bytes = pixel_bytes * frameBuffer->getStride();
+ buf_start = frameBuffer->data +
+ pixel_bytes * X +
+ stride_bytes * Y;
+
+ // FIXME: Check how efficient this thing really is
+ fl_draw_image(buf_start, X, Y, W, H, pixel_bytes, stride_bytes);
+}
+
+
+void DesktopWindow::handleUpdateTimeout(void *data)
+{
+ DesktopWindow *self = (DesktopWindow *)data;
+
+ assert(self);
+
+ self->updateWindow();
+}
+
+
+void DesktopWindow::handleColourMap(void *data)
+{
+ DesktopWindow *self = (DesktopWindow *)data;
+
+ assert(self);
+
+ if (self->pixelTrans != NULL)
+ self->pixelTrans->setColourMapEntries(0, 0);
+
+ self->Fl_Window::damage(FL_DAMAGE_ALL);
+}
+
+void DesktopWindow::handleClose(Fl_Widget *wnd, void *data)
+{
+ exit_vncviewer();
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#ifndef __DESKTOPWINDOW_H__
+#define __DESKTOPWINDOW_H__
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+
+#include <rfb/Rect.h>
+#include <rfb/Region.h>
+#include <rfb/Timer.h>
+#include <rfb/PixelBuffer.h>
+#include <rfb/PixelTransformer.h>
+
+class CConn;
+
+class DesktopWindow : public Fl_Window {
+public:
+
+ DesktopWindow(int w, int h, const char *name,
+ const rfb::PixelFormat& serverPF, CConn* cc_);
+ ~DesktopWindow();
+
+ // PixelFormat of incoming write operations
+ void setServerPF(const rfb::PixelFormat& pf);
+ // Most efficient format (from DesktopWindow's point of view)
+ const rfb::PixelFormat &getPreferredPF();
+
+ // setCursor() sets the shape of the local cursor
+ void setCursor(int width, int height, const rfb::Point& hotspot,
+ void* data, void* mask);
+
+ // Flush updates to screen
+ void updateWindow();
+
+ // Methods forwarded from CConn
+ void setName(const char *name);
+
+ void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs);
+
+ void fillRect(const rfb::Rect& r, rfb::Pixel pix) {
+ if (pixelTrans) {
+ rfb::Pixel pix2;
+ pixelTrans->translatePixels(&pix, &pix2, 1);
+ pix = pix2;
+ }
+
+ frameBuffer->fillRect(r, pix);
+ damageRect(r);
+ }
+ void imageRect(const rfb::Rect& r, void* pixels) {
+ if (pixelTrans)
+ pixelTrans->translateRect(pixels, r.width(),
+ rfb::Rect(0, 0, r.width(), r.height()),
+ frameBuffer->data, frameBuffer->getStride(),
+ r.tl);
+ else
+ frameBuffer->imageRect(r, pixels);
+ damageRect(r);
+ }
+ void copyRect(const rfb::Rect& r, int srcX, int srcY) {
+ frameBuffer->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY));
+ damageRect(r);
+ }
+
+ // Fl_Window callback methods
+ void draw();
+
+private:
+
+ void damageRect(const rfb::Rect& r) {
+ damage.assign_union(rfb::Region(r));
+ if (!Fl::has_timeout(handleUpdateTimeout, this))
+ Fl::add_timeout(0.100, handleUpdateTimeout, this);
+ };
+
+ static void handleUpdateTimeout(void *data);
+ static void handleColourMap(void *data);
+
+ static void handleClose(Fl_Widget *wnd, void *data);
+
+private:
+ CConn* cc;
+
+ rfb::ManagedPixelBuffer* frameBuffer;
+
+ rfb::PixelTransformer *pixelTrans;
+ rfb::SimpleColourMap colourMap;
+
+ rfb::Region damage;
+};
+
+#endif
--- /dev/null
+/* Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <FL/fl_ask.H>
+
+#include <rfb/util.h>
+#include <rfb/Password.h>
+#include <rfb/Exception.h>
+
+#include "i18n.h"
+#include "parameters.h"
+#include "UserDialog.h"
+
+using namespace rfb;
+
+UserDialog::UserDialog()
+{
+}
+
+UserDialog::~UserDialog()
+{
+}
+
+void UserDialog::getUserPasswd(char** user, char** password)
+{
+ CharArray passwordFileStr(passwordFile.getData());
+
+ assert(password);
+
+ if (!user && passwordFileStr.buf[0]) {
+ ObfuscatedPasswd obfPwd(256);
+ FILE* fp;
+
+ fp = fopen(passwordFileStr.buf, "r");
+ if (!fp)
+ throw rfb::Exception(_("Opening password file failed"));
+
+ obfPwd.length = fread(obfPwd.buf, 1, obfPwd.length, fp);
+ fclose(fp);
+
+ PlainPasswd passwd(obfPwd);
+ *password = passwd.takeBuf();
+
+ return;
+ }
+
+ if (!user) {
+ *password = strDup(fl_password(_("VNC authentication"), ""));
+ if (!*password)
+ throw rfb::Exception(_("Authentication cancelled"));
+
+ return;
+ }
+
+ fl_alert(_("NOT IMPLEMENTED!"));
+
+ *user = strDup("");
+ *password = strDup("");
+}
+
+bool UserDialog::showMsgBox(int flags, const char* title, const char* text)
+{
+ fl_message_title(title);
+ fl_message(text);
+
+ return false;
+}
--- /dev/null
+/* Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#ifndef __USERDIALOG_H__
+#define __USERDIALOG_H__
+
+#include <rfb/UserPasswdGetter.h>
+#include <rfb/UserMsgBox.h>
+
+class UserDialog : public rfb::UserPasswdGetter,
+ public rfb::UserMsgBox
+{
+public:
+ UserDialog();
+ ~UserDialog();
+
+ // UserPasswdGetter callbacks
+
+ void getUserPasswd(char** user, char** password);
+
+ // UserMsgBox callbacks
+
+ bool showMsgBox(int flags, const char* title, const char* text);
+};
+
+#endif
--- /dev/null
+/* 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 */
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#ifndef _I18N_H
+#define _I18N_H 1
+
+#include "gettext.h"
+
+#define _(String) gettext (String)
+#define gettext_noop(String) String
+#define N_(String) gettext_noop (String)
+
+#endif /* _I18N_H */
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#include "parameters.h"
+
+using namespace rfb;
+
+IntParameter pointerEventInterval("PointerEventInterval",
+ "Time in milliseconds to rate-limit"
+ " successive pointer events", 0);
+BoolParameter useLocalCursor("UseLocalCursor",
+ "Render the mouse cursor locally", true);
+BoolParameter dotWhenNoCursor("DotWhenNoCursor",
+ "Show the dot cursor when the server sends an "
+ "invisible cursor", true);
+
+StringParameter passwordFile("PasswordFile",
+ "Password file for VNC authentication", "");
+AliasParameter passwd("passwd", "Alias for PasswordFile", &passwordFile);
+
+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 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);
+
+BoolParameter fullScreen("FullScreen", "Full screen mode", false);
+StringParameter desktopSize("DesktopSize",
+ "Reconfigure desktop size on the server on "
+ "connect (if possible)", "");
+
+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 menuKey("MenuKey", "The key which brings up the popup menu",
+ "F8");
+
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+#ifndef __PARAMETERS_H__
+#define __PARAMETERS_H__
+
+#include <rfb/Configuration.h>
+
+extern rfb::IntParameter pointerEventInterval;
+extern rfb::BoolParameter useLocalCursor;
+extern rfb::BoolParameter dotWhenNoCursor;
+
+extern rfb::StringParameter passwordFile;
+
+extern rfb::BoolParameter autoSelect;
+extern rfb::BoolParameter fullColour;
+extern rfb::AliasParameter fullColourAlias;
+extern rfb::IntParameter lowColourLevel;
+extern rfb::AliasParameter lowColourLevelAlias;
+extern rfb::StringParameter preferredEncoding;
+extern rfb::BoolParameter customCompressLevel;
+extern rfb::IntParameter compressLevel;
+extern rfb::BoolParameter noJpeg;
+extern rfb::IntParameter qualityLevel;
+
+extern rfb::BoolParameter fullScreen;
+extern rfb::StringParameter desktopSize;
+
+extern rfb::BoolParameter viewOnly;
+extern rfb::BoolParameter shared;
+
+extern rfb::BoolParameter acceptClipboard;
+extern rfb::BoolParameter sendClipboard;
+extern rfb::BoolParameter sendPrimary;
+
+extern rfb::StringParameter menuKey;
+
+#endif
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011 Pierre Ossman <ossman@cendio.se> 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <locale.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <direct.h>
+#define mkdir(path, mode) _mkdir(path)
+#endif
+
+#include <os/os.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/SecurityClient.h>
+#include <rfb/Security.h>
+#ifdef HAVE_GNUTLS
+#include <rfb/CSecurityTLS.h>
+#endif
+#include <rfb/LogWriter.h>
+#include <rfb/Timer.h>
+#include <network/TcpSocket.h>
+
+#include <FL/Fl.H>
+#include <FL/Fl_Widget.H>
+#include <FL/fl_ask.H>
+
+#include "i18n.h"
+#include "parameters.h"
+#include "CConn.h"
+#include "UserDialog.h"
+
+rfb::LogWriter vlog("main");
+
+using namespace network;
+using namespace rfb;
+using namespace std;
+
+char aboutText[1024];
+
+static bool exitMainloop = false;
+
+void exit_vncviewer()
+{
+ exitMainloop = true;
+}
+
+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);
+}
+
+static void init_fltk()
+{
+ // Basic text size (10pt @ 96 dpi => 13px)
+ FL_NORMAL_SIZE = 13;
+
+#ifndef __APPLE__
+ // Select a FLTK scheme and background color that looks somewhat
+ // close to modern Linux and Windows.
+ Fl::scheme("gtk+");
+ Fl::background(220, 220, 220);
+#else
+ // On Mac OS X there is another scheme that fits better though.
+ Fl::scheme("plastic");
+#endif
+
+ // This makes the "icon" in dialogs rounded, which fits better
+ // with the above schemes.
+ fl_message_icon()->box(FL_UP_BOX);
+
+ // Turn off the annoying behaviour where popups track the mouse.
+ fl_message_hotspot(false);
+
+ // Avoid empty titles for popups
+ fl_message_title_default(_("TigerVNC Viewer"));
+
+#ifdef WIN32
+ // Most "normal" Windows apps use this font for UI elements.
+ Fl::set_font(FL_HELVETICA, "Tahoma");
+#endif
+
+ // FLTK exposes these so that we can translate them.
+ fl_no = _("No");
+ fl_yes = _("Yes");
+ fl_ok = _("OK");
+ fl_cancel = _("Cancel");
+ fl_close = _("Close");
+}
+
+static void mkvnchomedir()
+{
+ // 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;
+ }
+}
+
+static void usage(const char *programName)
+{
+ fprintf(stderr,
+ "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
+ " %s [parameters] -listen [port] [parameters]\n",
+ programName, programName);
+ fprintf(stderr,"\n"
+ "Parameters can be turned on with -<param> or off with -<param>=0\n"
+ "Parameters which take a value can be specified as "
+ "-<param> <value>\n"
+ "Other valid forms are <param>=<value> -<param>=<value> "
+ "--<param>=<value>\n"
+ "Parameter names are case-insensitive. The parameters are:\n\n");
+ Configuration::listParams(79, 14);
+ exit(1);
+}
+
+int main(int argc, char** argv)
+{
+ char* vncServerName = 0;
+ UserDialog dlg;
+
+ const char englishAbout[] = N_("TigerVNC Viewer version %s\n"
+ "Copyright (C) 2002-2005 RealVNC Ltd.\n"
+ "Copyright (C) 2000-2006 TightVNC Group\n"
+ "Copyright (C) 2004-2009 Peter Astrand for Cendio AB\n"
+ "See http://www.tigervnc.org for information on TigerVNC.");
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE_NAME, LOCALEDIR);
+ textdomain(PACKAGE_NAME);
+
+ rfb::SecurityClient::setDefaults();
+
+ // Write about text to console, still using normal locale codeset
+ snprintf(aboutText, sizeof(aboutText),
+ gettext(englishAbout), PACKAGE_VERSION);
+ 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, "UTF-8");
+ bind_textdomain_codeset("libc", "UTF-8");
+
+ // Re-create the aboutText for the GUI, now using GUI codeset
+ snprintf(aboutText, sizeof(aboutText),
+ gettext(englishAbout), PACKAGE_VERSION);
+
+ rfb::initStdIOLoggers();
+ rfb::LogWriter::setLogParams("*:stderr:30");
+
+#ifdef SIGHUP
+ signal(SIGHUP, CleanupSignalHandler);
+#endif
+ signal(SIGINT, CleanupSignalHandler);
+ signal(SIGTERM, CleanupSignalHandler);
+
+ init_fltk();
+
+ 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(argv[0]);
+ }
+
+ vncServerName = argv[i];
+ }
+
+ 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());
+ }
+
+ mkvnchomedir();
+
+ CSecurity::upg = &dlg;
+#ifdef HAVE_GNUTLS
+ CSecurityTLS::msg = &dlg;
+#endif
+
+ CConn cc(vncServerName);
+
+ while (!exitMainloop) {
+ int next_timer;
+
+ next_timer = Timer::checkTimeouts();
+ if (next_timer == 0)
+ next_timer = INT_MAX;
+
+ if (Fl::wait((double)next_timer / 1000.0) < 0.0) {
+ vlog.error(_("Internal FLTK error. Exiting."));
+ break;
+ }
+ }
+
+ return 0;
+}
configure_file(resdefs.h.cmake.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)