Changeset 50346 in vbox
- Timestamp:
- Feb 6, 2014 2:40:20 PM (11 years ago)
- Location:
- trunk/src/VBox/Additions/x11/VBoxClient
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp
r50338 r50346 96 96 * 97 97 * @note This class does not contain its own event thread, so an external thread must 98 * call next Event() for as long as events are wished.98 * call nextConfigurationEvent() for as long as events are wished. 99 99 * @todo This function should switch the guest to fullscreen mode. 100 100 */ … … 289 289 * @note Called from the guest event thread. 290 290 */ 291 void SeamlessX11::next Event(void)291 void SeamlessX11::nextConfigurationEvent(void) 292 292 { 293 293 XEvent event; … … 299 299 { 300 300 updateRects(); 301 mHost-> notify(mpRects, mcRects);301 mHost->sendRegionUpdate(mpRects, mcRects); 302 302 } 303 303 mChanged = false; … … 528 528 * @note This function should only be called from the host event thread. 529 529 */ 530 bool SeamlessX11::interruptEvent (void)530 bool SeamlessX11::interruptEventWait(void) 531 531 { 532 532 bool rc = false; -
trunk/src/VBox/Additions/x11/VBoxClient/seamless-x11.h
r50338 r50346 41 41 { 42 42 public: 43 virtual void notify(RTRECT *pRects, size_t cRects) = 0;43 virtual void sendRegionUpdate(RTRECT *pRects, size_t cRects) = 0; 44 44 }; 45 45 … … 216 216 void uninit(void) 217 217 { 218 if (0 != mHost) 219 { 218 if (mHost) 220 219 stop(); 221 } 222 mHost = 0; 220 mHost = NULL; 221 if (mDisplay) 222 XCloseDisplay(mDisplay); 223 mDisplay = NULL; 223 224 } 224 225 … … 237 238 238 239 /** Process next event in the guest event queue - called by the event thread. */ 239 void next Event(void);240 void nextConfigurationEvent(void); 240 241 /** Wake up the event thread if it is waiting for an event so that it can exit. */ 241 bool interruptEvent (void);242 bool interruptEventWait(void); 242 243 243 244 /* Methods to handle X11 events. These are public so that the unit test … … 255 256 { 256 257 uninit(); 257 if (mDisplay)258 XCloseDisplay(mDisplay);259 258 } 260 259 }; -
trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp
r50338 r50346 31 31 #include "seamless.h" 32 32 33 /** 34 * Start the service. 35 * @returns iprt status value 33 SeamlessMain::SeamlessMain(void) 34 { 35 LogRelFlowFunc(("\n")); 36 mX11MonitorThread = NIL_RTTHREAD; 37 mX11MonitorThreadStopping = false; 38 mHostEventThread = NIL_RTTHREAD; 39 mHostEventThreadRunning = false; 40 mHostEventThreadStopping = false; 41 } 42 43 SeamlessMain::~SeamlessMain() 44 { 45 LogRelFlowFunc(("\n")); 46 stop(); 47 } 48 49 /** 50 * Start the main service thread which listens for host state change 51 * notifications. 52 * @returns iprt status value. Service will be set to the stopped state on 53 * failure. 36 54 */ 37 55 int SeamlessMain::start(void) 38 56 { 39 int rc = VERR_NOT_SUPPORTED; 40 41 LogRelFlowFunc(("\n")); 42 if (mThread) /* Assertion */ 43 { 44 LogRel(("VBoxClient: seamless service started twice!\n")); 45 return VERR_INTERNAL_ERROR; 46 } 47 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0); 48 if (RT_FAILURE(rc)) 49 { 50 LogRel(("VBoxClient (seamless): failed to set the guest IRQ filter mask, rc=%Rrc\n", rc)); 51 } 52 rc = VbglR3SeamlessSetCap(true); 53 if (RT_SUCCESS(rc)) 54 { 55 LogRel(("VBoxClient: enabled seamless capability on host.\n")); 57 int rc; 58 const char *pszStage; 59 60 LogRelFlowFunc(("\n")); 61 do { 62 pszStage = "Checking that we are not already running"; 63 rc = VERR_INTERNAL_ERROR; 64 if (mHostEventThread) /* Assertion */ 65 break; 66 pszStage = "Connecting to the X server"; 67 rc = mX11Monitor.init(this); 68 if (RT_FAILURE(rc)) 69 break; 56 70 /* Create a thread to wait for requests from the host. This is currently 57 71 * done on a separate thread as the main thread monitors the X11 server … … 59 73 /** @todo Move the disconnection monitoring to its own thread (better, the 60 74 * VT monitor thread) and run this logic on the main service thread. */ 61 rc = RTThreadCreate(&mThread, threadFunction, this, 0, 62 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, 63 "Host events"); 64 if (RT_FAILURE(rc)) 65 { 66 LogRel(("VBoxClient: failed to start seamless event thread, rc=%Rrc. Disabled seamless capability on host again.\n", rc)); 67 VbglR3SeamlessSetCap(false); 68 } 69 } 75 pszStage = "Starting host event thread"; 76 rc = startHostEventThread(); 77 if (RT_FAILURE(rc)) 78 break; 79 pszStage = "Setting guest IRQ filter mask"; 80 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0); 81 if (RT_FAILURE(rc)) 82 break; 83 pszStage = "Reporting support for seamless capability"; 84 rc = VbglR3SeamlessSetCap(true); 85 if (RT_FAILURE(rc)) 86 break; 87 } while(0); 70 88 if (RT_FAILURE(rc)) 71 89 { 72 LogRel(("VBoxClient (seamless): failed to enable seamless capability on host, rc=%Rrc\n", rc)); 90 LogRel(("VBoxClient (seamless): failed to start. Stage: \"%s\" Error: %Rrc\n", 91 pszStage, rc)); 92 stop(); 73 93 } 74 94 LogRelFlowFunc(("returning %Rrc\n", rc)); … … 80 100 { 81 101 LogRelFlowFunc(("\n")); 82 if (!mThread) /* Assertion */ 83 LogRel(("VBoxClient: tried to stop seamless service which is not running!\n")); 84 else 85 stopThread(); 86 if (mX11MonitorRTThread) 87 stopX11Thread(); 102 VbglR3SeamlessSetCap(false); 88 103 VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST); 89 VbglR3SeamlessSetCap(false); 104 if (mHostEventThread) 105 stopHostEventThread(); 106 stopX11MonitorThread(); 107 mX11Monitor.uninit(); 90 108 LogRelFlowFunc(("returning\n")); 91 109 } … … 96 114 * @returns IRPT return code. 97 115 */ 98 int SeamlessMain::next Event(void)116 int SeamlessMain::nextStateChangeEvent(void) 99 117 { 100 118 VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled; … … 109 127 /* A simplified seamless mode, obtained by making the host VM window borderless and 110 128 making the guest desktop transparent. */ 111 #ifdef DEBUG 112 LogRelFunc(("VMMDev_Seamless_Visible_Region request received (VBoxClient).\n")); 113 #endif 114 mX11ThreadStopping = false; 129 LogRelFlowFunc(("VMMDev_Seamless_Visible_Region request received (VBoxClient).\n")); 115 130 /** @todo Do something on failure, like bail out. */ 116 if (RT_FAILURE(RTThreadCreate(&mX11MonitorRTThread, 117 x11ThreadFunction, this, 0, RTTHREADTYPE_MSG_PUMP, 118 RTTHREADFLAGS_WAITABLE, "X11 events"))) 119 LogRelFunc(("Warning: failed to start X11 monitor thread (VBoxClient).\n")); 131 startX11MonitorThread(); 120 132 break; 121 133 case VMMDev_Seamless_Host_Window: … … 127 139 /* fall through to case VMMDev_Seamless_Disabled */ 128 140 case VMMDev_Seamless_Disabled: 129 #ifdef DEBUG 130 LogRelFunc(("VMMDev_Seamless_Disabled set (VBoxClient).\n")); 131 #endif 132 if (mX11MonitorRTThread) 133 stopX11Thread(); 134 else 135 LogRelThisFunc(("Attempted to stop X11 monitor thread which is not running (VBoxClient)!\n")); 141 LogRelFlowFunc(("VMMDev_Seamless_Disabled set (VBoxClient).\n")); 142 stopX11MonitorThread(); 136 143 } 137 144 } … … 147 154 * Update the set of visible rectangles in the host. 148 155 */ 149 void SeamlessMain:: notify(RTRECT *pRects, size_t cRects)156 void SeamlessMain::sendRegionUpdate(RTRECT *pRects, size_t cRects) 150 157 { 151 158 LogRelFlowFunc(("\n")); … … 161 168 162 169 /** 163 * Th e actual event thread function.164 */ 165 int SeamlessMain:: threadFunction(RTTHREAD self, void *pvUser)170 * Thread to listen for seamless state change notifications from the host. 171 */ 172 int SeamlessMain::hostEventThread(RTTHREAD self, void *pvUser) 166 173 { 167 174 SeamlessMain *pHost = (SeamlessMain *)pvUser; 168 175 169 176 LogRelFlowFunc(("\n")); 170 pHost->m ThreadRunning = true;177 pHost->mHostEventThreadRunning = true; 171 178 if (0 != pHost) 172 179 { 173 while (!pHost->m ThreadStopping)180 while (!pHost->mHostEventThreadStopping) 174 181 { 175 if (RT_FAILURE(pHost->nextEvent()) && !pHost->mThreadStopping) 182 /* This thread is stopped by setting @a mHostEventThreadStopping 183 * and sending a cancel to the state change event wait, see below. 184 */ 185 if ( RT_FAILURE(pHost->nextStateChangeEvent()) 186 && !pHost->mHostEventThreadStopping) 176 187 { 177 188 /* If we are not stopping, sleep for a bit to avoid using up too … … 181 192 } 182 193 } 183 pHost->mThreadRunning = false; 184 LogRelFlowFunc(("returning VINF_SUCCESS\n")); 194 pHost->mHostEventThreadRunning = false; 185 195 return VINF_SUCCESS; 186 196 } 187 197 188 198 /** 189 * Send a signal to the thread that it should exit 190 */ 191 void SeamlessMain::stopThread() 199 * Start the seamless state change notification listener thread. 200 */ 201 int SeamlessMain::startHostEventThread() 202 { 203 int rc; 204 205 mHostEventThreadStopping = false; 206 rc = RTThreadCreate(&mHostEventThread, hostEventThread, this, 0, 207 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, 208 "Host events"); 209 if (RT_FAILURE(rc)) 210 LogRel(("VBoxClient: failed to start seamless event thread, rc=%Rrc.\n", 211 rc)); 212 return rc; 213 } 214 215 /** 216 * Send a signal to the host event thread that it should exit and poke it. 217 */ 218 void SeamlessMain::stopHostEventThread() 192 219 { 193 220 int rc; … … 200 227 * yield() should give it time to get to one of places mentioned above. 201 228 */ 202 m ThreadStopping = true;203 for (int i = 0; (i < 5) && m ThreadRunning; ++i)229 mHostEventThreadStopping = true; 230 for (int i = 0; (i < 5) && mHostEventThreadRunning; ++i) 204 231 { 205 232 cancelEvent(); 206 233 RTThreadYield(); 207 234 } 208 rc = RTThreadWait(m Thread, RT_INDEFINITE_WAIT, NULL);235 rc = RTThreadWait(mHostEventThread, RT_INDEFINITE_WAIT, NULL); 209 236 if (RT_SUCCESS(rc)) 210 m Thread = NIL_RTTHREAD;237 mHostEventThread = NIL_RTTHREAD; 211 238 else 212 239 LogRelThisFunc(("Failed to stop seamless event thread, rc=%Rrc!\n", … … 216 243 217 244 /** 218 * The actual X11 eventthread function.219 */ 220 int SeamlessMain::x11 ThreadFunction(RTTHREAD self, void *pvUser)245 * The actual X11 window configuration change monitor thread function. 246 */ 247 int SeamlessMain::x11MonitorThread(RTTHREAD self, void *pvUser) 221 248 { 222 249 SeamlessMain *pHost = (SeamlessMain *)pvUser; … … 227 254 if (RT_SUCCESS(rc)) 228 255 { 229 while (!pHost->mX11ThreadStopping) 230 { 231 pHost->mX11Monitor.nextEvent(); 232 } 256 while (!pHost->mX11MonitorThreadStopping) 257 pHost->mX11Monitor.nextConfigurationEvent(); 233 258 pHost->mX11Monitor.stop(); 234 259 } … … 238 263 239 264 /** 265 * Start the X11 window configuration change monitor thread. 266 */ 267 int SeamlessMain::startX11MonitorThread(void) 268 { 269 int rc; 270 271 mX11MonitorThreadStopping = false; 272 rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThread, this, 0, 273 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, 274 "X11 events"); 275 if (RT_FAILURE(rc)) 276 LogRelFunc(("Warning: failed to start X11 monitor thread (VBoxClient).\n")); 277 return rc; 278 } 279 280 /** 240 281 * Send a signal to the thread function that it should exit 241 282 */ 242 void SeamlessMain::stopX11Thread(void) 243 { 244 int rc; 245 246 mX11ThreadStopping = true; 247 mX11Monitor.interruptEvent(); 248 rc = RTThreadWait(mX11MonitorRTThread, RT_INDEFINITE_WAIT, NULL); 283 void SeamlessMain::stopX11MonitorThread(void) 284 { 285 int rc; 286 287 mX11MonitorThreadStopping = true; 288 if (!mX11MonitorThread) 289 return; 290 mX11Monitor.interruptEventWait(); 291 rc = RTThreadWait(mX11MonitorThread, RT_INDEFINITE_WAIT, NULL); 249 292 if (RT_SUCCESS(rc)) 250 mX11Monitor RTThread = NIL_RTTHREAD;293 mX11MonitorThread = NIL_RTTHREAD; 251 294 else 252 295 LogRelThisFunc(("Failed to stop X11 monitor thread, rc=%Rrc!\n", … … 269 312 virtual int run(bool fDaemonised /* = false */) 270 313 { 314 Display *pDisplay = NULL; 315 const char *pszStage; 316 XEvent ev; 271 317 int rc; 272 318 273 if (mIsInitialised) /* Assertion */ 319 do { 320 pszStage = "Checking that we are not already running"; 321 rc = VERR_INTERNAL_ERROR; 322 if (mIsInitialised) /* Assertion */ 323 break; 324 pszStage = "Connecting to the X server"; 325 rc = VERR_INTERNAL_ERROR; 326 pDisplay = XOpenDisplay(NULL); 327 if (!pDisplay) 328 break; 329 pszStage = "Starting the service"; 330 rc = mSeamless.start(); 331 if (RT_FAILURE(rc)) 332 break; 333 } while(0); 334 if (RT_FAILURE(rc)) 274 335 { 275 LogRelFunc(("error: called a second time! (VBoxClient)\n")); 276 rc = VERR_INTERNAL_ERROR; 277 } 278 if (RT_SUCCESS(rc)) 279 rc = mSeamless.init(); 280 if (RT_SUCCESS(rc)) 281 rc = mSeamless.start(); 282 if (RT_SUCCESS(rc)) 283 mIsInitialised = true; 284 if (RT_FAILURE(rc)) 285 { 286 LogRelFunc(("returning %Rrc (VBoxClient)\n", rc)); 336 LogRelFunc(("VBoxClient seamless service control: failed at stage: \"%s\". Error: %Rrc\n", 337 pszStage, rc)); 338 mSeamless.stop(); 339 if (pDisplay) 340 XCloseDisplay(pDisplay); 287 341 return rc; 288 342 } 343 mIsInitialised = true; 289 344 /* Stay running as long as X does... */ 290 Display *pDisplay = XOpenDisplay(NULL);291 XEvent ev;292 345 while (true) 293 346 XNextEvent(pDisplay, &ev); -
trunk/src/VBox/Additions/x11/VBoxClient/seamless.h
r50338 r50346 31 31 class SeamlessMain : public SeamlessHostProxy 32 32 { 33 public:34 /** Events which can be reported by this class */35 enum meEvent36 {37 /** Empty event */38 NONE,39 /** Request to enable seamless mode */40 ENABLE,41 /** Request to disable seamless mode */42 DISABLE43 };44 45 33 private: 46 34 // We don't want a copy constructor or assignment operator … … 48 36 SeamlessMain& operator=(const SeamlessMain&); 49 37 50 /** Have we been initialised yet? */51 bool mIsInitialised;52 38 /** X11 event monitor object */ 53 39 SeamlessX11 mX11Monitor; … … 55 41 /** Thread to start and stop when we enter and leave seamless mode which 56 42 * monitors X11 windows in the guest. */ 57 RTTHREAD mX11Monitor RTThread;43 RTTHREAD mX11MonitorThread; 58 44 /** Should the X11 monitor thread be stopping? */ 59 volatile bool mX11 ThreadStopping;45 volatile bool mX11MonitorThreadStopping; 60 46 /** Host seamless event thread. */ 61 RTTHREAD m Thread;47 RTTHREAD mHostEventThread; 62 48 /** Is the thread running? */ 63 volatile bool m ThreadRunning;49 volatile bool mHostEventThreadRunning; 64 50 /** Should the thread be stopping? */ 65 volatile bool m ThreadStopping;51 volatile bool mHostEventThreadStopping; 66 52 67 53 /** … … 71 57 * @returns IRPT return code. 72 58 */ 73 int next Event(void);59 int nextStateChangeEvent(void); 74 60 75 61 /** 76 * Interrupt an event wait and cause next Event() to return immediately.62 * Interrupt an event wait and cause nextStateChangeEvent() to return immediately. 77 63 */ 78 64 void cancelEvent(void) { VbglR3InterruptEventWaits(); } … … 80 66 /** Thread function to query seamless activation and deactivation events 81 67 * from the host. */ 82 static DECLCALLBACK(int) threadFunction(RTTHREAD self, void *pvUser); 68 static DECLCALLBACK(int) hostEventThread(RTTHREAD self, void *pvUser); 69 70 /** Helper to start the seamless state change notification listener 71 * thread. */ 72 int startHostEventThread(); 83 73 84 74 /** Helper to stop the event query thread again. */ 85 void stop Thread();75 void stopHostEventThread(); 86 76 87 77 /** Thread function to monitor X11 window configuration changes. */ 88 static DECLCALLBACK(int) x11ThreadFunction(RTTHREAD self, void *pvUser); 78 static DECLCALLBACK(int) x11MonitorThread(RTTHREAD self, void *pvUser); 79 80 /** Helper to start the X11 monitor thread. */ 81 int startX11MonitorThread(void); 89 82 90 83 /** Helper to stop the X11 monitor thread again. */ 91 void stopX11 Thread(void);84 void stopX11MonitorThread(void); 92 85 93 86 public: 94 /** 95 * Initialise the guest and ensure that it is capable of handling seamless mode 96 * @param pX11Monitor Object to monitor X11 guest windows. 97 * 98 * @returns iprt status code 99 */ 100 int init(void) 101 { 102 int rc; 103 104 LogRelFlowFunc(("\n")); 105 if (mIsInitialised) 106 return VERR_INTERNAL_ERROR; 107 rc = mX11Monitor.init(this); 108 if (RT_SUCCESS(rc)) 109 mIsInitialised = true; 110 return rc; 111 } 87 SeamlessMain(void); 88 ~SeamlessMain(); 112 89 113 90 /** … … 119 96 /** 120 97 * Stops the service. 121 * @param cMillies how long to wait for the thread to exit122 98 */ 123 99 void stop(); … … 126 102 * Update the set of visible rectangles in the host. 127 103 */ 128 virtual void notify(RTRECT *pRects, size_t cRects); 129 130 SeamlessMain(void) 131 { 132 mIsInitialised = false; 133 mX11MonitorRTThread = NIL_RTTHREAD; 134 mX11ThreadStopping = false; 135 mThread = NIL_RTTHREAD; 136 mThreadRunning = false; 137 mThreadStopping = false; 138 } 139 140 ~SeamlessMain() 141 { 142 LogRelFlowFunc(("\n")); 143 if (mThread) 144 stop(); 145 LogRelFlowFunc(("returning\n")); 146 } 104 virtual void sendRegionUpdate(RTRECT *pRects, size_t cRects); 147 105 }; 148 106 -
trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp
r50338 r50346 303 303 public: 304 304 testHost() : mfNotified(false) {} 305 virtual void notify(RTRECT *pRects, size_t cRects)305 virtual void sendRegionUpdate(RTRECT *pRects, size_t cRects) 306 306 { 307 307 mfNotified = true; … … 625 625 ++cErrs; 626 626 } 627 subject.next Event();627 subject.nextConfigurationEvent(); 628 628 if (!host.isNotified()) 629 629 { … … 633 633 } 634 634 smlsSetNextEvent(0, 0); 635 subject.next Event();635 subject.nextConfigurationEvent(); 636 636 if (!host.isNotified()) 637 637 { -
trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
r50338 r50346 35 35 pRects[i].yBottom); 36 36 } 37 return true;37 return VINF_SUCCESS; 38 38 } 39 39 … … 42 42 RTPrintf("%s\n", bState ? "Seamless capability set" 43 43 : "Seamless capability unset"); 44 return true;44 return VINF_SUCCESS; 45 45 } 46 46 … … 49 49 RTPrintf("IRQ filter mask changed. Or mask: 0x%x. Not mask: 0x%x\n", 50 50 u32OrMask, u32NotMask); 51 return true;51 return VINF_SUCCESS; 52 52 } 53 53 … … 70 70 } 71 71 } 72 return true;72 return rc; 73 73 } 74 74 … … 121 121 SeamlessMain seamless; 122 122 LogRel(("Starting seamless Guest Additions...\n")); 123 rc = seamless. init();123 rc = seamless.start(); 124 124 if (rc != VINF_SUCCESS) 125 125 { 126 RTPrintf("Failed to initialise seamless Additions, rc = % d\n", rc);126 RTPrintf("Failed to initialise seamless Additions, rc = %Rrc\n", rc); 127 127 } 128 128 RTStrmGetLine(g_pStdIn, ach, sizeof(ach));
Note:
See TracChangeset
for help on using the changeset viewer.