VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/xclient/seamless-x11.h@ 8016

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

Additions/x11: added flow logging statements to the VBoxClient code

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