diff options
Diffstat (limited to 'src')
9 files changed, 108 insertions, 133 deletions
diff --git a/src/VBox/Additions/x11/VBoxClient/Makefile.kmk b/src/VBox/Additions/x11/VBoxClient/Makefile.kmk index cbbfabe6f41..94b09f5b7c2 100644 --- a/src/VBox/Additions/x11/VBoxClient/Makefile.kmk +++ b/src/VBox/Additions/x11/VBoxClient/Makefile.kmk @@ -58,7 +58,6 @@ VBoxClient_LIBS += \ ifdef VBOX_X11_SEAMLESS_GUEST VBoxClient_DEFS += SEAMLESS_GUEST DYNAMIC_RESIZE VBoxClient_SOURCES += \ - seamless.cpp \ seamless-host.cpp \ seamless-x11.cpp \ display.cpp \ diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp b/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp index f3bbe2d0fc4..9e8bd28dd96 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp +++ b/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp @@ -1,10 +1,11 @@ /** @file - * X11 Guest client - seamless mode, missing proper description while using the - * potentially confusing word 'host'. + * X11 Guest client - seamless mode: main logic, communication with the host and + * wrapper interface for the main code of the VBoxClient deamon. The + * X11-specific parts are split out into their own file for ease of testing. */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2014 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -18,11 +19,15 @@ /***************************************************************************** * Header files * *****************************************************************************/ + +#include <X11/Xlib.h> + #include <VBox/log.h> #include <VBox/VMMDev.h> #include <VBox/VBoxGuestLib.h> #include <iprt/err.h> +#include "VBoxClient.h" #include "seamless-host.h" #include "seamless-x11.h" @@ -49,6 +54,11 @@ int VBoxGuestSeamlessHost::start(void) if (RT_SUCCESS(rc)) { LogRel(("VBoxClient: enabled seamless capability on host.\n")); + /* Create a thread to wait for requests from the host. This is currently + * done on a separate thread as the main thread monitors the X11 server + * for disconnections. */ + /** @todo Move the disconnection monitoring to its own thread (better, the + * VT monitor thread) and run this logic on the main service thread. */ rc = RTThreadCreate(&mThread, threadFunction, this, 0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, "Host events"); @@ -67,13 +77,13 @@ int VBoxGuestSeamlessHost::start(void) } /** Stops the service. */ -void VBoxGuestSeamlessHost::stop(RTMSINTERVAL cMillies /* = RT_INDEFINITE_WAIT */) +void VBoxGuestSeamlessHost::stop() { LogRelFlowFunc(("\n")); if (!mThread) /* Assertion */ LogRel(("VBoxClient: tried to stop seamless service which is not running!\n")); else - stopThread(cMillies); + stopThread(); if (mX11MonitorRTThread) stopX11Thread(); VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST); @@ -102,7 +112,6 @@ int VBoxGuestSeamlessHost::nextEvent(void) #ifdef DEBUG LogRelFunc(("VMMDev_Seamless_Visible_Region request received (VBoxClient).\n")); #endif - mState = ENABLE; mX11ThreadStopping = false; /** @todo Do something on failure, like bail out. */ if (RT_FAILURE(RTThreadCreate(&mX11MonitorRTThread, @@ -121,7 +130,6 @@ int VBoxGuestSeamlessHost::nextEvent(void) #ifdef DEBUG LogRelFunc(("VMMDev_Seamless_Disabled set (VBoxClient).\n")); #endif - mState = DISABLE; if (mX11MonitorRTThread) stopX11Thread(); else @@ -181,7 +189,7 @@ int VBoxGuestSeamlessHost::threadFunction(RTTHREAD self, void *pvUser) /** * Send a signal to the thread that it should exit */ -void VBoxGuestSeamlessHost::stopThread(RTMSINTERVAL cMillies) +void VBoxGuestSeamlessHost::stopThread() { int rc; @@ -216,14 +224,14 @@ int VBoxGuestSeamlessHost::x11ThreadFunction(RTTHREAD self, void *pvUser) int rc = VINF_SUCCESS; LogRelFlowFunc(("\n")); - rc = pHost->mX11Monitor->start(); + rc = pHost->mX11Monitor.start(); if (RT_SUCCESS(rc)) { while (!pHost->mX11ThreadStopping) { - pHost->mX11Monitor->nextEvent(); + pHost->mX11Monitor.nextEvent(); } - pHost->mX11Monitor->stop(); + pHost->mX11Monitor.stop(); } LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; @@ -237,7 +245,7 @@ void VBoxGuestSeamlessHost::stopX11Thread(void) int rc; mX11ThreadStopping = true; - mX11Monitor->interruptEvent(); + mX11Monitor.interruptEvent(); rc = RTThreadWait(mX11MonitorRTThread, RT_INDEFINITE_WAIT, NULL); if (RT_SUCCESS(rc)) mX11MonitorRTThread = NIL_RTTHREAD; @@ -245,3 +253,54 @@ void VBoxGuestSeamlessHost::stopX11Thread(void) LogRelThisFunc(("Failed to stop X11 monitor thread, rc=%Rrc!\n", rc)); } + +/** VBoxClient service class wrapping the logic for the seamless service while + * the main VBoxClient code provides the daemon logic needed by all services. + */ +class SeamlessService : public VBoxClient::Service +{ +private: + VBoxGuestSeamlessHost mSeamless; + bool mIsInitialised; +public: + virtual const char *getPidFilePath() + { + return ".vboxclient-seamless.pid"; + } + virtual int run(bool fDaemonised /* = false */) + { + int rc; + + if (mIsInitialised) /* Assertion */ + { + LogRelFunc(("error: called a second time! (VBoxClient)\n")); + rc = VERR_INTERNAL_ERROR; + } + if (RT_SUCCESS(rc)) + rc = mSeamless.init(); + if (RT_SUCCESS(rc)) + rc = mSeamless.start(); + if (RT_SUCCESS(rc)) + mIsInitialised = true; + if (RT_FAILURE(rc)) + { + LogRelFunc(("returning %Rrc (VBoxClient)\n", rc)); + return rc; + } + /* Stay running as long as X does... */ + Display *pDisplay = XOpenDisplay(NULL); + XEvent ev; + while (true) + XNextEvent(pDisplay, &ev); + return VERR_INTERRUPTED; + } + virtual void cleanup() + { + VbglR3SeamlessSetCap(false); + } +}; + +VBoxClient::Service *VBoxClient::GetSeamlessService() +{ + return new SeamlessService; +} diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-host.h b/src/VBox/Additions/x11/VBoxClient/seamless-host.h index 90bdf573c55..d80a9d06fac 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-host.h +++ b/src/VBox/Additions/x11/VBoxClient/seamless-host.h @@ -23,23 +23,12 @@ #include <VBox/log.h> #include <VBox/VBoxGuestLib.h> /* for the R3 guest library functions */ -class VBoxGuestSeamlessX11; - -/** - * Small virtual class which provides the interface for notifying the host of - * changes to the X11 window configuration, mainly split out from - * @a VBoxGuestSeamlessHost to simplify the unit test. - */ -class VBoxGuestSeamlessHostInt -{ -public: - virtual void notify(RTRECT *pRects, size_t cRects) = 0; -}; +#include "seamless-x11.h" /** * Interface to the host */ -class VBoxGuestSeamlessHost : public VBoxGuestSeamlessHostInt +class VBoxGuestSeamlessHost : public SeamlessHostProxy { public: /** Events which can be reported by this class */ @@ -58,11 +47,14 @@ private: VBoxGuestSeamlessHost(const VBoxGuestSeamlessHost&); VBoxGuestSeamlessHost& operator=(const VBoxGuestSeamlessHost&); + /** Have we been initialised yet? */ + bool mIsInitialised; + /** X11 event monitor object */ + VBoxGuestSeamlessX11 mX11Monitor; + /** Thread to start and stop when we enter and leave seamless mode which * monitors X11 windows in the guest. */ RTTHREAD mX11MonitorRTThread; - /** X11 event monitor class */ - VBoxGuestSeamlessX11 *mX11Monitor; /** Should the X11 monitor thread be stopping? */ volatile bool mX11ThreadStopping; /** Host seamless event thread. */ @@ -71,8 +63,6 @@ private: volatile bool mThreadRunning; /** Should the thread be stopping? */ volatile bool mThreadStopping; - /** Last request issued by the host. */ - meEvent mState; /** * Waits for a seamless state change events from the host and dispatch it. This is @@ -92,7 +82,7 @@ private: static DECLCALLBACK(int) threadFunction(RTTHREAD self, void *pvUser); /** Helper to stop the event query thread again. */ - void stopThread(RTMSINTERVAL cMillies); + void stopThread(); /** Thread function to monitor X11 window configuration changes. */ static DECLCALLBACK(int) x11ThreadFunction(RTTHREAD self, void *pvUser); @@ -107,17 +97,17 @@ public: * * @returns iprt status code */ - int init(VBoxGuestSeamlessX11 *pX11Monitor) + int init(void) { + int rc; + LogRelFlowFunc(("\n")); - if (mX11Monitor != NULL) /* Assertion */ - { - LogRel(("VBoxClient: ERROR: attempt to initialise seamless host object twice!\n")); + if (mIsInitialised) return VERR_INTERNAL_ERROR; - } - mX11Monitor = pX11Monitor; - LogRelFlowFunc(("returning VINF_SUCCESS\n")); - return VINF_SUCCESS; + rc = mX11Monitor.init(this); + if (RT_SUCCESS(rc)) + mIsInitialised = true; + return rc; } /** @@ -130,10 +120,7 @@ public: * Stops the service. * @param cMillies how long to wait for the thread to exit */ - void stop(RTMSINTERVAL cMillies = RT_INDEFINITE_WAIT); - - /** Returns the current state of the host - i.e. requesting seamless or not. */ - meEvent getState(void) { return mState; } + void stop(); /** * Update the set of visible rectangles in the host. @@ -142,23 +129,19 @@ public: VBoxGuestSeamlessHost(void) { + mIsInitialised = false; mX11MonitorRTThread = NIL_RTTHREAD; - mX11Monitor = NULL; mX11ThreadStopping = false; mThread = NIL_RTTHREAD; mThreadRunning = false; mThreadStopping = false; - mState = NONE; } ~VBoxGuestSeamlessHost() { LogRelFlowFunc(("\n")); - if (mThread) /* Assertion */ - { - LogRel(("VBoxClient: seamless host object still running! Stopping...\n")); - stop(2000); - } + if (mThread) + stop(); LogRelFlowFunc(("returning\n")); } }; diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp b/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp index 826a75cb5f8..57515228c5a 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp +++ b/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp @@ -70,7 +70,7 @@ static unsigned char *XXGetProperty (Display *aDpy, Window aWnd, Atom aPropType, * * @returns true if it can handle seamless, false otherwise */ -int VBoxGuestSeamlessX11::init(VBoxGuestSeamlessHostInt *pHost) +int VBoxGuestSeamlessX11::init(SeamlessHostProxy *pHost) { int rc = VINF_SUCCESS; diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-x11.h b/src/VBox/Additions/x11/VBoxClient/seamless-x11.h index 111727d851f..dc517b060a0 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-x11.h +++ b/src/VBox/Additions/x11/VBoxClient/seamless-x11.h @@ -22,9 +22,6 @@ #include <VBox/log.h> #include <iprt/avl.h> -#include "seamless-x11.h" -#include "seamless-host.h" - #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/extensions/shape.h> @@ -35,6 +32,17 @@ /* This is defined wrong in my X11 header files! */ #define VBoxShapeNotify 64 +/** + * Small virtual class which provides the interface for notifying the host of + * changes to the X11 window configuration, mainly split out from + * @a VBoxGuestSeamlessHost to simplify the unit test. + */ +class SeamlessHostProxy +{ +public: + virtual void notify(RTRECT *pRects, size_t cRects) = 0; +}; + /** Structure containing information about a guest window's position and visible area. Used inside of VBoxGuestWindowList. */ struct VBoxGuestWinInfo { @@ -155,7 +163,7 @@ private: // Private member variables /** Pointer to the host class. */ - VBoxGuestSeamlessHostInt *mHost; + SeamlessHostProxy *mHost; /** Our connection to the X11 display we are running on. */ Display *mDisplay; /** Class to keep track of visible guest windows. */ @@ -200,7 +208,7 @@ public: * * @returns iprt status code */ - int init(VBoxGuestSeamlessHostInt *pHost); + int init(SeamlessHostProxy *pHost); /** * Shutdown seamless event monitoring. diff --git a/src/VBox/Additions/x11/VBoxClient/seamless.cpp b/src/VBox/Additions/x11/VBoxClient/seamless.cpp deleted file mode 100644 index e3ab64a877a..00000000000 --- a/src/VBox/Additions/x11/VBoxClient/seamless.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/** @file - * - * Guest client: seamless mode. - */ - -/* - * Copyright (C) 2006-2012 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. - */ - -#include <unistd.h> - -#include <X11/Xlib.h> - -#include "VBoxClient.h" -#include "seamless.h" - -class SeamlessService : public VBoxClient::Service -{ -private: - VBoxGuestSeamless mSeamless; -public: - virtual const char *getPidFilePath() - { - return ".vboxclient-seamless.pid"; - } - virtual int run(bool fDaemonised /* = false */) - { - int rc = mSeamless.init(); - if (RT_FAILURE(rc)) - return rc; - /* Stay running as long as X does... */ - Display *pDisplay = XOpenDisplay(NULL); - XEvent ev; - while (true) - XNextEvent(pDisplay, &ev); - return VERR_INTERRUPTED; - } - virtual void cleanup() - { - VbglR3SeamlessSetCap(false); - } -}; - -VBoxClient::Service *VBoxClient::GetSeamlessService() -{ - return new SeamlessService; -} diff --git a/src/VBox/Additions/x11/VBoxClient/seamless.h b/src/VBox/Additions/x11/VBoxClient/seamless.h index 2bf07906596..68460b8fa01 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless.h +++ b/src/VBox/Additions/x11/VBoxClient/seamless.h @@ -27,7 +27,6 @@ class VBoxGuestSeamless { private: VBoxGuestSeamlessHost mHost; - VBoxGuestSeamlessX11 mGuest; bool isInitialised; public: @@ -43,11 +42,7 @@ public: } if (RT_SUCCESS(rc)) { - rc = mHost.init(&mGuest); - } - if (RT_SUCCESS(rc)) - { - rc = mGuest.init(&mHost); + rc = mHost.init(); } if (RT_SUCCESS(rc)) { @@ -65,20 +60,8 @@ public: return rc; } - void uninit(RTMSINTERVAL cMillies = RT_INDEFINITE_WAIT) - { - LogRelFlowFunc(("\n")); - if (isInitialised) - { - mHost.stop(cMillies); - mGuest.uninit(); - isInitialised = false; - } - LogRelFlowFunc(("returning\n")); - } - VBoxGuestSeamless() { isInitialised = false; } - ~VBoxGuestSeamless() { uninit(); } + ~VBoxGuestSeamless() { } }; #endif /* __Additions_xclient_seamless_h not defined */ diff --git a/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp b/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp index 88036cc7eee..b144a6b3c31 100644 --- a/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp +++ b/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp @@ -28,7 +28,6 @@ #include <iprt/string.h> #include "../seamless.h" -#include "../seamless-host.h" #undef DefaultRootWindow @@ -298,7 +297,7 @@ int XFlush(Display *display) } /** Dummy host class */ -class testHost: public VBoxGuestSeamlessHostInt +class testHost: public SeamlessHostProxy { bool mfNotified; public: diff --git a/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp b/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp index 638f2cff73b..30032f748e3 100644 --- a/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp +++ b/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp @@ -126,6 +126,5 @@ int main( int argc, char **argv) RTPrintf("Failed to initialise seamless Additions, rc = %d\n", rc); } RTStrmGetLine(g_pStdIn, ach, sizeof(ach)); - seamless.uninit(); return rc; } |