Changeset 83136 in vbox for trunk/src/VBox/Additions/x11/VBoxClient/display-svga-x11.cpp
- Timestamp:
- Feb 21, 2020 2:36:52 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/display-svga-x11.cpp
r83123 r83136 37 37 * - When VMSVGA is not enabled, VBoxClient --vmsvga should never stay running. 38 38 */ 39 #include "stdio.h"39 #include <stdio.h> 40 40 #include "VBoxClient.h" 41 41 … … 46 46 #include <iprt/file.h> 47 47 #include <iprt/string.h> 48 49 #include <sys/utsname.h> 48 #include <iprt/thread.h> 49 50 #include <X11/Xlib.h> 51 #include <X11/Xutil.h> 52 #include <X11/Xlibint.h> 53 #include <X11/extensions/shape.h> 54 #include <X11/extensions/Xrandr.h> 50 55 51 56 /** Maximum number of supported screens. DRM and X11 both limit this to 32. */ … … 53 58 * context structure. */ 54 59 #define VMW_MAX_HEADS 32 55 56 #include "seamless-x11.h" 57 58 #ifdef RT_OS_LINUX 59 # include <sys/ioctl.h> 60 #else /* Solaris and BSDs, in case they ever adopt the DRM driver. */ 61 # include <sys/ioccom.h> 62 #endif 63 64 #define USE_XRANDR_BIN 65 60 /** Monitor positions array. Allocated here and deallocated in the class descructor. */ 61 RTPOINT *mpMonitorPositions; 62 /** Thread to listen to some of the X server events. */ 63 RTTHREAD mX11MonitorThread = NIL_RTTHREAD; 66 64 67 65 struct X11VMWRECT /* xXineramaScreenInfo in Xlib headers. */ … … 83 81 int hRandRErrorBase; 84 82 int hEventMask; 83 /** The number of outputs (monitors, including disconnect ones) xrandr reports. */ 84 int hOutputCount; 85 85 Window rootWindow; 86 86 }; 87 88 static X11CONTEXT x11Context; 87 89 88 90 #define MAX_MODE_NAME_LEN 64 … … 93 95 static const char *pcszXrandr = "xrandr"; 94 96 static const char *pcszCvt = "cvt"; 95 /** The number of outputs (monitors, including disconnect ones) xrandr reports. */96 static int iOutputCount = 0;97 97 98 98 struct DRMCONTEXT … … 111 111 112 112 /** Forward declarations. */ 113 static void x11Connect(struct X11CONTEXT *pContext); 114 115 static bool init(struct X11CONTEXT *pContext) 116 { 117 if (!pContext) 113 static void x11Connect(); 114 static int determineOutputCount(); 115 116 /** This function assumes monitors are named as from Virtual1 to VirtualX. */ 117 static int getMonitorIdFromName(const char *sMonitorName) 118 { 119 if (!sMonitorName) 120 return -1; 121 int iLen = strlen(sMonitorName); 122 if (iLen <= 0) 123 return -1; 124 int iBase = 10; 125 int iResult = 0; 126 for (int i = iLen - 1; i >= 0; --i) 127 { 128 /* Stop upon seeing the first non-numeric char. */ 129 if (sMonitorName[i] < 48 || sMonitorName[i] > 57) 130 break; 131 iResult += (sMonitorName[i] - 48) * iBase / 10; 132 iBase *= 10; 133 } 134 return iResult; 135 } 136 137 static void queryMonitorPositions() 138 { 139 printf("==========================================================================================================================================="); 140 static const int iSentinelPosition = -1; 141 if (mpMonitorPositions) 142 { 143 free(mpMonitorPositions); 144 mpMonitorPositions = NULL; 145 } 146 // if (!mHostMonitorPositionSendCallback) 147 // { 148 // VBClLogFatalError("No monitor positions update callback\n"); 149 // return; 150 // } 151 152 XRRScreenResources *pScreenResources = XRRGetScreenResources (x11Context.pDisplay, DefaultRootWindow(x11Context.pDisplay)); 153 AssertReturnVoid(pScreenResources); 154 XRRFreeScreenResources (pScreenResources); 155 156 int iMonitorCount = 0; 157 XRRMonitorInfo *pMonitorInfo = XRRGetMonitors(x11Context.pDisplay, DefaultRootWindow(x11Context.pDisplay), true, &iMonitorCount); 158 if (iMonitorCount == -1) 159 VBClLogError("Could not get monitor info\n"); 160 else 161 { 162 getMonitorIdFromName("virtual123"); 163 mpMonitorPositions = (RTPOINT*)malloc(x11Context.hOutputCount * sizeof(RTPOINT)); 164 /* todo: memset? */ 165 for (int i = 0; i < x11Context.hOutputCount; ++i) 166 { 167 mpMonitorPositions[i].x = iSentinelPosition; 168 mpMonitorPositions[i].y = iSentinelPosition; 169 } 170 for (int i = 0; i < iMonitorCount; ++i) 171 { 172 int iMonitorID = getMonitorIdFromName(XGetAtomName(x11Context.pDisplay, pMonitorInfo[i].name)) - 1; 173 if (iMonitorID >= x11Context.hOutputCount || iMonitorID == -1) 174 continue; 175 VBClLogInfo("Monitor %d (w,h)=(%d,%d) (x,y)=(%d,%d)\n", 176 i, 177 pMonitorInfo[i].width, pMonitorInfo[i].height, 178 pMonitorInfo[i].x, pMonitorInfo[i].y); 179 mpMonitorPositions[iMonitorID].x = pMonitorInfo[i].x; 180 mpMonitorPositions[iMonitorID].y = pMonitorInfo[i].y; 181 } 182 // if (iMonitorCount > 0) 183 // mHostMonitorPositionSendCallback(mpMonitorPositions, x11Context.hOutputCount); 184 } 185 XRRFreeMonitors(pMonitorInfo); 186 } 187 188 static void monitorRandREvents() 189 { 190 XEvent event; 191 XNextEvent(x11Context.pDisplay, &event); 192 int eventTypeOffset = event.type - x11Context.hRandREventBase; 193 switch (eventTypeOffset) 194 { 195 case RRScreenChangeNotify: 196 VBClLogInfo("RRScreenChangeNotify\n"); 197 queryMonitorPositions(); 198 break; 199 case RRNotify: 200 VBClLogInfo("RRNotify\n"); 201 break; 202 default: 203 VBClLogInfo("Unknown RR event\n"); 204 break; 205 } 206 } 207 208 int x11MonitorThreadFunction(RTTHREAD hThreadSelf, void *pvUser) 209 { 210 (void)hThreadSelf; 211 (void*)pvUser; 212 while(1) 213 { 214 monitorRandREvents(); 215 } 216 return 0; 217 } 218 219 static int startX11MonitorThread() 220 { 221 int rc; 222 223 if (mX11MonitorThread == NIL_RTTHREAD) 224 { 225 rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThreadFunction, 0, 0, 226 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, 227 "X11 events"); 228 if (RT_FAILURE(rc)) 229 VBClLogFatalError("Warning: failed to start X11 monitor thread (VBoxClient) rc=%Rrc!\n", rc); 230 } 231 return rc; 232 } 233 234 static int stopX11MonitorThread(void) 235 { 236 int rc; 237 if (mX11MonitorThread != NIL_RTTHREAD) 238 { 239 //???????? 240 //mX11Monitor.interruptEventWait(); 241 rc = RTThreadWait(mX11MonitorThread, 1000, NULL); 242 if (RT_SUCCESS(rc)) 243 mX11MonitorThread = NIL_RTTHREAD; 244 else 245 VBClLogError("Failed to stop X11 monitor thread, rc=%Rrc!\n", rc); 246 } 247 return rc; 248 } 249 250 static bool init() 251 { 252 x11Connect(); 253 if (x11Context.pDisplay == NULL) 118 254 return false; 119 x11Connect(pContext); 120 if (pContext->pDisplay == NULL) 255 if (RT_FAILURE(startX11MonitorThread())) 121 256 return false; 257 XRRSelectInput(x11Context.pDisplay, x11Context.rootWindow, x11Context.hEventMask); 122 258 return true; 123 259 } 124 260 125 static void x11Connect(struct X11CONTEXT *pContext) 261 static void cleanup() 262 { 263 if (mpMonitorPositions) 264 { 265 free(mpMonitorPositions); 266 mpMonitorPositions = NULL; 267 } 268 stopX11MonitorThread(); 269 XRRSelectInput(x11Context.pDisplay, x11Context.rootWindow, 0); 270 XCloseDisplay(x11Context.pDisplay); 271 } 272 273 static void x11Connect() 126 274 { 127 275 int dummy; 128 if ( pContext->pDisplay != NULL)276 if (x11Context.pDisplay != NULL) 129 277 VBClLogFatalError("%s called with bad argument\n", __func__); 130 pContext->pDisplay = XOpenDisplay(NULL);131 if ( pContext->pDisplay == NULL)278 x11Context.pDisplay = XOpenDisplay(NULL); 279 if (x11Context.pDisplay == NULL) 132 280 return; 133 if(!XQueryExtension( pContext->pDisplay, "VMWARE_CTRL",134 & pContext->hVMWMajor, &dummy, &dummy))135 { 136 XCloseDisplay( pContext->pDisplay);137 pContext->pDisplay = NULL;138 } 139 if (!XRRQueryExtension( pContext->pDisplay, &pContext->hRandREventBase, &pContext->hRandRErrorBase))140 { 141 XCloseDisplay( pContext->pDisplay);142 pContext->pDisplay = NULL;143 } 144 if (!XRRQueryVersion( pContext->pDisplay, &pContext->hRandRMajor, &pContext->hRandRMinor))145 { 146 XCloseDisplay( pContext->pDisplay);147 pContext->pDisplay = NULL;148 } 149 pContext->hEventMask = RRScreenChangeNotifyMask;150 if ( pContext->hRandRMinor >= 2)151 pContext->hEventMask |= RRCrtcChangeNotifyMask |281 if(!XQueryExtension(x11Context.pDisplay, "VMWARE_CTRL", 282 &x11Context.hVMWMajor, &dummy, &dummy)) 283 { 284 XCloseDisplay(x11Context.pDisplay); 285 x11Context.pDisplay = NULL; 286 } 287 if (!XRRQueryExtension(x11Context.pDisplay, &x11Context.hRandREventBase, &x11Context.hRandRErrorBase)) 288 { 289 XCloseDisplay(x11Context.pDisplay); 290 x11Context.pDisplay = NULL; 291 } 292 if (!XRRQueryVersion(x11Context.pDisplay, &x11Context.hRandRMajor, &x11Context.hRandRMinor)) 293 { 294 XCloseDisplay(x11Context.pDisplay); 295 x11Context.pDisplay = NULL; 296 } 297 x11Context.hEventMask = RRScreenChangeNotifyMask; 298 if (x11Context.hRandRMinor >= 2) 299 x11Context.hEventMask |= RRCrtcChangeNotifyMask | 152 300 RROutputChangeNotifyMask | 153 301 RROutputPropertyNotifyMask; 154 pContext->rootWindow = DefaultRootWindow(pContext->pDisplay); 302 x11Context.rootWindow = DefaultRootWindow(x11Context.pDisplay); 303 x11Context.hOutputCount = determineOutputCount(); 155 304 } 156 305 … … 313 462 char szAddModeCommand[1024]; 314 463 /* try to add the new mode to all possible outputs. we currently dont care if most the are disabled. */ 315 for(int i = 0; i < iOutputCount; ++i)464 for(int i = 0; i < x11Context.hOutputCount; ++i) 316 465 { 317 466 RTStrPrintf(szAddModeCommand, sizeof(szAddModeCommand), "%s --addmode Virtual%d \"%s\"", pcszXrandr, i + 1, pszModeName); … … 350 499 RTStrPrintf(szCommand, sizeof(szCommand), "%s ", pcszXrandr); 351 500 352 for (int i = 0; i < iOutputCount; ++i)501 for (int i = 0; i < x11Context.hOutputCount; ++i) 353 502 { 354 503 char line[64]; … … 390 539 static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised) 391 540 { 392 iOutputCount = determineOutputCount();393 541 (void)ppInterface; 394 542 (void)fDaemonised; … … 398 546 * e.g. from before a guest reboot. */ 399 547 bool fAck = false; 400 struct X11CONTEXT x11Context = { NULL }; 401 if (!init( &x11Context))548 549 if (!init()) 402 550 return VINF_SUCCESS; 403 551 static struct VMMDevDisplayDef aMonitors[VMW_MAX_HEADS]; … … 458 606 struct RANDROUTPUT aOutputs[VMW_MAX_HEADS]; 459 607 int iRunningX = 0; 460 for (int j = 0; j < iOutputCount; ++j)608 for (int j = 0; j < x11Context.hOutputCount; ++j) 461 609 { 462 610 aOutputs[j].x = iRunningX; … … 477 625 VBClLogFatalError("Failure waiting for event, rc=%Rrc\n", rc); 478 626 } 627 cleanup(); 479 628 } 480 629
Note:
See TracChangeset
for help on using the changeset viewer.