Changeset 52562 in vbox
- Timestamp:
- Sep 2, 2014 6:28:04 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 95827
- Location:
- trunk/src/VBox/Additions/x11/VBoxClient
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h
r52231 r52562 24 24 25 25 /** Exit with a fatal error. */ 26 #define FatalError(format) \26 #define VBClFatalError(format) \ 27 27 do { \ 28 28 char *pszMessage = RTStrAPrintf2 format; \ 29 29 LogRel(format); \ 30 doFatalError(pszMessage); \30 vbclFatalError(pszMessage); \ 31 31 } while(0) 32 32 33 33 /** Exit with a fatal error. */ 34 extern void doFatalError(char *pszMessage);34 extern void vbclFatalError(char *pszMessage); 35 35 36 /** Namespace for VBoxClient-specific things*/37 namespace VBoxClient { 36 /** Call clean-up for the current service and exit. */ 37 extern void VBClCleanUp(); 38 38 39 /** A simple classdescribing a service. VBoxClient will run exactly one39 /** A simple interface describing a service. VBoxClient will run exactly one 40 40 * service per invocation. */ 41 class Service : public RTCNonCopyable 41 struct VBCLSERVICE 42 42 { 43 public:44 43 /** Get the services default path to pidfile, relative to $HOME */ 45 44 /** @todo Should this also have a component relative to the X server number? 46 45 */ 47 virtual const char *getPidFilePath() = 0;46 const char *(*getPidFilePath)(void); 48 47 /** Special initialisation, if needed. @a pause and @a resume are 49 48 * guaranteed not to be called until after this returns. */ 50 virtual int init() { return VINF_SUCCESS; }49 int (*init)(struct VBCLSERVICE **ppInterface); 51 50 /** Run the service main loop */ 52 virtual int run(bool fDaemonised = false) = 0;51 int (*run)(struct VBCLSERVICE **ppInterface, bool fDaemonised); 53 52 /** Pause the service loop. This must be safe to call on a different thread 54 53 * and potentially before @a run is or after it exits. … … 57 56 * is available then @a pause or @a resume will be called as soon as it starts 58 57 * up. */ 59 virtual int pause() { return VINF_SUCCESS; }58 int (*pause)(struct VBCLSERVICE **ppInterface); 60 59 /** Resume after pausing. The same applies here as for @a pause. */ 61 virtual int resume() { return VINF_SUCCESS; }60 int (*resume)(struct VBCLSERVICE **ppInterface); 62 61 /** Clean up any global resources before we shut down hard. The last calls 63 62 * to @a pause and @a resume are guaranteed to finish before this is called. 64 63 */ 65 virtual void cleanup() = 0; 66 /** Virtual destructor. Not used */ 67 virtual ~Service() {} 64 void (*cleanup)(struct VBCLSERVICE **ppInterface); 68 65 }; 69 66 70 extern Service *GetClipboardService(); 71 extern Service *GetSeamlessService(); 72 extern Service *GetDisplayService(); 73 extern Service *GetHostVersionService(); 67 /** Default handler for various struct VBCLSERVICE member functions. */ 68 static int VBClServiceDefaultHandler(struct VBCLSERVICE **pSelf) 69 { 70 return VINF_SUCCESS; 71 } 72 73 /** Default handler for the struct VBCLSERVICE clean-up member function. 74 * Usually used because the service is cleaned up automatically when the user 75 * process/X11 exits. */ 76 static void VBClServiceDefaultCleanup(struct VBCLSERVICE **ppInterface) 77 { 78 NOREF(ppInterface); 79 } 80 81 extern struct VBCLSERVICE **VBClGetClipboardService(); 82 extern struct VBCLSERVICE **VBClGetSeamlessService(); 83 extern struct VBCLSERVICE **VBClGetDisplayService(); 84 extern struct VBCLSERVICE **VBClGetHostVersionService(); 74 85 #ifdef VBOX_WITH_DRAG_AND_DROP 75 extern Service *GetDragAndDropService();86 extern struct VBCLSERVICE **VBClGetDragAndDropService(); 76 87 #endif /* VBOX_WITH_DRAG_AND_DROP */ 77 88 78 extern void CleanUp();79 80 } /* namespace VBoxClient */81 82 89 #endif /* !___vboxclient_vboxclient_h */ -
trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp
r48945 r52562 278 278 } 279 279 280 class ClipboardService : public VBoxClient::Service 281 { 282 public: 283 virtual const char *getPidFilePath() 284 { 285 return ".vboxclient-clipboard.pid"; 286 } 287 virtual int run(bool fDaemonised /* = false */) 288 { 289 int rc = vboxClipboardConnect(); 290 if (RT_SUCCESS(rc)) 291 rc = vboxClipboardMain(); 292 if (RT_FAILURE(rc)) 293 LogRelFunc(("guest clipboard service terminated abnormally: return code %Rrc\n", rc)); 294 return rc; 295 } 296 virtual void cleanup() 297 { 298 /* Nothing to do. */ 299 } 280 static const char *getPidFilePath() 281 { 282 return ".vboxclient-clipboard.pid"; 283 } 284 285 static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised) 286 { 287 int rc = vboxClipboardConnect(); 288 289 NOREF(ppInterface); 290 if (RT_SUCCESS(rc)) 291 rc = vboxClipboardMain(); 292 if (RT_FAILURE(rc)) 293 LogRelFunc(("guest clipboard service terminated abnormally: return code %Rrc\n", rc)); 294 return rc; 295 } 296 297 struct VBCLSERVICE vbclClipboardInterface = 298 { 299 getPidFilePath, 300 VBClServiceDefaultHandler, /* init */ 301 run, 302 VBClServiceDefaultHandler, /* pause */ 303 VBClServiceDefaultHandler, /* resume */ 304 VBClServiceDefaultCleanup 300 305 }; 301 306 302 VBoxClient::Service *VBoxClient::GetClipboardService() 303 { 304 return new ClipboardService; 305 } 307 struct CLIPBOARDSERVICE 308 { 309 struct VBCLSERVICE *pInterface; 310 }; 311 312 struct VBCLSERVICE **VBClGetClipboardService() 313 { 314 struct CLIPBOARDSERVICE *pService = 315 (struct CLIPBOARDSERVICE *)RTMemAlloc(sizeof(*pService)); 316 317 if (!pService) 318 VBClFatalError(("Out of memory\n")); 319 pService->pInterface = &vbclClipboardInterface; 320 return &pService->pInterface; 321 } -
trunk/src/VBox/Additions/x11/VBoxClient/display.cpp
r52231 r52562 64 64 int rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS); 65 65 if (RT_FAILURE(rc)) 66 FatalError(("Failed to unset graphics capability, rc=%Rrc.\n", rc));66 VBClFatalError(("Failed to unset graphics capability, rc=%Rrc.\n", rc)); 67 67 rc = VbglR3SetMouseStatus(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); 68 68 if (RT_FAILURE(rc)) 69 FatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));69 VBClFatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc)); 70 70 rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED 71 71 | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST); 72 72 if (RT_FAILURE(rc)) 73 FatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));73 VBClFatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc)); 74 74 return VINF_SUCCESS; 75 75 } … … 82 82 | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0); 83 83 if (RT_FAILURE(rc)) 84 FatalError(("Failed to set filter mask, rc=%Rrc.\n", rc));84 VBClFatalError(("Failed to set filter mask, rc=%Rrc.\n", rc)); 85 85 rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0); 86 86 if (RT_FAILURE(rc)) 87 FatalError(("Failed to set graphics capability, rc=%Rrc.\n", rc));87 VBClFatalError(("Failed to set graphics capability, rc=%Rrc.\n", rc)); 88 88 rc = VbglR3SetMouseStatus(0); 89 89 if (RT_FAILURE(rc)) 90 FatalError(("Failed to set mouse status, rc=%Rrc.\n", rc));90 VBClFatalError(("Failed to set mouse status, rc=%Rrc.\n", rc)); 91 91 return VINF_SUCCESS; 92 92 } … … 106 106 status = system(pState->pcszXrandr); 107 107 if (WEXITSTATUS(status) != 0) /* Utility or extension not available. */ 108 FatalError(("Failed to execute the xrandr utility.\n"));108 VBClFatalError(("Failed to execute the xrandr utility.\n")); 109 109 RTStrPrintf(szCommand, sizeof(szCommand), "%s --q12", pState->pcszXrandr); 110 110 status = system(szCommand); … … 130 130 * sizeof(*pState->paSizeHints)); 131 131 if (!pState->paSizeHints) 132 FatalError(("Failed to re-allocate size hint memory.\n"));132 VBClFatalError(("Failed to re-allocate size hint memory.\n")); 133 133 for (i = pState->cSizeHints; i < iDisplay + 1; ++i) 134 134 pState->paSizeHints[i] = 0; … … 151 151 status = system(szCommand); 152 152 if (WEXITSTATUS(status) != 0) 153 FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));153 VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand)); 154 154 } 155 155 else … … 164 164 status = system(szCommand); 165 165 if (WEXITSTATUS(status) != 0) 166 FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));166 VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand)); 167 167 } 168 168 if ((!fSetPosition || fEnabled) && cx != 0 && cy != 0) … … 173 173 status = system(szCommand); 174 174 if (WEXITSTATUS(status) != 0) 175 FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));175 VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand)); 176 176 } 177 177 if (!fEnabled) … … 183 183 status = system(szCommand); 184 184 if (WEXITSTATUS(status) != 0) 185 FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));185 VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand)); 186 186 } 187 187 } … … 206 206 rc = VbglR3VideoModeGetHighestSavedScreen(&cScreens); 207 207 if (RT_FAILURE(rc)) 208 FatalError(("Failed to get the number of saved screen modes, rc=%Rrc\n",208 VBClFatalError(("Failed to get the number of saved screen modes, rc=%Rrc\n", 209 209 rc)); 210 210 for (i = 0; i < RT_MAX(cScreens + 1, 8); ++i) … … 216 216 &fEnabled); 217 217 if (RT_SUCCESS(rc) && i > cScreens) /* Sanity */ 218 FatalError(("Internal error retrieving the number of saved screen modes.\n"));218 VBClFatalError(("Internal error retrieving the number of saved screen modes.\n")); 219 219 if (RT_SUCCESS(rc)) 220 220 setModeX11(pState, cx, cy, cBPP, i, x, y, fEnabled, … … 230 230 while(rc == VERR_INTERRUPTED); 231 231 if (RT_FAILURE(rc)) /* VERR_NO_MEMORY? */ 232 FatalError(("event wait failed, rc=%Rrc\n", rc));232 VBClFatalError(("event wait failed, rc=%Rrc\n", rc)); 233 233 if (fEvents & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED) 234 234 { … … 262 262 { 263 263 if (rc != VERR_NOT_IMPLEMENTED) 264 FatalError(("Failed to get display change request, rc=%Rrc\n",264 VBClFatalError(("Failed to get display change request, rc=%Rrc\n", 265 265 rc)); 266 266 fSetPosition = false; … … 276 276 fEnabled)); 277 277 if (RT_FAILURE(rc)) 278 FatalError(("Failed to retrieve size hint, rc=%Rrc\n", rc));278 VBClFatalError(("Failed to retrieve size hint, rc=%Rrc\n", rc)); 279 279 if (iDisplay > INT32_MAX) 280 FatalError(("Received a size hint for too high display number %u\n",280 VBClFatalError(("Received a size hint for too high display number %u\n", 281 281 (unsigned) iDisplay)); 282 282 rc = VbglR3SeamlessGetLastEvent(&Mode); 283 283 if (RT_FAILURE(rc)) 284 FatalError(("Failed to check seamless mode, rc=%Rrc\n", rc));284 VBClFatalError(("Failed to check seamless mode, rc=%Rrc\n", rc)); 285 285 if (Mode == VMMDev_Seamless_Disabled) 286 286 { … … 290 290 && rc != VERR_HGCM_SERVICE_NOT_FOUND 291 291 && rc != VERR_NOT_IMPLEMENTED /* No HGCM */) 292 FatalError(("Failed to save size hint, rc=%Rrc\n", rc));292 VBClFatalError(("Failed to save size hint, rc=%Rrc\n", rc)); 293 293 } 294 294 setModeX11(pState, cx, cy, cBPP, iDisplay, x, y, fEnabled, … … 298 298 } 299 299 300 class DisplayService : public VBoxClient::Service 301 { 300 /** Display magic number, start of a UUID. */ 301 #define DISPLAYSERVICE_MAGIC 0xf0029993 302 303 /** VBoxClient service class wrapping the logic for the display service while 304 * the main VBoxClient code provides the daemon logic needed by all services. 305 */ 306 struct DISPLAYSERVICE 307 { 308 /** The service interface. */ 309 struct VBCLSERVICE *pInterface; 310 /** Magic number for sanity checks. */ 311 uint32_t magic; 312 /** State related to the X server. */ 302 313 struct x11State mState; 314 /** Are we initialised yet? */ 303 315 bool mfInit; 304 public: 305 virtual const char *getPidFilePath() 306 { 307 return ".vboxclient-display.pid"; 308 } 309 virtual int init() 310 { 311 int rc; 312 313 if (mfInit) 314 return VERR_WRONG_ORDER; 315 rc = initX11(&mState); 316 if (RT_FAILURE(rc)) 317 return rc; 318 rc = enableEventsAndCaps(); 319 if (RT_SUCCESS(rc)) 320 mfInit = true; 316 }; 317 318 static const char *getPidFilePath() 319 { 320 return ".vboxclient-display.pid"; 321 } 322 323 static struct DISPLAYSERVICE *getClassFromInterface(struct VBCLSERVICE ** 324 ppInterface) 325 { 326 struct DISPLAYSERVICE *pSelf = (struct DISPLAYSERVICE *)ppInterface; 327 if (pSelf->magic != DISPLAYSERVICE_MAGIC) 328 VBClFatalError(("Bad display service object!\n")); 329 return pSelf; 330 } 331 332 static int init(struct VBCLSERVICE **ppInterface) 333 { 334 struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface); 335 int rc; 336 337 if (pSelf->mfInit) 338 return VERR_WRONG_ORDER; 339 rc = initX11(&pSelf->mState); 340 if (RT_FAILURE(rc)) 321 341 return rc; 322 } 323 virtual int run(bool fDaemonised /* = false */) 324 { 325 if (!mfInit) 326 return VERR_WRONG_ORDER; 327 runDisplay(&mState); 328 return VERR_INTERNAL_ERROR; /* "Should never reach here." */ 329 } 330 virtual int pause() 331 { 332 if (!mfInit) 333 return VERR_WRONG_ORDER; 334 return disableEventsAndCaps(); 335 } 336 virtual int resume() 337 { 338 if (!mfInit) 339 return VERR_WRONG_ORDER; 340 return enableEventsAndCaps(); 341 } 342 virtual void cleanup() 343 { 344 disableEventsAndCaps(); 345 } 346 DisplayService() { mfInit = false; } 342 rc = enableEventsAndCaps(); 343 if (RT_SUCCESS(rc)) 344 pSelf->mfInit = true; 345 return rc; 346 } 347 348 static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised) 349 { 350 struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface); 351 352 if (!pSelf->mfInit) 353 return VERR_WRONG_ORDER; 354 runDisplay(&pSelf->mState); 355 return VERR_INTERNAL_ERROR; /* "Should never reach here." */ 356 } 357 358 static int pause(struct VBCLSERVICE **ppInterface) 359 { 360 struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface); 361 362 if (!pSelf->mfInit) 363 return VERR_WRONG_ORDER; 364 return disableEventsAndCaps(); 365 } 366 367 static int resume(struct VBCLSERVICE **ppInterface) 368 { 369 struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface); 370 371 if (!pSelf->mfInit) 372 return VERR_WRONG_ORDER; 373 return enableEventsAndCaps(); 374 } 375 376 static void cleanup(struct VBCLSERVICE **ppInterface) 377 { 378 NOREF(ppInterface); 379 disableEventsAndCaps(); 380 } 381 382 struct VBCLSERVICE vbclDisplayInterface = 383 { 384 getPidFilePath, 385 init, 386 run, 387 pause, 388 resume, 389 cleanup 347 390 }; 348 391 349 VBoxClient::Service *VBoxClient::GetDisplayService() 350 { 351 return new DisplayService; 352 } 392 struct VBCLSERVICE **VBClGetDisplayService() 393 { 394 struct DISPLAYSERVICE *pService = 395 (struct DISPLAYSERVICE *)RTMemAlloc(sizeof(*pService)); 396 397 if (!pService) 398 VBClFatalError(("Out of memory\n")); 399 pService->pInterface = &vbclDisplayInterface; 400 pService->magic = DISPLAYSERVICE_MAGIC; 401 pService->mfInit = false; 402 return &pService->pInterface; 403 } -
trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
r51556 r52562 441 441 ******************************************************************************/ 442 442 443 class DragAndDropService : public VBoxClient::Service443 class DragAndDropService 444 444 { 445 445 public: … … 453 453 {} 454 454 455 virtual const char *getPidFilePath() { return ".vboxclient-draganddrop.pid"; } 456 457 virtual int run(bool fDaemonised = false); 458 459 virtual void cleanup(void) 460 { 461 /* Nothing to do, everything should be cleaned up automatically when the 462 * user process/X11 client exits. */ 463 }; 455 int run(bool fDaemonised = false); 464 456 465 457 private: … … 2387 2379 } 2388 2380 2381 /** Drag and drop magic number, start of a UUID. */ 2382 #define DRAGANDDROPSERVICE_MAGIC 0x67c97173 2383 2384 /** VBoxClient service class wrapping the logic for the service while 2385 * the main VBoxClient code provides the daemon logic needed by all services. 2386 */ 2387 struct DRAGANDDROPSERVICE 2388 { 2389 /** The service interface. */ 2390 struct VBCLSERVICE *pInterface; 2391 /** Magic number for sanity checks. */ 2392 uint32_t magic; 2393 /** Service object. */ 2394 DragAndDropService mDragAndDrop; 2395 }; 2396 2397 static const char *getPidFilePath() 2398 { 2399 return ".vboxclient-draganddrop.pid"; 2400 } 2401 2402 static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised) 2403 { 2404 struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface; 2405 2406 if (pSelf->magic != DRAGANDDROPSERVICE_MAGIC) 2407 VBClFatalError(("Bad display service object!\n")); 2408 return pSelf->mDragAndDrop.run(fDaemonised); 2409 } 2410 2411 struct VBCLSERVICE vbclDragAndDropInterface = 2412 { 2413 getPidFilePath, 2414 VBClServiceDefaultHandler, /* init */ 2415 run, 2416 VBClServiceDefaultHandler, /* pause */ 2417 VBClServiceDefaultHandler, /* resume */ 2418 VBClServiceDefaultCleanup 2419 }; 2420 2389 2421 /* Static factory */ 2390 VBoxClient::Service *VBoxClient::GetDragAndDropService(void) 2391 { 2392 DragAndDropService *pService = new DragAndDropService(); 2393 return pService; 2394 } 2395 2422 struct VBCLSERVICE **VBClGetDragAndDropService(void) 2423 { 2424 struct DRAGANDDROPSERVICE *pService = 2425 (struct DRAGANDDROPSERVICE *)RTMemAlloc(sizeof(*pService)); 2426 2427 if (!pService) 2428 VBClFatalError(("Out of memory\n")); 2429 pService->pInterface = &vbclDragAndDropInterface; 2430 pService->magic = DRAGANDDROPSERVICE_MAGIC; 2431 new(&pService->mDragAndDrop) DragAndDropService(); 2432 return &pService->pInterface; 2433 } 2434 -
trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp
r44529 r52562 17 17 #include <iprt/assert.h> 18 18 #include <iprt/err.h> 19 #include <iprt/mem.h> 19 20 #include <iprt/ldr.h> 20 21 #include <iprt/string.h> … … 32 33 #include "VBoxClient.h" 33 34 34 class HostVersionService : public VBoxClient::Service 35 { 36 37 public: 38 39 virtual const char *getPidFilePath() 40 { 41 return ".vboxclient-hostversion.pid"; 42 } 43 44 virtual int showNotify(const char *pcHeader, const char *pcBody) 45 { 46 int rc; 35 static const char *getPidFilePath() 36 { 37 return ".vboxclient-hostversion.pid"; 38 } 39 40 static int showNotify(const char *pcHeader, const char *pcBody) 41 { 42 int rc; 47 43 # ifdef VBOX_WITH_DBUS 48 DBusConnection *conn; 49 DBusMessage* msg = NULL; 50 conn = dbus_bus_get (DBUS_BUS_SESSON, NULL); 51 if (conn == NULL) 52 { 53 LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n")); 44 DBusConnection *conn; 45 DBusMessage* msg = NULL; 46 conn = dbus_bus_get (DBUS_BUS_SESSON, NULL); 47 if (conn == NULL) 48 { 49 LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n")); 50 rc = VERR_INVALID_HANDLE; 51 } 52 else 53 { 54 msg = dbus_message_new_method_call("org.freedesktop.Notifications", 55 "/org/freedesktop/Notifications", 56 "org.freedesktop.Notifications", 57 "Notify"); 58 if (msg == NULL) 59 { 60 LogRel(("Could not create D-BUS message!\n")); 54 61 rc = VERR_INVALID_HANDLE; 55 62 } 56 63 else 57 { 58 msg = dbus_message_new_method_call("org.freedesktop.Notifications", 59 "/org/freedesktop/Notifications", 60 "org.freedesktop.Notifications", 61 "Notify"); 62 if (msg == NULL) 64 rc = VINF_SUCCESS; 65 } 66 if (RT_SUCCESS(rc)) 67 { 68 uint32_t msg_replace_id = 0; 69 const char *msg_app = "VBoxClient"; 70 const char *msg_icon = ""; 71 const char *msg_summary = pcHeader; 72 const char *msg_body = pcBody; 73 int32_t msg_timeout = -1; /* Let the notification server decide */ 74 75 DBusMessageIter iter; 76 DBusMessageIter array; 77 DBusMessageIter dict; 78 DBusMessageIter value; 79 DBusMessageIter variant; 80 DBusMessageIter data; 81 82 /* Format: UINT32 org.freedesktop.Notifications.Notify 83 * (STRING app_name, UINT32 replaces_id, STRING app_icon, STRING summary, STRING body, 84 * ARRAY actions, DICT hints, INT32 expire_timeout) 85 */ 86 dbus_message_iter_init_append(msg,&iter); 87 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_app); 88 dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&msg_replace_id); 89 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_icon); 90 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_summary); 91 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_body); 92 dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array); 93 dbus_message_iter_close_container(&iter,&array); 94 dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&array); 95 dbus_message_iter_close_container(&iter,&array); 96 dbus_message_iter_append_basic(&iter,DBUS_TYPE_INT32,&msg_timeout); 97 98 DBusError err; 99 dbus_error_init(&err); 100 101 DBusMessage *reply; 102 reply = dbus_connection_send_with_reply_and_block(conn, msg, 103 30 * 1000 /* 30 seconds timeout */, &err); 104 if (dbus_error_is_set(&err)) 105 { 106 LogRel(("D-BUS returned an error while sending the notification: %s", err.message)); 107 } 108 else if (reply) 109 { 110 dbus_connection_flush(conn); 111 dbus_message_unref(reply); 112 } 113 if (dbus_error_is_set(&err)) 114 dbus_error_free(&err); 115 } 116 if (msg != NULL) 117 dbus_message_unref(msg); 118 # else 119 /* TODO: Implement me */ 120 rc = VINF_SUCCESS; 121 # endif /* VBOX_WITH_DBUS */ 122 return rc; 123 } 124 125 /** @todo Move this part in VbglR3 and just provide a callback for the platform-specific 126 notification stuff, since this is very similar to the VBoxTray code. */ 127 static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised) 128 { 129 int rc; 130 LogFlowFunc(("\n")); 131 132 NOREF(ppInterface); 133 /* Because we need desktop notifications to be displayed, wait 134 * some time to make the desktop environment load (as a work around). */ 135 if (fDaemonised) 136 RTThreadSleep(30 * 1000 /* Wait 30 seconds */); 137 138 # ifdef VBOX_WITH_DBUS 139 rc = RTDBusLoadLib(); 140 if (RT_FAILURE(rc)) 141 LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n")); 142 # else 143 rc = VERR_NOT_IMPLEMENTED; 144 # endif /* VBOX_WITH_DBUS */ 145 146 # ifdef VBOX_WITH_GUEST_PROPS 147 uint32_t uGuestPropSvcClientID; 148 if (RT_SUCCESS(rc)) 149 { 150 rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID); 151 if (RT_FAILURE(rc)) 152 LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc)); 153 } 154 155 if (RT_SUCCESS(rc)) 156 { 157 char *pszHostVersion; 158 char *pszGuestVersion; 159 bool bUpdate; 160 161 rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion); 162 if (RT_SUCCESS(rc)) 163 { 164 if (bUpdate) 63 165 { 64 LogRel(("Could not create D-BUS message!\n")); 65 rc = VERR_INVALID_HANDLE; 66 } 67 else 68 rc = VINF_SUCCESS; 69 } 70 if (RT_SUCCESS(rc)) 71 { 72 uint32_t msg_replace_id = 0; 73 const char *msg_app = "VBoxClient"; 74 const char *msg_icon = ""; 75 const char *msg_summary = pcHeader; 76 const char *msg_body = pcBody; 77 int32_t msg_timeout = -1; /* Let the notification server decide */ 78 79 DBusMessageIter iter; 80 DBusMessageIter array; 81 DBusMessageIter dict; 82 DBusMessageIter value; 83 DBusMessageIter variant; 84 DBusMessageIter data; 85 86 /* Format: UINT32 org.freedesktop.Notifications.Notify 87 * (STRING app_name, UINT32 replaces_id, STRING app_icon, STRING summary, STRING body, 88 * ARRAY actions, DICT hints, INT32 expire_timeout) 89 */ 90 dbus_message_iter_init_append(msg,&iter); 91 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_app); 92 dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&msg_replace_id); 93 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_icon); 94 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_summary); 95 dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_body); 96 dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array); 97 dbus_message_iter_close_container(&iter,&array); 98 dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&array); 99 dbus_message_iter_close_container(&iter,&array); 100 dbus_message_iter_append_basic(&iter,DBUS_TYPE_INT32,&msg_timeout); 101 102 DBusError err; 103 dbus_error_init(&err); 104 105 DBusMessage *reply; 106 reply = dbus_connection_send_with_reply_and_block(conn, msg, 107 30 * 1000 /* 30 seconds timeout */, &err); 108 if (dbus_error_is_set(&err)) 109 { 110 LogRel(("D-BUS returned an error while sending the notification: %s", err.message)); 111 } 112 else if (reply) 113 { 114 dbus_connection_flush(conn); 115 dbus_message_unref(reply); 116 } 117 if (dbus_error_is_set(&err)) 118 dbus_error_free(&err); 119 } 120 if (msg != NULL) 121 dbus_message_unref(msg); 122 # else 123 /* TODO: Implement me */ 124 rc = VINF_SUCCESS; 125 # endif /* VBOX_WITH_DBUS */ 126 return rc; 127 } 128 129 /** @todo Move this part in VbglR3 and just provide a callback for the platform-specific 130 notification stuff, since this is very similar to the VBoxTray code. */ 131 virtual int run(bool fDaemonised /* = false */) 132 { 133 int rc; 134 LogFlowFunc(("\n")); 135 136 /* Because we need desktop notifications to be displayed, wait 137 * some time to make the desktop environment load (as a work around). */ 138 if (fDaemonised) 139 RTThreadSleep(30 * 1000 /* Wait 30 seconds */); 140 141 # ifdef VBOX_WITH_DBUS 142 rc = RTDBusLoadLib(); 143 if (RT_FAILURE(rc)) 144 LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n")); 145 # else 146 rc = VERR_NOT_IMPLEMENTED; 147 # endif /* VBOX_WITH_DBUS */ 148 149 # ifdef VBOX_WITH_GUEST_PROPS 150 uint32_t uGuestPropSvcClientID; 151 if (RT_SUCCESS(rc)) 152 { 153 rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID); 154 if (RT_FAILURE(rc)) 155 LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc)); 156 } 157 158 if (RT_SUCCESS(rc)) 159 { 160 char *pszHostVersion; 161 char *pszGuestVersion; 162 bool bUpdate; 163 164 rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion); 165 if (RT_SUCCESS(rc)) 166 { 167 if (bUpdate) 168 { 169 char szMsg[1024]; 170 char szTitle[64]; 171 172 /** @todo add some translation macros here */ 173 RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!"); 166 char szMsg[1024]; 167 char szTitle[64]; 168 169 /** @todo add some translation macros here */ 170 RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!"); 174 171 #ifndef VBOX_OSE 175 176 177 172 RTStrPrintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. " 173 "We recommend updating to the latest version (%s) by choosing the " 174 "install option from the Devices menu.", pszGuestVersion, pszHostVersion); 178 175 #else 179 176 /* This is the message which appears for non-Oracle builds of the 180 181 177 * Guest Additions. Distributors are encouraged to customise this. */ 178 RTStrPrintf(szMsg, sizeof(szMsg), "Your virtual machine is currently running the Guest Additions version %s. Since you are running a version of the Guest Additions provided by the operating system you installed in the virtual machine we recommend that you update it to at least version %s using that system's update features, or alternatively that you remove this version and then install the " VBOX_VENDOR_SHORT " Guest Additions package using the install option from the Devices menu. Please consult the documentation for the operating system you are running to find out how to update or remove the current Guest Additions package.", pszGuestVersion, pszHostVersion); 182 179 #endif 183 rc = showNotify(szTitle, szMsg); 184 LogRel(("VBoxClient: VirtualBox Guest Additions update available!")); 185 if (RT_FAILURE(rc)) 186 LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc)); 187 } 188 189 /* Store host version to not notify again */ 190 rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion); 191 192 VbglR3GuestPropReadValueFree(pszHostVersion); 193 VbglR3GuestPropReadValueFree(pszGuestVersion); 180 rc = showNotify(szTitle, szMsg); 181 LogRel(("VBoxClient: VirtualBox Guest Additions update available!")); 182 if (RT_FAILURE(rc)) 183 LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc)); 194 184 } 195 VbglR3GuestPropDisconnect(uGuestPropSvcClientID); 196 } 185 186 /* Store host version to not notify again */ 187 rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion); 188 189 VbglR3GuestPropReadValueFree(pszHostVersion); 190 VbglR3GuestPropReadValueFree(pszGuestVersion); 191 } 192 VbglR3GuestPropDisconnect(uGuestPropSvcClientID); 193 } 197 194 # endif /* VBOX_WITH_GUEST_PROPS */ 198 LogFlowFunc(("returning %Rrc\n", rc)); 199 return rc; 200 } 201 202 virtual void cleanup() 203 { 204 205 } 195 LogFlowFunc(("returning %Rrc\n", rc)); 196 return rc; 197 } 198 199 struct VBCLSERVICE vbclHostVersionInterface = 200 { 201 getPidFilePath, 202 VBClServiceDefaultHandler, /* init */ 203 run, 204 VBClServiceDefaultHandler, /* pause */ 205 VBClServiceDefaultHandler, /* resume */ 206 VBClServiceDefaultCleanup 206 207 }; 207 208 209 struct HOSTVERSIONSERVICE 210 { 211 struct VBCLSERVICE *pInterface; 212 }; 213 208 214 /* Static factory */ 209 VBoxClient::Service *VBoxClient::GetHostVersionService() 210 { 211 return new HostVersionService; 212 } 213 215 struct VBCLSERVICE **VBClGetHostVersionService() 216 { 217 struct HOSTVERSIONSERVICE *pService = 218 (struct HOSTVERSIONSERVICE *)RTMemAlloc(sizeof(*pService)); 219 220 if (!pService) 221 VBClFatalError(("Out of memory\n")); 222 pService->pInterface = &vbclHostVersionInterface; 223 return &pService->pInterface; 224 } 225 -
trunk/src/VBox/Additions/x11/VBoxClient/main.cpp
r52231 r52562 48 48 /** Object representing the service we are running. This has to be global 49 49 * so that the cleanup routine can access it. */ 50 VBoxClient::Service*g_pService;50 struct VBCLSERVICE **g_pService; 51 51 /** The name of our pidfile. It is global for the benefit of the cleanup 52 52 * routine. */ … … 62 62 63 63 /** Exit with a fatal error. */ 64 void doFatalError(char *pszMessage)64 void vbclFatalError(char *pszMessage) 65 65 { 66 66 char *pszCommand; … … 77 77 /** Clean up if we get a signal or something. This is extern so that we 78 78 * can call it from other compilation units. */ 79 void VB oxClient::CleanUp()79 void VBClCleanUp() 80 80 { 81 81 /* We never release this, as we end up with a call to exit(3) which is not … … 89 89 } 90 90 if (g_pService) 91 g_pService->cleanup();91 (*g_pService)->cleanup(g_pService); 92 92 if (g_szPidFile[0] && g_hPidFile) 93 93 VbglR3ClosePidFile(g_szPidFile, g_hPidFile); … … 104 104 /** Disable seamless mode */ 105 105 RTPrintf(("VBoxClient: terminating...\n")); 106 VB oxClient::CleanUp();106 VBClCleanUp(); 107 107 } 108 108 … … 126 126 { 127 127 LogRel(("VBoxClient: a fatal guest X Window error occurred. This may just mean that the Window system was shut down while the client was still running.\n")); 128 VB oxClient::CleanUp();128 VBClCleanUp(); 129 129 return 0; /* We should never reach this. */ 130 130 } … … 200 200 pcszStage = "asking service to pause or resume"; 201 201 if (cTTY == cVT) 202 rc = g_pService->resume();202 rc = (*g_pService)->resume(g_pService); 203 203 else 204 rc = g_pService->pause();204 rc = (*g_pService)->pause(g_pService); 205 205 if (RT_FAILURE(rc)) 206 206 break; … … 214 214 if (RTCritSectIsOwner(&g_critSect)) 215 215 RTCritSectLeave(&g_critSect); 216 VB oxClient::CleanUp();216 VBClCleanUp(); 217 217 } 218 218 } … … 273 273 { 274 274 LogRel(("Monitor thread: poll failed, stopping.\n")); 275 VB oxClient::CleanUp();275 VBClCleanUp(); 276 276 } 277 277 } … … 397 397 if (g_pService) 398 398 break; 399 g_pService = VB oxClient::GetClipboardService();399 g_pService = VBClGetClipboardService(); 400 400 } 401 401 else if (!strcmp(argv[i], "--display")) … … 403 403 if (g_pService) 404 404 break; 405 g_pService = VB oxClient::GetDisplayService();405 g_pService = VBClGetDisplayService(); 406 406 } 407 407 else if (!strcmp(argv[i], "--seamless")) … … 409 409 if (g_pService) 410 410 break; 411 g_pService = VB oxClient::GetSeamlessService();411 g_pService = VBClGetSeamlessService(); 412 412 } 413 413 else if (!strcmp(argv[i], "--checkhostversion")) … … 415 415 if (g_pService) 416 416 break; 417 g_pService = VB oxClient::GetHostVersionService();417 g_pService = VBClGetHostVersionService(); 418 418 } 419 419 #ifdef VBOX_WITH_DRAG_AND_DROP … … 422 422 if (g_pService) 423 423 break; 424 g_pService = VB oxClient::GetDragAndDropService();424 g_pService = VBClGetDragAndDropService(); 425 425 } 426 426 #endif /* VBOX_WITH_DRAG_AND_DROP */ … … 455 455 pcszStage = "Creating pid-file path"; 456 456 rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile), 457 g_pService->getPidFilePath());457 (*g_pService)->getPidFilePath()); 458 458 if (RT_FAILURE(rc)) 459 459 break; … … 477 477 XSetIOErrorHandler(vboxClientXLibIOErrorHandler); 478 478 pcszStage = "Initialising service"; 479 rc = g_pService->init();479 rc = (*g_pService)->init(g_pService); 480 480 } while (0); 481 481 if (RT_FAILURE(rc)) … … 492 492 rc)); 493 493 else 494 g_pService->run(fDaemonise); /* Should never return. */495 VB oxClient::CleanUp();494 (*g_pService)->run(g_pService, fDaemonise); /* Should never return. */ 495 VBClCleanUp(); 496 496 return 1; 497 497 } -
trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp
r50637 r52562 27 27 #include <VBox/VBoxGuestLib.h> 28 28 #include <iprt/err.h> 29 #include <iprt/mem.h> 29 30 30 31 #include "VBoxClient.h" 31 32 #include "seamless.h" 33 34 #include <new> 32 35 33 36 SeamlessMain::SeamlessMain(void) … … 316 319 } 317 320 321 /** Service magic number, start of a UUID. */ 322 #define SEAMLESSSERVICE_MAGIC 0xd28ba727 323 318 324 /** VBoxClient service class wrapping the logic for the seamless service while 319 325 * the main VBoxClient code provides the daemon logic needed by all services. 320 326 */ 321 class SeamlessService : public VBoxClient::Service 322 { 323 private: 327 struct SEAMLESSSERVICE 328 { 329 /** The service interface. */ 330 struct VBCLSERVICE *pInterface; 331 /** Magic number for sanity checks. */ 332 uint32_t magic; 333 /** Seamless service object. */ 324 334 SeamlessMain mSeamless; 335 /** Are we initialised yet? */ 325 336 bool mIsInitialised; 326 public: 327 virtual const char *getPidFilePath() 328 { 329 return ".vboxclient-seamless.pid"; 330 } 331 virtual int init() 332 { 333 int rc; 334 335 if (mIsInitialised) 336 return VERR_INTERNAL_ERROR; 337 rc = mSeamless.init(); 338 if (RT_FAILURE(rc)) 339 return rc; 340 rc = mSeamless.selfTest(); 341 if (RT_FAILURE(rc)) 342 { 343 mSeamless.stop(); 344 return rc; 345 } 346 mIsInitialised = true; 347 return VINF_SUCCESS; 348 } 349 virtual int run(bool fDaemonised /* = false */) 350 { 351 int rc; 352 if (!mIsInitialised) 353 return VERR_INTERNAL_ERROR; 354 /* This only exits on error. */ 355 rc = mSeamless.run(); 356 mIsInitialised = false; 337 }; 338 339 static const char *getPidFilePath(void) 340 { 341 return ".vboxclient-seamless.pid"; 342 } 343 344 static struct SEAMLESSSERVICE *getClassFromInterface(struct VBCLSERVICE ** 345 ppInterface) 346 { 347 struct SEAMLESSSERVICE *pSelf = (struct SEAMLESSSERVICE *)ppInterface; 348 if (pSelf->magic != SEAMLESSSERVICE_MAGIC) 349 VBClFatalError(("Bad seamless service object!\n")); 350 return pSelf; 351 } 352 353 static int init(struct VBCLSERVICE **ppInterface) 354 { 355 struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface); 356 int rc; 357 358 if (pSelf->mIsInitialised) 359 return VERR_INTERNAL_ERROR; 360 rc = pSelf->mSeamless.init(); 361 if (RT_FAILURE(rc)) 357 362 return rc; 358 } 359 virtual int pause() { return mSeamless.pause(); } 360 virtual int resume() { return mSeamless.resume(); } 361 virtual void cleanup() 362 { 363 VbglR3SeamlessSetCap(false); 364 } 363 rc = pSelf->mSeamless.selfTest(); 364 if (RT_FAILURE(rc)) 365 { 366 pSelf->mSeamless.stop(); 367 return rc; 368 } 369 pSelf->mIsInitialised = true; 370 return VINF_SUCCESS; 371 } 372 373 static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised) 374 { 375 struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface); 376 int rc; 377 378 if (!pSelf->mIsInitialised) 379 return VERR_INTERNAL_ERROR; 380 /* This only exits on error. */ 381 rc = pSelf->mSeamless.run(); 382 pSelf->mIsInitialised = false; 383 return rc; 384 } 385 386 static int pause(struct VBCLSERVICE **ppInterface) 387 { 388 struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface); 389 390 return pSelf->mSeamless.pause(); 391 } 392 393 static int resume(struct VBCLSERVICE **ppInterface) 394 { 395 struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface); 396 397 return pSelf->mSeamless.resume(); 398 } 399 400 static void cleanup(struct VBCLSERVICE **ppInterface) 401 { 402 NOREF(ppInterface); 403 VbglR3SeamlessSetCap(false); 404 } 405 406 struct VBCLSERVICE vbclSeamlessInterface = 407 { 408 getPidFilePath, 409 init, 410 run, 411 pause, 412 resume, 413 cleanup 365 414 }; 366 415 367 VBoxClient::Service *VBoxClient::GetSeamlessService() 368 { 369 return new SeamlessService; 370 } 416 struct VBCLSERVICE **VBClGetSeamlessService() 417 { 418 struct SEAMLESSSERVICE *pService = 419 (struct SEAMLESSSERVICE *)RTMemAlloc(sizeof(*pService)); 420 421 if (!pService) 422 VBClFatalError(("Out of memory\n")); 423 pService->pInterface = &vbclSeamlessInterface; 424 pService->magic = SEAMLESSSERVICE_MAGIC; 425 new(&pService->mSeamless) SeamlessMain(); 426 pService->mIsInitialised = false; 427 return &pService->pInterface; 428 } -
trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
r50495 r52562 25 25 26 26 static RTSEMEVENT eventSem; 27 28 /** Exit with a fatal error. */ 29 void vbclFatalError(char *pszMessage) 30 { 31 RTPrintf("Fatal error: %s", pszMessage); 32 exit(1); 33 } 27 34 28 35 int VbglR3SeamlessSendRects(uint32_t cRects, PRTRECT pRects)
Note:
See TracChangeset
for help on using the changeset viewer.