VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp@ 50632

Last change on this file since 50632 was 50632, checked in by vboxsync, 11 years ago

Additions/x11/VBoxClient: remove broken test code from the seamless service.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.1 KB
Line 
1/** @file
2 * X11 Guest client - seamless mode: main logic, communication with the host and
3 * wrapper interface for the main code of the VBoxClient deamon. The
4 * X11-specific parts are split out into their own file for ease of testing.
5 */
6
7/*
8 * Copyright (C) 2006-2014 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/*****************************************************************************
20* Header files *
21*****************************************************************************/
22
23#include <X11/Xlib.h>
24
25#include <VBox/log.h>
26#include <VBox/VMMDev.h>
27#include <VBox/VBoxGuestLib.h>
28#include <iprt/err.h>
29
30#include "VBoxClient.h"
31#include "seamless.h"
32
33SeamlessMain::SeamlessMain(void)
34{
35 LogRelFlowFunc(("\n"));
36 mX11MonitorThread = NIL_RTTHREAD;
37 mX11MonitorThreadStopping = false;
38 mMode = VMMDev_Seamless_Disabled;
39 mfPaused = false;
40}
41
42SeamlessMain::~SeamlessMain()
43{
44 LogRelFlowFunc(("\n"));
45 stop();
46}
47
48/**
49 * initialise the service.
50 */
51int SeamlessMain::init(void)
52{
53 int rc;
54 const char *pcszStage;
55
56 LogRelFlowFunc(("\n"));
57 do {
58 pcszStage = "Connecting to the X server";
59 rc = mX11Monitor.init(this);
60 if (RT_FAILURE(rc))
61 break;
62 pcszStage = "Setting guest IRQ filter mask";
63 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0);
64 if (RT_FAILURE(rc))
65 break;
66 pcszStage = "Reporting support for seamless capability";
67 rc = VbglR3SeamlessSetCap(true);
68 if (RT_FAILURE(rc))
69 break;
70 } while(0);
71 if (RT_FAILURE(rc))
72 LogRel(("VBoxClient (seamless): failed to start. Stage: \"%s\" Error: %Rrc\n",
73 pcszStage, rc));
74 return rc;
75}
76
77/**
78 * Run the main service thread which listens for host state change
79 * notifications.
80 * @returns iprt status value. Service will be set to the stopped state on
81 * failure.
82 */
83int SeamlessMain::run(void)
84{
85 int rc = VINF_SUCCESS;
86
87 LogRelFlowFunc(("\n"));
88 /* This will only exit if something goes wrong. */
89 while (RT_SUCCESS(rc) || rc == VERR_INTERRUPTED)
90 {
91 if (RT_FAILURE(rc))
92 /* If we are not stopping, sleep for a bit to avoid using up too
93 much CPU while retrying. */
94 RTThreadYield();
95 rc = nextStateChangeEvent();
96 }
97 if (RT_FAILURE(rc))
98 {
99 LogRel(("VBoxClient (seamless): event loop failed with error: %Rrc\n",
100 rc));
101 stop();
102 }
103 return rc;
104}
105
106/** Stops the service. */
107void SeamlessMain::stop()
108{
109 LogRelFlowFunc(("\n"));
110 VbglR3SeamlessSetCap(false);
111 VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
112 stopX11MonitorThread();
113 mX11Monitor.uninit();
114 LogRelFlowFunc(("returning\n"));
115}
116
117/**
118 * Waits for a seamless state change events from the host and dispatch it.
119 *
120 * @returns IRPT return code.
121 */
122int SeamlessMain::nextStateChangeEvent(void)
123{
124 VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled;
125
126 LogRelFlowFunc(("\n"));
127 int rc = VbglR3SeamlessWaitEvent(&newMode);
128 if (RT_SUCCESS(rc))
129 {
130 mMode = newMode;
131 switch (newMode)
132 {
133 case VMMDev_Seamless_Visible_Region:
134 /* A simplified seamless mode, obtained by making the host VM window
135 * borderless and making the guest desktop transparent. */
136 LogRelFlowFunc(("\"Visible region\" mode requested (VBoxClient).\n"));
137 break;
138 case VMMDev_Seamless_Disabled:
139 LogRelFlowFunc(("\"Disabled\" mode requested (VBoxClient).\n"));
140 break;
141 case VMMDev_Seamless_Host_Window:
142 /* One host window represents one guest window. Not yet implemented. */
143 LogRelFunc(("Unsupported \"host window\" mode requested (VBoxClient).\n"));
144 return VERR_NOT_SUPPORTED;
145 default:
146 LogRelFunc(("Unsupported mode %d requested (VBoxClient).\n",
147 newMode));
148 return VERR_NOT_SUPPORTED;
149 }
150 }
151 if (RT_SUCCESS(rc) || rc == VERR_TRY_AGAIN)
152 {
153 if (mMode == VMMDev_Seamless_Visible_Region && !mfPaused)
154 /* This does it's own logging on failure. */
155 rc = startX11MonitorThread();
156 else
157 /* This does it's own logging on failure. */
158 rc = stopX11MonitorThread();
159 }
160 else
161 {
162 LogRelFunc(("VbglR3SeamlessWaitEvent returned %Rrc (VBoxClient)\n", rc));
163 }
164 LogRelFlowFunc(("returning %Rrc\n", rc));
165 return rc;
166}
167
168int SeamlessMain::cancelEvent(void)
169{
170 return VbglR3InterruptEventWaits();
171}
172
173/**
174 * Update the set of visible rectangles in the host.
175 */
176void SeamlessMain::sendRegionUpdate(RTRECT *pRects, size_t cRects)
177{
178 LogRelFlowFunc(("\n"));
179 if (cRects && !pRects) /* Assertion */
180 {
181 LogRelThisFunc(("ERROR: called with null pointer!\n"));
182 return;
183 }
184 VbglR3SeamlessSendRects(cRects, pRects);
185 LogRelFlowFunc(("returning\n"));
186}
187
188
189/**
190 * The actual X11 window configuration change monitor thread function.
191 */
192int SeamlessMain::x11MonitorThread(RTTHREAD self, void *pvUser)
193{
194 SeamlessMain *pHost = (SeamlessMain *)pvUser;
195 int rc = VINF_SUCCESS;
196
197 LogRelFlowFunc(("\n"));
198 rc = pHost->mX11Monitor.start();
199 if (RT_SUCCESS(rc))
200 {
201 while (!pHost->mX11MonitorThreadStopping)
202 pHost->mX11Monitor.nextConfigurationEvent();
203 pHost->mX11Monitor.stop();
204 }
205 LogRelFlowFunc(("returning %Rrc\n", rc));
206 return rc;
207}
208
209/**
210 * Start the X11 window configuration change monitor thread.
211 */
212int SeamlessMain::startX11MonitorThread(void)
213{
214 int rc;
215
216 mX11MonitorThreadStopping = false;
217 if (isX11MonitorThreadRunning())
218 return VINF_SUCCESS;
219 rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThread, this, 0,
220 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
221 "X11 events");
222 if (RT_FAILURE(rc))
223 LogRelFunc(("Warning: failed to start X11 monitor thread (VBoxClient).\n"));
224 return rc;
225}
226
227/**
228 * Send a signal to the thread function that it should exit
229 */
230int SeamlessMain::stopX11MonitorThread(void)
231{
232 int rc;
233
234 mX11MonitorThreadStopping = true;
235 if (!isX11MonitorThreadRunning())
236 return VINF_SUCCESS;
237 mX11Monitor.interruptEventWait();
238 rc = RTThreadWait(mX11MonitorThread, RT_INDEFINITE_WAIT, NULL);
239 if (RT_SUCCESS(rc))
240 mX11MonitorThread = NIL_RTTHREAD;
241 else
242 LogRelThisFunc(("Failed to stop X11 monitor thread, rc=%Rrc!\n",
243 rc));
244 return rc;
245}
246
247/** Pause the service loop. */
248int SeamlessMain::pause()
249{
250 int rc;
251 const char *pcszStage;
252
253 LogRelFlowFunc(("\n"));
254 mfPaused = true;
255 do {
256 pcszStage = "Reporting end of support for seamless capability";
257 rc = VbglR3SeamlessSetCap(false);
258 if (RT_FAILURE(rc))
259 break;
260 pcszStage = "Interrupting the event loop";
261 rc = cancelEvent();
262 if (RT_FAILURE(rc))
263 break;
264 } while (0);
265 if (RT_FAILURE(rc))
266 LogRelFunc(("Failure. Stage: \"%s\" Error: %Rrc (VBoxClient)\n",
267 pcszStage, rc));
268 return rc;
269}
270
271/** Resume after pausing. */
272int SeamlessMain::resume()
273{
274 int rc;
275 const char *pcszStage;
276
277 LogRelFlowFunc(("\n"));
278 mfPaused = false;
279 do {
280 pcszStage = "Reporting support for seamless capability";
281 rc = VbglR3SeamlessSetCap(true);
282 if (RT_FAILURE(rc))
283 break;
284 pcszStage = "Interrupting the event loop";
285 rc = cancelEvent();
286 if (RT_FAILURE(rc))
287 break;
288 } while (0);
289 if (RT_FAILURE(rc))
290 LogRelFunc(("Failure. Stage: \"%s\" Error: %Rrc (VBoxClient)\n",
291 pcszStage, rc));
292 return rc;
293}
294
295/** @todo Expand this? */
296int SeamlessMain::selfTest()
297{
298 int rc = VERR_INTERNAL_ERROR;
299 const char *pcszStage;
300
301 LogRelFlowFunc(("\n"));
302 do {
303 pcszStage = "Testing event loop cancellation";
304 VbglR3InterruptEventWaits();
305 if (RT_FAILURE(VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL)))
306 break;
307 if ( VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL)
308 != VERR_TIMEOUT)
309 break;
310 } while(0);
311 if (RT_FAILURE(rc))
312 LogRel(("VBoxClient (seamless): self test failed. Stage: \"%s\"\n",
313 pcszStage));
314 return rc;
315}
316
317/** VBoxClient service class wrapping the logic for the seamless service while
318 * the main VBoxClient code provides the daemon logic needed by all services.
319 */
320class SeamlessService : public VBoxClient::Service
321{
322private:
323 SeamlessMain mSeamless;
324 bool mIsInitialised;
325public:
326 virtual const char *getPidFilePath()
327 {
328 return ".vboxclient-seamless.pid";
329 }
330 virtual int init()
331 {
332 int rc;
333
334 if (mIsInitialised)
335 return VERR_INTERNAL_ERROR;
336 rc = mSeamless.init();
337 if (RT_FAILURE(rc))
338 return rc;
339 rc = mSeamless.selfTest();
340 if (RT_FAILURE(rc))
341 {
342 mSeamless.stop();
343 return rc;
344 }
345 mIsInitialised = true;
346 return VINF_SUCCESS;
347 }
348 virtual int run(bool fDaemonised /* = false */)
349 {
350 int rc;
351 if (!mIsInitialised)
352 return VERR_INTERNAL_ERROR;
353 /* This only exits on error. */
354 rc = mSeamless.run();
355 mIsInitialised = false;
356 return rc;
357 }
358 virtual int pause() { return mSeamless.pause(); }
359 virtual int resume() { return mSeamless.resume(); }
360 virtual void cleanup()
361 {
362 VbglR3SeamlessSetCap(false);
363 }
364};
365
366VBoxClient::Service *VBoxClient::GetSeamlessService()
367{
368 return new SeamlessService;
369}
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