VirtualBox

Changeset 44557 in vbox for trunk


Ignore:
Timestamp:
Feb 6, 2013 6:36:38 AM (12 years ago)
Author:
vboxsync
Message:

Additions/WINNT/VBoxTray: Support for dynamic operations on virtual secondary monitors
1) Enabling/ Disabling
2) Repositioning
3) Resizing.

Location:
trunk/src/VBox/Additions/WINNT
Files:
4 edited

Legend:

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

    r44550 r44557  
    1616
    1717#include "VBoxTray.h"
    18 
     18#define _WIN32_WINNT 0x0601
    1919#include <iprt/log.h>
    2020#include <iprt/err.h>
     
    2626#include <iprt/asm.h>
    2727#endif
     28
     29/* APIs specific to win7 and above WDDM architecture. Not available for Vista WDDM.
     30 * This is the reason they have not been put in the VBOXDISPIF struct in VBoxDispIf.h
     31 */
     32typedef struct _VBOXDISPLAYWDDMAPICONTEXT
     33{
     34    LONG (WINAPI * pfnSetDisplayConfig)(UINT numPathArrayElements,DISPLAYCONFIG_PATH_INFO *pathArray,UINT numModeInfoArrayElements,
     35                                    DISPLAYCONFIG_MODE_INFO *modeInfoArray, UINT Flags);
     36    LONG (WINAPI * pfnQueryDisplayConfig)(UINT Flags,UINT *pNumPathArrayElements, DISPLAYCONFIG_PATH_INFO *pPathInfoArray,
     37                                      UINT *pNumModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *pModeInfoArray,
     38                                      DISPLAYCONFIG_TOPOLOGY_ID *pCurrentTopologyId);
     39    LONG (WINAPI * pfnGetDisplayConfigBufferSizes)(UINT Flags, UINT *pNumPathArrayElements, UINT *pNumModeInfoArrayElements);
     40} _VBOXDISPLAYWDDMAPICONTEXT;
     41
     42static _VBOXDISPLAYWDDMAPICONTEXT gCtx = {0};
    2843
    2944/* display driver interface abstraction for XPDM & WDDM
     
    95110            Log((__FUNCTION__": VBoxDisplayInit: pfnEnumDisplayDevices = %p\n", pIf->modeData.wddm.pfnEnumDisplayDevices));
    96111            bSupported &= !!(pIf->modeData.wddm.pfnEnumDisplayDevices);
     112            /* for win 7 and above */
     113             if (OSinfo.dwMinorVersion >= 1)
     114            {
     115                *(uintptr_t *)&gCtx.pfnSetDisplayConfig = (uintptr_t)GetProcAddress(hUser, "SetDisplayConfig");
     116                Log((__FUNCTION__": VBoxDisplayInit: pfnSetDisplayConfig = %p\n", gCtx.pfnSetDisplayConfig));
     117                bSupported &= !!(gCtx.pfnSetDisplayConfig);
     118
     119                *(uintptr_t *)&gCtx.pfnQueryDisplayConfig = (uintptr_t)GetProcAddress(hUser, "QueryDisplayConfig");
     120                Log((__FUNCTION__": VBoxDisplayInit: pfnQueryDisplayConfig = %p\n", gCtx.pfnQueryDisplayConfig));
     121                bSupported &= !!(gCtx.pfnQueryDisplayConfig);
     122
     123                *(uintptr_t *)&gCtx.pfnGetDisplayConfigBufferSizes = (uintptr_t)GetProcAddress(hUser, "GetDisplayConfigBufferSizes");
     124                Log((__FUNCTION__": VBoxDisplayInit: pfnGetDisplayConfigBufferSizes = %p\n", gCtx.pfnGetDisplayConfigBufferSizes));
     125                bSupported &= !!(gCtx.pfnGetDisplayConfigBufferSizes);
     126            }
    97127
    98128            /* this is vista and up */
     
    11531183    Data.aScreenInfos[0].Mode.Height = pDeviceMode->dmPelsHeight;
    11541184    Data.aScreenInfos[0].Mode.BitsPerPixel = pDeviceMode->dmBitsPerPel;
     1185    if (pDeviceMode->dmPosition.x != 0 || pDeviceMode->dmPosition.y != 0) {
     1186        Data.aScreenInfos[0].Mode.PosX = pDeviceMode->dmPosition.x;
     1187        Data.aScreenInfos[0].Mode.PosY = pDeviceMode->dmPosition.y;
     1188    }
    11551189    DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), TRUE);
    11561190    if (err != NO_ERROR)
     
    11981232        pInfo->Height = paDeviceModes[i].dmPelsHeight;
    11991233        pInfo->BitsPerPixel = paDeviceModes[i].dmBitsPerPel;
     1234
     1235        if (i == iChangedMode && (paDeviceModes[i].dmPosition.x != 0 || paDeviceModes[i].dmPosition.y != 0) )
     1236        {
     1237                /* change position values only if not equal to 0*/
     1238                LogRel(("VBoxTray: (WDDM) Change Position x=%d*y=%d Display Device ID=%d\n", paDeviceModes[i].dmPosition.x, paDeviceModes[i].dmPosition.y, i));
     1239                pInfo->PosX = paDeviceModes[i].dmPosition.x;
     1240                pInfo->PosY =  paDeviceModes[i].dmPosition.y;
     1241        }
    12001242
    12011243        if (!hAdapter)
     
    12821324    return winEr;
    12831325}
     1326
     1327DWORD vboxDispIfWddmEnableDisplay(PCVBOXDISPIF const pIf, UINT Id, bool fEnabled)
     1328{
     1329    DISPLAYCONFIG_PATH_INFO PathInfoArray[10];
     1330    DISPLAYCONFIG_MODE_INFO ModeInfoArray[10];
     1331    UINT NumPathArrayElements = 0;
     1332    UINT NumModeInfoArrayElements = 0;
     1333    ULONG dwStatus;
     1334    UINT uFlag;
     1335
     1336    dwStatus = gCtx.pfnGetDisplayConfigBufferSizes(fEnabled ? QDC_ALL_PATHS : QDC_ONLY_ACTIVE_PATHS,&NumPathArrayElements,&NumModeInfoArrayElements);
     1337    if (dwStatus != ERROR_SUCCESS)
     1338    {
     1339        LogFlow(("VBoxTray: (WDDM) Failed GetDisplayConfigBufferSizes \n"));
     1340        return dwStatus;
     1341    }
     1342    dwStatus = gCtx.pfnQueryDisplayConfig(fEnabled ? QDC_ALL_PATHS : QDC_ONLY_ACTIVE_PATHS,&NumPathArrayElements, &PathInfoArray[0],&NumModeInfoArrayElements, &ModeInfoArray[0],NULL);
     1343    if (dwStatus != ERROR_SUCCESS)
     1344    {
     1345        LogFlow(("VBoxTray: (WDDM) Failed QueryDisplayConfig \n"));
     1346        return dwStatus;
     1347    }
     1348    for (unsigned int i=0; i < NumPathArrayElements; ++i)
     1349    {
     1350        if (PathInfoArray[i].sourceInfo.id == Id)
     1351        {
     1352            if (fEnabled)
     1353            {
     1354                LogRel(("VBoxTray: (WDDM) Enable the Display Device i =%d \n", i));
     1355                PathInfoArray[i].flags=DISPLAYCONFIG_PATH_ACTIVE;
     1356                break;
     1357            }
     1358            else
     1359            {
     1360                LogRel(("VBoxTray: (WDDM) Disable the Display Device  ID=%d and Sourceid=%d\n", i, PathInfoArray[i].sourceInfo.id));
     1361                PathInfoArray[i].flags=0;
     1362                break;
     1363            }
     1364        }
     1365    }
     1366    dwStatus = gCtx.pfnSetDisplayConfig(NumPathArrayElements, &PathInfoArray[0],NumModeInfoArrayElements, &ModeInfoArray[0],(SDC_APPLY | SDC_SAVE_TO_DATABASE| SDC_ALLOW_CHANGES | SDC_USE_SUPPLIED_DISPLAY_CONFIG));
     1367    if (dwStatus != ERROR_SUCCESS) {
     1368        LogRel(("VBoxTray:(WDDM) Failed to disable the monitor."));
     1369        return dwStatus;
     1370    }
     1371    return ERROR_SUCCESS;
     1372}
     1373
    12841374#endif /* VBOX_WITH_WDDM */
    12851375
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.h

    r44550 r44557  
    8787DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
    8888DWORD VBoxDispIfCancelPendingResize(PCVBOXDISPIF const pIf);
     89DWORD vboxDispIfWddmEnableDisplay(PCVBOXDISPIF const pIf, UINT Id, bool fEnabled);
    8990//DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange);
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp

    r44550 r44557  
    218218                                    VBOXDISPLAYCONTEXT *pCtx)
    219219{
    220     DISPLAY_DEVICE DisplayDeviceTmp;
    221     DISPLAY_DEVICE DisplayDevice;
    222     DEVMODE DeviceMode;
     220    DISPLAY_DEVICE displayDeviceTmp;
     221    DISPLAY_DEVICE displayDevice;
     222    DEVMODE devModePrimary;
     223    DEVMODE deviceMode;
    223224    DWORD DispNum = 0;
    224 
    225     ZeroMemory(&DisplayDeviceTmp, sizeof(DisplayDeviceTmp));
    226     DisplayDeviceTmp.cb = sizeof(DisplayDevice);
     225    DWORD dwStatus = DISP_CHANGE_SUCCESSFUL;
     226
     227    ZeroMemory(&displayDeviceTmp, sizeof(DISPLAY_DEVICE));
     228    displayDeviceTmp.cb = sizeof(DISPLAY_DEVICE);
    227229
    228230    Log(("EnableDisplayDevice Id=%d, width=%d height=%d \
     
    230232         Id, aWidth, aHeight, aPosX, aPosY, fEnabled, fExtDispSup));
    231233
    232     /* Disable all the devices apart from the device with ID = Id and
     234    /* Disable all the devices leaving the device with ID == Id and
    233235     * primary device.
    234236     */
    235     while (EnumDisplayDevices (NULL, DispNum, &DisplayDeviceTmp, 0))
     237    while (EnumDisplayDevices(NULL, DispNum, &displayDeviceTmp, 0))
    236238    {
    237239        /* Displays which are configured but not enabled, update their
     
    244246        if (DispNum != 0 && DispNum != Id)
    245247        {
    246             DEVMODE DeviceModeTmp;
    247             ZeroMemory(&DeviceModeTmp, sizeof(DEVMODE));
    248             DeviceModeTmp.dmSize = sizeof(DEVMODE);
    249             DeviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
     248            DEVMODE deviceModeTmp;
     249            ZeroMemory(&deviceModeTmp, sizeof(DEVMODE));
     250            deviceModeTmp.dmSize = sizeof(DEVMODE);
     251            deviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
    250252                                     | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
    251             gCtx.pfnChangeDisplaySettingsEx(DisplayDeviceTmp.DeviceName, &DeviceModeTmp, NULL,
    252                                     (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
     253            gCtx.pfnChangeDisplaySettingsEx(displayDeviceTmp.DeviceName, &deviceModeTmp, NULL,
     254                                           (CDS_UPDATEREGISTRY | CDS_NORESET), NULL);
    253255        }
    254256        DispNum++;
    255257    }
    256258
    257     ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
    258     DisplayDevice.cb = sizeof(DisplayDevice);
    259 
    260     ZeroMemory(&DeviceMode, sizeof(DEVMODE));
    261     DeviceMode.dmSize = sizeof(DEVMODE);
    262 
    263     EnumDisplayDevices (NULL, Id, &DisplayDevice, 0);
    264 
    265     if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
    266          ENUM_REGISTRY_SETTINGS, &DeviceMode))
    267     {
    268         Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings error %d\n", GetLastError ()));
    269         /* @todo: perhaps more intelligent error reporting is needed here
    270          * return DISP_CHANGE_BADMODE to avoid retries & thus infinite looping */
    271         return DISP_CHANGE_BADMODE;
    272     }
    273 
    274     if (DeviceMode.dmPelsWidth == 0
    275         || DeviceMode.dmPelsHeight == 0)
    276     {
    277         /* No ENUM_REGISTRY_SETTINGS yet. Seen on Vista after installation.
    278          * Get the current video mode then.
    279          */
    280         ZeroMemory(&DeviceMode, sizeof(DEVMODE));
    281         DeviceMode.dmSize = sizeof(DEVMODE);
    282         if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName,
    283              ENUM_CURRENT_SETTINGS, &DeviceMode))
    284         {
    285             /* ENUM_CURRENT_SETTINGS returns FALSE when the display is not active:
    286              * for example a disabled secondary display.
    287              * Do not return here, ignore the error and set the display info to 0x0x0.
    288              */
    289             Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ()));
    290             ZeroMemory(&DeviceMode, sizeof(DEVMODE));
    291         }
    292     }
    293 
    294     DeviceMode.dmFields =  DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
    295     if (fExtDispSup) /* Extended Display Support possible*/
    296     {
    297         Log(("VBoxTray: Extended Display Support. Change Position and Resolution \n"));
    298         if (fEnabled)
    299         {
    300             if (aWidth !=0 && aHeight != 0)
    301             {
    302                 Log(("VBoxTray: Mon ID = %d, Width = %d, Height = %d\n",
    303                     Id, aWidth, aHeight));
    304                 DeviceMode.dmFields |=  DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL ;
    305                 DeviceMode.dmPelsWidth = aWidth;
    306                 DeviceMode.dmPelsHeight = aHeight;
    307                 DeviceMode.dmBitsPerPel = aBitsPerPixel;
    308             }
    309             if (aPosX != 0 || aPosY != 0)
    310             {
    311                 Log(("VBoxTray: Mon ID = %d PosX = %d, PosY = %d\n",
    312                     Id, aPosX, aPosY));
    313                 DeviceMode.dmFields |=  DM_POSITION;
    314                 DeviceMode.dmPosition.x = aPosX;
    315                 DeviceMode.dmPosition.y = aPosY;
    316             }
    317         }
    318         else
    319         {
    320             /* Request is there to disable the monitor with ID = Id*/
    321             Log(("VBoxTray: Disable the Monitor ID = %d\n", Id));
    322             ZeroMemory(&DeviceMode, sizeof(DEVMODE));
    323             DeviceMode.dmSize = sizeof(DEVMODE);
    324             DeviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
    325                                      | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ;
    326         }
    327     }
    328     else /* Extended display support not possible. Just change the res.*/
    329     {
    330         if (aWidth !=0 && aHeight != 0)
    331         {
    332             Log(("VBoxTray: No Extended Display Support. Just Change Resolution. \
    333                  Mon ID = %d, Width = %d, Height = %d\n",
    334                  Id, aWidth, aHeight));
    335             DeviceMode.dmFields |=  DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL ;
    336             DeviceMode.dmPelsWidth = aWidth;
    337             DeviceMode.dmPelsHeight = aHeight;
    338             DeviceMode.dmBitsPerPel = aBitsPerPixel;
    339         }
    340     }
    341     Log(("VBoxTray: Changing Reslution of Monitor with ID = %d. Params \
    342          PosX = %d, PosY = %d, Width = %d, Height = %d\n",
    343          Id, DeviceMode.dmPosition.x, DeviceMode.dmPosition.y,
    344          DeviceMode.dmPelsWidth, DeviceMode.dmPelsHeight));
    345     gCtx.pfnChangeDisplaySettingsEx(DisplayDevice.DeviceName, &DeviceMode,
    346                                     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     /* @todo: if the pfnChangeDisplaySettingsEx returned status is
    351      * NOT DISP_CHANGE_SUCCESSFUL AND NOT DISP_CHANGE_BADMODE,
    352      * we will always end up in re-trying, see ResizeDisplayDevice
    353      * is this what we want actually?  */
     259    ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE));
     260    displayDevice.cb = sizeof(DISPLAY_DEVICE);
     261    DispNum = 0;
     262    while (EnumDisplayDevices(NULL, DispNum, &displayDevice, 0))
     263    {
     264        ZeroMemory(&deviceMode, sizeof(DEVMODE));
     265        deviceMode.dmSize = sizeof(DEVMODE);
     266        if (!EnumDisplaySettings((LPSTR)displayDevice.DeviceName,
     267             ENUM_REGISTRY_SETTINGS, &deviceMode))
     268        {
     269            LogRel(("VBoxTray: ENUM_REGISTRY_SETTINGS Failed \n"));
     270            return FALSE; // Store default failed
     271        }
     272        /* Save info about primary display */
     273        if(DispNum == 0)
     274            devModePrimary = deviceMode;
     275
     276        if (DispNum == Id)
     277        {
     278            if (fExtDispSup) /* Extended Display Support possible*/
     279            {
     280                if (fEnabled)
     281                {
     282                    /* Special case for enabling the secondary monitor. */
     283                    if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE))
     284                    {
     285                        LogRel(("VBoxTray: Secondary Monitor with ID=%d Not Enabled. Enabling it.\n", DispNum));
     286                        deviceMode.dmPosition.x = devModePrimary.dmPelsWidth;
     287                        deviceMode.dmPosition.y = 0;
     288                        /* dont any more flags here as, only DM_POISITON is used to enable the secondary display */
     289                        deviceMode.dmFields = DM_POSITION;
     290                        gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName,
     291                                                                  &deviceMode, NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
     292                        /* A second call to ChangeDisplaySettings updates the monitor.*/
     293                        gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL);
     294                        /* shouln't retry in case of enabling or disabling the display device. */
     295                        dwStatus = DISP_CHANGE_SUCCESSFUL;
     296                    }
     297                    else /* secondary monitor already enabled. Request to change the resolution or position. */
     298                    {
     299                        if (aWidth !=0 && aHeight != 0)
     300                        {
     301                            LogRel(("VBoxTray: Display ID: %d , Change Height: %d & Width: %d\n", Id, aWidth, aHeight));
     302                            deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL
     303                                                  | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
     304                            deviceMode.dmPelsWidth = aWidth;
     305                            deviceMode.dmPelsHeight = aHeight;
     306                            deviceMode.dmBitsPerPel = aBitsPerPixel;
     307                        }
     308                        if (aPosX != 0 || aPosY != 0)
     309                        {
     310                            LogRel(("VBoxTray: Display ID: %d PosX: %d, PosY: %d\n",
     311                                    Id, aPosX, aPosY));
     312                            deviceMode.dmFields |=  DM_POSITION;
     313                            deviceMode.dmPosition.x = aPosX;
     314                            deviceMode.dmPosition.y = aPosY;
     315                        }
     316                        dwStatus = gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName,
     317                                                                   &deviceMode, NULL, CDS_NORESET|CDS_UPDATEREGISTRY, NULL);
     318                         /* A second call to ChangeDisplaySettings updates the monitor. */
     319                        gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL);
     320                    }
     321                }
     322                else /* Request is there to disable the monitor with ID = Id*/
     323                {
     324                    LogRel(("VBoxTray: Disable the Display ID: %d\n", Id));
     325                    ZeroMemory(&deviceMode, sizeof(DEVMODE));
     326                    deviceMode.dmSize = sizeof(DEVMODE);
     327                    deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION
     328                                          | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
     329                    dwStatus = gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName,
     330                                                               &deviceMode, NULL, CDS_NORESET|CDS_UPDATEREGISTRY, NULL);
     331                    /* A second call to ChangeDisplaySettings updates the monitor. */
     332                    gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL);
     333                }
     334                break;
     335            }
     336            else/* Extended display support not possible. Just change the res.*/
     337            {
     338                if (aWidth !=0 && aHeight != 0)
     339                {
     340                    LogRel(("VBoxTray: No Extended Display Support. Just Change Resolution. \
     341                            Display ID = %d, Width = %d, Height = %d\n",Id, aWidth, aHeight));
     342                    deviceMode.dmFields |=  DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL ;
     343                    deviceMode.dmPelsWidth = aWidth;
     344                    deviceMode.dmPelsHeight = aHeight;
     345                    deviceMode.dmBitsPerPel = aBitsPerPixel;
     346                    dwStatus = gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName,
     347                                                                &deviceMode, NULL, CDS_NORESET|CDS_UPDATEREGISTRY, NULL);
     348                    /* A second call to ChangeDisplaySettings updates the monitor. */
     349                    gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL);
     350                }
     351            }
     352            break;
     353        }
     354        ZeroMemory(&displayDevice, sizeof(displayDevice));
     355        displayDevice.cb = sizeof(displayDevice);
     356        DispNum++;
     357    }
     358    /* we don't want to retry, as it may get stuck in an inifinite loop. */
    354359    return dwStatus;
    355 }
     360 }
    356361
    357362/* Returns TRUE to try again. */
     
    363368    BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0 &&
    364369                       dwNewPosX == 0 && dwNewPosY == 0);
     370    BOOL fChangePosRequest = false; /* change in position requested */
    365371
    366372    Log(("VBoxTray: ResizeDisplayDevice Width= %d, Height=%d , PosX=%d and PosY=%d \
     
    374380    DWORD dwStatus;
    375381
    376     ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
    377     DisplayDevice.cb = sizeof(DisplayDevice);
     382    ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
     383    DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
    378384
    379385    VBoxDispIfCancelPendingResize(&pCtx->pEnv->dispIf);
     
    451457
    452458            paDisplayDevices[DevNum] = DisplayDevice;
    453             /* Keep a record if the display with ID is already active or not. */
    454             if (paDisplayDevices[Id].StateFlags & DISPLAY_DEVICE_ACTIVE)
    455             {
    456                 LogFlow(("VBoxTray: Display with ID=%d already enabled\n", Id));
    457                 fDispAlreadyEnabled = TRUE;
    458             }
    459459
    460460            /* First try to get the video mode stored in registry (ENUM_REGISTRY_SETTINGS).
     
    468468            {
    469469                Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings error %d\n", GetLastError ()));
    470                 return FALSE;
    471470            }
    472471
     
    487486                     */
    488487                    Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ()));
    489                     ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE));
    490488                }
    491489            }
     
    493491            if (fExtDispSup)
    494492            {
    495                 Log(("VBoxTray: Extended Display Support.\n"));
    496                 Log(("VBoxTray: ResizeDisplayDevice1: %dx%dx%d at %d,%d\n",
     493                LogRel(("VBoxTray: Extended Display Support.\n"));
     494                Log(("VBoxTray: ResizeDisplayDevice1: %dx%dx%d at %d,%d . Id = %d and DevNum=%d, fEnabled=%d\n",
    497495                      paDeviceModes[Id].dmPelsWidth,
    498496                      paDeviceModes[Id].dmPelsHeight,
    499497                      paDeviceModes[Id].dmBitsPerPel,
    500498                      paDeviceModes[Id].dmPosition.x,
    501                       paDeviceModes[Id].dmPosition.y));
     499                      paDeviceModes[Id].dmPosition.y,
     500                      Id, DevNum, fEnabled));
    502501                if ((DevNum == Id && fEnabled == 1))
    503502                {
     
    505504                     * secondary monitor .
    506505                     */
    507                     paRects[DevNum].left = dwNewPosX;
    508                     paRects[DevNum].bottom = dwNewPosY;
    509                     paDeviceModes[DevNum].dmPosition.x = dwNewPosX;
    510                     paDeviceModes[DevNum].dmPosition.x = dwNewPosY;
     506                    /* Used when a secondary monitor just needs to be enabled, without any
     507                     * change in its position
     508                     */
     509                     if (dwNewPosX != 0)
     510                    {
     511                        LogRel(("VBoxTray: Setting Rectangle position x=%d*y=%d\n", dwNewPosX, dwNewPosY));
     512                        paDeviceModes[DevNum].dmPosition.x = dwNewPosX;
     513                        paDeviceModes[DevNum].dmPosition.y = dwNewPosY;
     514                        fChangePosRequest = true;
     515                    }
     516                    paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
     517                    paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
    511518                    paRects[DevNum].right  = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth;
    512519                    paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight;
     
    522529            else
    523530            {
     531                    LogRel(("VBoxTray: NO Ext Display Support \n"));
    524532                    paRects[DevNum].left   = paDeviceModes[DevNum].dmPosition.x;
    525533                    paRects[DevNum].top    = paDeviceModes[DevNum].dmPosition.y;
     
    533541        DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
    534542        i++;
     543    }
     544    /* Keep a record if the display with ID is already active or not. */
     545    if (paDisplayDevices[Id].StateFlags & DISPLAY_DEVICE_ACTIVE)
     546    {
     547        LogRel(("VBoxTray: Display with ID=%d already enabled\n", Id));
     548        fDispAlreadyEnabled = TRUE;
    535549    }
    536550
     
    566580     * all rect conditions are true. Thus in this case nothing has to be done.
    567581     */
    568     if ( !fModeReset && fEnabled && fDispAlreadyEnabled
     582    if ( !fModeReset && fEnabled && fDispAlreadyEnabled && !fChangePosRequest
    569583        && paRects[Id].right - paRects[Id].left == Width
    570584        && paRects[Id].bottom - paRects[Id].top == Height
    571585        && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel)
    572586    {
    573         Log(("VBoxTray: ResizeDisplayDevice: Already at desired resolution\n"));
     587        LogRel(("VBoxTray: Already at desired resolution. No Change.\n"));
    574588        return FALSE;
    575589    }
     
    601615             * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
    602616             */
    603             paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
    604 
    605             if (   i == Id
    606                 && BitsPerPixel != 0)
    607             {
     617            paDeviceModes[i].dmFields = DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
     618
     619            if (i == Id && BitsPerPixel != 0)
     620            {
     621                LogRel(("VBoxTray: (WDDM)Changing resolution and position. \n"));
    608622                /* Change dmBitsPerPel if requested. */
    609623                paDeviceModes[i].dmBitsPerPel = BitsPerPixel;
    610             }
    611 
    612             Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
     624                paDeviceModes[i].dmPelsWidth = Width;
     625                paDeviceModes[i].dmPelsHeight = Height;
     626                if (dwNewPosX != 0 || dwNewPosY != 0)
     627                {
     628                    paDeviceModes[Id].dmPosition.x = dwNewPosX;
     629                    paDeviceModes[Id].dmPosition.y = dwNewPosY;
     630                }
     631                else
     632                {
     633                    paDeviceModes[i].dmFields |= DM_POSITION;
     634                    paDeviceModes[Id].dmPosition.x = 0;
     635                    paDeviceModes[Id].dmPosition.y = 0;
     636                }
     637            }
     638
     639            Log(("VBoxTray: (WDDM) ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
    613640                  gCtx.pfnChangeDisplaySettingsEx,
    614641                  paDeviceModes[i].dmPelsWidth,
     
    619646
    620647        }
    621 
    622         DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, paDisplayDevices, paDeviceModes, NumDevices);
    623         if (err == NO_ERROR || err != ERROR_RETRY)
    624         {
    625             if (err == NO_ERROR)
    626                 Log(("VBoxTray: VBoxDisplayThread: (WDDM) VBoxDispIfResizeModes succeeded\n"));
    627             else
    628                 Log(("VBoxTray: VBoxDisplayThread: (WDDM) Failure VBoxDispIfResizeModes (%d)\n", err));
    629             return FALSE;
    630         }
    631 
     648        /* Reques to enable /disable the secondary Display Device. Won't take the resize request now.*/
     649        if (!fDispAlreadyEnabled && fEnabled || fDispAlreadyEnabled && !fEnabled)
     650        {
     651              OSVERSIONINFO OSinfo;
     652              OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
     653              GetVersionEx (&OSinfo);
     654
     655              /* for win 7 and above */
     656              if (OSinfo.dwMajorVersion >= 6 && OSinfo.dwMinorVersion >= 1)
     657              {
     658                  LogRel(("VBoxTray: (WDDM) Request to enable/disable %d display device\n", fEnabled));
     659                  DWORD dwStatus = vboxDispIfWddmEnableDisplay(&pCtx->pEnv->dispIf, Id, fEnabled);
     660                  if(dwStatus != ERROR_SUCCESS)
     661                  {
     662                      /* Not going to retry for enabling or disabling of the secondary display device.*/
     663                      LogRel(("VBoxTray: (WDDM) Failed to enable the Display Device \n"));
     664                  }
     665              }
     666              else /* case: vista in wddm mode. SetDisplayConfig APIs etc is not avilable in this mode. */
     667              {
     668                  /* use traditional approach of ChangeDisplaySettingEx to enable/disable secondary monitor for Vista WDDM mode.*/
     669                  dwStatus = EnableAndResizeDispDev(Id, Width, Height, BitsPerPixel,
     670                                      dwNewPosX, dwNewPosY,fEnabled,
     671                                      fExtDispSup, pCtx);
     672                  if (dwStatus != DISP_CHANGE_SUCCESSFUL )
     673                  {
     674                      /* Successfully set new video mode or our driver can not set
     675                       * the requested mode. Stop trying.
     676                       */
     677                       LogRel(("VBoxTray: (WDDM) Failed to enable/disable the Display Device \n"));
     678                  }
     679              }
     680              return FALSE; /* for enable disable not retrying */
     681        }
     682        else
     683        {
     684            /* Resize request. Secondary display device should be in an enabled state. */
     685            LogRel(("VBoxTray: (WDDM) Request to resize the display \n"));
     686            DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, paDisplayDevices, paDeviceModes, NumDevices);
     687            if (err == NO_ERROR || err != ERROR_RETRY)
     688            {
     689                if (err == NO_ERROR)
     690                    LogRel(("VBoxTray: VBoxDisplayThread: (WDDM) VBoxDispIfResizeModes succeeded\n"));
     691                else
     692                    LogRel(("VBoxTray: VBoxDisplayThread: (WDDM) Failure VBoxDispIfResizeModes (%d)\n", err));
     693                return FALSE;
     694            }
     695        }
    632696        Log(("VBoxTray: ResizeDisplayDevice: (WDDM) RETRY requested\n"));
    633697        return TRUE;
     
    666730        }
    667731
    668         Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
    669               gCtx.pfnChangeDisplaySettingsEx,
     732        Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx Current MonitorId=%d: %dx%dx%d at %d,%d\n",
     733              i,
    670734              paDeviceModes[i].dmPelsWidth,
    671735              paDeviceModes[i].dmPelsHeight,
  • trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h

    r44528 r44557  
    7878    DWORD Height;
    7979    DWORD BitsPerPixel;
     80    DWORD PosX;
     81    DWORD PosY;
    8082} VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO, *PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO;
    8183
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