Changeset 6290 in vbox
- Timestamp:
- Jan 9, 2008 10:49:16 AM (17 years ago)
- Location:
- trunk/src
- Files:
-
- 1 deleted
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibSeamless.cpp
r6000 r6290 54 54 #ifdef DEBUG 55 55 if (RT_SUCCESS(rc)) 56 LogRel(("Successfully enabled seamless modeon the host.\n"));56 LogRel(("Successfully set the seamless capability on the host.\n")); 57 57 else 58 LogRel(("Failed to enabled seamless modeon the host, rc = %Rrc.\n", rc));58 LogRel(("Failed to set the seamless capability on the host, rc = %Rrc.\n", rc)); 59 59 #endif 60 60 return rc; … … 116 116 int rc; 117 117 118 if (0 == cRects) 119 return VINF_SUCCESS; 118 120 rc = VbglR3GRAlloc((VMMDevRequestHeader **)&req, 119 121 sizeof(VMMDevVideoSetVisibleRegion) + (cRects - 1) * sizeof(RTRECT), -
trunk/src/VBox/Additions/x11/xclient/Makefile.kmk
r6233 r6290 20 20 21 21 ifneq ($(USERNAME),bird) # crap 22 PROGRAMS = vboxadd-xclient22 PROGRAMS = vboxadd-xclient 23 23 endif 24 24 … … 27 27 vboxadd-xclient_TEMPLATE = VBOXLNX32GUESTR3EXE 28 28 vboxadd-xclient_SOURCES = clipboard.cpp main.cpp 29 vboxadd-xclient_DEFS += CLIPBOARD_LINUX 30 29 31 ifdef LINUX_SEAMLESS_GUEST 30 vboxadd-xclient_SOURCES += \31 seamless-host.cpp \32 seamless-x11.cpp \33 thread.cpp32 vboxadd-xclient_SOURCES += \ 33 seamless-host.cpp \ 34 seamless-x11.cpp \ 35 thread.cpp 34 36 endif 35 37 vboxadd-xclient_LIBPATH = $(PATH_TARGET)/vboxadd-xclient $(VBOX_LIBPATH32_X11) 38 # Ugly recursive dependency between the runtime and the guest library. Sorry. 36 39 vboxadd-xclient_LIBS = \ 37 40 $(PATH_LIB)/RuntimeLnx32GuestR3.a \ 38 41 $(PATH_LIB)/VBoxGuestR3LibLinux.a \ 42 $(PATH_LIB)/RuntimeLnx32GuestR3.a \ 39 43 pthread \ 40 44 rt \ … … 42 46 Xext \ 43 47 X11 44 vboxadd-xclient_DEFS = _GNU_SOURCE VBOX_HGCM 48 vboxadd-xclient_DEFS += _GNU_SOURCE VBOX_HGCM 49 45 50 ifdef LINUX_SEAMLESS_GUEST 46 vboxadd-xclient_DEFS += LINUX_SEAMLESS 51 vboxadd-xclient_DEFS += SEAMLESS_LINUX 47 52 endif 48 53 … … 55 60 56 61 ifdef LINUX_SEAMLESS_GUEST 57 ifdef VBOX_WITH_CPPUNIT_TESTCASES 58 PROGRAMS += tstSeamlessX11 59 tstSeamlessX11_TEMPLATE = VBOXCPPUNITEXE 60 tstSeamlessX11_SOURCES = \ 61 testcase/tstSeamlessX11.cpp \ 62 seamless-x11.cpp 63 tstSeamlessX11_INST = $(INST_TESTCASE) 64 endif 62 ifdef VBOX_WITH_TESTCASES 63 # Additional testcase designed to be run manually, which initiates and starts the Linux 64 # guest client part of the seamless additions in the host, faking seamless events from 65 # the host and writing information about guest events to standard output. 66 PROGRAMS += tstSeamlessX11 67 tstSeamlessX11_TEMPLATE = VBOXR3EXE 68 tstSeamlessX11_SOURCES = \ 69 testcase/tstSeamlessX11.cpp \ 70 seamless-host.cpp \ 71 seamless-x11.cpp \ 72 thread.cpp 73 tstSeamlessX11_LIBS = \ 74 $(LIB_RUNTIME) \ 75 Xext \ 76 X11 77 tstSeamlessX11_INST = $(INST_TESTCASE) 78 endif 65 79 endif 66 80 -
trunk/src/VBox/Additions/x11/xclient/main.cpp
r6202 r6290 17 17 */ 18 18 19 #define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR19 // #define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR 20 20 21 21 #include <VBox/VBoxGuest.h> … … 24 24 25 25 #include <iostream> 26 27 using std::cout;28 using std::endl;29 26 30 27 #include <sys/types.h> … … 94 91 95 92 /** 96 * Xlib error handler , so that we don't abort when we get a BadAtom error.97 */ 98 int vboxCli pboardXLibErrorHandler(Display *pDisplay, XErrorEvent *pError)93 * Xlib error handler for certain errors that we can't avoid. 94 */ 95 int vboxClientXLibErrorHandler(Display *pDisplay, XErrorEvent *pError) 99 96 { 100 97 char errorText[1024]; 101 98 102 LogFlowFunc(("\n"));103 99 if (pError->error_code == BadAtom) 104 100 { 105 101 /* This can be triggered in debug builds if a guest application passes a bad atom 106 102 in its list of supported clipboard formats. As such it is harmless. */ 107 Log FlowFunc(("ignoring BadAtom error and returning\n"));103 Log(("VBoxService: ignoring BadAtom error and returning\n")); 108 104 return 0; 109 105 } 106 if (pError->error_code == BadWindow) 107 { 108 /* This can be triggered if a guest application destroys a window before we notice. */ 109 Log(("VBoxService: ignoring BadWindow error and returning\n")); 110 return 0; 111 } 112 #ifdef CLIPBOARD_LINUX 110 113 vboxClipboardDisconnect(); 114 #endif 111 115 XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText)); 112 if (!gbDaemonise) 113 { 114 cout << "An X Window protocol error occurred: " << errorText << endl 115 << " Request code: " << int(pError->request_code) << endl 116 << " Minor code: " << int(pError->minor_code) << endl 117 << " Serial number of the failed request: " << int(pError->serial) << endl; 118 } 119 Log(("%s: an X Window protocol error occurred: %s. Request code: %d, minor code: %d, serial number: %d\n", 120 __PRETTY_FUNCTION__, pError->error_code, pError->request_code, pError->minor_code, 121 pError->serial)); 122 LogFlowFunc(("exiting\n")); 116 LogRel(("VBoxService: an X Window protocol error occurred: %s. Request code: %d, minor code: %d, serial number: %d\n", 117 pError->error_code, pError->request_code, pError->minor_code, pError->serial)); 123 118 exit(1); 124 119 } … … 145 140 if (optind < argc) 146 141 { 147 cout << "Unrecognized command line argument: " << argv[argc] <<endl;142 std::cout << "Unrecognized command line argument: " << argv[argc] << std::endl; 148 143 exit(1); 149 144 } … … 156 151 break; 157 152 default: 158 cout << "Unrecognized command line option: " << static_cast<char>(cOpt) << endl; 153 std::cout << "Unrecognized command line option: " << static_cast<char>(cOpt) 154 << std::endl; 159 155 case '?': 160 156 exit(1); … … 167 163 /* Initialise our runtime before all else. */ 168 164 RTR3Init(false); 169 LogFlowFunc(("\n")); 165 rc = VbglR3Init(); 166 if (RT_FAILURE(rc)) 167 { 168 std::cout << "Failed to connect to the VirtualBox kernel service" << std::endl; 169 return 1; 170 } 171 LogRel(("VBoxService: starting...\n")); 170 172 /* Initialise threading in X11 and in Xt. */ 171 173 if (!XInitThreads() || !XtToolkitThreadInitialize()) 172 174 { 173 LogRelFunc(("Error initialising threads in X11, returning 1.")); 174 cout << "Your guest system appears to be using an old, single-threaded version of the X Window System libraries. This program cannot continue." << endl; 175 LogRel(("VBoxService: error initialising threads in X11, exiting.")); 175 176 return 1; 176 177 } 177 /* Set an X11 error handler, so that we don't die when we get BadAtom errors. */ 178 XSetErrorHandler(vboxClipboardXLibErrorHandler); 178 /* Set an X11 error handler, so that we don't die when we get unavoidable errors. */ 179 XSetErrorHandler(vboxClientXLibErrorHandler); 180 #ifdef CLIPBOARD_LINUX 179 181 /* Connect to the host clipboard. */ 180 LogRel((" Starting clipboard Guest Additions...\n"));182 LogRel(("VBoxService: starting clipboard Guest Additions...\n")); 181 183 rc = vboxClipboardConnect(); 182 if ( rc != VINF_SUCCESS)183 { 184 LogRel((" vboxClipboardConnect failed with rc = %d\n", rc));185 cout << "Failed to connect to the host clipboard." << endl;186 } 184 if (RT_SUCCESS(rc)) 185 { 186 LogRel(("VBoxService: vboxClipboardConnect failed with rc = %Rrc\n", rc)); 187 } 188 #endif /* CLIPBOARD_LINUX defined */ 187 189 #ifdef SEAMLESS_LINUX 188 190 try 189 191 { 190 LogRel((" Starting seamless Guest Additions...\n"));192 LogRel(("VBoxService: starting seamless Guest Additions...\n")); 191 193 rc = seamless.init(); 192 if (rc != VINF_SUCCESS) 193 { 194 LogRel(("Failed to initialise seamless Additions, rc = %d\n", rc)); 195 cout << "Failed to initialise seamless Additions." << endl; 194 if (RT_FAILURE(rc)) 195 { 196 LogRel(("VBoxService: failed to initialise seamless Additions, rc = %Rrc\n", rc)); 196 197 } 197 198 } 198 199 catch (std::exception e) 199 200 { 200 LogRel(("Failed to initialise seamless Additions - caught exception: %s\n", e.what())); 201 cout << "Failed to initialise seamless Additions\n" << endl; 201 LogRel(("VBoxService: failed to initialise seamless Additions - caught exception: %s\n", e.what())); 202 202 rc = VERR_UNRESOLVED_ERROR; 203 203 } 204 204 catch (...) 205 205 { 206 LogRel(("Failed to initialise seamless Additions - caught unknown exception.\n")); 207 cout << "Failed to initialise seamless Additions\n" << endl; 206 LogRel(("VBoxService: failed to initialise seamless Additions - caught unknown exception.\n")); 208 207 rc = VERR_UNRESOLVED_ERROR; 209 208 } 210 209 #endif /* SEAMLESS_LINUX defined */ 210 #ifdef CLIPBOARD_LINUX 211 LogRel(("VBoxService: connecting to the shared clipboard service.\n")); 211 212 vboxClipboardMain(); 212 213 vboxClipboardDisconnect(); 214 #else /* CLIPBOARD_LINUX not defined */ 215 LogRel(("VBoxService: sleeping...\n")); 216 pause(); 217 LogRel(("VBoxService: exiting...\n")); 218 #endif /* CLIPBOARD_LINUX not defined */ 213 219 #ifdef SEAMLESS_LINUX 214 220 try … … 218 224 catch (std::exception e) 219 225 { 220 LogRel((" Error shutting down seamless Additions - caught exception: %s\n", e.what()));226 LogRel(("VBoxService: error shutting down seamless Additions - caught exception: %s\n", e.what())); 221 227 rc = VERR_UNRESOLVED_ERROR; 222 228 } 223 229 catch (...) 224 230 { 225 LogRel((" Error shutting down seamless Additions - caught unknown exception.\n"));231 LogRel(("VBoxService: error shutting down seamless Additions - caught unknown exception.\n")); 226 232 rc = VERR_UNRESOLVED_ERROR; 227 233 } 228 234 #endif /* SEAMLESS_LINUX defined */ 229 LogFlowFunc(("returning %Vrc\n", rc));230 235 return rc; 231 236 } -
trunk/src/VBox/Additions/x11/xclient/seamless-glue.h
r6202 r6290 20 20 # define __Additions_client_seamless_glue_h 21 21 22 #if 023 24 #include "seamless-host.h"25 #include "seamless-guest.h"26 27 #endif28 29 22 class VBoxGuestSeamlessObserver 30 23 { … … 34 27 }; 35 28 36 #if 037 /**38 * Observer to connect the guest and the host parts of the seamless guest client.39 * It starts the host part when the guest reports that it supports seamless mode and40 * stops it when the guest no longer supports seamless. It also proxies enter and41 * exit seamless mode requests from the host part to the guest and informs the host42 * part when the guest's visible area changes.43 */44 class VBoxGuestSeamlessGlue45 {46 private:47 VBoxGuestSeamlessHost *mHost;48 VBoxGuestSeamlessGuestImpl *mGuest;49 50 public:51 VBoxGuestSeamlessGlue(VBoxGuestSeamlessHost *pHost, VBoxGuestSeamlessGuestImpl *pGuest)52 : mHost(pHost), mGuest(pGuest) {}53 ~VBoxGuestSeamlessGlue();54 55 /** State change notification callback for the guest. */56 void guestNotify(VBoxGuestSeamlessGuest::meEvent event)57 {58 switch(event)59 {60 case VBoxGuestSeamlessGuest::CAPABLE:61 mHost->start();62 break;63 case VBoxGuestSeamlessGuest::INCAPABLE:64 mHost->stop();65 break;66 case VBoxGuestSeamlessGuest::UPDATE:67 mHost->updateRects(mGuest->getRects());68 break;69 default:70 break;71 }72 }73 74 /** State change notification callback for the host. */75 void hostNotify(VBoxGuestSeamlessHost::meEvent event)76 {77 switch(event)78 {79 case VBoxGuestSeamlessHost::ENABLE:80 mGuest->start();81 break;82 case VBoxGuestSeamlessHost::DISABLE:83 mGuest->stop();84 break;85 default:86 break;87 }88 }89 };90 #endif /* 0 */91 92 29 #endif /* __Additions_client_seamless_glue_h not defined */ -
trunk/src/VBox/Additions/x11/xclient/seamless-guest.h
r6202 r6290 73 73 /** Get the current list of visible rectangles. */ 74 74 std::auto_ptr<std::vector<RTRECT> > getRects(void); 75 /** Process next event in the guest event queue - called by the event thread. */ 76 void nextEvent(void); 77 /** Wake up the event thread if it is waiting for an event so that it can exit. */ 78 bool interruptEvent(void); 75 79 }; 76 80 -
trunk/src/VBox/Additions/x11/xclient/seamless-host.cpp
r6202 r6290 26 26 #include "seamless-host.h" 27 27 28 #ifdef DEBUG29 # include <stdio.h>30 # define DPRINT(a) printf a31 #else32 # define DPRINT(a)33 #endif34 35 28 /** 36 29 * Start the service. … … 43 36 if (mRunning) /* Assertion */ 44 37 { 45 LogRelThisFunc(("Service started twice!\n")); 46 DPRINT(("Service started twice!\n")); 38 LogRel(("VBoxService: seamless service started twice!\n")); 47 39 return VERR_INTERNAL_ERROR; 48 40 } 49 if (VbglR3SeamlessSetCap(true)) 41 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0); 42 if (RT_FAILURE(rc)) 50 43 { 51 DPRINT(("Enabled host seamless.\n")); 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")); 52 50 rc = mThread.start(); 53 51 if (RT_SUCCESS(rc)) … … 57 55 else 58 56 { 59 DPRINT(("Disabled host seamless again.\n"));57 LogRel(("VBoxService: failed to start seamless event thread, rc=%Rrc. Disabled seamless capability on host again.\n", rc)); 60 58 VbglR3SeamlessSetCap(false); 61 59 } … … 63 61 if (RT_FAILURE(rc)) 64 62 { 65 DPRINT(("Failed to enable host seamless, rc=%d\n", rc));63 Log(("VBoxService (seamless): failed to enable seamless capability on host, rc=%Rrc\n", rc)); 66 64 } 67 65 return rc; … … 73 71 if (!mRunning) /* Assertion */ 74 72 { 75 LogRel ThisFunc(("Servicenot running!\n"));73 LogRel(("VBoxService: tried to stop seamless service which is not running!\n")); 76 74 return; 77 75 } 78 76 mThread.stop(0, 0); 77 VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST); 79 78 VbglR3SeamlessSetCap(false); 80 79 mRunning = false; … … 88 87 int VBoxGuestSeamlessHost::nextEvent(void) 89 88 { 90 VMMDevSeamlessMode newMode ;89 VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled; 91 90 92 91 int rc = VbglR3SeamlessWaitEvent(&newMode); 93 switch(newMode)92 if (RT_SUCCESS(rc)) 94 93 { 95 case VMMDev_Seamless_Visible_Region: 96 /* A simplified seamless mode, obtained by making the host VM window borderless and 97 making the guest desktop transparent. */ 98 mState = ENABLE; 99 mObserver->notify(); 100 break; 101 case VMMDev_Seamless_Host_Window: 102 /* One host window represents one guest window. Not yet implemented. */ 103 LogRelFunc(("Warning: VMMDev_Seamless_Host_Window request received.\n")); 104 /* fall through to default */ 105 default: 106 LogRelFunc(("Warning: unsupported VMMDev_Seamless request received.\n")); 107 /* fall through to case VMMDev_Seamless_Disabled */ 108 case VMMDev_Seamless_Disabled: 109 mState = DISABLE; 110 mObserver->notify(); 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)); 111 123 } 112 124 return rc; -
trunk/src/VBox/Additions/x11/xclient/seamless-host.h
r6202 r6290 123 123 if (mObserver != 0) /* Assertion */ 124 124 { 125 LogRel ThisFunc(("ERROR: attempt to initialise servicetwice!\n"));125 LogRel(("VBoxService: ERROR: attempt to initialise seamless host object twice!\n")); 126 126 return VERR_INTERNAL_ERROR; 127 127 } … … 149 149 VBoxGuestSeamlessHost(void) : mThreadFunction(this), 150 150 mThread(&mThreadFunction, 0, RTTHREADTYPE_MAIN_WORKER, 151 RTTHREADFLAGS_WAITABLE, " Seamless host event thead")151 RTTHREADFLAGS_WAITABLE, "Host events") 152 152 { 153 153 mObserver = 0; … … 160 160 if (mRunning) /* Assertion */ 161 161 { 162 LogRel ThisFunc(("Servicestill running! Stopping...\n"));162 LogRel(("VBoxService: seamless host object still running! Stopping...\n")); 163 163 stop(); 164 164 } -
trunk/src/VBox/Additions/x11/xclient/seamless-x11.cpp
r6202 r6290 67 67 { 68 68 int rc = VINF_SUCCESS; 69 /** Dummy value s for XShapeQueryExtension*/70 int error, event;69 /** Dummy value for XXGetProperty */ 70 unsigned long nItems; 71 71 72 72 if (0 != mObserver) /* Assertion */ 73 73 { 74 LogRel ThisFunc(("ERROR: attempt to initialise servicetwice!\n"));74 LogRel(("VBoxService: ERROR: attempt to initialise seamless guest object twice!\n")); 75 75 return VERR_INTERNAL_ERROR; 76 76 } 77 if (!mDisplay.i sValid())78 { 79 LogRel ThisFunc(("Failed to acquire a connection to the display.\n"));77 if (!mDisplay.init()) 78 { 79 LogRel(("VBoxService: seamless guest object failed to acquire a connection to the display.\n")); 80 80 return VERR_ACCESS_DENIED; 81 81 } 82 if ( !XShapeQueryExtension(mDisplay, &event, &error))83 {84 LogFlowFunc(("X11 shape extension not supported, returning.\n"));85 return VERR_NOT_SUPPORTED;82 if (0 == XXGetProperty(mDisplay, DefaultRootWindow(mDisplay.get()), XA_WINDOW, 83 NET_CLIENT_LIST, &nItems).get()) 84 { 85 LogRel(("VBoxService: _NET_CLIENT_LIST property not supported by guest window manager. Seamless mode will not be enabled.\n")); 86 86 } 87 87 mObserver = pObserver; … … 100 100 { 101 101 int rc = VINF_SUCCESS; 102 103 isEnabled = true; 104 monitorDesktopWindows(); 102 /** Dummy values for XShapeQueryExtension */ 103 int error, event; 104 105 mSupportsShape = XShapeQueryExtension(mDisplay, &event, &error); 106 mEnabled = true; 107 monitorClientList(); 108 rebuildWindowTree(); 105 109 return rc; 106 110 } … … 110 114 void VBoxGuestSeamlessX11::stop(void) 111 115 { 112 isEnabled = false; 116 mEnabled = false; 117 unmonitorClientList(); 113 118 freeWindowTree(); 114 119 } 115 120 116 void VBoxGuestSeamlessX11::monitorDesktopWindows(void) 117 { 118 VBoxGuestX11Pointer<unsigned char> virtualRoots; 121 void VBoxGuestSeamlessX11::monitorClientList(void) 122 { 123 XSelectInput(mDisplay, DefaultRootWindow(mDisplay.get()), PropertyChangeMask); 124 } 125 126 void VBoxGuestSeamlessX11::unmonitorClientList(void) 127 { 128 XSelectInput(mDisplay, DefaultRootWindow(mDisplay.get()), 0); 129 } 130 131 void VBoxGuestSeamlessX11::rebuildWindowTree(void) 132 { 133 VBoxGuestX11Pointer<unsigned char> clientListRaw; 134 VBoxGuestX11Pointer<Window> clientList; 119 135 unsigned long nItems; 120 136 121 XSelectInput(mDisplay, DefaultRootWindow(mDisplay.get()), PropertyChangeMask);122 virtualRoots = XXGetProperty(mDisplay, DefaultRootWindow(mDisplay.get()), XA_CARDINAL,123 VIRTUAL_ROOTS_PROP, &nItems);124 if ((0 != virtualRoots.get()) && (0 != nItems))125 {126 rebuildWindowTree();127 }128 }129 130 void VBoxGuestSeamlessX11::rebuildWindowTree(void)131 {132 VBoxGuestX11Pointer<unsigned char> virtualRoots;133 Window *desktopWindows;134 unsigned long nItems;135 136 137 freeWindowTree(); 137 virtualRoots = XXGetProperty(mDisplay, DefaultRootWindow(mDisplay.get()), XA_CARDINAL,138 VIRTUAL_ROOTS_PROP, &nItems);139 desktopWindows = reinterpret_cast<Window *>(virtualRoots.get());138 clientListRaw = XXGetProperty(mDisplay, DefaultRootWindow(mDisplay.get()), XA_WINDOW, 139 NET_CLIENT_LIST, &nItems); 140 clientList = reinterpret_cast<Window *>(clientListRaw.release()); 140 141 for (unsigned i = 0; i < nItems; ++i) 141 142 { 142 addDesktopWindow(desktopWindows[i]); 143 } 144 /* This must be done last, so that we do not treat the desktop windows just added as 145 child windows. */ 146 addDesktopWindow(DefaultRootWindow(mDisplay.get())); 147 } 148 149 /** 150 * Store information about a desktop window and register for structure events on it. 151 * If it is mapped, go through the list of it's children and add information about 152 * mapped children to the tree of visible windows, making sure that those windows are 153 * not already in our list of desktop windows. 154 * 155 * @param hWin the window concerned - should be a "desktop" window 156 */ 157 void VBoxGuestSeamlessX11::addDesktopWindow(Window hWin) 158 { 159 unsigned int cChildren = 0; 160 VBoxGuestX11Pointer<Window> children; 161 XWindowAttributes winAttrib; 162 /** Dummies */ 163 Window root, parent, *pChildren; 164 165 if (!XGetWindowAttributes(mDisplay, hWin, &winAttrib)) 166 { 167 LogRelFunc(("Failed to get the window attributes for window %d\n", hWin)); 168 return; 169 } 170 mDesktopWindows.push_back(VBoxGuestDesktopInfo(hWin, winAttrib.x, winAttrib.y, 171 (IsUnmapped != winAttrib.map_state))); 172 XSelectInput(mDisplay, hWin, 173 StructureNotifyMask | SubstructureNotifyMask | PropertyChangeMask); 174 XQueryTree(mDisplay, hWin, &root, &parent, &pChildren, &cChildren); 175 children = pChildren; 176 if (0 == children.get()) 177 { 178 LogRelFunc(("Failed to get the tree of active X11 windows.\n")); 179 } 180 else 181 { 182 for (unsigned int i = 0; i < cChildren; ++i) 143 VBoxGuestX11Pointer<unsigned char> windowTypeRaw; 144 VBoxGuestX11Pointer<Atom> windowType; 145 unsigned long ulCount; 146 147 windowTypeRaw = XXGetProperty(mDisplay, clientList.get()[i], XA_ATOM, 148 WM_TYPE_PROP, &ulCount); 149 windowType = reinterpret_cast<Atom *>(windowTypeRaw.release()); 150 if ( (ulCount != 0) 151 && (*windowType != XInternAtom(mDisplay, WM_TYPE_DESKTOP_PROP, True))) 183 152 { 184 bool found = false; 185 186 for (unsigned int j = 0; j < mDesktopWindows.size() && !found; ++j) 187 { 188 if (children.get()[i] == mDesktopWindows[j].mWin) 189 { 190 found = true; 191 } 192 } 193 if (!found) 194 { 195 addWindowToList(children.get()[i], hWin); 196 } 153 addClientWindow(clientList.get()[i]); 197 154 } 198 155 } 199 156 } 200 157 201 void VBoxGuestSeamlessX11::add WindowToList(const Window hWin, const Window hParent)158 void VBoxGuestSeamlessX11::addClientWindow(const Window hWin) 202 159 { 203 160 XWindowAttributes winAttrib; 204 161 VBoxGuestX11Pointer<XRectangle> rects; 205 int cRects, iOrdering; 206 unsigned iParent; 207 bool isVisible = false, found = false; 162 int cRects = 0, iOrdering; 163 int x, y; 164 /** Dummy value for XTranslateCoordinates */ 165 Window dummyWin; 208 166 209 167 if (!XGetWindowAttributes(mDisplay, hWin, &winAttrib)) 210 168 { 211 LogRelFunc((" Failed to get the window attributes for window %d\n", hWin));169 LogRelFunc(("VBoxService: Failed to get the window attributes for window %d\n", hWin)); 212 170 return; 213 171 } 214 XShapeSelectInput(mDisplay, hWin, ShapeNotify); 215 rects = XShapeGetRectangles(mDisplay, hWin, ShapeClip, &cRects, &iOrdering); 216 if (0 == rects.get()) 217 { 218 cRects = 0; 219 } 220 if (IsViewable == winAttrib.map_state) 221 { 222 isVisible = true; 223 } 224 for (iParent = 0; iParent < mDesktopWindows.size() && !found; ++iParent) 225 { 226 if (hParent == mDesktopWindows[iParent].mWin) 172 if (mSupportsShape) 173 { 174 XShapeSelectInput(mDisplay, hWin, ShapeNotify); 175 rects = XShapeGetRectangles(mDisplay, hWin, ShapeClip, &cRects, &iOrdering); 176 if (0 == rects.get()) 227 177 { 228 found = true;178 cRects = 0; 229 179 } 230 180 } 231 if (found)232 {233 mGuestWindows.addWindow(hWin, isVisible, winAttrib.x, winAttrib.y,234 winAttrib.width, winAttrib.height, cRects, rects, hParent);235 }181 XSelectInput(mDisplay, hWin, StructureNotifyMask); 182 XTranslateCoordinates(mDisplay, hWin, DefaultRootWindow(mDisplay.get()), winAttrib.x, 183 winAttrib.y, &x, &y, &dummyWin); 184 mGuestWindows.addWindow(hWin, winAttrib.map_state != IsUnmapped, x, y, 185 winAttrib.width, winAttrib.height, cRects, rects); 236 186 } 237 187 … … 241 191 void VBoxGuestSeamlessX11::freeWindowTree(void) 242 192 { 243 for (unsigned int i = 0; i != mDesktopWindows.size(); ++i)244 {245 XSelectInput(mDisplay, mDesktopWindows[i].mWin, 0);246 }247 mDesktopWindows.clear();248 193 /* We use post-increment in the operation to prevent the iterator from being invalidated. */ 249 194 for (VBoxGuestWindowList::iterator it = mGuestWindows.begin(); it != mGuestWindows.end(); 250 195 mGuestWindows.removeWindow(it++)) 251 196 { 197 XSelectInput(mDisplay, it->first, 0); 252 198 XShapeSelectInput(mDisplay, it->first, 0); 253 199 } … … 290 236 291 237 /** 292 * Handle a configuration event in the seamless event thread by setting the new position and 293 * updating the host's rectangle information. 238 * Handle a configuration event in the seamless event thread by setting the new position. 294 239 * 295 240 * @param event the X11 event structure … … 297 242 void VBoxGuestSeamlessX11::doConfigureEvent(const XConfigureEvent *event) 298 243 { 299 bool found = false; 300 unsigned i = 0; 301 302 for (i = 0; i < mDesktopWindows.size() && !found; ++i) 303 { 304 if (event->window == mDesktopWindows[i].mWin) 305 { 306 found = true; 307 } 308 } 309 if (found) 310 { 311 mDesktopWindows[i].mx = event->x; 312 mDesktopWindows[i].my = event->y; 313 } 314 else 315 { 316 VBoxGuestWindowList::iterator iter; 317 318 iter = mGuestWindows.find(event->window); 319 if (iter != mGuestWindows.end()) 320 { 321 iter->second->mx = event->x; 322 iter->second->my = event->y; 323 } 324 } 325 } 326 327 /** 328 * Handle a map event in the seamless event thread by adding the guest window to the list of 329 * visible windows and updating the host's rectangle information. 244 VBoxGuestWindowList::iterator iter; 245 246 iter = mGuestWindows.find(event->window); 247 if (iter != mGuestWindows.end()) 248 { 249 iter->second->mX = event->x; 250 iter->second->mY = event->y; 251 iter->second->mWidth = event->width; 252 iter->second->mHeight = event->height; 253 } 254 } 255 256 /** 257 * Handle a map event in the seamless event thread. 330 258 * 331 259 * @param event the X11 event structure … … 334 262 { 335 263 VBoxGuestWindowList::iterator iter; 336 bool found = false; 337 338 /* Is one of our desktop windows? */ 339 for (unsigned i = 0; i < mDesktopWindows.size() && !found; ++i) 340 { 341 if (event->window == mDesktopWindows[i].mWin) 342 { 343 mDesktopWindows[i].mMapped = true; 344 found = true; 345 } 346 } 347 if (!found) 348 { 349 /* Make sure that the window is not already present in the tree */ 350 iter = mGuestWindows.find(event->window); 351 if (iter != mGuestWindows.end()) 352 { 353 LogRelFunc(("Warning: MapNotify event received for a window listed as mapped\n")); 354 mGuestWindows.removeWindow(event->window); 355 } 356 addWindowToList(event->window, event->event); 357 } 358 } 359 360 /** 361 * If the list of virtual root windows changes, completely rescan visible windows. 264 265 iter = mGuestWindows.find(event->window); 266 if (iter != mGuestWindows.end()) 267 { 268 iter->second->mMapped = true; 269 } 270 } 271 272 /** 273 * If the list of client windows changes, rebuild the list. 362 274 * 363 275 * @param event the X11 event structure … … 365 277 void VBoxGuestSeamlessX11::doPropertyEvent(const XPropertyEvent *event) 366 278 { 367 if (XInternAtom(mDisplay, VIRTUAL_ROOTS_PROP, true) == event->atom)279 if (XInternAtom(mDisplay, NET_CLIENT_LIST, true) == event->atom) 368 280 { 369 281 rebuildWindowTree(); … … 372 284 373 285 /** 374 * Handle a window shape change event in the seamless event thread by changing the set of 375 * visible rectangles for the window in the list of visible guest windows and updating the 376 * host's rectangle information. 286 * Handle a window shape change event in the seamless event thread. 377 287 * 378 288 * @param event the X11 event structure … … 398 308 399 309 /** 400 * Handle an unmap event in the seamless event thread by removing the guest window from the 401 * list of visible windows and updating the host's rectangle information. 310 * Handle an unmap event in the seamless event thread. 402 311 * 403 312 * @param event the X11 event structure … … 406 315 { 407 316 VBoxGuestWindowList::iterator iter; 408 bool found = false; 409 410 /* Is this is one of our desktop windows? */ 411 for (unsigned i = 0; i < mDesktopWindows.size() && !found; ++i) 412 { 413 if (event->window == mDesktopWindows[i].mWin) 414 { 415 mDesktopWindows[i].mMapped = false; 416 found = true; 417 } 418 } 419 if (!found) 420 { 421 /* Make sure that the window is not already present in the tree */ 422 iter = mGuestWindows.find(event->window); 423 if (iter != mGuestWindows.end()) 424 { 425 mGuestWindows.removeWindow(event->window); 426 } 427 else 428 { 429 LogRelFunc(("Warning: UnmapNotify event received for a window not listed as mapped\n")); 430 } 317 318 iter = mGuestWindows.find(event->window); 319 if (iter != mGuestWindows.end()) 320 { 321 iter->second->mMapped = true; 431 322 } 432 323 } … … 447 338 it != mGuestWindows.end(); ++it) 448 339 { 449 Window hParent = it->second->mParent; 450 unsigned iParent; 451 bool found = false; 452 453 for (iParent = 0; iParent < mDesktopWindows.size() && !found; ++iParent) 340 if (it->second->mMapped) 454 341 { 455 if ( mDesktopWindows[iParent].mWin == hParent)342 if (it->second->mcRects > 0) 456 343 { 457 found = true; 344 for (int i = 0; i < it->second->mcRects; ++i) 345 { 346 RTRECT rect; 347 rect.xLeft = it->second->mX 348 + it->second->mapRects.get()[i].x; 349 rect.yBottom = it->second->mY 350 + it->second->mapRects.get()[i].y 351 + it->second->mapRects.get()[i].height; 352 rect.xRight = it->second->mX 353 + it->second->mapRects.get()[i].x 354 + it->second->mapRects.get()[i].width; 355 rect.yTop = it->second->mY 356 + it->second->mapRects.get()[i].y; 357 apRects.get()->push_back(rect); 358 } 359 cRects += it->second->mcRects; 360 } 361 else 362 { 363 RTRECT rect; 364 rect.xLeft = it->second->mX; 365 rect.yBottom = it->second->mY 366 + it->second->mHeight; 367 rect.xRight = it->second->mX 368 + it->second->mWidth; 369 rect.yTop = it->second->mY; 370 apRects.get()->push_back(rect); 371 ++cRects; 458 372 } 459 373 } 460 if (found && mDesktopWindows[iParent - 1].mMapped && it->second->mMapped)461 {462 for (int i = 0; i < it->second->mcRects; ++i)463 {464 RTRECT rect;465 rect.xLeft = it->second->mx466 + it->second->mapRects.get()[i].x467 + mDesktopWindows[iParent].mx;468 rect.yBottom = it->second->my469 + it->second->mapRects.get()[i].y470 + it->second->mapRects.get()[i].height471 + mDesktopWindows[iParent].my;472 rect.xRight = it->second->mx473 + it->second->mapRects.get()[i].x474 + it->second->mapRects.get()[i].width475 + mDesktopWindows[iParent].mx;476 rect.yTop = it->second->my477 + it->second->mapRects.get()[i].y478 + mDesktopWindows[iParent].my;479 apRects.get()->push_back(rect);480 }481 cRects += it->second->mcRects;482 }483 374 } 484 375 mcRects = cRects; … … 493 384 bool VBoxGuestSeamlessX11::interruptEvent(void) 494 385 { 495 XClientMessageEvent clientMessage = { ClientMessage }; /* Other members set to zero. */ 496 XSendEvent(mDisplay, DefaultRootWindow(mDisplay.get()), false, StructureNotifyMask, 497 reinterpret_cast<XEvent *>(&clientMessage)); 498 return true; 499 } 386 /* Message contents set to zero. */ 387 XClientMessageEvent clientMessage = { ClientMessage, 0, 0, 0, 0, 0, 8 }; 388 389 if (0 != XSendEvent(mDisplay, DefaultRootWindow(mDisplay.get()), false, PropertyChangeMask, 390 reinterpret_cast<XEvent *>(&clientMessage))) 391 { 392 XFlush(mDisplay); 393 return true; 394 } 395 return false; 396 } -
trunk/src/VBox/Additions/x11/xclient/seamless-x11.h
r6202 r6290 29 29 30 30 #define VIRTUAL_ROOTS_PROP "_NET_VIRTUAL_ROOTS" 31 #define WM_TYPE_PROP "_NET_WM_WINDOW_TYPE" 32 #define WM_TYPE_DESKTOP_PROP "_NET_WM_WINDOW_TYPE_DESKTOP" 33 #define NET_CLIENT_LIST "_NET_CLIENT_LIST" 31 34 32 35 /** … … 132 135 Display *mDisplay; 133 136 public: 134 VBoxGuestX11Display(char *name = 0) 137 VBoxGuestX11Display(void) {} 138 bool init(char *name = 0) 135 139 { 136 140 mDisplay = XOpenDisplay(name); 141 return (0 != mDisplay); 137 142 } 138 143 operator Display *() { return mDisplay; } … … 147 152 struct VBoxGuestWinInfo { 148 153 public: 149 /** Is th iswindow currently mapped? */154 /** Is the window currently mapped? */ 150 155 bool mMapped; 151 156 /** Co-ordinates in the guest screen. */ 152 int m x, my;157 int mX, mY; 153 158 /** Window dimensions. */ 154 int m width, mheight;159 int mWidth, mHeight; 155 160 /** Number of rectangles used to represent the visible area. */ 156 161 int mcRects; … … 158 163 and will be freed automatically if non-null when the class is destroyed. */ 159 164 VBoxGuestX11Pointer<XRectangle> mapRects; 160 /** The index of the virtual root that this window is a child of. */161 int mParent;162 165 /** Constructor. */ 163 VBoxGuestWinInfo(bool mapped, int x, int y, int w, int h, int cRects,164 VBoxGuestX11Pointer<XRectangle> rects , int parent)166 VBoxGuestWinInfo(bool isMapped, int x, int y, int w, int h, int cRects, 167 VBoxGuestX11Pointer<XRectangle> rects) 165 168 : mapRects(rects) 166 169 { 167 mMapped = mapped; mx = x; my = y; mwidth = w; mheight = h; mcRects = cRects; 168 mParent = parent; 170 mMapped = isMapped, mX = x; mY = y; mWidth = w; mHeight = h; mcRects = cRects; 169 171 } 170 172 … … 214 216 215 217 void addWindow(Window hWin, bool isMapped, int x, int y, int w, int h, int cRects, 216 VBoxGuestX11Pointer<XRectangle> rects , int parent)218 VBoxGuestX11Pointer<XRectangle> rects) 217 219 { 218 220 VBoxGuestWinInfo *pInfo = new VBoxGuestWinInfo(isMapped, x, y, w, h, cRects, 219 rects , parent);221 rects); 220 222 mWindows.insert(std::pair<Window, VBoxGuestWinInfo *>(hWin, pInfo)); 221 223 } … … 230 232 { 231 233 removeWindow(find(hWin)); 232 }233 };234 235 /** Structure containing information about a windows handle and position, for keeping236 track of desktop windows. Used internally by VBoxGuestSeamlessX11. */237 struct VBoxGuestDesktopInfo238 {239 /** The Window handle for this window. */240 Window mWin;241 /** Co-ordinates relative to the root window (I hope!). */242 int mx, my;243 /** Is this window mapped? */244 bool mMapped;245 246 /** Constructor */247 VBoxGuestDesktopInfo(Window hWin, int x, int y, bool mapped)248 {249 mWin = hWin;250 mx = x;251 my = y;252 mMapped = mapped;253 234 } 254 235 }; … … 268 249 /** Our connection to the X11 display we are running on. */ 269 250 VBoxGuestX11Display mDisplay; 270 /** Vector to keep track of which windows are to be treated as desktop windows. */271 std::vector<VBoxGuestDesktopInfo> mDesktopWindows;272 251 /** Class to keep track of visible guest windows. */ 273 252 VBoxGuestWindowList mGuestWindows; … … 276 255 the vector of rectangles passed to the host. */ 277 256 int mcRects; 257 /** Do we support the X shaped window extension? */ 258 bool mSupportsShape; 278 259 /** Is seamles mode currently enabled? */ 279 bool isEnabled;260 bool mEnabled; 280 261 281 262 // Private methods … … 297 278 * @param hWin the window concerned - should be a "desktop" window 298 279 */ 299 void addDesktopWindow(Window hWin); 300 bool addNonDesktopWindow(Window hWin); 301 void addWindowToList(Window hWin, Window hParent); 302 void monitorDesktopWindows(void); 280 void monitorClientList(void); 281 void unmonitorClientList(void); 303 282 void rebuildWindowTree(void); 283 void addClientWindow(Window hWin); 304 284 void freeWindowTree(void); 305 285 void updateHostSeamlessInfo(void); … … 337 317 std::auto_ptr<std::vector<RTRECT> > getRects(void); 338 318 339 /** Process next event in the X11event queue - called by the event thread. */319 /** Process next event in the guest event queue - called by the event thread. */ 340 320 void nextEvent(void); 341 /** Send ourselves an X11 client event to wake up the event thread - called by 342 the event thread. */ 321 /** Wake up the event thread if it is waiting for an event so that it can exit. */ 343 322 bool interruptEvent(void); 344 323 345 324 VBoxGuestSeamlessX11(void) 346 325 { 347 mObserver = 0; mcRects = 0; isEnabled= false;326 mObserver = 0; mcRects = 0; mEnabled = false; mSupportsShape = false; 348 327 } 349 328 -
trunk/src/VBox/Additions/x11/xclient/seamless.h
r6202 r6290 29 29 /** The guest class "owning" us. */ 30 30 VBoxGuestSeamlessGuestImpl *mGuest; 31 /** The guest observer monitoring the guest. */ 32 VBoxGuestSeamlessObserver *mObserver; 31 33 /** Should we exit the thread? */ 32 34 bool mExit; … … 37 39 38 40 public: 39 VBoxGuestSeamlessGuestThread(VBoxGuestSeamlessGuestImpl *pGuest) 40 { mGuest = pGuest; mExit = false; } 41 VBoxGuestSeamlessGuestThread(VBoxGuestSeamlessGuestImpl *pGuest, 42 VBoxGuestSeamlessObserver *pObserver) 43 { mGuest = pGuest; mObserver = pObserver; mExit = false; } 41 44 virtual ~VBoxGuestSeamlessGuestThread(void) {} 42 45 /** … … 48 51 virtual int threadFunction(VBoxGuestThread *pThread) 49 52 { 50 while (!pThread->isStopping) 53 int rc = VINF_SUCCESS; 54 55 rc = mGuest->start(); 56 if (RT_SUCCESS(rc)) 51 57 { 52 mGuest->nextEvent(); 58 while (!pThread->isStopping()) 59 { 60 mGuest->nextEvent(); 61 } 62 mGuest->stop(); 53 63 } 54 return VINF_SUCCESS;64 return rc; 55 65 } 56 66 /** … … 66 76 private: 67 77 VBoxGuestSeamlessHost *mHost; 68 VBoxGuest SeamlessGuestImpl *mGuest;78 VBoxGuestThread *mGuestThread; 69 79 70 80 public: 71 81 VBoxGuestSeamlessHostObserver(VBoxGuestSeamlessHost *pHost, 72 VBoxGuest SeamlessGuestImpl *pGuest)82 VBoxGuestThread *pGuestThread) 73 83 { 74 84 mHost = pHost; 75 mGuest = pGuest;85 mGuestThread = pGuestThread; 76 86 } 77 87 78 v oid notify(void)88 virtual void notify(void) 79 89 { 80 90 switch (mHost->getState()) 81 91 { 82 case VBoxGuestSeamless Guest::ENABLE:83 mGuest ->start();92 case VBoxGuestSeamlessHost::ENABLE: 93 mGuestThread->start(); 84 94 break; 85 case VBoxGuestSeamless Guest::DISABLE:86 mGuest ->stop();95 case VBoxGuestSeamlessHost::DISABLE: 96 mGuestThread->stop(RT_INDEFINITE_WAIT, 0); 87 97 break; 88 98 default: … … 108 118 } 109 119 110 v oid notify(void)120 virtual void notify(void) 111 121 { 112 122 mHost->updateRects(mGuest->getRects()); … … 119 129 VBoxGuestSeamlessHost mHost; 120 130 VBoxGuestSeamlessGuestImpl mGuest; 131 VBoxGuestSeamlessGuestThread mGuestFunction; 132 VBoxGuestThread mGuestThread; 121 133 VBoxGuestSeamlessHostObserver mHostObs; 122 134 VBoxGuestSeamlessGuestObserver mGuestObs; 123 VBoxGuestSeamlessGuestThread mGuestFunction;124 VBoxGuestThread mGuestThread;125 135 126 136 bool isInitialised; … … 132 142 if (isInitialised) /* Assertion */ 133 143 { 134 LogRelFunc(("error: called a second time! \n"));144 LogRelFunc(("error: called a second time! (VBoxService)\n")); 135 145 rc = VERR_INTERNAL_ERROR; 136 146 } … … 149 159 if (RT_SUCCESS(rc)) 150 160 { 151 rc = mGuestThread.start();161 isInitialised = true; 152 162 } 153 isInitialised = true; 163 if (RT_FAILURE(rc)) 164 { 165 LogFunc(("returning %Rrc (VBoxService)\n", rc)); 166 } 154 167 return rc; 155 168 } … … 159 172 if (isInitialised) 160 173 { 161 mGuestThread.stop();162 174 mHost.stop(); 175 mGuestThread.stop(RT_INDEFINITE_WAIT, 0); 163 176 mGuest.uninit(); 164 177 isInitialised = false; … … 166 179 } 167 180 168 VBoxGuestSeamless() : mHostObs(&mHost, &mGuest), mHostObs(&mHost, &mGuest), 169 mGuestFunction(&mGuest), mGuestThread(&mGuestFunction) 181 VBoxGuestSeamless() : mGuestFunction(&mGuest, &mGuestObs), 182 mGuestThread(&mGuestFunction, 0, RTTHREADTYPE_MSG_PUMP, 183 RTTHREADFLAGS_WAITABLE, "Guest events"), 184 mHostObs(&mHost, &mGuestThread), mGuestObs(&mHost, &mGuest) 170 185 { 171 186 isInitialised = false; -
trunk/src/VBox/Additions/x11/xclient/thread.h
r6202 r6290 30 30 { 31 31 public: 32 VBoxGuestThreadFunction(void);32 // VBoxGuestThreadFunction(void); 33 33 virtual ~VBoxGuestThreadFunction(void) {} 34 34 /** -
trunk/src/testcase/tstRunTestcases.cpp
r5999 r6290 61 61 "testcase/tstSDL", 62 62 "testcase/tstTime-3", 63 "testcase/tstSeamlessX11", 63 64 "./tstRunTestcases", 64 65 "./tstAnimate",
Note:
See TracChangeset
for help on using the changeset viewer.