aboutsummaryrefslogtreecommitdiffstats
path: root/win/vncviewer/CConn.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'win/vncviewer/CConn.cxx')
-rw-r--r--win/vncviewer/CConn.cxx863
1 files changed, 0 insertions, 863 deletions
diff --git a/win/vncviewer/CConn.cxx b/win/vncviewer/CConn.cxx
deleted file mode 100644
index b067134a..00000000
--- a/win/vncviewer/CConn.cxx
+++ /dev/null
@@ -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);
-}
-