Changeset 50495 in vbox for trunk/src/VBox/Additions/x11/VBoxClient
- Timestamp:
- Feb 18, 2014 2:57:35 PM (11 years ago)
- Location:
- trunk/src/VBox/Additions/x11/VBoxClient
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp
r50471 r50495 36 36 mX11MonitorThread = NIL_RTTHREAD; 37 37 mX11MonitorThreadStopping = false; 38 mMode = VMMDev_Seamless_Disabled; 39 mfPaused = false; 38 40 } 39 41 … … 45 47 46 48 /** 47 * Start the main service thread which listens for host state change 49 * initialise the service. 50 */ 51 int 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 48 79 * notifications. 49 80 * @returns iprt status value. Service will be set to the stopped state on 50 81 * failure. 51 82 */ 52 int SeamlessMain::start(void) 53 { 54 int rc; 55 const char *pszStage; 56 57 LogRelFlowFunc(("\n")); 58 do { 59 pszStage = "Testing event loop cancellation"; 60 VbglR3InterruptEventWaits(); 61 if (RT_FAILURE(VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL))) 62 break; 63 if ( VbglR3WaitEvent(VMMDEV_EVENT_VALID_EVENT_MASK, 0, NULL) 64 != VERR_TIMEOUT) 65 break; 66 pszStage = "Connecting to the X server"; 67 rc = mX11Monitor.init(this); 68 if (RT_FAILURE(rc)) 69 break; 70 pszStage = "Setting guest IRQ filter mask"; 71 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0); 72 if (RT_FAILURE(rc)) 73 break; 74 pszStage = "Reporting support for seamless capability"; 75 rc = VbglR3SeamlessSetCap(true); 76 if (RT_FAILURE(rc)) 77 break; 78 pszStage = "Running event loop"; 79 /* This will only exit if something goes wrong. */ 80 /** @todo Add a "stopping" variable. Actually "pausing" the service 81 * should be enough. */ 82 while (RT_SUCCESS(rc) || rc == VERR_TRY_AGAIN || rc == VERR_INTERRUPTED) 83 { 84 if (RT_FAILURE(rc)) 85 /* If we are not stopping, sleep for a bit to avoid using up too 86 much CPU while retrying. */ 87 RTThreadYield(); 88 rc = nextStateChangeEvent(); 89 } 90 } while(0); 91 if (RT_FAILURE(rc)) 92 { 93 LogRel(("VBoxClient (seamless): failed to start. Stage: \"%s\" Error: %Rrc\n", 94 pszStage, rc)); 83 int 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)); 95 101 stop(); 96 102 } 97 LogRelFlowFunc(("returning %Rrc\n", rc));98 103 return rc; 99 104 } … … 123 128 if (RT_SUCCESS(rc)) 124 129 { 125 switch(newMode) 130 mMode = newMode; 131 switch (newMode) 126 132 { 127 133 case VMMDev_Seamless_Visible_Region: 128 /* A simplified seamless mode, obtained by making the host VM window borderless and 129 making the guest desktop transparent. */ 130 LogRelFlowFunc(("VMMDev_Seamless_Visible_Region request received (VBoxClient).\n")); 131 /** @todo Do something on failure, like bail out. */ 132 startX11MonitorThread(); 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")); 133 140 break; 134 141 case VMMDev_Seamless_Host_Window: 135 142 /* One host window represents one guest window. Not yet implemented. */ 136 LogRelFunc((" Warning: VMMDev_Seamless_Host_Window request received (VBoxClient).\n"));137 /* fall through to default */143 LogRelFunc(("Unsupported \"host window\" mode requested (VBoxClient).\n")); 144 return VERR_NOT_SUPPORTED; 138 145 default: 139 LogRelFunc(("Warning: unsupported VMMDev_Seamless request %d received (VBoxClient).\n", newMode)); 140 /* fall through to case VMMDev_Seamless_Disabled */ 141 case VMMDev_Seamless_Disabled: 142 LogRelFlowFunc(("VMMDev_Seamless_Disabled set (VBoxClient).\n")); 143 stopX11MonitorThread(); 146 LogRelFunc(("Unsupported mode %d requested (VBoxClient).\n", 147 newMode)); 148 return VERR_NOT_SUPPORTED; 144 149 } 145 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 } 146 160 else 147 161 { … … 150 164 LogRelFlowFunc(("returning %Rrc\n", rc)); 151 165 return rc; 166 } 167 168 int SeamlessMain::cancelEvent(void) 169 { 170 return VbglR3InterruptEventWaits(); 152 171 } 153 172 … … 196 215 197 216 mX11MonitorThreadStopping = false; 217 if (isX11MonitorThreadRunning()) 218 return VINF_SUCCESS; 198 219 rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThread, this, 0, 199 220 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, … … 207 228 * Send a signal to the thread function that it should exit 208 229 */ 209 voidSeamlessMain::stopX11MonitorThread(void)230 int SeamlessMain::stopX11MonitorThread(void) 210 231 { 211 232 int rc; 212 233 213 234 mX11MonitorThreadStopping = true; 214 if (! mX11MonitorThread)215 return ;235 if (!isX11MonitorThreadRunning()) 236 return VINF_SUCCESS; 216 237 mX11Monitor.interruptEventWait(); 217 238 rc = RTThreadWait(mX11MonitorThread, RT_INDEFINITE_WAIT, NULL); … … 221 242 LogRelThisFunc(("Failed to stop X11 monitor thread, rc=%Rrc!\n", 222 243 rc)); 223 } 224 225 /** @todo Re-arrange the service to support pausing and resuming. The state 226 * needs to become more complex: we need to know: whether seamless is currently 227 * requested by the host; whether we are currently in charge of the guest 228 * desktop; whether the guest monitoring thead is currently active. */ 244 return rc; 245 } 246 247 /** Pause the service loop. */ 248 int 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. */ 272 int 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? */ 296 int 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 pcszStage = "Testing pause"; /* Other states are dangerous to test. */ 311 mMode = VMMDev_Seamless_Visible_Region; 312 pause(); 313 if (RT_FAILURE(nextStateChangeEvent())) 314 break; 315 if (isX11MonitorThreadRunning()) 316 break; 317 mMode = VMMDev_Seamless_Disabled; 318 mfPaused = false; 319 rc = VINF_SUCCESS; 320 } while(0); 321 if (RT_FAILURE(rc)) 322 LogRel(("VBoxClient (seamless): self test failed. Stage: \"%s\"\n", 323 pcszStage)); 324 return rc; 325 } 326 229 327 /** VBoxClient service class wrapping the logic for the seamless service while 230 328 * the main VBoxClient code provides the daemon logic needed by all services. … … 240 338 return ".vboxclient-seamless.pid"; 241 339 } 242 virtual int run(bool fDaemonised /* = false */)340 virtual int init() 243 341 { 244 342 int rc; 343 245 344 if (mIsInitialised) 246 345 return VERR_INTERNAL_ERROR; 346 rc = mSeamless.init(); 347 if (RT_FAILURE(rc)) 348 return rc; 349 rc = mSeamless.selfTest(); 350 if (RT_FAILURE(rc)) 351 { 352 mSeamless.stop(); 353 return rc; 354 } 247 355 mIsInitialised = true; 248 rc = mSeamless.start(); 249 LogRelFunc(("VBoxClient: seamless service failed to start. Error: %Rrc\n", 250 rc)); 356 return VINF_SUCCESS; 357 } 358 virtual int run(bool fDaemonised /* = false */) 359 { 360 int rc; 361 if (!mIsInitialised) 362 return VERR_INTERNAL_ERROR; 363 /* This only exits on error. */ 364 rc = mSeamless.run(); 365 mIsInitialised = false; 251 366 return rc; 252 367 } 368 virtual int pause() { return mSeamless.pause(); } 369 virtual int resume() { return mSeamless.resume(); } 253 370 virtual void cleanup() 254 371 { -
trunk/src/VBox/Additions/x11/VBoxClient/seamless.h
r50471 r50495 45 45 volatile bool mX11MonitorThreadStopping; 46 46 47 /** The current seamless mode we are in. */ 48 VMMDevSeamlessMode mMode; 49 /** Is the service currently paused? */ 50 volatile bool mfPaused; 51 47 52 /** 48 53 * Waits for a seamless state change events from the host and dispatch it. This is … … 54 59 55 60 /** 56 * Interrupt an event wait and cause nextStateChangeEvent() to return immediately. 61 * Interrupt an event wait and cause the current or next 62 * @a nextStateChangeEvent call to return immediately. 57 63 */ 58 void cancelEvent(void) { VbglR3InterruptEventWaits(); }64 int cancelEvent(void); 59 65 60 66 /** Thread function to monitor X11 window configuration changes. */ … … 65 71 66 72 /** Helper to stop the X11 monitor thread again. */ 67 void stopX11MonitorThread(void); 73 int stopX11MonitorThread(void); 74 75 /** Is the service currently actively monitoring X11 windows? */ 76 bool isX11MonitorThreadRunning() 77 { 78 return mX11MonitorThread != NIL_RTTHREAD; 79 } 68 80 69 81 public: … … 72 84 73 85 /** 74 * Start the service. 86 * Initialise the service. 87 */ 88 int init(void); 89 90 /** 91 * Run the service. 75 92 * @returns iprt status value 76 93 */ 77 int start(void);94 int run(void); 78 95 79 96 /** … … 82 99 void stop(); 83 100 101 /** Pause the service loop. This must be safe to call on a different thread 102 * and potentially before @a run is or after it exits. 103 * This is called by the VT monitoring thread to allow the service to disable 104 * itself when the X server is switched out. If the monitoring functionality 105 * is available then @a pause or @a resume will be called as soon as it starts 106 * up. */ 107 int pause(); 108 /** Resume after pausing. The same applies here as for @a pause. */ 109 int resume(); 110 84 111 /** 85 112 * Update the set of visible rectangles in the host. 86 113 */ 87 114 virtual void sendRegionUpdate(RTRECT *pRects, size_t cRects); 115 116 /** Run a few tests to be sure everything is working as intended. */ 117 int selfTest(); 88 118 }; 89 119 -
trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
r50471 r50495 120 120 SeamlessMain seamless; 121 121 LogRel(("Starting seamless Guest Additions...\n")); 122 rc = seamless. start();122 rc = seamless.init(); 123 123 if (rc != VINF_SUCCESS) 124 124 { 125 125 RTPrintf("Failed to initialise seamless Additions, rc = %Rrc\n", rc); 126 126 } 127 rc = seamless.run(); 128 if (rc != VINF_SUCCESS) 129 { 130 RTPrintf("Failed to run seamless Additions, rc = %Rrc\n", rc); 131 } 127 132 return rc; 128 133 }
Note:
See TracChangeset
for help on using the changeset viewer.