VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp@ 23794

Last change on this file since 23794 was 21227, checked in by vboxsync, 15 years ago

VBoxGuest.h/VMMDev.h/VBoxGuestLib.h usage cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.3 KB
Line 
1/** @file
2 * X11 Guest client - seamless mode, missing proper description while using the
3 * potentially confusing word 'host'.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*****************************************************************************
23* Header files *
24*****************************************************************************/
25#include <VBox/log.h>
26#include <VBox/VMMDev.h>
27#include <VBox/VBoxGuestLib.h>
28#include <iprt/err.h>
29
30#include "seamless-host.h"
31
32/**
33 * Start the service.
34 * @returns iprt status value
35 */
36int VBoxGuestSeamlessHost::start(void)
37{
38 int rc = VERR_NOT_SUPPORTED;
39
40 LogFlowThisFunc(("\n"));
41 if (mRunning) /* Assertion */
42 {
43 LogRel(("VBoxClient: seamless service started twice!\n"));
44 return VERR_INTERNAL_ERROR;
45 }
46 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0);
47 if (RT_FAILURE(rc))
48 {
49 LogRel(("VBoxClient (seamless): failed to set the guest IRQ filter mask, rc=%Rrc\n", rc));
50 }
51 rc = VbglR3SeamlessSetCap(true);
52 if (RT_SUCCESS(rc))
53 {
54 Log(("VBoxClient: enabled seamless capability on host.\n"));
55 rc = mThread.start();
56 if (RT_SUCCESS(rc))
57 {
58 mRunning = true;
59 }
60 else
61 {
62 LogRel(("VBoxClient: failed to start seamless event thread, rc=%Rrc. Disabled seamless capability on host again.\n", rc));
63 VbglR3SeamlessSetCap(false);
64 }
65 }
66 if (RT_FAILURE(rc))
67 {
68 Log(("VBoxClient (seamless): failed to enable seamless capability on host, rc=%Rrc\n", rc));
69 }
70 LogFlowThisFunc(("returning %Rrc\n", rc));
71 return rc;
72}
73
74/** Stops the service. */
75void VBoxGuestSeamlessHost::stop(unsigned cMillies /* = RT_INDEFINITE_WAIT */)
76{
77 LogFlowThisFunc(("returning\n"));
78 if (!mRunning) /* Assertion */
79 {
80 LogRel(("VBoxClient: tried to stop seamless service which is not running!\n"));
81 return;
82 }
83 mThread.stop(cMillies, 0);
84 VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
85 VbglR3SeamlessSetCap(false);
86 mRunning = false;
87 LogFlowThisFunc(("returning\n"));
88}
89
90/**
91 * Waits for a seamless state change events from the host and dispatch it.
92 *
93 * @returns IRPT return code.
94 */
95int VBoxGuestSeamlessHost::nextEvent(void)
96{
97 VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled;
98
99 LogFlowThisFunc(("\n"));
100 int rc = VbglR3SeamlessWaitEvent(&newMode);
101 if (RT_SUCCESS(rc))
102 {
103 switch(newMode)
104 {
105 case VMMDev_Seamless_Visible_Region:
106 /* A simplified seamless mode, obtained by making the host VM window borderless and
107 making the guest desktop transparent. */
108#ifdef DEBUG
109 LogRelFunc(("VMMDev_Seamless_Visible_Region request received (VBoxClient).\n"));
110#endif
111 mState = ENABLE;
112 mObserver->notify();
113 break;
114 case VMMDev_Seamless_Host_Window:
115 /* One host window represents one guest window. Not yet implemented. */
116 LogRelFunc(("Warning: VMMDev_Seamless_Host_Window request received (VBoxClient).\n"));
117 /* fall through to default */
118 default:
119 LogRelFunc(("Warning: unsupported VMMDev_Seamless request %d received (VBoxClient).\n", newMode));
120 /* fall through to case VMMDev_Seamless_Disabled */
121 case VMMDev_Seamless_Disabled:
122#ifdef DEBUG
123 LogRelFunc(("VMMDev_Seamless_Disabled set (VBoxClient).\n"));
124#endif
125 mState = DISABLE;
126 mObserver->notify();
127 }
128 }
129 else
130 {
131 LogFunc(("VbglR3SeamlessWaitEvent returned %Rrc (VBoxClient)\n", rc));
132 }
133 LogFlowThisFunc(("returning %Rrc\n", rc));
134 return rc;
135}
136
137/**
138 * Update the set of visible rectangles in the host.
139 */
140void VBoxGuestSeamlessHost::updateRects(std::auto_ptr<std::vector<RTRECT> > pRects)
141{
142 LogFlowThisFunc(("\n"));
143 if (0 == pRects.get()) /* Assertion */
144 {
145 LogRelThisFunc(("ERROR: called with null pointer!\n"));
146 return;
147 }
148 VbglR3SeamlessSendRects(pRects.get()->size(), pRects.get()->empty() ? NULL : &pRects.get()->front());
149 LogFlowThisFunc(("returning\n"));
150}
151
152/**
153 * The actual thread function.
154 *
155 * @returns iprt status code as thread return value
156 * @param pParent the VBoxGuestThread running this thread function
157 */
158int VBoxGuestSeamlessHostThread::threadFunction(VBoxGuestThread *pThread)
159{
160 LogFlowThisFunc(("\n"));
161 if (0 != mHost)
162 {
163 mThread = pThread;
164 while (!mThread->isStopping())
165 {
166 if (RT_FAILURE(mHost->nextEvent()) && !mThread->isStopping())
167 {
168 /* If we are not stopping, sleep for a bit to avoid using up too
169 much CPU while retrying. */
170 mThread->yield();
171 }
172 }
173 }
174 LogFlowThisFunc(("returning VINF_SUCCESS\n"));
175 return VINF_SUCCESS;
176}
177
178/**
179 * Send a signal to the thread function that it should exit
180 */
181void VBoxGuestSeamlessHostThread::stop(void)
182{
183 LogFlowThisFunc(("\n"));
184 if (0 != mHost)
185 {
186 /**
187 * @todo is this reasonable? If the thread is in the event loop then the cancelEvent()
188 * will cause it to exit. If it enters or exits the event loop it will also
189 * notice that we wish it to exit. And if it is somewhere in-between, the
190 * yield() should give it time to get to one of places mentioned above.
191 */
192 for (int i = 0; (i < 5) && mThread->isRunning(); ++i)
193 {
194 mHost->cancelEvent();
195 mThread->yield();
196 }
197 }
198 LogFlowThisFunc(("returning\n"));
199}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette