seamless-x11.h revision 9d088c69cafcc736acc5bcc234c5ea68cf9e9620
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync/** @file
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync *
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * Seamless mode:
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * Linux guest.
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync/*
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * Copyright (C) 2006-2011 Oracle Corporation
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync *
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * available from http://www.virtualbox.org. This file is free software;
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * General Public License (GPL) as published by the Free Software
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#ifndef __Additions_linux_seamless_x11_h
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync# define __Additions_linux_seamless_x11_h
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#include <VBox/log.h>
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#include <iprt/avl.h>
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#include "seamless-x11.h"
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#include "seamless-host.h"
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#include <X11/Xlib.h>
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#include <X11/Xutil.h>
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#include <X11/extensions/shape.h>
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#define WM_TYPE_PROP "_NET_WM_WINDOW_TYPE"
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync#define WM_TYPE_DESKTOP_PROP "_NET_WM_WINDOW_TYPE_DESKTOP"
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync/* This is defined wrong in my X11 header files! */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync#define VBoxShapeNotify 64
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync/** Structure containing information about a guest window's position and visible area.
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync Used inside of VBoxGuestWindowList. */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsyncstruct VBoxGuestWinInfo {
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsyncpublic:
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync /** Header structure for insertion into an AVL tree */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync AVLU32NODECORE Core;
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync /** Is the window currently mapped? */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync bool mhasShape;
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync /** Co-ordinates in the guest screen. */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync int mX, mY;
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync /** Window dimensions. */
d9658602103599d13b5449fc1ea49d765a23e6f1vboxsync int mWidth, mHeight;
/** Number of rectangles used to represent the visible area. */
int mcRects;
/** Rectangles representing the visible area. These must be allocated
* by XMalloc and will be freed automatically if non-null when the class
* is destroyed. */
XRectangle *mpRects;
/** Constructor. */
VBoxGuestWinInfo(bool hasShape, int x, int y, int w, int h, int cRects,
XRectangle *pRects)
: mhasShape(hasShape), mX(x), mY(y), mWidth(w), mHeight(h),
mcRects(cRects), mpRects(pRects) {}
/** Destructor */
~VBoxGuestWinInfo()
{
if (mpRects)
XFree(mpRects);
}
private:
// We don't want a copy constructor or assignment operator
VBoxGuestWinInfo(const VBoxGuestWinInfo&);
VBoxGuestWinInfo& operator=(const VBoxGuestWinInfo&);
};
/** Callback type used for "DoWithAll" calls */
typedef DECLCALLBACK(int) VBOXGUESTWINCALLBACK(VBoxGuestWinInfo *, void *);
/** Pointer to VBOXGUESTWINCALLBACK */
typedef VBOXGUESTWINCALLBACK *PVBOXGUESTWINCALLBACK;
DECLCALLBACK(int) inline VBoxGuestWinCleanup(VBoxGuestWinInfo *pInfo, void *)
{
delete pInfo;
return VINF_SUCCESS;
}
/**
* This class is just a wrapper around a map of structures containing
* information about the windows on the guest system. It has a function for
* adding a structure (see addWindow) and one for removing it by window
* handle (see removeWindow).
*/
class VBoxGuestWindowList
{
private:
// We don't want a copy constructor or an assignment operator
VBoxGuestWindowList(const VBoxGuestWindowList&);
VBoxGuestWindowList& operator=(const VBoxGuestWindowList&);
// Private class members
AVLU32TREE mWindows;
public:
// Constructor
VBoxGuestWindowList(void) : mWindows(NULL) {}
// Destructor
~VBoxGuestWindowList()
{
/** @todo having this inside the container class hard codes that the
* elements have to be allocated with the "new" operator, and
* I don't see a need to require this. */
doWithAll(VBoxGuestWinCleanup, NULL);
}
// Standard operations
VBoxGuestWinInfo *find(Window hWin)
{
return (VBoxGuestWinInfo *)RTAvlU32Get(&mWindows, hWin);
}
void detachAll(PVBOXGUESTWINCALLBACK pCallback, void *pvParam)
{
RTAvlU32Destroy(&mWindows, (PAVLU32CALLBACK)pCallback, pvParam);
}
int doWithAll(PVBOXGUESTWINCALLBACK pCallback, void *pvParam)
{
return RTAvlU32DoWithAll(&mWindows, 1, (PAVLU32CALLBACK)pCallback,
pvParam);
}
bool addWindow(Window hWin, bool isMapped, int x, int y, int w, int h, int cRects,
XRectangle *pRects)
{
LogRelFlowFunc(("\n"));
VBoxGuestWinInfo *pInfo = new VBoxGuestWinInfo(isMapped, x, y, w, h, cRects,
pRects);
pInfo->Core.Key = hWin;
LogRelFlowFunc(("returning\n"));
return RTAvlU32Insert(&mWindows, &pInfo->Core);
}
VBoxGuestWinInfo *removeWindow(Window hWin)
{
LogRelFlowFunc(("called\n"));
return (VBoxGuestWinInfo *)RTAvlU32Remove(&mWindows, hWin);
}
};
class VBoxGuestSeamlessX11
{
private:
// We don't want a copy constructor or assignment operator
VBoxGuestSeamlessX11(const VBoxGuestSeamlessX11&);
VBoxGuestSeamlessX11& operator=(const VBoxGuestSeamlessX11&);
// Private member variables
/** Pointer to the host class. */
VBoxGuestSeamlessHostInt *mHost;
/** Our connection to the X11 display we are running on. */
Display *mDisplay;
/** Class to keep track of visible guest windows. */
VBoxGuestWindowList mGuestWindows;
/** The current set of seamless rectangles. */
RTRECT *mpRects;
/** The current number of seamless rectangles. */
int mcRects;
/** Do we support the X shaped window extension? */
bool mSupportsShape;
/** Is seamless mode currently enabled? */
bool mEnabled;
/** Have there been changes since the last time we sent a notification? */
bool mChanged;
// Private methods
// Methods to manage guest window information
/**
* Store information about a desktop window and register for structure events on it.
* If it is mapped, go through the list of it's children and add information about
* mapped children to the tree of visible windows, making sure that those windows are
* not already in our list of desktop windows.
*
* @param hWin the window concerned - should be a "desktop" window
*/
void monitorClientList(void);
void unmonitorClientList(void);
void rebuildWindowTree(void);
void addClients(const Window hRoot);
bool isVirtualRoot(Window hWin);
void addClientWindow(Window hWin);
void freeWindowTree(void);
void updateHostSeamlessInfo(void);
int updateRects(void);
public:
/**
* Initialise the guest and ensure that it is capable of handling seamless mode
* @param pHost Host interface class to notify of window configuration
* changes.
*
* @returns iprt status code
*/
int init(VBoxGuestSeamlessHostInt *pHost);
/**
* Shutdown seamless event monitoring.
*/
void uninit(void)
{
if (0 != mHost)
{
stop();
}
mHost = 0;
}
/**
* Initialise seamless event reporting in the guest.
*
* @returns IPRT status code
*/
int start(void);
/** Stop reporting seamless events. */
void stop(void);
/** Get the current list of visible rectangles. */
RTRECT *getRects(void);
/** Get the number of visible rectangles in the current list */
size_t getRectCount(void);
/** Process next event in the guest event queue - called by the event thread. */
void nextEvent(void);
/** Wake up the event thread if it is waiting for an event so that it can exit. */
bool interruptEvent(void);
/* Methods to handle X11 events. These are public so that the unit test
* can call them. */
void doConfigureEvent(Window hWin);
void doMapEvent(Window hWin);
void doUnmapEvent(Window hWin);
void doShapeEvent(Window hWin);
VBoxGuestSeamlessX11(void)
: mHost(0), mDisplay(NULL), mpRects(NULL), mcRects(0),
mSupportsShape(false), mEnabled(false), mChanged(false) {}
~VBoxGuestSeamlessX11()
{
uninit();
if (mDisplay)
XCloseDisplay(mDisplay);
}
};
#endif /* __Additions_linux_seamless_x11_h not defined */