VirtualBox

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

Last change on this file was 99600, checked in by vboxsync, 13 months ago

Guest Additions/VBoxClient: Moved the X11-specific code for seamless mode into an own submodule and using the actual service as a (runtime) wrapper (for also the Wayland-specific code later). bugref:10427

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 8.7 KB
RevLine 
[55401]1/* $Id: seamless-x11.h 99600 2023-05-04 10:29:18Z vboxsync $ */
[6202]2/** @file
[79482]3 * Seamless mode - X11 guests.
[6202]4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[6202]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[6202]26 */
27
[76563]28#ifndef GA_INCLUDED_SRC_x11_VBoxClient_seamless_x11_h
29#define GA_INCLUDED_SRC_x11_VBoxClient_seamless_x11_h
[76535]30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
[6202]33
[7449]34#include <VBox/log.h>
[36685]35#include <iprt/avl.h>
[79482]36#ifdef RT_NEED_NEW_AND_DELETE
37# include <iprt/mem.h>
38# include <new>
39#endif
[7449]40
[6202]41#include <X11/Xlib.h>
[11602]42#include <X11/Xutil.h>
[6202]43#include <X11/extensions/shape.h>
44
[6290]45#define WM_TYPE_PROP "_NET_WM_WINDOW_TYPE"
46#define WM_TYPE_DESKTOP_PROP "_NET_WM_WINDOW_TYPE_DESKTOP"
[6202]47
[21207]48/* This is defined wrong in my X11 header files! */
49#define VBoxShapeNotify 64
50
[50337]51/**
[52564]52 * Callback which provides the interface for notifying the host of changes to
53 * the X11 window configuration, mainly split out from @a VBoxGuestSeamlessHost
54 * to simplify the unit test.
[50337]55 */
[52564]56typedef void FNSENDREGIONUPDATE(RTRECT *pRects, size_t cRects);
57typedef FNSENDREGIONUPDATE *PFNSENDREGIONUPDATE;
[50337]58
[6202]59/** Structure containing information about a guest window's position and visible area.
60 Used inside of VBoxGuestWindowList. */
[85121]61struct VBoxGuestWinInfo
62{
[6202]63public:
[36685]64 /** Header structure for insertion into an AVL tree */
65 AVLU32NODECORE Core;
[6290]66 /** Is the window currently mapped? */
[7106]67 bool mhasShape;
[6202]68 /** Co-ordinates in the guest screen. */
[6290]69 int mX, mY;
[6202]70 /** Window dimensions. */
[6290]71 int mWidth, mHeight;
[6202]72 /** Number of rectangles used to represent the visible area. */
73 int mcRects;
[36662]74 /** Rectangles representing the visible area. These must be allocated
75 * by XMalloc and will be freed automatically if non-null when the class
76 * is destroyed. */
77 XRectangle *mpRects;
[6202]78 /** Constructor. */
[85121]79 VBoxGuestWinInfo(bool hasShape, int x, int y, int w, int h, int cRects, XRectangle *pRects)
80 : mhasShape(hasShape), mX(x), mY(y), mWidth(w), mHeight(h)
81 , mcRects(cRects), mpRects(pRects)
82 {}
[36662]83
84 /** Destructor */
85 ~VBoxGuestWinInfo()
[6202]86 {
[36662]87 if (mpRects)
88 XFree(mpRects);
[6202]89 }
[79482]90#ifdef RT_NEED_NEW_AND_DELETE
91 RTMEM_IMPLEMENT_NEW_AND_DELETE();
92#endif
[6202]93
94private:
95 // We don't want a copy constructor or assignment operator
[85121]96 VBoxGuestWinInfo(const VBoxGuestWinInfo &);
97 VBoxGuestWinInfo &operator=(const VBoxGuestWinInfo &);
[6202]98};
99
[36685]100/** Callback type used for "DoWithAll" calls */
[85121]101typedef DECLCALLBACKTYPE(int, FNVBOXGUESTWINCALLBACK,(VBoxGuestWinInfo *, void *));
[36685]102/** Pointer to VBOXGUESTWINCALLBACK */
[85121]103typedef FNVBOXGUESTWINCALLBACK *PFNVBOXGUESTWINCALLBACK;
[36685]104
[85121]105static inline DECLCALLBACK(int) VBoxGuestWinCleanup(VBoxGuestWinInfo *pInfo, void *)
[36685]106{
107 delete pInfo;
108 return VINF_SUCCESS;
109}
110
[6202]111/**
[36685]112 * This class is just a wrapper around a map of structures containing
113 * information about the windows on the guest system. It has a function for
114 * adding a structure (see addWindow) and one for removing it by window
115 * handle (see removeWindow).
[6202]116 */
117class VBoxGuestWindowList
118{
119private:
120 // We don't want a copy constructor or an assignment operator
121 VBoxGuestWindowList(const VBoxGuestWindowList&);
122 VBoxGuestWindowList& operator=(const VBoxGuestWindowList&);
123
124 // Private class members
[36685]125 AVLU32TREE mWindows;
[6202]126
127public:
128 // Constructor
[36685]129 VBoxGuestWindowList(void) : mWindows(NULL) {}
[6202]130 // Destructor
131 ~VBoxGuestWindowList()
132 {
[36685]133 /** @todo having this inside the container class hard codes that the
134 * elements have to be allocated with the "new" operator, and
135 * I don't see a need to require this. */
136 doWithAll(VBoxGuestWinCleanup, NULL);
[6202]137 }
138
[79482]139#ifdef RT_NEED_NEW_AND_DELETE
140 RTMEM_IMPLEMENT_NEW_AND_DELETE();
141#endif
142
[6202]143 // Standard operations
[36685]144 VBoxGuestWinInfo *find(Window hWin)
145 {
146 return (VBoxGuestWinInfo *)RTAvlU32Get(&mWindows, hWin);
147 }
[6202]148
[85121]149 void detachAll(PFNVBOXGUESTWINCALLBACK pfnCallback, void *pvParam)
[36685]150 {
[85121]151 RTAvlU32Destroy(&mWindows, (PAVLU32CALLBACK)pfnCallback, pvParam);
[36685]152 }
153
[85121]154 int doWithAll(PFNVBOXGUESTWINCALLBACK pfnCallback, void *pvParam)
[36685]155 {
[85121]156 return RTAvlU32DoWithAll(&mWindows, 1, (PAVLU32CALLBACK)pfnCallback, pvParam);
[36685]157 }
158
159 bool addWindow(Window hWin, bool isMapped, int x, int y, int w, int h, int cRects,
[36662]160 XRectangle *pRects)
[6202]161 {
[57208]162 LogRelFlowFunc(("hWin=%lu, isMapped=%RTbool, x=%d, y=%d, w=%d, h=%d, cRects=%d\n",
163 (unsigned long) hWin, isMapped, x, y, w, h, cRects));
[85121]164 VBoxGuestWinInfo *pInfo = new VBoxGuestWinInfo(isMapped, x, y, w, h, cRects, pRects);
[36685]165 pInfo->Core.Key = hWin;
[81040]166 LogRelFlowFuncLeave();
[36685]167 return RTAvlU32Insert(&mWindows, &pInfo->Core);
[6202]168 }
169
[36685]170 VBoxGuestWinInfo *removeWindow(Window hWin)
[6202]171 {
[81040]172 LogRelFlowFuncEnter();
[36685]173 return (VBoxGuestWinInfo *)RTAvlU32Remove(&mWindows, hWin);
[6202]174 }
175};
176
[99600]177class VBClX11SeamlessMonitor
[6202]178{
179private:
180 // We don't want a copy constructor or assignment operator
[99600]181 VBClX11SeamlessMonitor(const VBClX11SeamlessMonitor&);
182 VBClX11SeamlessMonitor& operator=(const VBClX11SeamlessMonitor&);
[6202]183
184 // Private member variables
[52564]185 /** Pointer to the host callback. */
186 PFNSENDREGIONUPDATE mHostCallback;
[6202]187 /** Our connection to the X11 display we are running on. */
[36662]188 Display *mDisplay;
[6202]189 /** Class to keep track of visible guest windows. */
190 VBoxGuestWindowList mGuestWindows;
[36806]191 /** The current set of seamless rectangles. */
192 RTRECT *mpRects;
193 /** The current number of seamless rectangles. */
[6202]194 int mcRects;
[6290]195 /** Do we support the X shaped window extension? */
196 bool mSupportsShape;
[33540]197 /** Is seamless mode currently enabled? */
[6290]198 bool mEnabled;
[21441]199 /** Have there been changes since the last time we sent a notification? */
200 bool mChanged;
[6202]201
202 // Private methods
203
204 // Methods to manage guest window information
205 /**
206 * Store information about a desktop window and register for structure events on it.
207 * If it is mapped, go through the list of it's children and add information about
208 * mapped children to the tree of visible windows, making sure that those windows are
209 * not already in our list of desktop windows.
210 *
211 * @param hWin the window concerned - should be a "desktop" window
212 */
[6290]213 void monitorClientList(void);
214 void unmonitorClientList(void);
[6202]215 void rebuildWindowTree(void);
[7048]216 void addClients(const Window hRoot);
217 bool isVirtualRoot(Window hWin);
[6290]218 void addClientWindow(Window hWin);
[6202]219 void freeWindowTree(void);
220 void updateHostSeamlessInfo(void);
[36806]221 int updateRects(void);
[6202]222
223public:
224 /**
225 * Initialise the guest and ensure that it is capable of handling seamless mode
[65122]226 * @param pHostCallback Host interface callback to notify of window configuration
227 * changes.
[6202]228 *
229 * @returns iprt status code
230 */
[52564]231 int init(PFNSENDREGIONUPDATE pHostCallback);
[6202]232
233 /**
234 * Shutdown seamless event monitoring.
235 */
[86394]236 void uninit(void);
[6202]237
238 /**
239 * Initialise seamless event reporting in the guest.
240 *
241 * @returns IPRT status code
242 */
243 int start(void);
244 /** Stop reporting seamless events. */
245 void stop(void);
246 /** Get the current list of visible rectangles. */
[36806]247 RTRECT *getRects(void);
248 /** Get the number of visible rectangles in the current list */
249 size_t getRectCount(void);
[6202]250
[6290]251 /** Process next event in the guest event queue - called by the event thread. */
[50346]252 void nextConfigurationEvent(void);
[6290]253 /** Wake up the event thread if it is waiting for an event so that it can exit. */
[50346]254 bool interruptEventWait(void);
[6202]255
[21207]256 /* Methods to handle X11 events. These are public so that the unit test
257 * can call them. */
[21216]258 void doConfigureEvent(Window hWin);
259 void doShapeEvent(Window hWin);
[21207]260
[99600]261 VBClX11SeamlessMonitor(void)
[52564]262 : mHostCallback(NULL), mDisplay(NULL), mpRects(NULL), mcRects(0),
[36806]263 mSupportsShape(false), mEnabled(false), mChanged(false) {}
[6202]264
[99600]265 ~VBClX11SeamlessMonitor()
[6893]266 {
[37025]267 uninit();
[6893]268 }
[79482]269
270#ifdef RT_NEED_NEW_AND_DELETE
271 RTMEM_IMPLEMENT_NEW_AND_DELETE();
272#endif
[6202]273};
274
[76563]275#endif /* !GA_INCLUDED_SRC_x11_VBoxClient_seamless_x11_h */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use