diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
---|---|---|
committer | <> | 2014-05-08 15:03:54 +0000 |
commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp | |
parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
download | VirtualBox-master.tar.gz |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp')
-rw-r--r-- | src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp | 388 |
1 files changed, 311 insertions, 77 deletions
diff --git a/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp b/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp index b0c19261..a3473600 100644 --- a/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp +++ b/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -62,7 +62,7 @@ int VBoxDisplayInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStart OSinfo.dwOSVersionInfoSize = sizeof (OSinfo); GetVersionEx (&OSinfo); - HMODULE hUser = GetModuleHandle("USER32"); + HMODULE hUser = GetModuleHandle("user32.dll"); gCtx.pEnv = pEnv; @@ -89,7 +89,8 @@ int VBoxDisplayInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStart { Log(("VBoxTray: VBoxDisplayInit: WDDM driver is installed, switching display driver if to WDDM mode\n")); /* this is hacky, but the most easiest way */ - DWORD err = VBoxDispIfSwitchMode(const_cast<PVBOXDISPIF>(&pEnv->dispIf), VBOXDISPIF_MODE_WDDM, NULL /* old mode, we don't care about it */); + VBOXDISPIF_MODE enmMode = (OSinfo.dwMajorVersion > 6 || OSinfo.dwMinorVersion > 0) ? VBOXDISPIF_MODE_WDDM_W7 : VBOXDISPIF_MODE_WDDM; + DWORD err = VBoxDispIfSwitchMode(const_cast<PVBOXDISPIF>(&pEnv->dispIf), enmMode, NULL /* old mode, we don't care about it */); if (err == NO_ERROR) Log(("VBoxTray: VBoxDisplayInit: DispIf switched to WDDM mode successfully\n")); else @@ -212,19 +213,108 @@ static bool isVBoxDisplayDriverActive(VBOXDISPLAYCONTEXT *pCtx) #endif } -/* Returns TRUE to try again. */ -static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel, - VBOXDISPLAYCONTEXT *pCtx) +DWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight, + DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY, BOOL fEnabled, BOOL fExtDispSup) { - BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0); + DISPLAY_DEVICE displayDeviceTmp; + DISPLAY_DEVICE displayDevice; + DEVMODE deviceMode; + DWORD dwStatus = DISP_CHANGE_SUCCESSFUL; + DWORD iter ; - if (!gCtx.fAnyX) - Width &= 0xFFF8; + deviceMode = paDeviceModes[Id]; + displayDevice = paDisplayDevices[Id]; + + for (iter = 0; iter < totalDispNum; iter++) + { + if (iter != 0 && iter != Id && !(paDisplayDevices[iter].StateFlags & DISPLAY_DEVICE_ACTIVE)) + { + LogRel(("VBoxTray:Initially disabling the monitor with id = %d . Total Monitor=%d\n", iter, totalDispNum)); + DEVMODE deviceModeTmp; + ZeroMemory(&deviceModeTmp, sizeof(DEVMODE)); + deviceModeTmp.dmSize = sizeof(DEVMODE); + deviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION + | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ; + displayDeviceTmp = paDisplayDevices[iter]; + gCtx.pfnChangeDisplaySettingsEx(displayDeviceTmp.DeviceName, &deviceModeTmp, NULL, + (CDS_UPDATEREGISTRY | CDS_NORESET), NULL); + } + } + + if (fExtDispSup) /* Extended Display Support possible*/ + { + if (fEnabled) + { + /* Special case for enabling the secondary monitor. */ + if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE)) + { + LogRel(("VBoxTray: Secondary Monitor with ID=%d and name=%s Not Enabled. Enabling it.\n", Id, displayDevice.DeviceName)); + deviceMode.dmPosition.x = paDeviceModes[0].dmPelsWidth; + deviceMode.dmPosition.y = 0; + deviceMode.dmBitsPerPel = 32; + OSVERSIONINFO OSinfo; + OSinfo.dwOSVersionInfoSize = sizeof (OSinfo); + GetVersionEx (&OSinfo); + + if (OSinfo.dwMajorVersion < 6) + /* dont any more flags here as, only DM_POISITON is used to enable the secondary display */ + deviceMode.dmFields = DM_POSITION; + else /* for win 7 and above */ + /* for vista and above DM_BITSPERPEL is necessary */ + deviceMode.dmFields = DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION; + + dwStatus = gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName,&deviceMode, NULL, (CDS_UPDATEREGISTRY | CDS_NORESET), NULL); + /* A second call to ChangeDisplaySettings updates the monitor.*/ + gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL); + } + else /* secondary monitor already enabled. Request to change the resolution or position. */ + { + if (aWidth !=0 && aHeight != 0) + { + LogRel(("VBoxTray: Display : %s , Change Height: %d & Width: %d\n", displayDevice.DeviceName, aWidth, aHeight)); + deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL + | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS; + deviceMode.dmPelsWidth = aWidth; + deviceMode.dmPelsHeight = aHeight; + deviceMode.dmBitsPerPel = aBitsPerPixel; + } + if (aPosX != 0 || aPosY != 0) + { + LogRel(("VBoxTray: Display: %s PosX: %d, PosY: %d\n", displayDevice.DeviceName, aPosX, aPosY)); + deviceMode.dmFields |= DM_POSITION; + deviceMode.dmPosition.x = aPosX; + deviceMode.dmPosition.y = aPosY; + } + dwStatus = gCtx.pfnChangeDisplaySettingsEx((LPSTR)displayDevice.DeviceName, + &deviceMode, NULL, CDS_NORESET|CDS_UPDATEREGISTRY, NULL); + /* A second call to ChangeDisplaySettings updates the monitor. */ + gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL); + } + } + else /* Request is there to disable the monitor with ID = Id*/ + { + LogRel(("VBoxTray: Disable the Display: %d\n", displayDevice.DeviceName)); + + DEVMODE deviceModeTmp; + ZeroMemory(&deviceModeTmp, sizeof(DEVMODE)); + deviceModeTmp.dmSize = sizeof(DEVMODE); + deviceModeTmp.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_POSITION + | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS ; + displayDeviceTmp = paDisplayDevices[Id]; + dwStatus = gCtx.pfnChangeDisplaySettingsEx(displayDeviceTmp.DeviceName, &deviceModeTmp, NULL, + (CDS_UPDATEREGISTRY | CDS_NORESET), NULL); + gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL,0, NULL); + } + } + return dwStatus; +} +DWORD VBoxGetDisplayConfigCount() +{ DISPLAY_DEVICE DisplayDevice; - ZeroMemory(&DisplayDevice, sizeof(DisplayDevice)); - DisplayDevice.cb = sizeof(DisplayDevice); + ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); + DisplayDevice.cb = sizeof(DISPLAY_DEVICE); /* Find out how many display devices the system has */ DWORD NumDevices = 0; @@ -250,26 +340,21 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP i++; } - Log(("VBoxTray: ResizeDisplayDevice: Found total %d devices. err %d\n", NumDevices, GetLastError ())); - - if (NumDevices == 0 || Id >= NumDevices) - { - Log(("VBoxTray: ResizeDisplayDevice: Requested identifier %d is invalid. err %d\n", Id, GetLastError ())); - return FALSE; - } - - DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices); - DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices); - RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices); + return NumDevices; +} +DWORD VBoxGetDisplayConfig(const DWORD NumDevices, DWORD *pDevPrimaryNum, DWORD *pNumDevices, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes) +{ /* Fetch information about current devices and modes. */ DWORD DevNum = 0; DWORD DevPrimaryNum = 0; + DISPLAY_DEVICE DisplayDevice; + ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE)); DisplayDevice.cb = sizeof(DISPLAY_DEVICE); - i = 0; + DWORD i = 0; while (EnumDisplayDevices (NULL, i, &DisplayDevice, 0)) { Log(("VBoxTray: ResizeDisplayDevice: [%d(%d)] %s\n", i, DevNum, DisplayDevice.DeviceName)); @@ -293,8 +378,8 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP { if (DevNum >= NumDevices) { - Log(("VBoxTray: ResizeDisplayDevice: %d >= %d\n", NumDevices, DevNum)); - return FALSE; + WARN(("VBoxTray: ResizeDisplayDevice: %d >= %d\n", NumDevices, DevNum)); + return ERROR_BUFFER_OVERFLOW; } paDisplayDevices[DevNum] = DisplayDevice; @@ -309,7 +394,6 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP ENUM_REGISTRY_SETTINGS, &paDeviceModes[DevNum])) { Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings error %d\n", GetLastError ())); - return FALSE; } if ( paDeviceModes[DevNum].dmPelsWidth == 0 @@ -328,21 +412,10 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP * Do not return here, ignore the error and set the display info to 0x0x0. */ Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings(ENUM_CURRENT_SETTINGS) error %d\n", GetLastError ())); - ZeroMemory(&paDeviceModes[DevNum], sizeof(DEVMODE)); } } - Log(("VBoxTray: ResizeDisplayDevice: %dx%dx%d at %d,%d\n", - paDeviceModes[DevNum].dmPelsWidth, - paDeviceModes[DevNum].dmPelsHeight, - paDeviceModes[DevNum].dmBitsPerPel, - paDeviceModes[DevNum].dmPosition.x, - paDeviceModes[DevNum].dmPosition.y)); - - paRects[DevNum].left = paDeviceModes[DevNum].dmPosition.x; - paRects[DevNum].top = paDeviceModes[DevNum].dmPosition.y; - paRects[DevNum].right = paDeviceModes[DevNum].dmPosition.x + paDeviceModes[DevNum].dmPelsWidth; - paRects[DevNum].bottom = paDeviceModes[DevNum].dmPosition.y + paDeviceModes[DevNum].dmPelsHeight; + DevNum++; } @@ -351,32 +424,146 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP i++; } + *pNumDevices = DevNum; + + return NO_ERROR; +} + +/* Returns TRUE to try again. */ +static BOOL ResizeDisplayDevice(UINT Id, DWORD Width, DWORD Height, DWORD BitsPerPixel, + BOOL fEnabled, DWORD dwNewPosX, DWORD dwNewPosY, + VBOXDISPLAYCONTEXT *pCtx, BOOL fExtDispSup) +{ + BOOL fDispAlreadyEnabled = false; /* check whether the monitor with ID is already enabled. */ + BOOL fModeReset = (Width == 0 && Height == 0 && BitsPerPixel == 0 && + dwNewPosX == 0 && dwNewPosY == 0); + DWORD dmFields = 0; + + Log(("VBoxTray: ResizeDisplayDevice Width= %d, Height=%d , PosX=%d and PosY=%d \ + fEnabled = %d, fExtDisSup = %d\n", + Width, Height, dwNewPosX, dwNewPosY, fEnabled, fExtDispSup)); + + if (!gCtx.fAnyX) + Width &= 0xFFF8; + + VBoxDispIfCancelPendingResize(&pCtx->pEnv->dispIf); + + DWORD NumDevices = VBoxGetDisplayConfigCount(); + + if (NumDevices == 0 || Id >= NumDevices) + { + WARN(("VBoxTray: ResizeDisplayDevice: Requested identifier %d is invalid. err %d\n", Id, GetLastError ())); + return FALSE; + } + + Log(("VBoxTray: ResizeDisplayDevice: Found total %d devices. err %d\n", NumDevices, GetLastError ())); + + DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices); + DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices); + RECTL *paRects = (RECTL *)alloca (sizeof (RECTL) * NumDevices); + DWORD DevNum = 0; + DWORD DevPrimaryNum = 0; + DWORD dwStatus = VBoxGetDisplayConfig(NumDevices, &DevPrimaryNum, &DevNum, paDisplayDevices, paDeviceModes); + if (dwStatus != NO_ERROR) + { + WARN(("VBoxTray: ResizeDisplayDevice: VBoxGetDisplayConfig failed, %d\n", dwStatus)); + return dwStatus; + } + + if (NumDevices != DevNum) + WARN(("VBoxTray: ResizeDisplayDevice: NumDevices(%d) != DevNum(%d)\n", NumDevices, DevNum)); + + DWORD i = 0; + + for (i = 0; i < DevNum; ++i) + { + if (fExtDispSup) + { + LogRel(("VBoxTray: Extended Display Support.\n")); + Log(("VBoxTray: ResizeDisplayDevice1: %dx%dx%d at %d,%d . Id = %d and DevNum=%d, fEnabled=%d\n", + paDeviceModes[Id].dmPelsWidth, + paDeviceModes[Id].dmPelsHeight, + paDeviceModes[Id].dmBitsPerPel, + paDeviceModes[Id].dmPosition.x, + paDeviceModes[Id].dmPosition.y, + Id, DevNum, fEnabled)); + } + else + { + LogRel(("VBoxTray: NO Ext Display Support \n")); + } + + paRects[i].left = paDeviceModes[i].dmPosition.x; + paRects[i].top = paDeviceModes[i].dmPosition.y; + paRects[i].right = paDeviceModes[i].dmPosition.x + paDeviceModes[i].dmPelsWidth; + paRects[i].bottom = paDeviceModes[i].dmPosition.y + paDeviceModes[i].dmPelsHeight; + } + + /* Keep a record if the display with ID is already active or not. */ + if (paDisplayDevices[Id].StateFlags & DISPLAY_DEVICE_ACTIVE) + { + LogRel(("VBoxTray: Display with ID=%d already enabled\n", Id)); + fDispAlreadyEnabled = TRUE; + } + /* Width, height equal to 0 means that this value must be not changed. * Update input parameters if necessary. * Note: BitsPerPixel is taken into account later, when new rectangles * are assigned to displays. */ if (Width == 0) - { Width = paRects[Id].right - paRects[Id].left; - } + else + dmFields |= DM_PELSWIDTH; if (Height == 0) - { Height = paRects[Id].bottom - paRects[Id].top; + else + dmFields |= DM_PELSHEIGHT; + + if (BitsPerPixel == 0) + BitsPerPixel = paDeviceModes[Id].dmBitsPerPel; + else + dmFields |= DM_BITSPERPEL; + + if (!dwNewPosX && !dwNewPosY) + { + /* @fixme: zero position is a valid state, so another values should be used as a special case !!! */ + dwNewPosX = paRects[Id].left; + dwNewPosY = paRects[Id].top; } + else + dmFields |= DM_POSITION; - /* Check whether a mode reset or a change is requested. */ - if ( !fModeReset + /* Check whether a mode reset or a change is requested. + * Rectangle position is recalculated only if fEnabled is 1. + * For non extended supported modes (old Host VMs), fEnabled + * is always 1. + */ + /* Handled the case where previouseresolution of secondary monitor + * was for eg. 1024*768*32 and monitor was in disabled state. + * User gives the command + * setvideomode 1024 768 32 1 yes. + * Now in this case the resolution request is same as previous one but + * monitor is going from disabled to enabled state so the below condition + * shour return false + * The below condition will only return true , if no mode reset has + * been requested AND fEnabled is 1 and fDispAlreadyEnabled is also 1 AND + * all rect conditions are true. Thus in this case nothing has to be done. + */ + if ( !fModeReset && (!fEnabled == !fDispAlreadyEnabled) + && paRects[Id].left == dwNewPosX + && paRects[Id].top == dwNewPosY && paRects[Id].right - paRects[Id].left == Width && paRects[Id].bottom - paRects[Id].top == Height && paDeviceModes[Id].dmBitsPerPel == BitsPerPixel) { - Log(("VBoxTray: ResizeDisplayDevice: Already at desired resolution\n")); + LogRel(("VBoxTray: Already at desired resolution. No Change.\n")); return FALSE; } - hlpResizeRect(paRects, NumDevices, DevPrimaryNum, Id, Width, Height); + hlpResizeRect(paRects, NumDevices, DevPrimaryNum, Id, + fEnabled ? Width : 0, fEnabled ? Height : 0, dwNewPosX, dwNewPosY); #ifdef Log for (i = 0; i < NumDevices; i++) { @@ -399,35 +586,38 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP paDeviceModes[i].dmPelsWidth = paRects[i].right - paRects[i].left; paDeviceModes[i].dmPelsHeight = paRects[i].bottom - paRects[i].top; + if (i == Id) + paDeviceModes[i].dmBitsPerPel = BitsPerPixel; + + paDeviceModes[i].dmFields |= dmFields; + /* On Vista one must specify DM_BITSPERPEL. * Note that the current mode dmBitsPerPel is already in the DEVMODE structure. */ - paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL; - - if ( i == Id - && BitsPerPixel != 0) + if (!(paDeviceModes[i].dmFields & DM_BITSPERPEL)) { - /* Change dmBitsPerPel if requested. */ - paDeviceModes[i].dmBitsPerPel = BitsPerPixel; + WARN(("VBoxTray: (WDDM) no DM_BITSPERPEL\n")); + paDeviceModes[i].dmFields |= DM_BITSPERPEL; + paDeviceModes[i].dmBitsPerPel = 32; } - Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n", + Log(("VBoxTray: (WDDM) ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n", gCtx.pfnChangeDisplaySettingsEx, paDeviceModes[i].dmPelsWidth, paDeviceModes[i].dmPelsHeight, paDeviceModes[i].dmBitsPerPel, paDeviceModes[i].dmPosition.x, paDeviceModes[i].dmPosition.y)); - } - DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, paDisplayDevices, paDeviceModes, NumDevices); + Log(("VBoxTray: (WDDM) Request to resize the displa\n")); + DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, fEnabled, fExtDispSup, paDisplayDevices, paDeviceModes, DevNum); if (err == NO_ERROR || err != ERROR_RETRY) { if (err == NO_ERROR) Log(("VBoxTray: VBoxDisplayThread: (WDDM) VBoxDispIfResizeModes succeeded\n")); else - Log(("VBoxTray: VBoxDisplayThread: (WDDM) Failure VBoxDispIfResizeModes (%d)\n", err)); + WARN(("VBoxTray: VBoxDisplayThread: (WDDM) Failure VBoxDispIfResizeModes (%d)\n", err)); return FALSE; } @@ -467,8 +657,8 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP paDeviceModes[i].dmBitsPerPel = BitsPerPixel; } - Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n", - gCtx.pfnChangeDisplaySettingsEx, + Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx Current MonitorId=%d: %dx%dx%d at %d,%d\n", + i, paDeviceModes[i].dmPelsWidth, paDeviceModes[i].dmPelsHeight, paDeviceModes[i].dmBitsPerPel, @@ -480,15 +670,18 @@ static BOOL ResizeDisplayDevice(ULONG Id, DWORD Width, DWORD Height, DWORD BitsP Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", status, GetLastError ())); } - /* A second call to ChangeDisplaySettings updates the monitor. */ - LONG status = gCtx.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL); - Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status)); - if (status == DISP_CHANGE_SUCCESSFUL || status == DISP_CHANGE_BADMODE) + Log(("VBoxTray: Enable And Resize Device. Id = %d, Width=%d Height=%d, \ + dwNewPosX = %d, dwNewPosY = %d fEnabled=%d & fExtDispSupport = %d \n", + Id, Width, Height, dwNewPosX, dwNewPosY, fEnabled, fExtDispSup)); + dwStatus = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, DevNum, Id, Width, Height, BitsPerPixel, + dwNewPosX, dwNewPosY, fEnabled, fExtDispSup); + if (dwStatus == DISP_CHANGE_SUCCESSFUL || dwStatus == DISP_CHANGE_BADMODE) { - /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */ + /* Successfully set new video mode or our driver can not set + * the requested mode. Stop trying. + */ return FALSE; } - /* Retry the request. */ return TRUE; } @@ -515,15 +708,13 @@ unsigned __stdcall VBoxDisplayThread(void *pInstance) return 0; } - int rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0); - if (RT_FAILURE(rc)) - { - LogRel(("VBoxTray: VBoxDisplayThread: Failed to set the graphics capability with rc=%Rrc, thread exiting\n", rc)); - return 0; - } + PostMessage(ghwndToolWindow, WM_VBOX_GRAPHICS_SUPPORTED, 0, 0); + + VBoxDispIfResizeStarted(&pCtx->pEnv->dispIf); do { + BOOL fExtDispSup = TRUE; /* Wait for a display change event. */ VBoxGuestWaitEventInfo waitEvent; waitEvent.u32TimeoutIn = 1000; @@ -552,20 +743,44 @@ unsigned __stdcall VBoxDisplayThread(void *pInstance) if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST) { Log(("VBoxTray: VBoxDisplayThread: going to get display change information\n")); + BOOL fDisplayChangeQueried; + /* We got at least one event. Read the requested resolution * and try to set it until success. New events will not be seen * but a new resolution will be read in this poll loop. */ - VMMDevDisplayChangeRequest2 displayChangeRequest = {0}; - displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest2); + /* Try if extended mode display information is available from the host. */ + VMMDevDisplayChangeRequestEx displayChangeRequest = {0}; + fExtDispSup = TRUE; + displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequestEx); displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION; - displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest2; + displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequestEx; displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; - BOOL fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest2)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), + fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequestEx)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequestEx), + &displayChangeRequest, sizeof(VMMDevDisplayChangeRequestEx), &cbReturned, NULL); + + if (!fDisplayChangeQueried) + { + Log(("VBoxTray: Extended Display Not Supported. Trying VMMDevDisplayChangeRequest2\n")); + fExtDispSup = FALSE; /* Extended display Change request is not supported */ + + displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest2); + displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION; + displayChangeRequest.header.requestType = VMMDevReq_GetDisplayChangeRequest2; + displayChangeRequest.eventAck = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; + fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest2)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest2), &cbReturned, NULL); + displayChangeRequest.cxOrigin = 0; + displayChangeRequest.cyOrigin = 0; + displayChangeRequest.fChangeOrigin = 0; + displayChangeRequest.fEnabled = 1; /* Always Enabled for old VMs on Host.*/ + } + if (!fDisplayChangeQueried) { + Log(("VBoxTray: Extended Display Not Supported. Trying VMMDevDisplayChangeRequest\n")); + fExtDispSup = FALSE; /*Extended display Change request is not supported */ /* Try the old version of the request for old VBox hosts. */ displayChangeRequest.header.size = sizeof(VMMDevDisplayChangeRequest); displayChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION; @@ -574,6 +789,10 @@ unsigned __stdcall VBoxDisplayThread(void *pInstance) fDisplayChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevDisplayChangeRequest)), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest), &displayChangeRequest, sizeof(VMMDevDisplayChangeRequest), &cbReturned, NULL); displayChangeRequest.display = 0; + displayChangeRequest.cxOrigin = 0; + displayChangeRequest.cyOrigin = 0; + displayChangeRequest.fChangeOrigin = 0; + displayChangeRequest.fEnabled = 1; /* Always Enabled for old VMs on Host.*/ } if (fDisplayChangeQueried) @@ -602,17 +821,31 @@ unsigned __stdcall VBoxDisplayThread(void *pInstance) if (pCtx->pfnChangeDisplaySettingsEx != 0) { Log(("VBoxTray: VBoxDisplayThread: Detected W2K or later\n")); - /* W2K or later. */ + 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", + displayChangeRequest.display, + displayChangeRequest.xres, + displayChangeRequest.yres, + displayChangeRequest.bpp, + displayChangeRequest.fEnabled, + displayChangeRequest.cxOrigin, + displayChangeRequest.cyOrigin, + displayChangeRequest.fChangeOrigin)); if (!ResizeDisplayDevice(displayChangeRequest.display, displayChangeRequest.xres, displayChangeRequest.yres, displayChangeRequest.bpp, - pCtx + displayChangeRequest.fEnabled, + displayChangeRequest.cxOrigin, + displayChangeRequest.cyOrigin, + pCtx, + fExtDispSup )) { + Log(("ResizeDipspalyDevice return 0\n")); break; } + } else { @@ -727,7 +960,8 @@ unsigned __stdcall VBoxDisplayThread(void *pInstance) } if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED) hlpReloadCursor(); - } else + } + else { Log(("VBoxTray: VBoxDisplayThread: error 0 from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n")); /* sleep a bit to not eat too much CPU in case the above call always fails */ @@ -746,7 +980,7 @@ unsigned __stdcall VBoxDisplayThread(void *pInstance) maskInfo.u32NotMask = VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED; if (!DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL)) Log(("VBoxTray: VBoxDisplayThread: DeviceIOControl(CtlMask - not) failed\n")); - VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS); + PostMessage(ghwndToolWindow, WM_VBOX_GRAPHICS_UNSUPPORTED, 0, 0); Log(("VBoxTray: VBoxDisplayThread: finished display change request thread\n")); return 0; |