VirtualBox

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

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

Additions/x11: seamless for Linux guests now works in a limited way on X.org 1.3 and above with KDE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.8 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 "seamless-guest.h"
23
24#include <X11/Xlib.h>
25#include <X11/extensions/shape.h>
26
27#include <map>
28#include <vector>
29
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"
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 mDisplay = XOpenDisplay(name);
141 return (mDisplay != NULL);
142 }
143 operator Display *() { return mDisplay; }
144 Display *get(void) { return mDisplay; }
145 bool isValid(void) { return (mDisplay != NULL); }
146 int close(void)
147 {
148 int rc = XCloseDisplay(mDisplay);
149 mDisplay = NULL;
150 return rc;
151 }
152 ~VBoxGuestX11Display()
153 {
154 if (mDisplay != NULL)
155 close();
156 }
157};
158
159/** Structure containing information about a guest window's position and visible area.
160 Used inside of VBoxGuestWindowList. */
161struct VBoxGuestWinInfo {
162public:
163 /** Is the window currently mapped? */
164 bool mMapped;
165 /** Co-ordinates in the guest screen. */
166 int mX, mY;
167 /** Window dimensions. */
168 int mWidth, mHeight;
169 /** Number of rectangles used to represent the visible area. */
170 int mcRects;
171 /** Rectangles representing the visible area. These must be allocated by XMalloc
172 and will be freed automatically if non-null when the class is destroyed. */
173 VBoxGuestX11Pointer<XRectangle> mapRects;
174 /** Constructor. */
175 VBoxGuestWinInfo(bool isMapped, int x, int y, int w, int h, int cRects,
176 VBoxGuestX11Pointer<XRectangle> rects)
177 : mapRects(rects)
178 {
179 mMapped = isMapped, mX = x; mY = y; mWidth = w; mHeight = h; mcRects = cRects;
180 }
181
182private:
183 // We don't want a copy constructor or assignment operator
184 VBoxGuestWinInfo(const VBoxGuestWinInfo&);
185 VBoxGuestWinInfo& operator=(const VBoxGuestWinInfo&);
186};
187
188/**
189 * This class is just a wrapper around a map of structures containing information about
190 * the windows on the guest system. It has a function for adding a structure (see addWindow),
191 * for removing it by window handle (see removeWindow) and an iterator for
192 * going through the list.
193 */
194class VBoxGuestWindowList
195{
196private:
197 // We don't want a copy constructor or an assignment operator
198 VBoxGuestWindowList(const VBoxGuestWindowList&);
199 VBoxGuestWindowList& operator=(const VBoxGuestWindowList&);
200
201 // Private class members
202 std::map<Window, VBoxGuestWinInfo *> mWindows;
203
204public:
205 // Just proxy iterators to map::iterator
206 typedef std::map<Window, VBoxGuestWinInfo *>::const_iterator const_iterator;
207 typedef std::map<Window, VBoxGuestWinInfo *>::iterator iterator;
208
209 // Constructor
210 VBoxGuestWindowList(void) {}
211 // Destructor
212 ~VBoxGuestWindowList()
213 {
214 /* We use post-increment in the operation to prevent the iterator from being invalidated. */
215 try
216 {
217 for (iterator it = begin(); it != end(); removeWindow(it++));
218 }
219 catch(...) {}
220 }
221
222 // Standard operations
223 const_iterator begin() const { return mWindows.begin(); }
224 iterator begin() { return mWindows.begin(); }
225 const_iterator end() const { return mWindows.end(); }
226 iterator end() { return mWindows.end(); }
227 const_iterator find(Window win) const { return mWindows.find(win); }
228 iterator find(Window win) { return mWindows.find(win); }
229
230 void addWindow(Window hWin, bool isMapped, int x, int y, int w, int h, int cRects,
231 VBoxGuestX11Pointer<XRectangle> rects)
232 {
233 VBoxGuestWinInfo *pInfo = new VBoxGuestWinInfo(isMapped, x, y, w, h, cRects,
234 rects);
235 mWindows.insert(std::pair<Window, VBoxGuestWinInfo *>(hWin, pInfo));
236 }
237
238 void removeWindow(iterator it)
239 {
240 delete it->second;
241 mWindows.erase(it);
242 }
243
244 void removeWindow(Window hWin)
245 {
246 removeWindow(find(hWin));
247 }
248};
249
250class VBoxGuestSeamlessX11;
251
252class VBoxGuestSeamlessX11 : public VBoxGuestSeamlessGuest
253{
254private:
255 // We don't want a copy constructor or assignment operator
256 VBoxGuestSeamlessX11(const VBoxGuestSeamlessX11&);
257 VBoxGuestSeamlessX11& operator=(const VBoxGuestSeamlessX11&);
258
259 // Private member variables
260 /** Pointer to the observer class. */
261 VBoxGuestSeamlessObserver *mObserver;
262 /** Our connection to the X11 display we are running on. */
263 VBoxGuestX11Display mDisplay;
264 /** Class to keep track of visible guest windows. */
265 VBoxGuestWindowList mGuestWindows;
266 /** Keeps track of the total number of rectangles needed for the visible area of all
267 guest windows on the last call to getRects. Used for pre-allocating space in
268 the vector of rectangles passed to the host. */
269 int mcRects;
270 /** Do we support the X shaped window extension? */
271 bool mSupportsShape;
272 /** Is seamles mode currently enabled? */
273 bool mEnabled;
274
275 // Private methods
276
277 // Methods to handle X11 events
278 void doConfigureEvent(const XConfigureEvent *event);
279 void doMapEvent(const XMapEvent *event);
280 void doPropertyEvent(const XPropertyEvent *event);
281 void doUnmapEvent(const XUnmapEvent *event);
282 void doShapeEvent(const XShapeEvent *event);
283
284 // Methods to manage guest window information
285 /**
286 * Store information about a desktop window and register for structure events on it.
287 * If it is mapped, go through the list of it's children and add information about
288 * mapped children to the tree of visible windows, making sure that those windows are
289 * not already in our list of desktop windows.
290 *
291 * @param hWin the window concerned - should be a "desktop" window
292 */
293 void monitorClientList(void);
294 void unmonitorClientList(void);
295 void rebuildWindowTree(void);
296 void addClients(const Window hRoot);
297 bool isVirtualRoot(Window hWin);
298 void addClientWindow(Window hWin);
299 void freeWindowTree(void);
300 void updateHostSeamlessInfo(void);
301
302public:
303 /**
304 * Initialise the guest and ensure that it is capable of handling seamless mode
305 * @param pObserver Observer class to connect host and guest interfaces
306 *
307 * @returns iprt status code
308 */
309 int init(VBoxGuestSeamlessObserver *pObserver);
310
311 /**
312 * Shutdown seamless event monitoring.
313 */
314 void uninit(void)
315 {
316 if (0 != mObserver)
317 {
318 stop();
319 }
320 mObserver = 0;
321 }
322
323 /**
324 * Initialise seamless event reporting in the guest.
325 *
326 * @returns IPRT status code
327 */
328 int start(void);
329 /** Stop reporting seamless events. */
330 void stop(void);
331 /** Get the current list of visible rectangles. */
332 std::auto_ptr<std::vector<RTRECT> > getRects(void);
333
334 /** Process next event in the guest event queue - called by the event thread. */
335 void nextEvent(void);
336 /** Wake up the event thread if it is waiting for an event so that it can exit. */
337 bool interruptEvent(void);
338
339 VBoxGuestSeamlessX11(void)
340 {
341 mObserver = 0; mcRects = 0; mEnabled = false; mSupportsShape = false;
342 }
343
344 ~VBoxGuestSeamlessX11()
345 {
346 try
347 {
348 uninit();
349 }
350 catch(...) {}
351 }
352};
353
354typedef VBoxGuestSeamlessX11 VBoxGuestSeamlessGuestImpl;
355
356#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