diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Additions/x11/VBoxClient/seamless-x11.h | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/x11/VBoxClient/seamless-x11.h')
-rw-r--r-- | src/VBox/Additions/x11/VBoxClient/seamless-x11.h | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-x11.h b/src/VBox/Additions/x11/VBoxClient/seamless-x11.h new file mode 100644 index 00000000..f7c0c268 --- /dev/null +++ b/src/VBox/Additions/x11/VBoxClient/seamless-x11.h @@ -0,0 +1,261 @@ +/* $Id: seamless-x11.h $ */ +/** @file + * + * Seamless mode: + * Linux guest. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + */ + +#ifndef GA_INCLUDED_SRC_x11_VBoxClient_seamless_x11_h +#define GA_INCLUDED_SRC_x11_VBoxClient_seamless_x11_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/log.h> +#include <iprt/avl.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/shape.h> + +#define WM_TYPE_PROP "_NET_WM_WINDOW_TYPE" +#define WM_TYPE_DESKTOP_PROP "_NET_WM_WINDOW_TYPE_DESKTOP" + +/* This is defined wrong in my X11 header files! */ +#define VBoxShapeNotify 64 + +/** + * Callback which provides the interface for notifying the host of changes to + * the X11 window configuration, mainly split out from @a VBoxGuestSeamlessHost + * to simplify the unit test. + */ +typedef void FNSENDREGIONUPDATE(RTRECT *pRects, size_t cRects); +typedef FNSENDREGIONUPDATE *PFNSENDREGIONUPDATE; + +/** Structure containing information about a guest window's position and visible area. + Used inside of VBoxGuestWindowList. */ +struct VBoxGuestWinInfo { +public: + /** Header structure for insertion into an AVL tree */ + AVLU32NODECORE Core; + /** Is the window currently mapped? */ + bool mhasShape; + /** Co-ordinates in the guest screen. */ + int mX, mY; + /** Window dimensions. */ + 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(("hWin=%lu, isMapped=%RTbool, x=%d, y=%d, w=%d, h=%d, cRects=%d\n", + (unsigned long) hWin, isMapped, x, y, w, h, cRects)); + 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 SeamlessX11 +{ +private: + // We don't want a copy constructor or assignment operator + SeamlessX11(const SeamlessX11&); + SeamlessX11& operator=(const SeamlessX11&); + + // Private member variables + /** Pointer to the host callback. */ + PFNSENDREGIONUPDATE mHostCallback; + /** 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 pHostCallback Host interface callback to notify of window configuration + * changes. + * + * @returns iprt status code + */ + int init(PFNSENDREGIONUPDATE pHostCallback); + + /** + * Shutdown seamless event monitoring. + */ + void uninit(void) + { + if (mHostCallback) + stop(); + mHostCallback = NULL; + if (mDisplay) + XCloseDisplay(mDisplay); + mDisplay = NULL; + } + + /** + * 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 nextConfigurationEvent(void); + /** Wake up the event thread if it is waiting for an event so that it can exit. */ + bool interruptEventWait(void); + + /* Methods to handle X11 events. These are public so that the unit test + * can call them. */ + void doConfigureEvent(Window hWin); + void doShapeEvent(Window hWin); + + SeamlessX11(void) + : mHostCallback(NULL), mDisplay(NULL), mpRects(NULL), mcRects(0), + mSupportsShape(false), mEnabled(false), mChanged(false) {} + + ~SeamlessX11() + { + uninit(); + } +}; + +#endif /* !GA_INCLUDED_SRC_x11_VBoxClient_seamless_x11_h */ |