/** @file * * Guest client: seamless mode. */ /* * Copyright (C) 2006-2007 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ #ifndef __Additions_xclient_seamless_h # define __Additions_xclient_seamless_h #include #include "seamless-host.h" #include "seamless-guest.h" #include "seamless-glue.h" /** Thread function class for VBoxGuestSeamlessGuest. */ class VBoxGuestSeamlessGuestThread: public VBoxGuestThreadFunction { private: /** The guest class "owning" us. */ VBoxGuestSeamlessGuestImpl *mGuest; /** The guest observer monitoring the guest. */ VBoxGuestSeamlessObserver *mObserver; /** Should we exit the thread? */ bool mExit; // Copying or assigning a thread object is not sensible VBoxGuestSeamlessGuestThread(const VBoxGuestSeamlessGuestThread&); VBoxGuestSeamlessGuestThread& operator=(const VBoxGuestSeamlessGuestThread&); public: VBoxGuestSeamlessGuestThread(VBoxGuestSeamlessGuestImpl *pGuest, VBoxGuestSeamlessObserver *pObserver) { mGuest = pGuest; mObserver = pObserver; mExit = false; } virtual ~VBoxGuestSeamlessGuestThread(void) {} /** * The actual thread function. * * @returns iprt status code as thread return value * @param pParent the VBoxGuestThread running this thread function */ virtual int threadFunction(VBoxGuestThread *pThread) { int rc = VINF_SUCCESS; LogRelFlowFunc(("\n")); rc = mGuest->start(); if (RT_SUCCESS(rc)) { while (!pThread->isStopping()) { mGuest->nextEvent(); } mGuest->stop(); } LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } /** * Send a signal to the thread function that it should exit */ virtual void stop(void) { mGuest->interruptEvent(); } }; /** Observer for the host class - start and stop seamless reporting in the guest when the host requests. */ class VBoxGuestSeamlessHostObserver : public VBoxGuestSeamlessObserver { private: VBoxGuestSeamlessHost *mHost; VBoxGuestThread *mGuestThread; public: VBoxGuestSeamlessHostObserver(VBoxGuestSeamlessHost *pHost, VBoxGuestThread *pGuestThread) { mHost = pHost; mGuestThread = pGuestThread; } virtual void notify(void) { switch (mHost->getState()) { case VBoxGuestSeamlessHost::ENABLE: mGuestThread->start(); break; case VBoxGuestSeamlessHost::DISABLE: mGuestThread->stop(RT_INDEFINITE_WAIT, 0); break; default: break; } } }; /** Observer for the guest class - send the host updated seamless rectangle information when it becomes available. */ class VBoxGuestSeamlessGuestObserver : public VBoxGuestSeamlessObserver { private: VBoxGuestSeamlessHost *mHost; VBoxGuestSeamlessGuestImpl *mGuest; public: VBoxGuestSeamlessGuestObserver(VBoxGuestSeamlessHost *pHost, VBoxGuestSeamlessGuestImpl *pGuest) { mHost = pHost; mGuest = pGuest; } virtual void notify(void) { mHost->updateRects(mGuest->getRects()); } }; class VBoxGuestSeamless { private: VBoxGuestSeamlessHost mHost; VBoxGuestSeamlessGuestImpl mGuest; VBoxGuestSeamlessGuestThread mGuestFunction; VBoxGuestThread mGuestThread; VBoxGuestSeamlessHostObserver mHostObs; VBoxGuestSeamlessGuestObserver mGuestObs; bool isInitialised; public: int init(void) { int rc = VINF_SUCCESS; LogRelFlowFunc(("\n")); if (isInitialised) /* Assertion */ { LogRelFunc(("error: called a second time! (VBoxClient)\n")); rc = VERR_INTERNAL_ERROR; } if (RT_SUCCESS(rc)) { rc = mHost.init(&mHostObs); } if (RT_SUCCESS(rc)) { rc = mGuest.init(&mGuestObs); } if (RT_SUCCESS(rc)) { rc = mHost.start(); } if (RT_SUCCESS(rc)) { isInitialised = true; } if (RT_FAILURE(rc)) { LogRelFunc(("returning %Rrc (VBoxClient)\n", rc)); } LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } void uninit(RTMSINTERVAL cMillies = RT_INDEFINITE_WAIT) { LogRelFlowFunc(("\n")); if (isInitialised) { mHost.stop(cMillies); mGuestThread.stop(cMillies, 0); mGuest.uninit(); isInitialised = false; } LogRelFlowFunc(("returning\n")); } VBoxGuestSeamless() : mGuestFunction(&mGuest, &mGuestObs), mGuestThread(&mGuestFunction, 0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, "Guest events"), mHostObs(&mHost, &mGuestThread), mGuestObs(&mHost, &mGuest) { isInitialised = false; } ~VBoxGuestSeamless() { uninit(); } }; #endif /* __Additions_xclient_seamless_h not defined */