seamless.cpp revision 1e8749f718360f779a7a345fd29ac8f758f6527d
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/** @file
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * X11 Guest client - seamless mode: main logic, communication with the host and
3184fc1a3e65025cd55704cdb1629f4ab1f3ccd2vboxsync * wrapper interface for the main code of the VBoxClient deamon. The
3184fc1a3e65025cd55704cdb1629f4ab1f3ccd2vboxsync * X11-specific parts are split out into their own file for ease of testing.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
d97357e2036109245c83ba553d0290212e28ea40vboxsync/*
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * Copyright (C) 2006-2014 Oracle Corporation
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync *
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * available from http://www.virtualbox.org. This file is free software;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * you can redistribute it and/or modify it under the terms of the GNU
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * General Public License (GPL) as published by the Free Software
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
be6a7ee8f237a71cf075c128e8e391e6c3654687vboxsync/*****************************************************************************
2fa05a4e777b070ba9bf01e3dd46434c99cd06a3vboxsync* Header files *
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync*****************************************************************************/
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync#include <X11/Xlib.h>
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync#include <VBox/log.h>
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync#include <VBox/VMMDev.h>
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync#include <VBox/VBoxGuestLib.h>
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync#include <iprt/err.h>
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync#include "VBoxClient.h"
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync#include "seamless.h"
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncSeamlessMain::SeamlessMain(void)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mX11MonitorThread = NIL_RTTHREAD;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mX11MonitorThreadStopping = false;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mMode = VMMDev_Seamless_Disabled;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mfPaused = false;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncSeamlessMain::~SeamlessMain()
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync stop();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/**
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * initialise the service.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync */
1cede4c702f5b7f8734214a2a5d5bc516b47b330vboxsyncint SeamlessMain::init(void)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
1cede4c702f5b7f8734214a2a5d5bc516b47b330vboxsync int rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync const char *pcszStage;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync do {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pcszStage = "Connecting to the X server";
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = mX11Monitor.init(this);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync break;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pcszStage = "Setting guest IRQ filter mask";
d97357e2036109245c83ba553d0290212e28ea40vboxsync rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync break;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pcszStage = "Reporting support for seamless capability";
d97357e2036109245c83ba553d0290212e28ea40vboxsync rc = VbglR3SeamlessSetCap(true);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync break;
d97357e2036109245c83ba553d0290212e28ea40vboxsync } while(0);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRel(("VBoxClient (seamless): failed to start. Stage: \"%s\" Error: %Rrc\n",
d97357e2036109245c83ba553d0290212e28ea40vboxsync pcszStage, rc));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/**
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * Run the main service thread which listens for host state change
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * notifications.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * @returns iprt status value. Service will be set to the stopped state on
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * failure.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncint SeamlessMain::run(void)
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync int rc = VINF_SUCCESS;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync /* This will only exit if something goes wrong. */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync while (RT_SUCCESS(rc) || rc == VERR_INTERRUPTED)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync /* If we are not stopping, sleep for a bit to avoid using up too
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync much CPU while retrying. */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync RTThreadYield();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = nextStateChangeEvent();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
d97357e2036109245c83ba553d0290212e28ea40vboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRel(("VBoxClient (seamless): event loop failed with error: %Rrc\n",
d97357e2036109245c83ba553d0290212e28ea40vboxsync rc));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync stop();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
d97357e2036109245c83ba553d0290212e28ea40vboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/** Stops the service. */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncvoid SeamlessMain::stop()
d97357e2036109245c83ba553d0290212e28ea40vboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync VbglR3SeamlessSetCap(false);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync stopX11MonitorThread();
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync mX11Monitor.uninit();
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelFlowFunc(("returning\n"));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/**
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * Waits for a seamless state change events from the host and dispatch it.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync *
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * @returns IRPT return code.
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncint SeamlessMain::nextStateChangeEvent(void)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync int rc = VbglR3SeamlessWaitEvent(&newMode);
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync if (RT_SUCCESS(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
d97357e2036109245c83ba553d0290212e28ea40vboxsync mMode = newMode;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync switch (newMode)
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync {
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync case VMMDev_Seamless_Visible_Region:
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync /* A simplified seamless mode, obtained by making the host VM window
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync * borderless and making the guest desktop transparent. */
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelFlowFunc(("\"Visible region\" mode requested (VBoxClient).\n"));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync break;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync case VMMDev_Seamless_Disabled:
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelFlowFunc(("\"Disabled\" mode requested (VBoxClient).\n"));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync break;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync case VMMDev_Seamless_Host_Window:
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync /* One host window represents one guest window. Not yet implemented. */
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelFunc(("Unsupported \"host window\" mode requested (VBoxClient).\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VERR_NOT_SUPPORTED;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync default:
d97357e2036109245c83ba553d0290212e28ea40vboxsync LogRelFunc(("Unsupported mode %d requested (VBoxClient).\n",
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync newMode));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VERR_NOT_SUPPORTED;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync if (RT_SUCCESS(rc) || rc == VERR_TRY_AGAIN)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync if (mMode == VMMDev_Seamless_Visible_Region && !mfPaused)
d97357e2036109245c83ba553d0290212e28ea40vboxsync /* This does it's own logging on failure. */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = startX11MonitorThread();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync else
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync /* This does it's own logging on failure. */
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync rc = stopX11MonitorThread();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync else
d97357e2036109245c83ba553d0290212e28ea40vboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFunc(("VbglR3SeamlessWaitEvent returned %Rrc (VBoxClient)\n", rc));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("returning %Rrc\n", rc));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync}
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncint SeamlessMain::cancelEvent(void)
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VbglR3InterruptEventWaits();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/**
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * Update the set of visible rectangles in the host.
d97357e2036109245c83ba553d0290212e28ea40vboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncvoid SeamlessMain::sendRegionUpdate(RTRECT *pRects, size_t cRects)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
d97357e2036109245c83ba553d0290212e28ea40vboxsync LogRelFlowFunc(("\n"));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync if (cRects && !pRects) /* Assertion */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelThisFunc(("ERROR: called with null pointer!\n"));
d97357e2036109245c83ba553d0290212e28ea40vboxsync return;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync VbglR3SeamlessSendRects(cRects, pRects);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("returning\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/**
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * The actual X11 window configuration change monitor thread function.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncint SeamlessMain::x11MonitorThread(RTTHREAD self, void *pvUser)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync SeamlessMain *pHost = (SeamlessMain *)pvUser;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync int rc = VINF_SUCCESS;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = pHost->mX11Monitor.start();
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync if (RT_SUCCESS(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync while (!pHost->mX11MonitorThreadStopping)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pHost->mX11Monitor.nextConfigurationEvent();
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync pHost->mX11Monitor.stop();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("returning %Rrc\n", rc));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync}
d97357e2036109245c83ba553d0290212e28ea40vboxsync
d97357e2036109245c83ba553d0290212e28ea40vboxsync/**
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * Start the X11 window configuration change monitor thread.
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync */
1d5386c32e68116bca5e054dbef008b1f516bb25vboxsyncint SeamlessMain::startX11MonitorThread(void)
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync int rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mX11MonitorThreadStopping = false;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (isX11MonitorThreadRunning())
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VINF_SUCCESS;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThread, this, 0,
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync "X11 events");
d97357e2036109245c83ba553d0290212e28ea40vboxsync if (RT_FAILURE(rc))
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync LogRelFunc(("Warning: failed to start X11 monitor thread (VBoxClient).\n"));
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync/**
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync * Send a signal to the thread function that it should exit
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncint SeamlessMain::stopX11MonitorThread(void)
d97357e2036109245c83ba553d0290212e28ea40vboxsync{
d97357e2036109245c83ba553d0290212e28ea40vboxsync int rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync mX11MonitorThreadStopping = true;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync if (!isX11MonitorThreadRunning())
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VINF_SUCCESS;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mX11Monitor.interruptEventWait();
d97357e2036109245c83ba553d0290212e28ea40vboxsync rc = RTThreadWait(mX11MonitorThread, RT_INDEFINITE_WAIT, NULL);
d97357e2036109245c83ba553d0290212e28ea40vboxsync if (RT_SUCCESS(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mX11MonitorThread = NIL_RTTHREAD;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync else
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelThisFunc(("Failed to stop X11 monitor thread, rc=%Rrc!\n",
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync rc));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync return rc;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync/** Pause the service loop. */
254e593d079dbddd48135ebe2893334eb36dcbafvboxsyncint SeamlessMain::pause()
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync int rc;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync const char *pcszStage;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelFlowFunc(("\n"));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync mfPaused = true;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync do {
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync pcszStage = "Reporting end of support for seamless capability";
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = VbglR3SeamlessSetCap(false);
d97357e2036109245c83ba553d0290212e28ea40vboxsync if (RT_FAILURE(rc))
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync break;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync pcszStage = "Interrupting the event loop";
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync rc = cancelEvent();
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync if (RT_FAILURE(rc))
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync break;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync } while (0);
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync if (RT_FAILURE(rc))
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelFunc(("Failure. Stage: \"%s\" Error: %Rrc (VBoxClient)\n",
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync pcszStage, rc));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync return rc;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync}
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync/** Resume after pausing. */
254e593d079dbddd48135ebe2893334eb36dcbafvboxsyncint SeamlessMain::resume()
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync{
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync int rc;
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync const char *pcszStage;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync LogRelFlowFunc(("\n"));
254e593d079dbddd48135ebe2893334eb36dcbafvboxsync mfPaused = false;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync do {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pcszStage = "Reporting support for seamless capability";
d97357e2036109245c83ba553d0290212e28ea40vboxsync rc = VbglR3SeamlessSetCap(true);
d97357e2036109245c83ba553d0290212e28ea40vboxsync if (RT_FAILURE(rc))
d97357e2036109245c83ba553d0290212e28ea40vboxsync break;
d97357e2036109245c83ba553d0290212e28ea40vboxsync pcszStage = "Interrupting the event loop";
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = cancelEvent();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync break;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync } while (0);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFunc(("Failure. Stage: \"%s\" Error: %Rrc (VBoxClient)\n",
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pcszStage, rc));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync/** @todo Expand this? */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncint SeamlessMain::selfTest()
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync int rc = VERR_INTERNAL_ERROR;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync const char *pcszStage;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRelFlowFunc(("\n"));
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync do {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pcszStage = "Testing event loop cancellation";
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync VbglR3InterruptEventWaits();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL)))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync break;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if ( VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync != VERR_TIMEOUT)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync break;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync } while(0);
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync LogRel(("VBoxClient (seamless): self test failed. Stage: \"%s\"\n",
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync pcszStage));
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
d97357e2036109245c83ba553d0290212e28ea40vboxsync/** VBoxClient service class wrapping the logic for the seamless service while
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync * the main VBoxClient code provides the daemon logic needed by all services.
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncclass SeamlessService : public VBoxClient::Service
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncprivate:
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync SeamlessMain mSeamless;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync bool mIsInitialised;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncpublic:
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync virtual const char *getPidFilePath()
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return ".vboxclient-seamless.pid";
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync virtual int init()
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync int rc;
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (mIsInitialised)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VERR_INTERNAL_ERROR;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = mSeamless.init();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = mSeamless.selfTest();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (RT_FAILURE(rc))
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mSeamless.stop();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
d97357e2036109245c83ba553d0290212e28ea40vboxsync mIsInitialised = true;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VINF_SUCCESS;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync virtual int run(bool fDaemonised /* = false */)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
d97357e2036109245c83ba553d0290212e28ea40vboxsync int rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync if (!mIsInitialised)
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return VERR_INTERNAL_ERROR;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync /* This only exits on error. */
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync rc = mSeamless.run();
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync mIsInitialised = false;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return rc;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync virtual int pause() { return mSeamless.pause(); }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync virtual int resume() { return mSeamless.resume(); }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync virtual void cleanup()
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync {
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync VbglR3SeamlessSetCap(false);
1041613dd6ee5da259fa80b5555bb556f4dd8aafvboxsync }
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync};
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsyncVBoxClient::Service *VBoxClient::GetSeamlessService()
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync{
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync return new SeamlessService;
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync}
18470279db8a9fdd714617adbe1aa8b63cc80aeevboxsync