VirtualBox

Ignore:
Timestamp:
Dec 19, 2012 11:01:38 AM (12 years ago)
Author:
vboxsync
Message:

VboxTray/VideoMode: Dynamic configuration of secondary monitor for windows guest. (Enabling/disabling/Change of resolution/position)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp

    r42232 r44161  
    213213}
    214214
     215static DWORD EnableAndResizeDispDev(ULONG Id, DWORD aWidth, DWORD aHeight,
     216                                   DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY,
     217                                   BOOL fEnabled, VBOXDISPLAYCONTEXT *pCtx)
     218{
     219    DISPLAY_DEVICE DisplayDeviceTmp;
     220    DISPLAY_DEVICE DisplayDevice;
     221    DEVMODE DeviceModeTmp;
     222    DEVMODE DeviceMode;
     223    DWORD DispNum = 0;
     224
     225    ZeroMemory(&DisplayDeviceTmp, sizeof(DisplayDeviceTmp));
     226    DisplayDeviceTmp.cb = sizeof(DisplayDevice);
     227    ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
     228    DisplayDevice.cb = sizeof(DisplayDevice);
     229
     230    Log(("EnableDisplayDevice Id=%d, width=%d height=%d \
     231         PosX = %d PosY = %d \n",Id, aWidth, aHeight, aPosX, aPosY));
     232
     233    /* Disable all the devices apart from the device with ID = Id and
     234     * primary device.
     235     */
     236    while (EnumDisplayDevices (NULL, DispNum, &DisplayDeviceTmp, 0))
     237    {
     238        if (DispNum == Id) {
     239            DisplayDevice = DisplayDeviceTmp;
     240        }
     241        /* Displays which are configured but not enabled, update their
     242         * registry entries for parameters width , height, posX and
     243         * posY as 0. This is done so that they are not enabled when
     244         * ChangeDisplaySettings(NULL) is called
     245         */
     246        if (DispNum != 0 && DispNum != Id)
     247        {
     248            ZeroMemory(&DeviceModeTmp, sizeof(DEVMODE));
     249            DeviceModeTmp.dmSize = sizeof(DEVMODE);
     250            DeviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
     251                                     | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
     252            if (!EnumDisplaySettings((LPSTR)DisplayDeviceTmp.DeviceName,
     253                                     ENUM_REGISTRY_SETTINGS, &DeviceModeTmp))
     254            {
     255                Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings error %d\n", GetLastError ()));
     256                return FALSE;
     257            }
     258            if (DeviceModeTmp.dmPelsWidth == 0 || DeviceModeTmp.dmPelsHeight == 0)
     259            {
     260                /* No ENUM_REGISTRY_SETTINGS yet. Seen on Vista after installation.
     261                * Get the current video mode then.
     262                */
     263                ZeroMemory(&DeviceModeTmp, sizeof(DEVMODE));
     264                DeviceModeTmp.dmSize = sizeof(DEVMODE);
     265                if (!EnumDisplaySettings((LPSTR)DisplayDeviceTmp.DeviceName,
     266                                         ENUM_CURRENT_SETTINGS, &DeviceModeTmp))
     267                {
     268                    /* ENUM_CURRENT_SETTINGS returns FALSE when the display is not active:
     269                    * for example a disabled secondary display.
     270                    * Do not return here, ignore the error and set the display info to 0x0x0.
     271                    */
     272                    Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ()));
     273                    ZeroMemory(&DeviceMode, sizeof(DEVMODE));
     274                }
     275            }
     276            ZeroMemory(&DeviceModeTmp, sizeof(DEVMODE));
     277            DeviceModeTmp.dmSize = sizeof(DEVMODE);
     278            DeviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
     279                                     | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
     280            ChangeDisplaySettingsEx(DisplayDeviceTmp.DeviceName, &DeviceModeTmp, NULL,
     281                                     (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
     282        }
     283        DispNum++;
     284    }
     285
     286    /* Enable and set position for the monitor with ID = Id */
     287    ZeroMemory(&DeviceMode, sizeof(DEVMODE));
     288    DeviceMode.dmSize = sizeof(DEVMODE);
     289    EnumDisplayDevices (NULL, Id, &DisplayDevice, 0);
     290
     291    if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
     292         ENUM_REGISTRY_SETTINGS, &DeviceMode))
     293    {
     294        Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings error %d\n", GetLastError ()));
     295        return FALSE;
     296    }
     297
     298    if (DeviceMode.dmPelsWidth == 0
     299        || DeviceMode.dmPelsHeight == 0)
     300    {
     301        /* No ENUM_REGISTRY_SETTINGS yet. Seen on Vista after installation.
     302         * Get the current video mode then.
     303         */
     304        ZeroMemory(&DeviceMode, sizeof(DEVMODE));
     305        DeviceMode.dmSize = sizeof(DEVMODE);
     306        if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
     307             ENUM_CURRENT_SETTINGS, &DeviceMode))
     308        {
     309            /* ENUM_CURRENT_SETTINGS returns FALSE when the display is not active:
     310             * for example a disabled secondary display.
     311             * Do not return here, ignore the error and set the display info to 0x0x0.
     312             */
     313            Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ()));
     314            ZeroMemory(&DeviceMode, sizeof(DEVMODE));
     315        }
     316    }
     317
     318    DeviceMode.dmFields =  DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
     319    if (fEnabled) {
     320        if (aWidth !=0 && aHeight != 0)
     321        {
     322            Log(("VBoxTray: Mon ID = %d, Width = %d, Height = %d\n",
     323                Id, aWidth, aHeight));
     324            DeviceMode.dmFields |=  DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL ;
     325            DeviceMode.dmPelsWidth = aWidth;
     326            DeviceMode.dmPelsHeight = aHeight;
     327            DeviceMode.dmBitsPerPel = aBitsPerPixel;
     328        }
     329        if (aPosX != 0 || aPosY != 0)
     330        {
     331            Log(("VBoxTray: Mon ID = %d PoxX = %d, PoxY = %d\n",
     332                Id, aWidth, aHeight));
     333            DeviceMode.dmFields |=  DM_POSITION;
     334            DeviceMode.dmPosition.x = aPosX;
     335            DeviceMode.dmPosition.y = aPosY;
     336        }
     337    }
     338    else
     339    {
     340        /* Request is there to disable the monitor with ID = Id*/
     341        ZeroMemory(&DeviceModeTmp, sizeof(DEVMODE));
     342        DeviceModeTmp.dmSize = sizeof(DEVMODE);
     343        DeviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
     344                                 | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
     345    }
     346    gCtx.pfnChangeDisplaySettingsEx(DisplayDevice.DeviceName, &DeviceMode, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
     347    Log(("VBoxTray: ChangeDisplay return erroNo = %d\n", GetLastError()));
     348    DWORD dwStatus = gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
     349    Log(("VBoxTray: ChangeDisplay return errorNo = %d\n", GetLastError()));
     350    return dwStatus;
     351}
     352
    215353/* Returns TRUE to try again. */
    216354static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel,
    217                                         VBOXDISPLAYCONTEXT *pCtx)
     355                                BOOL fEnabled, DWORD dwNewPosX, DWORD dwNewPosY,
     356                                VBOXDISPLAYCONTEXT *pCtx, BOOL fExtDispSup)
    218357{
    219358    BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0);
     
    223362
    224363    DISPLAY_DEVICE DisplayDevice;
     364    DWORD dwStatus;
    225365
    226366    ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
     
    333473            }
    334474
    335             Log(("VBoxTray: ResizeDisplayDevice: %dx%dx%d at %d,%d\n",
    336                     paDeviceModes[DevNum].dmPelsWidth,
    337                     paDeviceModes[DevNum].dmPelsHeight,
    338                     paDeviceModes[DevNum].dmBitsPerPel,
    339                     paDeviceModes[DevNum].dmPosition.x,
    340                     paDeviceModes[DevNum].dmPosition.y));
    341 
    342             paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
    343             paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
    344             paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
    345             paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
     475            if (fExtDispSup)
     476            {
     477                Log(("VBoxTray: Extended Display Support.\n"));
     478                Log(("VBoxTray: ResizeDisplayDevice1: %dx%dx%d at %d,%d\n",
     479                        paDeviceModes[DevNum].dmPelsWidth,
     480                        paDeviceModes[DevNum].dmPelsHeight,
     481                        paDeviceModes[DevNum].dmBitsPerPel,
     482                        paDeviceModes[DevNum].dmPosition.x,
     483                        paDeviceModes[DevNum].dmPosition.y));
     484                if ((DevNum == Id && fEnabled == 1))
     485                {
     486                    /* Calculation of new position for enabled
     487                     * secondary monitor .
     488                     */
     489                    paRects[DevNum].left = dwNewPosX;
     490                    paRects[DevNum].bottom = dwNewPosY;
     491                    paDeviceModes[DevNum].dmPosition.x = dwNewPosX;
     492                    paDeviceModes[DevNum].dmPosition.x = dwNewPosY;
     493                    paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
     494                    paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
     495                }
     496                else
     497                {
     498                    paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
     499                    paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
     500                    paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
     501                    paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
     502                }
     503            }
     504            else
     505            {
     506                    paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
     507                    paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
     508                    paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
     509                    paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
     510            }
    346511            DevNum++;
    347512        }
     
    480645        Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", status, GetLastError ()));
    481646    }
    482 
    483     /* A second call to ChangeDisplaySettings updates the monitor. */
    484     LONG status = gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
    485     Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
    486     if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE)
    487     {
    488         /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
     647    if (fExtDispSup)
     648    {
     649        Log(("VBoxTray: Extended Display Supported. Width=%d Height=%d, \
     650             dwNewPosX=%d, dwNewPosY=%d \n",Width, Height, dwNewPosX, dwNewPosY));
     651        dwStatus = EnableAndResizeDispDev(Id, Width, Height, BitsPerPixel,
     652                                          dwNewPosX, dwNewPosY,fEnabled, pCtx);
     653    }
     654    else
     655    {
     656        Log(("VBoxTray: Extended Display Not Supported."));
     657        dwStatus = EnableAndResizeDispDev(Id, Width, Height, BitsPerPixel, 0, 0, 0, pCtx);
     658    }
     659    if (dwStatus == DISP_CHANGE_SUCCESSFUL || dwStatus == DISP_CHANGE_BADMODE)
     660    {
     661        /* Successfully set new video mode or our driver can not set
     662         * the requested mode. Stop trying.
     663         */
    489664        return FALSE;
    490665    }
    491 
    492666    /* Retry the request. */
    493667    return TRUE;
     
    525699    do
    526700    {
     701        BOOL fExtDispSup = TRUE;
    527702        /* Wait for a display change event. */
    528703        VBoxGuestWaitEventInfo waitEvent;
     
    553728            {
    554729                Log(("VBoxTray: VBoxDisplayThread: going to get display change information\n"));
     730                BOOL fDisplayChangeQueried;
     731
    555732
    556733                /* We got at least one event. Read the requested resolution
     
    558735                 * but a new resolution will be read in this poll loop.
    559736                 */
    560                 VMMDevDisplayChangeRequest2 displayChangeRequest = {0};
    561                 displayChangeRequest.header.size        = sizeof(VMMDevDisplayChangeRequest2);
     737                /* Try if extended mode display information is available from the host. */
     738                VMMDevDisplayChangeRequestEx displayChangeRequest = {0};
     739                displayChangeRequest.header.size        = sizeof(VMMDevDisplayChangeRequestEx);
    562740                displayChangeRequest.header.version     = VMMDEV_REQUEST_HEADER_VERSION;
    563                 displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest2;
     741                displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequestEx;
    564742                displayChangeRequest.eventAck           = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
    565                 BOOL fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest2)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2),
     743                fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequestEx)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequestEx),
     744                                                                 &displayChangeRequest, sizeof(VMMDevDisplayChangeRequestEx), &cbReturned, NULL);
     745
     746                if (!fDisplayChangeQueried) {
     747                    fExtDispSup = FALSE; /* Extended display Change request is not supported */
     748                    VMMDevDisplayChangeRequest2 displayChangeRequest = {0};
     749                    displayChangeRequest.header.size        = sizeof(VMMDevDisplayChangeRequest2);
     750                    displayChangeRequest.header.version     = VMMDEV_REQUEST_HEADER_VERSION;
     751                    displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest2;
     752                    displayChangeRequest.eventAck           = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST;
     753                    fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest2)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2),
    566754                                                             &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), &cbReturned, NULL);
     755                }
     756
    567757                if (!fDisplayChangeQueried)
    568758                {
     759                    fExtDispSup = FALSE; /*Extended display Change request is not supported */
    569760                    /* Try the old version of the request for old VBox hosts. */
    570761                    displayChangeRequest.header.size        = sizeof(VMMDevDisplayChangeRequest);
     
    603794                            {
    604795                                Log(("VBoxTray: VBoxDisplayThread: Detected W2K or later\n"));
    605 
    606796                                /* W2K or later. */
    607                                 if (!ResizeDisplayDevice(displayChangeRequest.display,
    608                                                          displayChangeRequest.xres,
    609                                                          displayChangeRequest.yres,
    610                                                          displayChangeRequest.bpp,
    611                                                          pCtx
    612                                                          ))
     797                                if (!fExtDispSup) { /* Extended display support not query possible */
     798                                    if (!ResizeDisplayDevice(displayChangeRequest.display,
     799                                                             displayChangeRequest.xres,
     800                                                             displayChangeRequest.yres,
     801                                                             displayChangeRequest.bpp,
     802                                                             0, /* NA for Normal Disp Change Req */
     803                                                             0, /* NA for Normal Disp Change Req */
     804                                                             0, /* NA for Normal Disp Change Req */
     805                                                             pCtx,
     806                                                             fExtDispSup
     807                                                             ))
     808                                    {
     809                                        Log(("ResizeDipspalyDevice return 0\n"));
     810                                        break;
     811                                    }
     812                                }
     813                                else /* Extended display support query possible */
    613814                                {
    614                                     break;
     815                                    Log(("DisplayChangeReqEx parameters  aDisplay=%d x xRes=%d x yRes=%d x bpp=%d x SecondayMonEnb=%d x NewOriginX=%d x NewOriginY=%d x ChangeOrigin=%d\n",
     816                                     displayChangeRequest.display,
     817                                     displayChangeRequest.xres,
     818                                     displayChangeRequest.yres,
     819                                     displayChangeRequest.bpp,
     820                                     displayChangeRequest.fEnabled,
     821                                     displayChangeRequest.cxOrigin,
     822                                     displayChangeRequest.cyOrigin,
     823                                     displayChangeRequest.fChangeOrigin));
     824                                    if (!ResizeDisplayDevice(displayChangeRequest.display,
     825                                                             displayChangeRequest.xres,
     826                                                             displayChangeRequest.yres,
     827                                                             displayChangeRequest.bpp,
     828                                                             displayChangeRequest.fEnabled,
     829                                                             displayChangeRequest.cxOrigin,
     830                                                             displayChangeRequest.cyOrigin,
     831                                                             pCtx,
     832                                                             fExtDispSup
     833                                                             ))
     834                                    {
     835                                        Log(("ResizeDipspalyDevice return 0\n"));
     836                                        break;
     837                                    }
    615838                                }
    616839                            }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette