VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/seamless-x11.h@ 23794

Last change on this file since 23794 was 21441, checked in by vboxsync, 15 years ago

Additions/x11/seamless: small performance improvement

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.4 KB
Line 
1/** @file
2 *
3 * Seamless mode:
4 * Linux guest.
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#ifndef __Additions_linux_seamless_x11_h
24# define __Additions_linux_seamless_x11_h
25
26#include <VBox/log.h>
27
28#include "seamless-guest.h"
29
30#include <X11/Xlib.h>
31#include <X11/Xutil.h>
32#include <X11/extensions/shape.h>
33
34#include <map>
35#include <vector>
36
37#define WM_TYPE_PROP "_NET_WM_WINDOW_TYPE"
38#define WM_TYPE_DESKTOP_PROP "_NET_WM_WINDOW_TYPE_DESKTOP"
39
40/* This is defined wrong in my X11 header files! */
41#define VBoxShapeNotify 64
42
43/**
44 * Wrapper class around the VBoxGuestX11Pointer to provide reference semantics.
45 * See auto_ptr in the C++ <memory> header.
46 */
47template <class T>
48struct VBoxGuestX11PointerRef
49{
50 T *mValue;
51
52 VBoxGuestX11PointerRef(T* pValue) { mValue = pValue; }
53};
54
55/** An auto pointer for pointers which have to be XFree'd. */
56template <class T>
57class VBoxGuestX11Pointer
58{
59private:
60 T *mValue;
61public:
62 VBoxGuestX11Pointer(T *pValue = 0) { mValue = pValue; }
63 ~VBoxGuestX11Pointer() { if (0 != mValue) XFree(mValue); }
64
65 /** release method to get the pointer's value and "reset" the pointer. */
66 T *release(void) { T *pTmp = mValue; mValue = 0; return pTmp; }
67
68 /** reset the pointer value to zero or to another pointer. */
69 void reset(T* pValue = 0) { if (pValue != mValue) { XFree(mValue); mValue = pValue; } }
70
71 /** Copy constructor */
72 VBoxGuestX11Pointer(VBoxGuestX11Pointer &orig) { mValue = orig.release(); }
73
74 /** Copy from equivalent class */
75 template <class T1>
76 VBoxGuestX11Pointer(VBoxGuestX11Pointer<T1> &orig) { mValue = orig.release(); }
77
78 /** Assignment operator. */
79 VBoxGuestX11Pointer& operator=(VBoxGuestX11Pointer &orig)
80 {
81 reset(orig.release());
82 return *this;
83 }
84
85 /** Assignment from equivalent class. */
86 template <class T1>
87 VBoxGuestX11Pointer& operator=(VBoxGuestX11Pointer<T1> &orig)
88 {
89 reset(orig.release);
90 return *this;
91 }
92
93 /** Assignment from a pointer. */
94 VBoxGuestX11Pointer& operator=(T *pValue)
95 {
96 if (0 != mValue)
97 {
98 XFree(mValue);
99 }
100 mValue = pValue;
101 return *this;
102 }
103
104 /** Dereference with * operator. */
105 T &operator*() { return *mValue; }
106
107 /** Dereference with -> operator. */
108 T *operator->() { return mValue; }
109
110 /** Accessing the value inside. */
111 T *get(void) { return mValue; }
112
113 /** Convert a reference structure into an X11 pointer. */
114 VBoxGuestX11Pointer(VBoxGuestX11PointerRef<T> ref) { mValue = ref.mValue; }
115
116 /** Assign from a reference structure into an X11 pointer. */
117 VBoxGuestX11Pointer& operator=(VBoxGuestX11PointerRef<T> ref)
118 {
119 if (ref.mValue != mValue)
120 {
121 XFree(mValue);
122 mValue = ref.mValue;
123 }
124 return *this;
125 }
126
127 /** Typecast an X11 pointer to a reference structure. */
128 template <class T1>
129 operator VBoxGuestX11PointerRef<T1>() { return VBoxGuestX11PointerRef<T1>(release()); }
130
131 /** Typecast an X11 pointer to an X11 pointer around a different type. */
132 template <class T1>
133 operator VBoxGuestX11Pointer<T1>() { return VBoxGuestX11Pointer<T1>(release()); }
134};
135
136/**
137 * Wrapper class around an X11 display pointer which takes care of closing the display
138 * when it is destroyed at the latest.
139 */
140class VBoxGuestX11Display
141{
142private:
143 Display *mDisplay;
144public:
145 VBoxGuestX11Display(void) { mDisplay = NULL; }
146 bool init(char *name = NULL)
147 {
148 LogFlowThisFunc(("\n"));
149 mDisplay = XOpenDisplay(name);
150 LogFlowThisFunc(("returning\n"));
151 return (mDisplay != NULL);
152 }
153 operator Display *() { return mDisplay; }
154 Display *get(void) { return mDisplay; }
155 bool isValid(void) { return (mDisplay != NULL); }
156 int close(void)
157 {
158 LogFlowThisFunc(("\n"));
159 int rc = XCloseDisplay(mDisplay);
160 mDisplay = NULL;
161 LogFlowThisFunc(("returning\n"));
162 return rc;
163 }
164 ~VBoxGuestX11Display()
165 {
166 if (mDisplay != NULL)
167 close();
168 }
169};
170
171/** Structure containing information about a guest window's position and visible area.
172 Used inside of VBoxGuestWindowList. */
173struct VBoxGuestWinInfo {
174public:
175 /** Is the window currently mapped? */
176 bool mhasShape;
177 /** Co-ordinates in the guest screen. */
178 int mX, mY;
179 /** Window dimensions. */
180 int mWidth, mHeight;
181 /** Number of rectangles used to represent the visible area. */
182 int mcRects;
183 /** Rectangles representing the visible area. These must be allocated by XMalloc
184 and will be freed automatically if non-null when the class is destroyed. */
185 VBoxGuestX11Pointer<XRectangle> mapRects;
186 /** Constructor. */
187 VBoxGuestWinInfo(bool hasShape, int x, int y, int w, int h, int cRects,
188 VBoxGuestX11Pointer<XRectangle> rects)
189 : mapRects(rects)
190 {
191 mhasShape = hasShape, mX = x; mY = y; mWidth = w; mHeight = h; mcRects = cRects;
192 }
193
194private:
195 // We don't want a copy constructor or assignment operator
196 VBoxGuestWinInfo(const VBoxGuestWinInfo&);
197 VBoxGuestWinInfo& operator=(const VBoxGuestWinInfo&);
198};
199
200/**
201 * This class is just a wrapper around a map of structures containing information about
202 * the windows on the guest system. It has a function for adding a structure (see addWindow),
203 * for removing it by window handle (see removeWindow) and an iterator for
204 * going through the list.
205 */
206class VBoxGuestWindowList
207{
208private:
209 // We don't want a copy constructor or an assignment operator
210 VBoxGuestWindowList(const VBoxGuestWindowList&);
211 VBoxGuestWindowList& operator=(const VBoxGuestWindowList&);
212
213 // Private class members
214 std::map<Window, VBoxGuestWinInfo *> mWindows;
215
216public:
217 // Just proxy iterators to map::iterator
218 typedef std::map<Window, VBoxGuestWinInfo *>::const_iterator const_iterator;
219 typedef std::map<Window, VBoxGuestWinInfo *>::iterator iterator;
220
221 // Constructor
222 VBoxGuestWindowList(void) {}
223 // Destructor
224 ~VBoxGuestWindowList()
225 {
226 /* We use post-increment in the operation to prevent the iterator from being invalidated. */
227 try
228 {
229 for (iterator it = begin(); it != end(); removeWindow(it++))
230 ;
231 }
232 catch(...) {}
233 }
234
235 // Standard operations
236 const_iterator begin() const { return mWindows.begin(); }
237 iterator begin() { return mWindows.begin(); }
238 const_iterator end() const { return mWindows.end(); }
239 iterator end() { return mWindows.end(); }
240 const_iterator find(Window win) const { return mWindows.find(win); }
241 iterator find(Window win) { return mWindows.find(win); }
242
243 void addWindow(Window hWin, bool isMapped, int x, int y, int w, int h, int cRects,
244 VBoxGuestX11Pointer<XRectangle> rects)
245 {
246 LogFlowThisFunc(("\n"));
247 VBoxGuestWinInfo *pInfo = new VBoxGuestWinInfo(isMapped, x, y, w, h, cRects,
248 rects);
249 mWindows.insert(std::pair<Window, VBoxGuestWinInfo *>(hWin, pInfo));
250 LogFlowThisFunc(("returning\n"));
251 }
252
253 void removeWindow(iterator it)
254 {
255 LogFlowThisFunc(("called\n"));
256 delete it->second;
257 mWindows.erase(it);
258 }
259
260 void removeWindow(Window hWin)
261 {
262 LogFlowThisFunc(("called\n"));
263 removeWindow(find(hWin));
264 }
265};
266
267class VBoxGuestSeamlessX11;
268
269class VBoxGuestSeamlessX11 : public VBoxGuestSeamlessGuest
270{
271private:
272 // We don't want a copy constructor or assignment operator
273 VBoxGuestSeamlessX11(const VBoxGuestSeamlessX11&);
274 VBoxGuestSeamlessX11& operator=(const VBoxGuestSeamlessX11&);
275
276 // Private member variables
277 /** Pointer to the observer class. */
278 VBoxGuestSeamlessObserver *mObserver;
279 /** Our connection to the X11 display we are running on. */
280 VBoxGuestX11Display mDisplay;
281 /** Class to keep track of visible guest windows. */
282 VBoxGuestWindowList mGuestWindows;
283 /** Keeps track of the total number of rectangles needed for the visible area of all
284 guest windows on the last call to getRects. Used for pre-allocating space in
285 the vector of rectangles passed to the host. */
286 int mcRects;
287 /** Do we support the X shaped window extension? */
288 bool mSupportsShape;
289 /** Is seamles mode currently enabled? */
290 bool mEnabled;
291 /** Have there been changes since the last time we sent a notification? */
292 bool mChanged;
293
294 // Private methods
295
296 // Methods to manage guest window information
297 /**
298 * Store information about a desktop window and register for structure events on it.
299 * If it is mapped, go through the list of it's children and add information about
300 * mapped children to the tree of visible windows, making sure that those windows are
301 * not already in our list of desktop windows.
302 *
303 * @param hWin the window concerned - should be a "desktop" window
304 */
305 void monitorClientList(void);
306 void unmonitorClientList(void);
307 void rebuildWindowTree(void);
308 void addClients(const Window hRoot);
309 bool isVirtualRoot(Window hWin);
310 void addClientWindow(Window hWin);
311 void freeWindowTree(void);
312 void updateHostSeamlessInfo(void);
313
314public:
315 /**
316 * Initialise the guest and ensure that it is capable of handling seamless mode
317 * @param pObserver Observer class to connect host and guest interfaces
318 *
319 * @returns iprt status code
320 */
321 int init(VBoxGuestSeamlessObserver *pObserver);
322
323 /**
324 * Shutdown seamless event monitoring.
325 */
326 void uninit(void)
327 {
328 if (0 != mObserver)
329 {
330 stop();
331 }
332 mObserver = 0;
333 }
334
335 /**
336 * Initialise seamless event reporting in the guest.
337 *
338 * @returns IPRT status code
339 */
340 int start(void);
341 /** Stop reporting seamless events. */
342 void stop(void);
343 /** Get the current list of visible rectangles. */
344 std::auto_ptr<std::vector<RTRECT> > getRects(void);
345
346 /** Process next event in the guest event queue - called by the event thread. */
347 void nextEvent(void);
348 /** Wake up the event thread if it is waiting for an event so that it can exit. */
349 bool interruptEvent(void);
350
351 /* Methods to handle X11 events. These are public so that the unit test
352 * can call them. */
353 void doConfigureEvent(Window hWin);
354 void doMapEvent(Window hWin);
355 void doUnmapEvent(Window hWin);
356 void doShapeEvent(Window hWin);
357
358 VBoxGuestSeamlessX11(void)
359 {
360 mObserver = 0; mcRects = 0; mEnabled = false; mSupportsShape = false;
361 }
362
363 ~VBoxGuestSeamlessX11()
364 {
365 try
366 {
367 uninit();
368 }
369 catch(...) {}
370 }
371};
372
373typedef VBoxGuestSeamlessX11 VBoxGuestSeamlessGuestImpl;
374
375#endif /* __Additions_linux_seamless_x11_h not defined */
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