"Fossies" - the Fresh Open Source Software archive

Member "tvnserver-2.0.4/desktop-ipc/UpdateHandlerClient.cpp" of archive tvnserver-2.0.4-src.zip:


// Copyright (C) 2008, 2009, 2010 GlavSoft LLC.
// All rights reserved.
//
//-------------------------------------------------------------------------
// This file is part of the TightVNC software.  Please visit our Web site:
//
//                       http://www.tightvnc.com/
//
// 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 of the License, 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 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.
//-------------------------------------------------------------------------
//

#include "win-system/PipeClient.h"
#include "util/Log.h"
#include "UpdateHandlerClient.h"
#include "ReconnectException.h"

UpdateHandlerClient::UpdateHandlerClient(BlockingGate *forwGate,
                                         DesktopSrvDispatcher *dispatcher,
                                         UpdateListener *externalUpdateListener)
: DesktopServerProto(forwGate),
  m_externalUpdateListener(externalUpdateListener)
{
  dispatcher->registerNewHandle(UPDATE_DETECTED, this);

  PixelFormat termPF;
  Dimension termDim;
  getScreenProperties(&termPF, &termDim);

  m_backupFrameBuffer.setProperties(&termDim, &termPF);

  sendInit(m_forwGate);
}

UpdateHandlerClient::~UpdateHandlerClient()
{
}

void UpdateHandlerClient::onRequest(UINT8 reqCode, BlockingGate *backGate)
{
  switch (reqCode) {
  case UPDATE_DETECTED:
    m_externalUpdateListener->onUpdate();
    break;
  default:
    StringStorage errMess;
    errMess.format(_T("Unknown %d protocol code received from a pipe ")
                   _T("update detector"), (int)reqCode);
    throw Exception(errMess.getString());
    break;
  }
}

void UpdateHandlerClient::extract(UpdateContainer *updateContainer)
{
  updateContainer->clear();

  AutoLock al(m_forwGate);

  UpdateContainer updCont;
  try {
    Log::info(_T("UpdateHandlerClient: send EXTRACT_REQ"));
    m_forwGate->writeUInt8(EXTRACT_REQ); 

    updCont.screenSizeChanged = m_forwGate->readUInt8() != 0;

    if (updCont.screenSizeChanged) {
      Log::info(_T("UpdateHandlerClient: screen size changed"));
      PixelFormat oldPf = m_backupFrameBuffer.getPixelFormat();
      Dimension oldDim = m_backupFrameBuffer.getDimension();
      PixelFormat newPf;
      readPixelFormat(&newPf, m_forwGate);
      Dimension newDim = readDimension(m_forwGate);;
      if (!newPf.isEqualTo(&oldPf) || !newDim.isEqualTo(&oldDim)) {
        Log::info(_T("UpdateHandlerClient: new screen size: %dx%d"), newDim.width,
                                                                     newDim.height);
        Log::info(_T("UpdateHandlerClient: new pixel format: ")
                  _T("%d, %d, %d, %d, %d, %d, %d, %d"),
                                (int)newPf.bigEndian,
                                (int)newPf.bitsPerPixel,
                                (int)newPf.redMax,
                                (int)newPf.greenMax,
                                (int)newPf.blueMax,
                                (int)newPf.redShift,
                                (int)newPf.greenShift,
                                (int)newPf.blueShift);
        m_backupFrameBuffer.setProperties(&newDim, &newPf);
      }
    } else {
      readRegion(&updCont.videoRegion, m_forwGate);
      unsigned int countChangedRect = m_forwGate->readUInt32();
      Log::info(_T("UpdateHandlerClient: count changed rectangles = %u"), countChangedRect);
      for (unsigned int i = 0; i < countChangedRect; i++) {
        Rect r = readRect(m_forwGate);
        updCont.changedRegion.addRect(&r);
        readFrameBuffer(&m_backupFrameBuffer, &r, m_forwGate);
      }

      unsigned char hasCopyRect = m_forwGate->readUInt8();
      if (hasCopyRect) {
        Log::info(_T("UpdateHandlerClient: has \"CopyRect\""));
        updCont.copySrc = readPoint(m_forwGate);
        Rect r = readRect(m_forwGate);
        updCont.copiedRegion.addRect(&r);
        readFrameBuffer(&m_backupFrameBuffer, &r, m_forwGate);
      }

      updCont.cursorPosChanged = m_forwGate->readUInt8() != 0;
      if (updCont.cursorPosChanged) {
        Log::info(_T("UpdateHandlerClient: cursor pos changed"));
        updCont.cursorPos = readPoint(m_forwGate);
      }

      updCont.cursorShapeChanged = m_forwGate->readUInt8() != 0;
      if (updCont.cursorShapeChanged) {
        Log::info(_T("UpdateHandlerClient: cursor shape changed"));
        PixelFormat newPf = m_backupFrameBuffer.getPixelFormat();
        Dimension newDim = readDimension(m_forwGate);
        Point newHotSpot = readPoint(m_forwGate);

        m_cursorShape.setProperties(&newDim, &newPf);
        m_cursorShape.setHotSpot(newHotSpot.x, newHotSpot.y);

        m_forwGate->readFully(m_cursorShape.getPixels()->getBuffer(),
                              m_cursorShape.getPixelsSize());
        m_forwGate->readFully((void *)m_cursorShape.getMask(),
                              m_cursorShape.getMaskSize());
      }
    }
  } catch (ReconnectException &) {
    Log::info(_T("UpdateHandlerClient: ReconnectException catching in the extract function"));
  }
  *updateContainer = updCont;
}

void UpdateHandlerClient::setFullUpdateRequested(const Region *region)
{
  AutoLock al(m_forwGate);

  try {
    m_forwGate->writeUInt8(SET_FULL_UPD_REQ_REGION);
    sendRegion(region, m_forwGate);
  } catch (ReconnectException &) {
  }
}

void UpdateHandlerClient::setExcludedRegion(const Region *excludedRegion)
{
  AutoLock al(m_forwGate);

  try {
    m_forwGate->writeUInt8(SET_EXCLUDING_REGION);
    sendRegion(excludedRegion, m_forwGate);
  } catch (ReconnectException &) {
  }
}

bool UpdateHandlerClient::checkForUpdates(Region *region)
{
  return false;
}

void UpdateHandlerClient::getScreenProperties(PixelFormat *pf, Dimension *dim)
{
  AutoLock al(m_forwGate);

  m_forwGate->writeUInt8(SCREEN_PROP_REQ);
  readPixelFormat(pf, m_forwGate);
  *dim = readDimension(m_forwGate);
}

void UpdateHandlerClient::sendInit(BlockingGate *gate)
{
  AutoLock al(gate);
  gate->writeUInt8(FRAME_BUFFER_INIT);

  sendPixelFormat(&m_backupFrameBuffer.getPixelFormat(), gate);
  Dimension dim = m_backupFrameBuffer.getDimension();
  sendDimension(&dim, gate);
  sendFrameBuffer(&m_backupFrameBuffer, &dim.getRect(), gate);
}