aboutsummaryrefslogtreecommitdiffstats
path: root/vncviewer_unix/CConn.cxx
diff options
context:
space:
mode:
authorConstantin Kaplinsky <const@tightvnc.com>2006-05-25 05:36:48 +0000
committerConstantin Kaplinsky <const@tightvnc.com>2006-05-25 05:36:48 +0000
commitd1e4e901e29d8ef27a6583648c7148b1a5b2facf (patch)
treefb34ead4006e43ac22aa6368c6a622320f234261 /vncviewer_unix/CConn.cxx
parent729598cb00d791bbdfe23ebe0023d3a1c3962f83 (diff)
downloadtigervnc-d1e4e901e29d8ef27a6583648c7148b1a5b2facf.tar.gz
tigervnc-d1e4e901e29d8ef27a6583648c7148b1a5b2facf.zip
Migrating to new directory structure adopted from the RealVNC's source tree. Windows part should be complete. For the Unix part, more changes will follow.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@592 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'vncviewer_unix/CConn.cxx')
-rw-r--r--vncviewer_unix/CConn.cxx749
1 files changed, 0 insertions, 749 deletions
diff --git a/vncviewer_unix/CConn.cxx b/vncviewer_unix/CConn.cxx
deleted file mode 100644
index eabe33a0..00000000
--- a/vncviewer_unix/CConn.cxx
+++ /dev/null
@@ -1,749 +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.cxx
-//
-
-#include <unistd.h>
-#include "CConn.h"
-#include <rfb/CMsgWriter.h>
-#include <rfb/encodings.h>
-#include <rfb/secTypes.h>
-#include <rfb/CSecurityNone.h>
-#include <rfb/CSecurityVncAuth.h>
-#include <rfb/Hostname.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
-#include <rfb/Password.h>
-#include <network/TcpSocket.h>
-
-#include "TXViewport.h"
-#include "DesktopWindow.h"
-#include "ServerDialog.h"
-#include "PasswdDialog.h"
-#include "parameters.h"
-
-using namespace rfb;
-
-static rfb::LogWriter vlog("CConn");
-
-IntParameter debugDelay("DebugDelay","Milliseconds to display inverted "
- "pixel data - a debugging feature", 0);
-
-StringParameter menuKey("MenuKey", "The key which brings up the popup menu",
- "F8");
-StringParameter windowName("name", "The X window name", "");
-
-CConn::CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_,
- char* vncServerName, bool reverse)
- : dpy(dpy_), argc(argc_),
- argv(argv_), serverHost(0), serverPort(0), sock(sock_), viewport(0),
- desktop(0), desktopEventHandler(0),
- currentEncoding(encodingZRLE), lastServerEncoding((unsigned int)-1),
- fullColour(::fullColour),
- autoSelect(::autoSelect), shared(::shared), formatChange(false),
- encodingChange(false), sameMachine(false), fullScreen(::fullScreen),
- ctrlDown(false), altDown(false),
- menuKeysym(0), menu(dpy, this), options(dpy, this), about(dpy), info(dpy),
- reverseConnection(reverse)
-{
- CharArray menuKeyStr(menuKey.getData());
- menuKeysym = XStringToKeysym(menuKeyStr.buf);
-
- setShared(shared);
- addSecType(secTypeNone);
- addSecType(secTypeVncAuth);
- CharArray encStr(preferredEncoding.getData());
- int encNum = encodingNum(encStr.buf);
- if (encNum != -1) {
- currentEncoding = encNum;
- }
- cp.supportsDesktopResize = true;
- cp.supportsLocalCursor = useLocalCursor;
- cp.customCompressLevel = customCompressLevel;
- cp.compressLevel = compressLevel;
- cp.noJpeg = noJpeg;
- cp.qualityLevel = qualityLevel;
- initMenu();
-
- if (sock) {
- char* name = sock->getPeerEndpoint();
- vlog.info("Accepted connection from %s", name);
- if (name) free(name);
- } else {
- if (vncServerName) {
- getHostAndPort(vncServerName, &serverHost, &serverPort);
- } else {
- ServerDialog dlg(dpy, &options, &about);
- if (!dlg.show() || dlg.entry.getText()[0] == 0) {
- exit(1);
- }
- getHostAndPort(dlg.entry.getText(), &serverHost, &serverPort);
- }
-
- sock = new network::TcpSocket(serverHost, serverPort);
- vlog.info("connected to host %s port %d", serverHost, serverPort);
- }
-
- sameMachine = sock->sameMachine();
- sock->inStream().setBlockCallback(this);
- setServerName(sock->getPeerEndpoint());
- setStreams(&sock->inStream(), &sock->outStream());
- initialiseProtocol();
-}
-
-CConn::~CConn() {
- free(serverHost);
- delete desktop;
- delete viewport;
- delete sock;
-}
-
-// deleteWindow() is called when the user closes the desktop or menu windows.
-
-void CConn::deleteWindow(TXWindow* w) {
- if (w == &menu) {
- menu.unmap();
- } else if (w == viewport) {
- exit(1);
- }
-}
-
-// handleEvent() filters all events on the desktop and menu. Most are passed
-// straight through. The exception is the F8 key. When pressed on the
-// desktop, it is used to bring up the menu. An F8 press or release on the
-// menu is passed through as if it were on the desktop.
-
-void CConn::handleEvent(TXWindow* w, XEvent* ev)
-{
- KeySym ks;
- char str[256];
-
- switch (ev->type) {
- case KeyPress:
- case KeyRelease:
- XLookupString(&ev->xkey, str, 256, &ks, NULL);
- if (ks == menuKeysym && (ev->xkey.state & (ShiftMask|ControlMask)) == 0) {
- if (w == desktop && ev->type == KeyPress) {
- showMenu(ev->xkey.x_root, ev->xkey.y_root);
- break;
- } else if (w == &menu) {
- if (ev->type == KeyPress) menu.unmap();
- desktopEventHandler->handleEvent(w, ev);
- break;
- }
- }
- // drop through
-
- default:
- if (w == desktop) desktopEventHandler->handleEvent(w, ev);
- else if (w == &menu) menuEventHandler->handleEvent(w, ev);
- }
-}
-
-// blockCallback() is called when reading from the socket would block. We
-// process X events until the socket is ready for reading again.
-
-void CConn::blockCallback() {
- fd_set rfds;
- do {
- struct timeval tv;
- struct timeval* tvp = 0;
-
- // Process any incoming X events
- TXWindow::handleXEvents(dpy);
-
- // Process expired timers and get the time until the next one
- int timeoutMs = Timer::checkTimeouts();
- if (timeoutMs) {
- tv.tv_sec = timeoutMs / 1000;
- tv.tv_usec = (timeoutMs % 1000) * 1000;
- tvp = &tv;
- }
-
- // If there are X requests pending then poll, don't wait!
- if (XPending(dpy)) {
- tv.tv_usec = tv.tv_sec = 0;
- tvp = &tv;
- }
-
- // Wait for X events, VNC traffic, or the next timer expiry
- FD_ZERO(&rfds);
- FD_SET(ConnectionNumber(dpy), &rfds);
- FD_SET(sock->getFd(), &rfds);
- int n = select(FD_SETSIZE, &rfds, 0, 0, tvp);
- if (n < 0) throw rdr::SystemException("select",errno);
- } while (!(FD_ISSET(sock->getFd(), &rfds)));
-}
-
-
-// getPasswd() is called by the CSecurity object when it needs us to read a
-// password from the user.
-
-void CConn::getUserPasswd(char** user, char** password)
-{
- CharArray passwordFileStr(passwordFile.getData());
- if (!user && passwordFileStr.buf[0]) {
- FILE* fp = fopen(passwordFileStr.buf, "r");
- if (!fp) throw rfb::Exception("Opening password file failed");
- ObfuscatedPasswd obfPwd(256);
- obfPwd.length = fread(obfPwd.buf, 1, obfPwd.length, fp);
- fclose(fp);
- PlainPasswd passwd(obfPwd);
- *password = passwd.takeBuf();
- return;
- }
-
- const char* secType = secTypeName(getCurrentCSecurity()->getType());
- const char* titlePrefix = _("VNC authentication");
- unsigned int titleLen = strlen(titlePrefix) + strlen(secType) + 4;
- CharArray title(titleLen);
- snprintf(title.buf, titleLen, "%s [%s]", titlePrefix, secType);
- PasswdDialog dlg(dpy, title.buf, !user);
- if (!dlg.show()) throw rfb::Exception("Authentication cancelled");
- if (user)
- *user = strDup(dlg.userEntry.getText());
- *password = strDup(dlg.passwdEntry.getText());
-}
-
-
-// CConnection callback methods
-
-// getCSecurity() gets the appropriate CSecurity object for the security
-// types which we support.
-CSecurity* CConn::getCSecurity(int secType) {
- switch (secType) {
- case secTypeNone:
- return new CSecurityNone();
- case secTypeVncAuth:
- return new CSecurityVncAuth(this);
- default:
- throw rfb::Exception("Unsupported secType?");
- }
-}
-
-// 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 = true;
- }
-
- serverPF = cp.pf();
- desktop = new DesktopWindow(dpy, cp.width, cp.height, serverPF, this);
- desktopEventHandler = desktop->setEventHandler(this);
- desktop->addEventMask(KeyPressMask | KeyReleaseMask);
- fullColourPF = desktop->getPF();
- if (!serverPF.trueColour)
- fullColour = true;
- recreateViewport();
- 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);
- if (desktop) {
- desktop->resize(w, h);
- recreateViewport();
- }
-}
-
-// 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() {
- if (debugDelay != 0) {
- XSync(dpy, False);
- struct timeval tv;
- tv.tv_sec = debugDelay / 1000;
- tv.tv_usec = (debugDelay % 1000) * 1000;
- select(0, 0, 0, 0, &tv);
- std::list<rfb::Rect>::iterator i;
- for (i = debugRects.begin(); i != debugRects.end(); i++) {
- desktop->invertRect(*i);
- }
- debugRects.clear();
- }
- desktop->framebufferUpdateEnd();
- if (autoSelect)
- autoSelectFormatAndEncoding();
- requestNewUpdate();
-}
-
-// 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() { XBell(dpy, 0); }
-
-void CConn::serverCutText(const char* str, int 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, unsigned int encoding)
-{
- sock->inStream().startTiming();
- if (encoding != encodingCopyRect) {
- lastServerEncoding = encoding;
- }
-}
-
-void CConn::endRect(const Rect& r, unsigned int encoding)
-{
- sock->inStream().stopTiming();
- if (debugDelay != 0) {
- desktop->invertRect(r);
- debugRects.push_back(r);
- }
-}
-
-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);
-}
-
-
-// Menu stuff - menuSelect() is called when the user selects a menu option.
-
-enum { ID_OPTIONS, ID_INFO, ID_FULLSCREEN, ID_REFRESH, ID_F8, ID_CTRLALTDEL,
- ID_ABOUT, ID_DISMISS, ID_EXIT, ID_NEWCONN, ID_CTRL, ID_ALT };
-
-void CConn::initMenu() {
- menuEventHandler = menu.setEventHandler(this);
- menu.addEventMask(KeyPressMask | KeyReleaseMask);
- menu.addEntry(_("Exit viewer"), ID_EXIT);
- menu.addEntry(0, 0);
- menu.addEntry(_("Full screen"), ID_FULLSCREEN);
- menu.check(ID_FULLSCREEN, fullScreen);
- menu.addEntry(0, 0);
- menu.addEntry(_("Ctrl"), ID_CTRL);
- menu.addEntry(_("Alt"), ID_ALT);
- CharArray menuKeyStr(menuKey.getData());
- CharArray sendMenuKey(64);
- snprintf(sendMenuKey.buf, 64, _("Send %s"), menuKeyStr.buf);
- menu.addEntry(sendMenuKey.buf, ID_F8);
- menu.addEntry(_("Send Ctrl-Alt-Del"), ID_CTRLALTDEL);
- menu.addEntry(0, 0);
- menu.addEntry(_("Refresh screen"), ID_REFRESH);
- menu.addEntry(0, 0);
- menu.addEntry(_("New connection..."), ID_NEWCONN);
- menu.addEntry(_("Options..."), ID_OPTIONS);
- menu.addEntry(_("Connection info..."), ID_INFO);
- menu.addEntry(_("About VNCviewer..."), ID_ABOUT);
- menu.addEntry(0, 0);
- menu.addEntry(_("Dismiss menu"), ID_DISMISS);
- menu.toplevel(_("VNC Menu"), this);
- menu.setBorderWidth(1);
-}
-
-void CConn::showMenu(int x, int y) {
- menu.check(ID_FULLSCREEN, fullScreen);
- if (x + menu.width() > viewport->width())
- x = viewport->width() - menu.width();
- if (y + menu.height() > viewport->height())
- y = viewport->height() - menu.height();
- menu.move(x, y);
- menu.raise();
- menu.map();
-}
-
-void CConn::menuSelect(long id, TXMenu* m) {
- switch (id) {
- case ID_NEWCONN:
- {
- menu.unmap();
- if (fullScreen) {
- fullScreen = false;
- if (viewport) recreateViewport();
- }
- int pid = fork();
- if (pid < 0) { perror("fork"); exit(1); }
- if (pid == 0) {
- delete sock;
- close(ConnectionNumber(dpy));
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 200*1000;
- select(0, 0, 0, 0, &tv);
- execlp(programName, programName, 0);
- perror("execlp"); exit(1);
- }
- break;
- }
- case ID_OPTIONS:
- menu.unmap();
- options.show();
- break;
- case ID_INFO:
- {
- menu.unmap();
- char pfStr[100];
- char spfStr[100];
- cp.pf().print(pfStr, 100);
- serverPF.print(spfStr, 100);
- int secType = getCurrentCSecurity()->getType();
- char infoText[1024];
- snprintf(infoText, sizeof(infoText),
- _("Desktop name: %.80s\n"
- "Host: %.80s port: %d\n"
- "Size: %d x %d\n"
- "Pixel format: %s\n"
- "(server default %s)\n"
- "Requested encoding: %s\n"
- "Last used encoding: %s\n"
- "Line speed estimate: %d kbit/s\n"
- "Protocol version: %d.%d\n"
- "Security method: %s\n"),
- cp.name(), serverHost, serverPort, cp.width, cp.height,
- pfStr, spfStr, encodingName(currentEncoding),
- encodingName(lastServerEncoding),
- sock->inStream().kbitsPerSecond(),
- cp.majorVersion, cp.minorVersion,
- secTypeName(secType));
- info.setText(infoText);
- info.show();
- break;
- }
- case ID_FULLSCREEN:
- menu.unmap();
- fullScreen = !fullScreen;
- if (viewport) recreateViewport();
- break;
- case ID_REFRESH:
- menu.unmap();
- writer()->writeFramebufferUpdateRequest(Rect(0, 0, cp.width, cp.height),
- false);
- break;
- case ID_F8:
- menu.unmap();
- if (!viewOnly) {
- writer()->keyEvent(menuKeysym, true);
- writer()->keyEvent(menuKeysym, false);
- }
- break;
- case ID_CTRLALTDEL:
- menu.unmap();
- if (!viewOnly) {
- writer()->keyEvent(XK_Control_L, true);
- writer()->keyEvent(XK_Alt_L, true);
- writer()->keyEvent(XK_Delete, true);
- writer()->keyEvent(XK_Delete, false);
- writer()->keyEvent(XK_Alt_L, false);
- writer()->keyEvent(XK_Control_L, false);
- }
- break;
- case ID_CTRL:
- menu.unmap();
- if (!viewOnly) {
- ctrlDown = !ctrlDown;
- writer()->keyEvent(XK_Control_L, ctrlDown);
- menu.check(ID_CTRL, ctrlDown);
- }
- break;
- case ID_ALT:
- menu.unmap();
- if (!viewOnly) {
- altDown = !altDown;
- writer()->keyEvent(XK_Alt_L, altDown);
- menu.check(ID_ALT, altDown);
- }
- break;
- case ID_ABOUT:
- menu.unmap();
- about.show();
- break;
- case ID_DISMISS:
- menu.unmap();
- break;
- case ID_EXIT:
- exit(1);
- break;
- }
-}
-
-
-// OptionsDialogCallback. setOptions() sets the options dialog's checkboxes
-// etc to reflect our flags. getOptions() sets our flags according to the
-// options dialog's checkboxes.
-
-void CConn::setOptions() {
- char digit[2] = "0";
- options.autoSelect.checked(autoSelect);
- options.fullColour.checked(fullColour);
- options.veryLowColour.checked(!fullColour && lowColourLevel == 0);
- options.lowColour.checked(!fullColour && lowColourLevel == 1);
- options.mediumColour.checked(!fullColour && lowColourLevel == 2);
- options.tight.checked(currentEncoding == encodingTight);
- options.zrle.checked(currentEncoding == encodingZRLE);
- options.hextile.checked(currentEncoding == encodingHextile);
- options.raw.checked(currentEncoding == encodingRaw);
-
- options.customCompressLevel.checked(customCompressLevel);
- digit[0] = '0' + compressLevel;
- options.compressLevel.setText(digit);
- options.noJpeg.checked(!noJpeg);
- digit[0] = '0' + qualityLevel;
- options.qualityLevel.setText(digit);
-
- options.viewOnly.checked(viewOnly);
- options.acceptClipboard.checked(acceptClipboard);
- options.sendClipboard.checked(sendClipboard);
- options.sendPrimary.checked(sendPrimary);
- if (state() == RFBSTATE_NORMAL)
- options.shared.disabled(true);
- else
- options.shared.checked(shared);
- options.fullScreen.checked(fullScreen);
- options.useLocalCursor.checked(useLocalCursor);
- options.dotWhenNoCursor.checked(dotWhenNoCursor);
-}
-
-void CConn::getOptions() {
- autoSelect = options.autoSelect.checked();
- if (fullColour != options.fullColour.checked())
- formatChange = true;
- fullColour = options.fullColour.checked();
- if (!fullColour) {
- int newLowColourLevel = (options.veryLowColour.checked() ? 0 :
- options.lowColour.checked() ? 1 : 2);
- if (newLowColourLevel != lowColourLevel) {
- lowColourLevel.setParam(newLowColourLevel);
- formatChange = true;
- }
- }
- unsigned int newEncoding = (options.tight.checked() ? encodingTight :
- options.zrle.checked() ? encodingZRLE :
- options.hextile.checked() ? encodingHextile :
- encodingRaw);
- if (newEncoding != currentEncoding) {
- currentEncoding = newEncoding;
- encodingChange = true;
- }
-
- customCompressLevel.setParam(options.customCompressLevel.checked());
- if (cp.customCompressLevel != customCompressLevel) {
- cp.customCompressLevel = customCompressLevel;
- encodingChange = true;
- }
- compressLevel.setParam(options.compressLevel.getText());
- if (cp.compressLevel != compressLevel) {
- cp.compressLevel = compressLevel;
- encodingChange = true;
- }
- noJpeg.setParam(!options.noJpeg.checked());
- if (cp.noJpeg != noJpeg) {
- cp.noJpeg = noJpeg;
- encodingChange = true;
- }
- qualityLevel.setParam(options.qualityLevel.getText());
- if (cp.qualityLevel != qualityLevel) {
- cp.qualityLevel = qualityLevel;
- encodingChange = true;
- }
-
- viewOnly.setParam(options.viewOnly.checked());
- acceptClipboard.setParam(options.acceptClipboard.checked());
- sendClipboard.setParam(options.sendClipboard.checked());
- sendPrimary.setParam(options.sendPrimary.checked());
- shared = options.shared.checked();
- setShared(shared);
- if (fullScreen != options.fullScreen.checked()) {
- fullScreen = options.fullScreen.checked();
- if (viewport) recreateViewport();
- }
- useLocalCursor.setParam(options.useLocalCursor.checked());
- if (cp.supportsLocalCursor != useLocalCursor) {
- cp.supportsLocalCursor = useLocalCursor;
- encodingChange = true;
- if (desktop)
- desktop->resetLocalCursor();
- }
- dotWhenNoCursor.setParam(options.dotWhenNoCursor.checked());
- checkEncodings();
-}
-
-void CConn::recreateViewport()
-{
- TXViewport* oldViewport = viewport;
- viewport = new TXViewport(dpy, cp.width, cp.height);
- desktop->setViewport(viewport);
- CharArray windowNameStr(windowName.getData());
- if (!windowNameStr.buf[0]) {
- windowNameStr.replaceBuf(new char[256]);
- snprintf(windowNameStr.buf, 256, "VNC: %.240s", cp.name());
- }
- viewport->toplevel(windowNameStr.buf, this, argc, argv);
- viewport->setBumpScroll(fullScreen);
- XSetWindowAttributes attr;
- attr.override_redirect = fullScreen;
- XChangeWindowAttributes(dpy, viewport->win(), CWOverrideRedirect, &attr);
- XChangeWindowAttributes(dpy, menu.win(), CWOverrideRedirect, &attr);
- XChangeWindowAttributes(dpy, options.win(), CWOverrideRedirect, &attr);
- XChangeWindowAttributes(dpy, about.win(), CWOverrideRedirect, &attr);
- XChangeWindowAttributes(dpy, info.win(), CWOverrideRedirect, &attr);
- reconfigureViewport();
- menu.setTransientFor(viewport->win());
- viewport->map();
- if (fullScreen) {
- XGrabKeyboard(dpy, desktop->win(), True, GrabModeAsync, GrabModeAsync,
- CurrentTime);
- } else {
- XUngrabKeyboard(dpy, CurrentTime);
- }
- if (oldViewport) delete oldViewport;
-}
-
-void CConn::reconfigureViewport()
-{
- viewport->setMaxSize(cp.width, cp.height);
- if (fullScreen) {
- viewport->resize(DisplayWidth(dpy,DefaultScreen(dpy)),
- DisplayHeight(dpy,DefaultScreen(dpy)));
- } else {
- int w = cp.width;
- int h = cp.height;
- if (w + wmDecorationWidth >= DisplayWidth(dpy,DefaultScreen(dpy)))
- w = DisplayWidth(dpy,DefaultScreen(dpy)) - wmDecorationWidth;
- if (h + wmDecorationHeight >= DisplayHeight(dpy,DefaultScreen(dpy)))
- h = DisplayHeight(dpy,DefaultScreen(dpy)) - wmDecorationHeight;
-
- int x = (DisplayWidth(dpy,DefaultScreen(dpy)) - w - wmDecorationWidth) / 2;
- int y = (DisplayHeight(dpy,DefaultScreen(dpy)) - h - wmDecorationHeight)/2;
-
- CharArray geometryStr(geometry.getData());
- viewport->setGeometry(geometryStr.buf, x, y, w, h);
- }
-}
-
-// Note: The method below is duplicated in vncviewer/cview.cxx!
-
-// autoSelectFormatAndEncoding() chooses the format and encoding appropriate
-// to the connection speed:
-//
-// Above 16Mbps (timing for at least a second), switch to hextile
-// Otherwise, switch to ZRLE
-//
-// Above 256Kbps, use full colour mode
-//
-void CConn::autoSelectFormatAndEncoding()
-{
- int kbitsPerSecond = sock->inStream().kbitsPerSecond();
- unsigned int newEncoding = currentEncoding;
- bool newFullColour = fullColour;
- unsigned int timeWaited = sock->inStream().timeWaited();
-
- // Select best encoding
- if (kbitsPerSecond > 16000 && timeWaited >= 10000) {
- newEncoding = encodingHextile;
- } else {
- newEncoding = encodingZRLE;
- }
-
- if (newEncoding != currentEncoding) {
- vlog.info("Throughput %d kbit/s - changing to %s encoding",
- kbitsPerSecond, encodingName(newEncoding));
- currentEncoding = newEncoding;
- encodingChange = true;
- }
-
- if (kbitsPerSecond == 0) {
- return;
- }
-
- 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 = 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) {
- if (fullColour) {
- desktop->setPF(fullColourPF);
- } else {
- if (lowColourLevel == 0)
- desktop->setPF(PixelFormat(8,3,0,1,1,1,1,2,1,0));
- else if (lowColourLevel == 1)
- desktop->setPF(PixelFormat(8,6,0,1,3,3,3,4,2,0));
- else
- desktop->setPF(PixelFormat(8,8,0,0));
- }
- char str[256];
- desktop->getPF().print(str, 256);
- vlog.info("Using pixel format %s",str);
- cp.setPF(desktop->getPF());
- writer()->writeSetPixelFormat(cp.pf());
- }
- checkEncodings();
- writer()->writeFramebufferUpdateRequest(Rect(0, 0, cp.width, cp.height),
- !formatChange);
- formatChange = false;
-}