VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xclient/seamless-host.cpp@ 6290

Last change on this file since 6290 was 6290, checked in by vboxsync, 17 years ago

Guest Additions: update for the Linux seamless additions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.5 KB
Line 
1/** @file
2 *
3 * Seamless mode:
4 * Linux guest.
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
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 <iprt/log.h>
24#include <iprt/err.h>
25
26#include "seamless-host.h"
27
28/**
29 * Start the service.
30 * @returns iprt status value
31 */
32int VBoxGuestSeamlessHost::start(void)
33{
34 int rc = VERR_NOT_SUPPORTED;
35
36 if (mRunning) /* Assertion */
37 {
38 LogRel(("VBoxService: seamless service started twice!\n"));
39 return VERR_INTERNAL_ERROR;
40 }
41 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0);
42 if (RT_FAILURE(rc))
43 {
44 LogRel(("VBoxService (seamless): failed to set the guest IRQ filter mask, rc=%Rrc\n", rc));
45 }
46 rc = VbglR3SeamlessSetCap(true);
47 if (RT_SUCCESS(rc))
48 {
49 Log(("VBoxService: enabled seamless capability on host.\n"));
50 rc = mThread.start();
51 if (RT_SUCCESS(rc))
52 {
53 mRunning = true;
54 }
55 else
56 {
57 LogRel(("VBoxService: failed to start seamless event thread, rc=%Rrc. Disabled seamless capability on host again.\n", rc));
58 VbglR3SeamlessSetCap(false);
59 }
60 }
61 if (RT_FAILURE(rc))
62 {
63 Log(("VBoxService (seamless): failed to enable seamless capability on host, rc=%Rrc\n", rc));
64 }
65 return rc;
66}
67
68/** Stops the service. */
69void VBoxGuestSeamlessHost::stop(void)
70{
71 if (!mRunning) /* Assertion */
72 {
73 LogRel(("VBoxService: tried to stop seamless service which is not running!\n"));
74 return;
75 }
76 mThread.stop(0, 0);
77 VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
78 VbglR3SeamlessSetCap(false);
79 mRunning = false;
80}
81
82/**
83 * Waits for a seamless state change events from the host and dispatch it.
84 *
85 * @returns IRPT return code.
86 */
87int VBoxGuestSeamlessHost::nextEvent(void)
88{
89 VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled;
90
91 int rc = VbglR3SeamlessWaitEvent(&newMode);
92 if (RT_SUCCESS(rc))
93 {
94 switch(newMode)
95 {
96 case VMMDev_Seamless_Visible_Region:
97 /* A simplified seamless mode, obtained by making the host VM window borderless and
98 making the guest desktop transparent. */
99 #ifdef DEBUG
100 LogRelFunc(("VMMDev_Seamless_Visible_Region request received (VBoxService).\n"));
101 #endif
102 mState = ENABLE;
103 mObserver->notify();
104 break;
105 case VMMDev_Seamless_Host_Window:
106 /* One host window represents one guest window. Not yet implemented. */
107 LogRelFunc(("Warning: VMMDev_Seamless_Host_Window request received (VBoxService).\n"));
108 /* fall through to default */
109 default:
110 LogRelFunc(("Warning: unsupported VMMDev_Seamless request %d received (VBoxService).\n", newMode));
111 /* fall through to case VMMDev_Seamless_Disabled */
112 case VMMDev_Seamless_Disabled:
113 #ifdef DEBUG
114 LogRelFunc(("VMMDev_Seamless_Disabled set (VBoxService).\n"));
115 #endif
116 mState = DISABLE;
117 mObserver->notify();
118 }
119 }
120 else
121 {
122 LogFunc(("VbglR3SeamlessWaitEvent returned %Rrc (VBoxService)\n", rc));
123 }
124 return rc;
125}
126
127/**
128 * Update the set of visible rectangles in the host.
129 */
130void VBoxGuestSeamlessHost::updateRects(std::auto_ptr<std::vector<RTRECT> > pRects)
131{
132 if (0 == pRects.get()) /* Assertion */
133 {
134 LogRelThisFunc(("ERROR: called with null pointer!\n"));
135 return;
136 }
137 VbglR3SeamlessSendRects(pRects.get()->size(), pRects.get()->data());
138}
139
140/**
141 * The actual thread function.
142 *
143 * @returns iprt status code as thread return value
144 * @param pParent the VBoxGuestThread running this thread function
145 */
146int VBoxGuestSeamlessHostThread::threadFunction(VBoxGuestThread *pThread)
147{
148 if (0 != mHost)
149 {
150 mThread = pThread;
151 while (!mThread->isStopping())
152 {
153 if (RT_FAILURE(mHost->nextEvent()) && !mThread->isStopping())
154 {
155 /* If we are not stopping, sleep for a bit to avoid using up too
156 much CPU while retrying. */
157 mThread->yield();
158 }
159 }
160 }
161 return VINF_SUCCESS;
162}
163
164/**
165 * Send a signal to the thread function that it should exit
166 */
167void VBoxGuestSeamlessHostThread::stop(void)
168{
169 if (0 != mHost)
170 {
171 /**
172 * @todo is this reasonable? If the thread is in the event loop then the cancelEvent()
173 * will cause it to exit. If it enters or exits the event loop it will also
174 * notice that we wish it to exit. And if it is somewhere in-between, the
175 * yield() should give it time to get to one of places mentioned above.
176 */
177 for (int i = 0; (i < 5) && mThread->isRunning(); ++i)
178 {
179 mHost->cancelEvent();
180 mThread->yield();
181 }
182 }
183}
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