VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxvideo/getmode.c@ 54040

Last change on this file since 54040 was 54040, checked in by vboxsync, 10 years ago

Devices/Graphics, Main: optionally send cursor integration toggle and guest cursor position information through the graphics device. X11/Linux Additions support, actually make the cursor visible after toggling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.7 KB
Line 
1/* $Id: getmode.c 54040 2015-01-29 19:25:48Z vboxsync $ */
2/** @file
3 * VirtualBox X11 Additions graphics driver dynamic video mode functions.
4 */
5
6/*
7 * Copyright (C) 2006-2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "vboxvideo.h"
19#include <VBox/VMMDev.h>
20
21#define NEED_XF86_TYPES
22#include <iprt/string.h>
23
24#include "xf86.h"
25#include "dixstruct.h"
26#ifdef VBOX_GUESTR3XF86MOD
27# define EXTENSION_PROC_ARGS char *name, GCPtr pGC
28#endif
29#include "extnsionst.h"
30#include "windowstr.h"
31#include <X11/extensions/randrproto.h>
32
33#ifdef XORG_7X
34# include <stdio.h>
35# include <stdlib.h>
36#endif
37
38#ifdef VBOXVIDEO_13
39# ifdef RT_OS_LINUX
40# include "randrstr.h"
41# include "xf86_OSproc.h"
42# include <linux/input.h>
43# ifndef EVIOCGRAB
44# define EVIOCGRAB _IOW('E', 0x90, int)
45# endif
46# ifndef KEY_SWITCHVIDEOMODE
47# define KEY_SWITCHVIDEOMODE 227
48# endif
49# include <dirent.h>
50# include <errno.h>
51# include <fcntl.h>
52# include <unistd.h>
53# endif /* RT_OS_LINUX */
54#endif /* VBOXVIDEO_13 */
55/**************************************************************************
56* Main functions *
57**************************************************************************/
58
59/**
60 * Fills a display mode M with a built-in mode of name pszName and dimensions
61 * cx and cy.
62 */
63static void vboxFillDisplayMode(ScrnInfoPtr pScrn, DisplayModePtr m,
64 const char *pszName, unsigned cx, unsigned cy)
65{
66 VBOXPtr pVBox = pScrn->driverPrivate;
67 char szName[256];
68 DisplayModePtr pPrev = m->prev;
69 DisplayModePtr pNext = m->next;
70
71 if (!pszName)
72 {
73 sprintf(szName, "%ux%u", cx, cy);
74 pszName = szName;
75 }
76 TRACE_LOG("pszName=%s, cx=%u, cy=%u\n", pszName, cx, cy);
77 if (m->name)
78 free((void*)m->name);
79 memset(m, '\0', sizeof(*m));
80 m->prev = pPrev;
81 m->next = pNext;
82 m->status = MODE_OK;
83 m->type = M_T_BUILTIN;
84 /* Older versions of VBox only support screen widths which are a multiple
85 * of 8 */
86 if (pVBox->fAnyX)
87 m->HDisplay = cx;
88 else
89 m->HDisplay = cx & ~7;
90 m->HSyncStart = m->HDisplay + 2;
91 m->HSyncEnd = m->HDisplay + 4;
92 m->HTotal = m->HDisplay + 6;
93 m->VDisplay = cy;
94 m->VSyncStart = m->VDisplay + 2;
95 m->VSyncEnd = m->VDisplay + 4;
96 m->VTotal = m->VDisplay + 6;
97 m->Clock = m->HTotal * m->VTotal * 60 / 1000; /* kHz */
98 m->name = xnfstrdup(pszName);
99}
100
101/** vboxvideo's list of standard video modes */
102struct
103{
104 /** mode width */
105 uint32_t cx;
106 /** mode height */
107 uint32_t cy;
108} vboxStandardModes[] =
109{
110 { 1600, 1200 },
111 { 1440, 1050 },
112 { 1280, 960 },
113 { 1024, 768 },
114 { 800, 600 },
115 { 640, 480 },
116 { 0, 0 }
117};
118enum
119{
120 vboxNumStdModes = sizeof(vboxStandardModes) / sizeof(vboxStandardModes[0])
121};
122
123/**
124 * Returns a standard mode which the host likes. Can be called multiple
125 * times with the index returned by the previous call to get a list of modes.
126 * @returns the index of the mode in the list, or 0 if no more modes are
127 * available
128 * @param pScrn the screen information structure
129 * @param pScrn->bitsPerPixel
130 * if this is non-null, only modes with this BPP will be
131 * returned
132 * @param cIndex the index of the last mode queried, or 0 to query the
133 * first mode available. Note: the first index is 1
134 * @param pcx where to store the mode's width
135 * @param pcy where to store the mode's height
136 * @param pcBits where to store the mode's BPP
137 */
138unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,
139 uint32_t *pcx, uint32_t *pcy)
140{
141 unsigned i;
142
143 VBVXASSERT(cIndex < vboxNumStdModes,
144 ("cIndex = %d, vboxNumStdModes = %d\n", cIndex,
145 vboxNumStdModes));
146 for (i = cIndex; i < vboxNumStdModes - 1; ++i)
147 {
148 uint32_t cx = vboxStandardModes[i].cx;
149 uint32_t cy = vboxStandardModes[i].cy;
150
151 if (pcx)
152 *pcx = cx;
153 if (pcy)
154 *pcy = cy;
155 return i + 1;
156 }
157 return 0;
158}
159
160/**
161 * Allocates an empty display mode and links it into the doubly linked list of
162 * modes pointed to by pScrn->modes. Returns a pointer to the newly allocated
163 * memory.
164 */
165static DisplayModePtr vboxAddEmptyScreenMode(ScrnInfoPtr pScrn)
166{
167 DisplayModePtr pMode = xnfcalloc(sizeof(DisplayModeRec), 1);
168
169 TRACE_ENTRY();
170 if (!pScrn->modes)
171 {
172 pScrn->modes = pMode;
173 pMode->next = pMode;
174 pMode->prev = pMode;
175 }
176 else
177 {
178 pMode->next = pScrn->modes;
179 pMode->prev = pScrn->modes->prev;
180 pMode->next->prev = pMode;
181 pMode->prev->next = pMode;
182 }
183 return pMode;
184}
185
186/**
187 * Create display mode entries in the screen information structure for each
188 * of the graphics modes that we wish to support, that is:
189 * - A dynamic mode in first place which will be updated by the RandR code.
190 * - Several standard modes.
191 * - Any modes that the user requested in xorg.conf/XFree86Config.
192 */
193void vboxAddModes(ScrnInfoPtr pScrn)
194{
195 unsigned cx = 0, cy = 0, cIndex = 0;
196 unsigned i;
197 DisplayModePtr pMode;
198
199 /* Add two dynamic mode entries. When we receive a new size hint we will
200 * update whichever of these is not current. */
201 pMode = vboxAddEmptyScreenMode(pScrn);
202 vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
203 pMode = vboxAddEmptyScreenMode(pScrn);
204 vboxFillDisplayMode(pScrn, pMode, NULL, 1024, 768);
205 /* Add standard modes supported by the host */
206 for ( ; ; )
207 {
208 cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy);
209 if (cIndex == 0)
210 break;
211 pMode = vboxAddEmptyScreenMode(pScrn);
212 vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);
213 }
214 /* And finally any modes specified by the user. We assume here that
215 * the mode names reflect the mode sizes. */
216 for (i = 0; pScrn->display->modes && pScrn->display->modes[i]; i++)
217 {
218 if (sscanf(pScrn->display->modes[i], "%ux%u", &cx, &cy) == 2)
219 {
220 pMode = vboxAddEmptyScreenMode(pScrn);
221 vboxFillDisplayMode(pScrn, pMode, pScrn->display->modes[i], cx, cy);
222 }
223 }
224}
225
226/** Set the initial values for the guest screen size hints by reading saved
227 * values from files. */
228/** @todo Actually read the files instead of setting dummies. */
229void VBoxInitialiseSizeHints(ScrnInfoPtr pScrn)
230{
231 VBOXPtr pVBox = VBOXGetRec(pScrn);
232 DisplayModePtr pMode;
233 unsigned i;
234
235 for (i = 0; i < pVBox->cScreens; ++i)
236 {
237 pVBox->pScreens[i].aPreferredSize.cx = 1024;
238 pVBox->pScreens[i].aPreferredSize.cy = 768;
239 pVBox->pScreens[i].afConnected = true;
240 }
241 /* Set up the first mode correctly to match the requested initial mode. */
242 pScrn->modes->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
243 pScrn->modes->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
244 /* RandR 1.1 quirk: make sure that the initial resolution is always present
245 * in the mode list as RandR will always advertise a mode of the initial
246 * virtual resolution via GetScreenInfo. */
247 pMode = vboxAddEmptyScreenMode(pScrn);
248 vboxFillDisplayMode(pScrn, pMode, NULL, pVBox->pScreens[0].aPreferredSize.cx,
249 pVBox->pScreens[0].aPreferredSize.cy);
250}
251
252static void updateUseHardwareCursor(VBOXPtr pVBox, uint32_t fCursorCapabilities)
253{
254 bool fGuestCanReportAbsolutePosition = false;
255 bool fHostWishesToReportAbsolutePosition = false;
256
257 if ( (fCursorCapabilities & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE)
258#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
259 /* As of this version (server 1.6) all major Linux releases
260 * are known to handle USB tablets correctly. */
261 || (fCursorCapabilities & VMMDEV_MOUSE_HOST_HAS_ABS_DEV)
262#endif
263 )
264 fGuestCanReportAbsolutePosition = true;
265 if ( !(fCursorCapabilities & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
266 && (fCursorCapabilities & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
267 fHostWishesToReportAbsolutePosition = true;
268 pVBox->fUseHardwareCursor = fGuestCanReportAbsolutePosition && fHostWishesToReportAbsolutePosition;
269}
270
271# define SIZE_HINTS_PROPERTY "VBOX_SIZE_HINTS"
272# define MOUSE_CAPABILITIES_PROPERTY "VBOX_MOUSE_CAPABILITIES"
273
274/** Read in information about the most recent size hints requested for the
275 * guest screens. A client application sets the hint information as a root
276 * window property. */
277/* TESTING: dynamic resizing and absolute pointer toggling work on old guest X servers and recent ones on Linux at the log-in screen. */
278/** @note we try to maximise code coverage by typically using all code paths (HGSMI and properties) in a single X session. */
279void VBoxUpdateSizeHints(ScrnInfoPtr pScrn)
280{
281 VBOXPtr pVBox = VBOXGetRec(pScrn);
282 size_t cModesFromProperty, cDummy;
283 int32_t *paModeHints, *pfCursorCapabilities;
284 unsigned i;
285 uint32_t fCursorCapabilities;
286 bool fOldUseHardwareCursor = pVBox->fUseHardwareCursor;
287
288 if (vbvxGetIntegerPropery(pScrn, SIZE_HINTS_PROPERTY, &cModesFromProperty, &paModeHints) != VINF_SUCCESS)
289 paModeHints = NULL;
290 if ( vbvxGetIntegerPropery(pScrn, MOUSE_CAPABILITIES_PROPERTY, &cDummy, &pfCursorCapabilities) != VINF_SUCCESS
291 || cDummy != 1)
292 pfCursorCapabilities = NULL;
293#ifdef VBOXVIDEO_13
294 if (!pVBox->fHaveReadHGSMIModeHintData && RT_SUCCESS(VBoxHGSMIGetModeHints(&pVBox->guestCtx, pVBox->cScreens,
295 pVBox->paVBVAModeHints)))
296 {
297 for (i = 0; i < pVBox->cScreens; ++i)
298 {
299 if (pVBox->paVBVAModeHints[i].magic == VBVAMODEHINT_MAGIC)
300 {
301 pVBox->pScreens[i].aPreferredSize.cx = pVBox->paVBVAModeHints[i].cx;
302 pVBox->pScreens[i].aPreferredSize.cy = pVBox->paVBVAModeHints[i].cy;
303 pVBox->pScreens[i].afConnected = pVBox->paVBVAModeHints[i].fEnabled;
304 /* Do not re-read this if we have data from HGSMI. */
305 if (paModeHints != NULL && i < cModesFromProperty)
306 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
307 }
308 }
309 }
310 if (!pVBox->fHaveReadHGSMIModeHintData)
311 {
312 if (RT_SUCCESS(VBoxQueryConfHGSMI(&pVBox->guestCtx, VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &fCursorCapabilities)))
313 updateUseHardwareCursor(pVBox, fCursorCapabilities);
314 else
315 pVBox->fUseHardwareCursor = false;
316 /* Do not re-read this if we have data from HGSMI. */
317 if (pfCursorCapabilities != NULL)
318 pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
319 }
320 pVBox->fHaveReadHGSMIModeHintData = true;
321#endif
322 if (paModeHints != NULL)
323 for (i = 0; i < cModesFromProperty && i < pVBox->cScreens; ++i)
324 {
325 if (paModeHints[i] != 0 && paModeHints[i] != pVBox->pScreens[i].lastModeHintFromProperty)
326 {
327 if (paModeHints[i] == -1)
328 pVBox->pScreens[i].afConnected = false;
329 else
330 {
331 pVBox->pScreens[i].aPreferredSize.cx = paModeHints[i] >> 16;
332 pVBox->pScreens[i].aPreferredSize.cy = paModeHints[i] & 0x8fff;
333 pVBox->pScreens[i].afConnected = true;
334 }
335 pVBox->pScreens[i].lastModeHintFromProperty = paModeHints[i];
336 }
337 }
338 if (pfCursorCapabilities != NULL && *pfCursorCapabilities != pVBox->fLastCursorCapabilitiesFromProperty)
339 {
340 updateUseHardwareCursor(pVBox, (uint32_t)*pfCursorCapabilities);
341 pVBox->fLastCursorCapabilitiesFromProperty = *pfCursorCapabilities;
342 }
343 if (pVBox->fUseHardwareCursor != fOldUseHardwareCursor)
344 vbvxReprobeCursor(pScrn);
345}
346
347#ifndef VBOXVIDEO_13
348
349/** The RandR "proc" vector, which we wrap with our own in order to notice
350 * when a client sends a GetScreenInfo request. */
351static int (*g_pfnVBoxRandRProc)(ClientPtr) = NULL;
352/** The swapped RandR "proc" vector. */
353static int (*g_pfnVBoxRandRSwappedProc)(ClientPtr) = NULL;
354
355/* TESTING: dynamic resizing and toggling cursor integration work with older guest X servers (1.2 and older). */
356static void vboxRandRDispatchCore(ClientPtr pClient)
357{
358 xRRGetScreenInfoReq *pReq = (xRRGetScreenInfoReq *)pClient->requestBuffer;
359 WindowPtr pWin;
360 ScrnInfoPtr pScrn;
361 VBOXPtr pVBox;
362 DisplayModePtr pMode;
363
364 if (pClient->req_len != sizeof(xRRGetScreenInfoReq) >> 2)
365 return;
366 pWin = (WindowPtr)SecurityLookupWindow(pReq->window, pClient,
367 SecurityReadAccess);
368 if (!pWin)
369 return;
370 pScrn = xf86Screens[pWin->drawable.pScreen->myNum];
371 pVBox = VBOXGetRec(pScrn);
372 TRACE_LOG("pVBox->fUseHardwareCursor=%u\n", pVBox->fUseHardwareCursor);
373 VBoxUpdateSizeHints(pScrn);
374 pMode = pScrn->modes;
375 if (pScrn->currentMode == pMode)
376 pMode = pMode->next;
377 pMode->HDisplay = pVBox->pScreens[0].aPreferredSize.cx;
378 pMode->VDisplay = pVBox->pScreens[0].aPreferredSize.cy;
379}
380
381static int vboxRandRDispatch(ClientPtr pClient)
382{
383 xReq *pReq = (xReq *)pClient->requestBuffer;
384
385 if (pReq->data == X_RRGetScreenInfo)
386 vboxRandRDispatchCore(pClient);
387 return g_pfnVBoxRandRProc(pClient);
388}
389
390static int vboxRandRSwappedDispatch(ClientPtr pClient)
391{
392 xReq *pReq = (xReq *)pClient->requestBuffer;
393
394 if (pReq->data == X_RRGetScreenInfo)
395 vboxRandRDispatchCore(pClient);
396 return g_pfnVBoxRandRSwappedProc(pClient);
397}
398
399static Bool vboxRandRCreateScreenResources(ScreenPtr pScreen)
400{
401 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
402 VBOXPtr pVBox = VBOXGetRec(pScrn);
403 ExtensionEntry *pExt;
404
405 pScreen->CreateScreenResources = pVBox->pfnCreateScreenResources;
406 if (!pScreen->CreateScreenResources(pScreen))
407 return FALSE;
408 /* I doubt we can be loaded twice - should I fail here? */
409 if (g_pfnVBoxRandRProc)
410 return TRUE;
411 pExt = CheckExtension(RANDR_NAME);
412 if (!pExt)
413 {
414 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
415 "RandR extension not found, disabling dynamic resizing.\n");
416 return TRUE;
417 }
418 if ( !ProcVector[pExt->base]
419#if !defined(XF86_VERSION_CURRENT) \
420 || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
421 /* SwappedProcVector is not exported in XFree86, so we will not support
422 * swapped byte order clients. I doubt this is a big issue. */
423 || !SwappedProcVector[pExt->base]
424#endif
425 )
426 FatalError("RandR \"proc\" vector not initialised\n");
427 g_pfnVBoxRandRProc = ProcVector[pExt->base];
428 ProcVector[pExt->base] = vboxRandRDispatch;
429#if !defined(XF86_VERSION_CURRENT) \
430 || XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4, 3, 99, 0, 0)
431 g_pfnVBoxRandRSwappedProc = SwappedProcVector[pExt->base];
432 SwappedProcVector[pExt->base] = vboxRandRSwappedDispatch;
433#endif
434 return TRUE;
435}
436
437/** Install our private RandR hook procedure, so that we can detect
438 * GetScreenInfo requests from clients to update our dynamic mode. This works
439 * by installing a wrapper around CreateScreenResources(), which will be called
440 * after RandR is initialised. The wrapper then in turn wraps the RandR "proc"
441 * vectors with its own handlers which will get called on any client RandR
442 * request. This should not be used in conjunction with RandR 1.2 or later.
443 * A couple of points of interest in our RandR 1.1 support:
444 * * We use the first two screen modes as dynamic modes. When a new mode hint
445 * arrives we update the first of the two which is not the current mode with
446 * the new size.
447 * * RandR 1.1 always advertises a mode of the size of the initial virtual
448 * resolution via GetScreenInfo(), so we make sure that a mode of that size
449 * is always present in the list.
450 * * RandR adds each new mode it sees to an internal array, but never removes
451 * entries. This array might end up getting rather long given that we can
452 * report a lot more modes than physical hardware.
453 */
454void VBoxSetUpRandR11(ScreenPtr pScreen)
455{
456 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
457
458 if (!pScreen->CreateScreenResources)
459 FatalError("called to early: CreateScreenResources not yet initialised\n");
460 pVBox->pfnCreateScreenResources = pScreen->CreateScreenResources;
461 pScreen->CreateScreenResources = vboxRandRCreateScreenResources;
462}
463
464#endif /* !VBOXVIDEO_13 */
465
466#ifdef VBOXVIDEO_13
467# ifdef RT_OS_LINUX
468/* TESTING: dynamic resizing works on recent Linux guest X servers at the log-in screen. */
469/** @note to maximise code coverage we only read data from HGSMI once, and only when responding to an ACPI event. */
470static void acpiEventHandler(int fd, void *pvData)
471{
472 ScreenPtr pScreen = (ScreenPtr)pvData;
473 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
474 struct input_event event;
475 ssize_t rc;
476
477 pVBox->fHaveReadHGSMIModeHintData = false;
478 RRGetInfo(pScreen
479# if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5
480 , TRUE
481# endif
482 );
483 VBVXASSERT(pVBox->fHaveReadHGSMIModeHintData == true, ("fHaveReadHGSMIModeHintData not set.\n"));
484 do
485 rc = read(fd, &event, sizeof(event));
486 while (rc > 0 || (rc == -1 && errno == EINTR));
487 /* Why do they return EAGAIN instead of zero bytes read like everyone else does? */
488 VBVXASSERT(rc != -1 || errno == EAGAIN, ("Reading ACPI input event failed.\n"));
489}
490
491void VBoxSetUpLinuxACPI(ScreenPtr pScreen)
492{
493 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
494 struct dirent *pDirent;
495 DIR *pDir;
496 int fd = -1;
497
498 if (pVBox->fdACPIDevices != -1 || pVBox->hACPIEventHandler != NULL)
499 FatalError("ACPI input file descriptor not initialised correctly.\n");
500 pDir = opendir("/dev/input");
501 if (pDir == NULL)
502 return;
503 for (pDirent = readdir(pDir); pDirent != NULL; pDirent = readdir(pDir))
504 {
505 if (strncmp(pDirent->d_name, "event", sizeof("event") - 1) == 0)
506 {
507#define BITS_PER_BLOCK (sizeof(unsigned long) * 8)
508 char pszFile[64] = "/dev/input/";
509 char pszDevice[64] = "";
510 unsigned long afKeys[KEY_MAX / BITS_PER_BLOCK];
511
512 strncat(pszFile, pDirent->d_name, sizeof(pszFile));
513 if (fd != -1)
514 close(fd);
515 fd = open(pszFile, O_RDONLY | O_NONBLOCK);
516 if ( fd == -1
517 || ioctl(fd, EVIOCGNAME(sizeof(pszDevice)), pszDevice) == -1
518 || strcmp(pszDevice, "Video Bus") != 0)
519 continue;
520 if ( ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(afKeys)), afKeys) == -1
521 || (( afKeys[KEY_SWITCHVIDEOMODE / BITS_PER_BLOCK]
522 >> KEY_SWITCHVIDEOMODE % BITS_PER_BLOCK) & 1) == 0)
523 break;
524 if (ioctl(fd, EVIOCGRAB, (void *)1) != 0)
525 break;
526 pVBox->hACPIEventHandler
527 = xf86AddGeneralHandler(fd, acpiEventHandler, pScreen);
528 if (pVBox->hACPIEventHandler == NULL)
529 break;
530 pVBox->fdACPIDevices = fd;
531 fd = -1;
532 break;
533#undef BITS_PER_BLOCK
534 }
535 }
536 if (fd != -1)
537 close(fd);
538 closedir(pDir);
539}
540
541void VBoxCleanUpLinuxACPI(ScreenPtr pScreen)
542{
543 VBOXPtr pVBox = VBOXGetRec(xf86Screens[pScreen->myNum]);
544 if (pVBox->fdACPIDevices != -1)
545 close(pVBox->fdACPIDevices);
546 pVBox->fdACPIDevices = -1;
547 xf86RemoveGeneralHandler(pVBox->hACPIEventHandler);
548 pVBox->hACPIEventHandler = NULL;
549}
550# endif /* RT_OS_LINUX */
551#endif /* VBOXVIDEO_13 */
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