<div dir="ltr">Hi Frediano,<div><br></div><div>Thanks for the review.</div><div>I'll fix the issues and resend the patch.</div><div><span style="font-family:monospace,monospace;font-size:12.8px">Regarding </span><span style="font-family:monospace,monospace;font-size:12.8px">“underscore uppercase” issue, I have already checked the style in other files</span><div style="font-family:monospace,monospace;font-size:12.8px"><span style="font-size:12.8px">and that's how they did it. For example in desktop_layout.h the identifier is "</span><font face="monospace, monospace">_H_DESKTOP_LAYOUT".</font></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Aug 3, 2016 at 7:42 PM, Frediano Ziglio <span dir="ltr"><<a href="mailto:fziglio@redhat.com" target="_blank">fziglio@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">><br>
> The Connecting and Configuring Displays (CCD) Win32 APIs<br>
> provide more control over the desktop display setup. The CCD APIs<br>
> move away from using Windows Graphics Device Interface (GDI)<br>
> concepts like view name and toward Windows Display Driver Model<br>
> (WDDM) concepts like adapter, source, and target identifiers.<br>
> More info on the CCD API can be found here:<br>
> <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff539590(v=vs.85).aspx" rel="noreferrer" target="_blank">https://msdn.microsoft.com/en-us/library/windows/hardware/ff539590(v=vs.85).aspx</a><br>
><br>
> This patch introduces partial functionality from the CCD API<br>
> needed by vdagent. It is needed by vdagent in order to support<br>
> multiple monitors and arbitrary resolution on Windows 10.<br>
><br>
> Based on a patch by Sandy Stutsman <<a href="mailto:sstutsma@redhat.com">sstutsma@redhat.com</a>><br>
><br>
> Signed-off-by: Dmitry Fleytman <<a href="mailto:dfleytma@redhat.com">dfleytma@redhat.com</a>><br>
> Signed-off-by: Sameeh Jubran <<a href="mailto:sameeh@daynix.com">sameeh@daynix.com</a>><br>
> ---<br>
> Makefile.am | 2 +<br>
> vdagent/display_configuration.cpp | 509<br>
> ++++++++++++++++++++++++++++++++++++++<br>
> vdagent/display_configuration.h | 94 +++++++<br>
> 3 files changed, 605 insertions(+)<br>
> create mode 100755 vdagent/display_configuration.cpp<br>
> create mode 100755 vdagent/display_configuration.h<br>
><br>
> diff --git a/Makefile.am b/Makefile.am<br>
> index c3fc6bf..84507e8 100644<br>
> --- a/Makefile.am<br>
> +++ b/Makefile.am<br>
> @@ -31,6 +31,8 @@ vdagent_SOURCES = \<br>
> common/vdcommon.h \<br>
> common/vdlog.cpp \<br>
> common/vdlog.h \<br>
> + vdagent/display_configuration.cpp \<br>
> + vdagent/display_configuration.h \<br>
> vdagent/desktop_layout.cpp \<br>
> vdagent/desktop_layout.h \<br>
> vdagent/display_setting.cpp \<br>
> diff --git a/vdagent/display_configuration.cpp<br>
> b/vdagent/display_configuration.cpp<br>
> new file mode 100755<br>
> index 0000000..12b9c22<br>
> --- /dev/null<br>
> +++ b/vdagent/display_configuration.cpp<br>
> @@ -0,0 +1,509 @@<br>
> +/*<br>
> +Copyright (C) 2015 Red Hat, Inc.<br>
> +<br>
> +This program is free software; you can redistribute it and/or<br>
> +modify it under the terms of the GNU General Public License as<br>
> +published by the Free Software Foundation; either version 2 of<br>
> +the License, or (at your option) any later version.<br>
> +<br>
> +This program is distributed in the hope that it will be useful,<br>
> +but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
> +GNU General Public License for more details.<br>
> +<br>
> +You should have received a copy of the GNU General Public License<br>
> +along with this program. If not, see <<a href="http://www.gnu.org/licenses/" rel="noreferrer" target="_blank">http://www.gnu.org/licenses/</a>>.<br>
> +*/<br>
> +<br>
> +#include "display_configuration.h"<br>
> +#include <winternl.h><br>
> +<br>
> +/* The following definitions and structures are taken<br>
> +from the wine project repository and can be found<br>
> +under: "wine/include/wingdi.h" */<br>
> +<br>
> +#define QDC_ALL_PATHS 0x00000001<br>
> +<br>
> +#define SDC_USE_SUPPLIED_DISPLAY_CONFIG 0x00000020<br>
> +#define SDC_APPLY 0x00000080<br>
> +#define SDC_FORCE_MODE_ENUMERATION 0x00001000<br>
> +<br>
> +#define DISPLAYCONFIG_PATH_ACTIVE 0x00000001<br>
> +#define DISPLAYCONFIG_PATH_MODE_IDX_INVALID 0xffffffff<br>
> +<br>
> +enum DISPLAYCONFIG_DEVICE_INFO_TYPE {<br>
> + DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1<br>
> +};<br>
> +<br>
> +enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY {};<br>
> +<br>
> +enum DISPLAYCONFIG_ROTATION {};<br>
> +<br>
> +enum DISPLAYCONFIG_SCANLINE_ORDERING {};<br>
> +<br>
> +enum DISPLAYCONFIG_SCALING {};<br>
> +<br>
> +enum DISPLAYCONFIG_PIXELFORMAT {};<br>
> +<br>
> +enum DISPLAYCONFIG_MODE_INFO_TYPE {};<br>
> +<br>
> +struct DISPLAYCONFIG_DEVICE_INFO_HEADER {<br>
> + DISPLAYCONFIG_DEVICE_INFO_TYPE type;<br>
> + UINT32 size;<br>
> + LUID adapterId;<br>
> + UINT32 id;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_SOURCE_DEVICE_NAME {<br>
> + DISPLAYCONFIG_DEVICE_INFO_HEADER header;<br>
> + WCHAR<br>
> viewGdiDeviceName[CCHDEVICENAME];<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO {<br>
> + POINTL PathSourceSize;<br>
> + RECTL DesktopImageRegion;<br>
> + RECTL DesktopImageClip;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_RATIONAL {<br>
> + UINT32 Numerator;<br>
> + UINT32 Denominator;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_2DREGION {<br>
> + UINT32 cx;<br>
> + UINT32 cy;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO {<br>
> + UINT64 pixelRate;<br>
> + DISPLAYCONFIG_RATIONAL hSyncFreq;<br>
> + DISPLAYCONFIG_RATIONAL vSyncFreq;<br>
> + DISPLAYCONFIG_2DREGION activeSize;<br>
> + DISPLAYCONFIG_2DREGION totalSize;<br>
> + union {<br>
> + struct {<br>
> + UINT32 videoStandard :16;<br>
> + UINT32 vSyncFreqDivider :6;<br>
> + UINT32 reserved :10;<br>
> + } AdditionalSignalInfo;<br>
> + UINT32 videoStandard;<br>
> + } DUMMYUNIONNAME;<br>
> + DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_TARGET_MODE {<br>
> + DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_SOURCE_MODE {<br>
> + UINT32 width;<br>
> + UINT32 height;<br>
> + DISPLAYCONFIG_PIXELFORMAT pixelFormat;<br>
> + POINTL position;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_MODE_INFO {<br>
> + DISPLAYCONFIG_MODE_INFO_TYPE infoType;<br>
> + UINT32 id;<br>
> + LUID adapterId;<br>
> + union {<br>
> + DISPLAYCONFIG_TARGET_MODE targetMode;<br>
> + DISPLAYCONFIG_SOURCE_MODE sourceMode;<br>
> + DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo;<br>
> + } DUMMYUNIONNAME;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_PATH_SOURCE_INFO {<br>
> + LUID adapterId;<br>
> + UINT32 id;<br>
> + union {<br>
> + UINT32 modeInfoIdx;<br>
> + struct {<br>
> + UINT32 cloneGroupId :16;<br>
> + UINT32 sourceModeInfoIdx :16;<br>
> + } DUMMYSTRUCTNAME;<br>
> + } DUMMYUNIONNAME;<br>
> + UINT32 statusFlags;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_PATH_TARGET_INFO {<br>
> + LUID adapterId;<br>
> + UINT32 id;<br>
> + union {<br>
> + UINT32 modeInfoIdx;<br>
> + struct {<br>
> + UINT32 desktopModeInfoIdx :16;<br>
> + UINT32 targetModeInfoIdx :16;<br>
> + } DUMMYSTRUCTNAME;<br>
> + } DUMMYUNIONNAME;<br>
> + DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;<br>
> + DISPLAYCONFIG_ROTATION rotation;<br>
> + DISPLAYCONFIG_SCALING scaling;<br>
> + DISPLAYCONFIG_RATIONAL refreshRate;<br>
> + DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;<br>
> + BOOL targetAvailable;<br>
> + UINT32 statusFlags;<br>
> +};<br>
> +<br>
> +struct DISPLAYCONFIG_PATH_INFO {<br>
> + DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;<br>
> + DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;<br>
> + UINT32 flags;<br>
> +};<br>
> +<br>
> +CCD::CCD()<br>
> + :_NumPathElements(0)<br>
> + ,_NumModeElements(0)<br>
> + ,_pPathInfo(NULL)<br>
> + ,_pModeInfo(NULL)<br>
> + ,_pfnGetDeviceInfo(NULL)<br>
> + ,_pfnGetDisplayConfigBufferSizes(NULL)<br>
> + ,_pfnQueryDisplayConfig(NULL)<br>
> + ,_pfnSetDisplayConfig(NULL)<br>
> + ,_error(0)<br>
> + ,_primary_detached(false)<br>
> + ,_path_state(PATH_UPDATED)<br>
> +{<br>
> + if (load_api()) {<br>
> + get_config_buffers();<br>
> + }<br>
> +}<br>
> +<br>
> +CCD::~CCD()<br>
> +{<br>
> + free_config_buffers();<br>
> +}<br>
> +<br>
> +bool CCD::query_display_config()<br>
> +{<br>
> + LONG query_error(ERROR_SUCCESS);<br>
> +<br>
> + //Until we get it or error != ERROR_INSUFFICIENT_BUFFER<br>
> + do {<br>
> + query_error = _pfnQueryDisplayConfig(QDC_ALL_PATHS,<br>
> &_NumPathElements, _pPathInfo,<br>
> + &_NumModeElements, _pModeInfo, NULL);<br>
> +<br>
> + // if ERROR_INSUFFICIENT_BUFFER need to retry QueryDisplayConfig<br>
> + // to get a new set of config buffers<br>
> + //(see<br>
> <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff569215(v=vs.85).aspx" rel="noreferrer" target="_blank">https://msdn.microsoft.com/en-us/library/windows/hardware/ff569215(v=vs.85).aspx</a><br>
> )<br>
> + if (query_error) {<br>
> + if (query_error == ERROR_INSUFFICIENT_BUFFER) {<br>
> + free_config_buffers();<br>
> + if (!get_config_buffers())<br>
> + return false;<br>
> + } else {<br>
> + _error = query_error;<br>
> + vd_printf("%s failed QueryDisplayConfig with 0x%lx",<br>
> __FUNCTION__, _error);<br>
> + return false;<br>
> + }<br>
> + }<br>
> + } while(query_error);<br>
> + _path_state = PATH_CURRENT;<br>
> + return true;<br>
> +}<br>
> +<br>
> +DISPLAYCONFIG_MODE_INFO* CCD::get_active_mode(LPCTSTR device_name, bool<br>
> return_on_error)<br>
> +{<br>
> + DISPLAYCONFIG_PATH_INFO* active_path;<br>
> +<br>
> + active_path = get_device_path(device_name, true);<br>
> +<br>
> + if (!active_path ) {<br>
> + vd_printf("%s:%S failed", __FUNCTION__, device_name);<br>
> + return NULL;<br>
> + }<br>
> + return &_pModeInfo[active_path->sourceInfo.modeInfoIdx];<br>
> +}<br>
> +<br>
> +bool CCD::set_display_config() {<br>
> +<br>
> + debug_print_config("Before SetDisplayConfig");<br>
> +<br>
> + if (_path_state == PATH_CURRENT) {<br>
> + vd_printf("%s: path states says nothing changed", __FUNCTION__);<br>
> + return true;<br>
> + }<br>
> +<br>
> + if (!(_error = _pfnSetDisplayConfig(_NumPathElements, _pPathInfo,<br>
> + _NumModeElements, _pModeInfo,<br>
> + SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG |<br>
> SDC_FORCE_MODE_ENUMERATION))) {<br>
> + return true;<br>
> + }<br>
> +<br>
> + vd_printf("%s failed SetDisplayConfig with 0x%lx", __FUNCTION__,<br>
> _error);<br>
> + debug_print_config("After failed SetDisplayConfig");<br>
> + return false;<br>
> +}<br>
> +<br>
> +DISPLAYCONFIG_PATH_INFO* CCD::get_device_path(LPCTSTR device_name, bool<br>
> bActive)<br>
> +{<br>
> + //Search for device's active path<br>
> + for (UINT32 i = 0; i < _NumPathElements; i++) {<br>
> + DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br>
> +<br>
> + //if bActive, return only paths that are currently active<br>
> + if (bActive && !is_active_path(path_info))<br>
> + continue;<br>
> + if (!is_device_path(device_name, path_info))<br>
> + continue;<br>
> + return path_info;<br>
> + }<br>
> + _error = ERROR_GEN_FAILURE;<br>
> + return NULL;<br>
> +}<br>
> +<br>
> +void CCD::debug_print_config(const char* prefix)<br>
> +{<br>
> + TCHAR dev_name[CCHDEVICENAME];<br>
> + for (UINT32 i = 0; i < _NumPathElements; i++) {<br>
> + DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br>
> + if (!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE))<br>
> + continue;<br>
> + get_device_name_config(path_info, dev_name);<br>
> +<br>
> + if (path_info->sourceInfo.modeInfoIdx ==<br>
> DISPLAYCONFIG_PATH_MODE_IDX_INVALID) {<br>
> + vd_printf("%s: %S [%s] This path is active but has invalid mode<br>
> set.", __FUNCTION__,<br>
> + dev_name, prefix);<br>
> + continue;<br>
> + }<br>
> + DISPLAYCONFIG_MODE_INFO* mode =<br>
> &_pModeInfo[path_info->sourceInfo.modeInfoIdx];<br>
> + vd_printf("%s: %S [%s] (%ld,%ld) (%ux%u).", __FUNCTION__, dev_name,<br>
> prefix,<br>
> + mode->sourceMode.position.x, mode->sourceMode.position.y,<br>
> + mode->sourceMode.width, mode->sourceMode.height);<br>
> + }<br>
> +}<br>
> +<br>
> +bool CCD::load_api()<br>
> +{<br>
> + HMODULE hModule = LoadLibrary(L"user32.dll");<br>
> + if(!hModule) {<br>
> + return false;<br>
> + }<br>
> +<br>
> + bool bFound_all(false);<br>
> + do {<br>
> + if (!(_pfnGetDeviceInfo = (PDISPLAYCONFIG_GETDEVICEINFO)<br>
> + GetProcAddress(hModule, "DisplayConfigGetDeviceInfo"))) {<br>
> + break;<br>
> + }<br>
> +<br>
> + if (!(_pfnGetDisplayConfigBufferSizes =<br>
> (PGETDISPLAYCONFIG_BUFFERSIZES)<br>
> + GetProcAddress(hModule, "GetDisplayConfigBufferSizes"))) {<br>
> + break;<br>
> + }<br>
> +<br>
> + if (!(_pfnQueryDisplayConfig = (PQUERYDISPLAYCONFIG)<br>
> + GetProcAddress(hModule, "QueryDisplayConfig"))) {<br>
> + break;<br>
> + }<br>
> +<br>
> + if (!(_pfnSetDisplayConfig = (PSETDISPLAYCONFIG)<br>
> + GetProcAddress(hModule, "SetDisplayConfig"))) {<br>
> + break;<br>
> + }<br>
> + bFound_all = true;<br>
> + }<br>
> + while(0);<br>
> +<br>
> + FreeLibrary(hModule);<br>
<br>
</div></div>You'll get a possible crash if you are really freeing<br>
the library. I think however would be better to just use<br>
GetModuleHandle instead of LoadLibrary.<br>
<br>
The reason of the crash is that if the module is not loaded<br>
you load with LoadLibrary, get the function pointer then<br>
with FreeLibrary the library is unloaded and the pointers<br>
are now invalid resulting in a crash if used. However being<br>
user32 surely be used by this application using GetModuleHandle<br>
avoid this issue.<br>
<span class=""><br>
> + return bFound_all;<br>
> +}<br>
> +<br>
> +bool CCD::get_config_buffers()<br>
> +{<br>
> + //Get Config Buffer Sizes<br>
> + free_config_buffers();<br>
> + _error = _pfnGetDisplayConfigBufferSizes(QDC_ALL_PATHS,<br>
> &_NumPathElements,<br>
> + &_NumModeElements);<br>
> + if (_error) {<br>
> + vd_printf("%s: GetDisplayConfigBufferSizes failed with 0x%lx",<br>
> __FUNCTION__, _error);<br>
> + return false;<br>
> + }<br>
> +<br>
> + //Allocate arrays<br>
> + _pPathInfo = ((DISPLAYCONFIG_PATH_INFO*)<br>
> malloc(sizeof(DISPLAYCONFIG_PATH_INFO) * _NumPathElements));<br>
> + _pModeInfo = ((DISPLAYCONFIG_MODE_INFO*)<br>
> malloc(sizeof(DISPLAYCONFIG_MODE_INFO) * _NumModeElements));<br>
> +<br>
<br>
</span>I'm a bit puzzled about the memory style. Sometimes it's new/delete<br>
sometimes is something more low level like malloc/free.<br>
Actually I thought the idea was reducing memory and avoid using<br>
exceptions or STL however I also found a std::vector usage (and other<br>
containers too).<br>
<div><div class="h5"><br>
> + if (!_pPathInfo || !_pModeInfo) {<br>
> + vd_printf("%s OOM ", __FUNCTION__);<br>
> + return false;<br>
> + }<br>
> +<br>
> + ///clear the above arrays<br>
> + ZeroMemory(_pPathInfo, sizeof(DISPLAYCONFIG_PATH_INFO) *<br>
> _NumPathElements);<br>
> + ZeroMemory(_pModeInfo, sizeof(DISPLAYCONFIG_MODE_INFO) *<br>
> _NumModeElements);<br>
> + return true;<br>
> +}<br>
> +<br>
> +void CCD::free_config_buffers()<br>
> +{<br>
> + if (_pModeInfo) {<br>
> + free(_pModeInfo);<br>
> + _pModeInfo = NULL;<br>
> + }<br>
> + if (_pPathInfo) {<br>
> + free(_pPathInfo);<br>
> + _pPathInfo = NULL;<br>
> + }<br>
> + _NumModeElements = _NumPathElements = 0;<br>
> +}<br>
> +<br>
> +bool CCD::get_device_name_config(DISPLAYCONFIG_PATH_INFO* path, LPCTSTR<br>
> dev_name)<br>
> +{<br>
> + DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name;<br>
> + source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;<br>
> + source_name.header.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME);<br>
> + source_name.header.adapterId = path->sourceInfo.adapterId;<br>
> + <a href="http://source_name.header.id" rel="noreferrer" target="_blank">source_name.header.id</a> = path->sourceInfo.id;<br>
> +<br>
> + _error = _pfnGetDeviceInfo(&source_name.header);<br>
> + if (_error) {<br>
> + vd_printf("%s DisplayConfigGetDeviceInfo failed with %lu",<br>
> __FUNCTION__, _error);<br>
> + return false;<br>
> + }<br>
> + memcpy((void *)dev_name, source_name.viewGdiDeviceName, CCHDEVICENAME*<br>
> sizeof(TCHAR));<br>
> + return true;<br>
> +}<br>
> +<br>
> +bool CCD::is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path)<br>
> +{<br>
> + //Does this path belong to device_name?<br>
> + TCHAR dev_name[CCHDEVICENAME];<br>
> + if (!get_device_name_config(path, dev_name)) {<br>
> + return false;<br>
> + }<br>
> + if (_tcscmp(dev_name, device_name)) {<br>
> + return false;<br>
> + }<br>
> + return true;<br>
> +}<br>
> +<br>
> +// If we have detached the primary monitor, then we need to reset the<br>
> positions of the remaining<br>
> +// monitors to insure that at least one is positioned at (0,0)<br>
> +bool CCD::verify_primary_position()<br>
> +{<br>
> + LONG leftmost_x(0);<br>
> + if (!_primary_detached) {<br>
> + return true;<br>
> + }<br>
> + _primary_detached = false;<br>
> +<br>
> + for (UINT32 i = 0; i < _NumPathElements; i++) {<br>
> + DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br>
> + if (!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE))<br>
> + continue;<br>
> +<br>
> + DISPLAYCONFIG_MODE_INFO* mode =<br>
> &_pModeInfo[path_info->sourceInfo.modeInfoIdx];<br>
> + if (leftmost_x > mode->sourceMode.position.x) {<br>
> + leftmost_x = mode->sourceMode.position.x;<br>
> + }<br>
> + }<br>
> +<br>
> + if (leftmost_x == 0) {<br>
> + return false;<br>
> + }<br>
> +<br>
> + for (UINT32 i = 0; i < _NumPathElements; i++) {<br>
> + DISPLAYCONFIG_PATH_INFO* path_info = &_pPathInfo[i];<br>
> + if ((!(path_info->flags & DISPLAYCONFIG_PATH_ACTIVE)))<br>
> + continue;<br>
> + DISPLAYCONFIG_MODE_INFO* mode =<br>
> &_pModeInfo[path_info->sourceInfo.modeInfoIdx];<br>
> + vd_printf("%s: setting mode x to %lu", __FUNCTION__,<br>
> mode->sourceMode.position.x);<br>
> + mode->sourceMode.position.x -= leftmost_x;<br>
> + }<br>
> + _path_state = PATH_UPDATED;<br>
> + return true;<br>
> +}<br>
> +<br>
> +bool CCD::update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode)<br>
> +{<br>
> + DISPLAYCONFIG_MODE_INFO* mode = get_active_mode(device_name, false);<br>
> + if (!mode)<br>
> + return false;<br>
> +<br>
> + mode->sourceMode.position.x = dev_mode->dmPosition.x;<br>
> + mode->sourceMode.position.y = dev_mode->dmPosition.y;<br>
> + vd_printf("%s: %S updated path mode to (%lu, %lu) - (%u x%u)",<br>
> __FUNCTION__,<br>
> + device_name,<br>
> + mode->sourceMode.position.x, mode->sourceMode.position.y,<br>
> + mode->sourceMode.width, mode->sourceMode.height);<br>
> + _path_state = PATH_UPDATED;<br>
> + return true;<br>
> +<br>
> +}<br>
> +<br>
> +bool CCD::update_mode_size(LPCTSTR device_name, DEVMODE* dev_mode)<br>
> +{<br>
> + DISPLAYCONFIG_MODE_INFO* mode = get_active_mode(device_name, false);<br>
> + if (!mode) {<br>
> + return false;<br>
> + }<br>
> +<br>
> + mode->sourceMode.width = dev_mode->dmPelsWidth;<br>
> + mode->sourceMode.height = dev_mode->dmPelsHeight;<br>
> + vd_printf("%s: %S updated path mode to (%lu, %lu - (%u x %u)",<br>
> __FUNCTION__,<br>
> + device_name,<br>
> + mode->sourceMode.position.x, mode->sourceMode.position.y,<br>
> + mode->sourceMode.width, mode->sourceMode.height);<br>
> + _path_state = PATH_UPDATED;<br>
> + return true;<br>
> +}<br>
> +<br>
> +void CCD::update_detached_primary_state(LPCTSTR device_name,<br>
> DISPLAYCONFIG_PATH_INFO * path_info)<br>
> +{<br>
> + DISPLAYCONFIG_MODE_INFO* mode(get_active_mode(device_name, false));<br>
> +<br>
> + //will need to reset monitor positions if primary detached<br>
> + path_info->flags = path_info->flags & ~DISPLAYCONFIG_PATH_ACTIVE;<br>
> + if (!mode|| mode->sourceMode.position.x != 0 ||<br>
> mode->sourceMode.position.y != 0) {<br>
> + return ;<br>
> + }<br>
> + _primary_detached = true;<br>
> +}<br>
> +<br>
> +bool CCD::set_path_state(LPCTSTR device_name, MONITOR_STATE new_state)<br>
> +{<br>
> + DISPLAYCONFIG_PATH_INFO* path(get_device_path(device_name, false));<br>
> + MONITOR_STATE current_path_state(MONITOR_DETACHED);<br>
> +<br>
> + if (path && (path->flags & DISPLAYCONFIG_PATH_ACTIVE)) {<br>
> + current_path_state = MONITOR_ATTACHED;<br>
> + }<br>
> +<br>
> + //If state didn't change, nothing to do<br>
> + if (current_path_state == new_state ) {<br>
> + return true;<br>
> + }<br>
> +<br>
> + if (!path) {<br>
> + return false;<br>
> + }<br>
> +<br>
> + _path_state = PATH_UPDATED;<br>
> + if (new_state == MONITOR_DETACHED) {<br>
> + update_detached_primary_state(device_name, path);<br>
> + } else {<br>
> + path->flags = path->flags | DISPLAYCONFIG_PATH_ACTIVE;<br>
> + set_display_config();<br>
> + }<br>
> + return true;<br>
> +}<br>
> +<br>
> +bool CCD::is_attached(LPCTSTR device_name)<br>
> +{<br>
> + DISPLAYCONFIG_PATH_INFO* path(get_device_path(device_name, false));<br>
> + if (!path) {<br>
> + return false;<br>
> + }<br>
> + return (path->flags & DISPLAYCONFIG_PATH_ACTIVE);<br>
> +}<br>
> +<br>
> +bool CCD::is_active_path(DISPLAYCONFIG_PATH_INFO * path)<br>
> +{<br>
> + if (!path || !(path->flags & DISPLAYCONFIG_PATH_ACTIVE) ||<br>
> + (path->sourceInfo.modeInfoIdx ==<br>
> DISPLAYCONFIG_PATH_MODE_IDX_INVALID)) {<br>
> + return false;<br>
> + }<br>
> + return true;<br>
> +}<br>
> diff --git a/vdagent/display_configuration.h<br>
> b/vdagent/display_configuration.h<br>
> new file mode 100755<br>
> index 0000000..4a1a7d4<br>
> --- /dev/null<br>
> +++ b/vdagent/display_configuration.h<br>
> @@ -0,0 +1,94 @@<br>
> +/*<br>
> +Copyright (C) 2015 Red Hat, Inc.<br>
> +<br>
> +This program is free software; you can redistribute it and/or<br>
> +modify it under the terms of the GNU General Public License as<br>
> +published by the Free Software Foundation; either version 2 of<br>
> +the License, or (at your option) any later version.<br>
> +<br>
> +This program is distributed in the hope that it will be useful,<br>
> +but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
> +GNU General Public License for more details.<br>
> +<br>
> +You should have received a copy of the GNU General Public License<br>
> +along with this program. If not, see <<a href="http://www.gnu.org/licenses/" rel="noreferrer" target="_blank">http://www.gnu.org/licenses/</a>>.<br>
> +*/<br>
> +#ifndef _H_DISPLAY_CONFIGURATION<br>
> +#define _H_DISPLAY_CONFIGURATION<br>
> +<br>
<br>
</div></div>Underscore uppercase identifiers are deprecated since C99 and C++89,<br>
and this is C++ so 27 years ago.<br>
<div class="HOEnZb"><div class="h5"><br>
> +#include <spice/qxl_windows.h><br>
> +#include <spice/qxl_dev.h><br>
> +#include "desktop_layout.h"<br>
> +#include "vdlog.h"<br>
> +<br>
> +enum MONITOR_STATE {<br>
> + MONITOR_DETACHED,<br>
> + MONITOR_ATTACHED,<br>
> +};<br>
> +<br>
> +enum PATH_STATE {<br>
> + PATH_UPDATED,<br>
> + PATH_CURRENT,<br>
> +};<br>
> +<br>
> +enum DISPLAYCONFIG_TOPOLOGY_ID {};<br>
> +<br>
> +struct DISPLAYCONFIG_DEVICE_INFO_HEADER;<br>
> +struct DISPLAYCONFIG_MODE_INFO;<br>
> +struct DISPLAYCONFIG_PATH_INFO;<br>
> +<br>
> +//Makes calls into the CCD API for getting/setting display settings on WDDM<br>
> drivers<br>
> +//Use is exclusive to wddm display config class<br>
> +<br>
> +typedef LONG(APIENTRY*<br>
> PDISPLAYCONFIG_GETDEVICEINFO)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);<br>
> +typedef LONG(APIENTRY* PGETDISPLAYCONFIG_BUFFERSIZES)(UINT32, UINT32*,<br>
> UINT32*);<br>
> +typedef LONG(APIENTRY* PQUERYDISPLAYCONFIG)(UINT32, UINT32*,<br>
> DISPLAYCONFIG_PATH_INFO*, UINT32*,<br>
> + DISPLAYCONFIG_MODE_INFO*,<br>
> DISPLAYCONFIG_TOPOLOGY_ID*);<br>
> +typedef LONG(APIENTRY* PSETDISPLAYCONFIG)(UINT32, DISPLAYCONFIG_PATH_INFO*,<br>
> UINT32,<br>
> + DISPLAYCONFIG_MODE_INFO*, UINT32);<br>
> +<br>
> +class CCD {<br>
> +public:<br>
> + CCD();<br>
> + ~CCD();<br>
> +<br>
> + bool query_display_config();<br>
> + bool set_display_config();<br>
> + bool update_mode_position(LPCTSTR device_name, DEVMODE* dev_mode);<br>
> + bool update_mode_size(LPCTSTR DeviceNmae, DEVMODE* dev_mode);<br>
> + void update_detached_primary_state(LPCTSTR device_name,<br>
> DISPLAYCONFIG_PATH_INFO * path_info);<br>
> + bool set_path_state(LPCTSTR device_name, MONITOR_STATE state);<br>
> + bool is_attached(LPCTSTR device_name);<br>
> + bool is_active_path(DISPLAYCONFIG_PATH_INFO * path);<br>
> + LONG error() { return _error; }<br>
> + DISPLAYCONFIG_MODE_INFO* get_active_mode(LPCTSTR device_name, bool<br>
> return_on_error);<br>
> + DISPLAYCONFIG_PATH_INFO* get_device_path(LPCTSTR device_name, bool<br>
> bActive);<br>
> + bool verify_primary_position();<br>
> + void debug_print_config(const char* prefix = NULL);<br>
> +<br>
> +private:<br>
> + bool load_api();<br>
> + bool get_config_buffers();<br>
> + void free_config_buffers();<br>
> + bool is_device_path(LPCTSTR device_name, DISPLAYCONFIG_PATH_INFO* path);<br>
> + bool get_device_name_config(DISPLAYCONFIG_PATH_INFO* path, LPCTSTR<br>
> dev_name);<br>
> +<br>
> + //CCD API stuff<br>
> + UINT32 _NumPathElements;<br>
> + UINT32 _NumModeElements;<br>
> + DISPLAYCONFIG_PATH_INFO* _pPathInfo;<br>
> + DISPLAYCONFIG_MODE_INFO* _pModeInfo;<br>
> +<br>
> + //CCD API function pointers<br>
> + PDISPLAYCONFIG_GETDEVICEINFO _pfnGetDeviceInfo;<br>
> + PGETDISPLAYCONFIG_BUFFERSIZES _pfnGetDisplayConfigBufferSizes;<br>
> + PQUERYDISPLAYCONFIG _pfnQueryDisplayConfig;<br>
> + PSETDISPLAYCONFIG _pfnSetDisplayConfig;<br>
> +<br>
> + LONG _error;<br>
> + bool _primary_detached;<br>
> + PATH_STATE _path_state;<br>
> +};<br>
> +<br>
> +#endif<br>
> \ No newline at end of file<br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">Frediano<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><font size="4" color="#0b5394" face="times new roman, serif">Respectfully,<br></font><div style="font-size:12.8px;color:rgb(136,136,136)"><font size="4" color="#0b5394" face="times new roman, serif"><b><i>Sameeh Jubran</i></b></font></div><div style="font-size:12.8px;color:rgb(136,136,136)"><i style="color:rgb(7,55,99);font-family:"times new roman",serif;font-size:large"><span style="line-height:15px"><a href="https://il.linkedin.com/pub/sameeh-jubran/87/747/a8a" title="View public profile" name="UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_14e2c1de96f8c195_UNIQUE_ID_SafeHtmlFilter_SafeHtmlFilter_SafeHtmlFilter_webProfileURL" style="color:rgb(17,85,204);margin:0px;padding:0px;border-width:0px;outline:none;vertical-align:baseline;text-decoration:none" target="_blank">Linkedin</a></span></i><br></div><div style="font-size:12.8px;color:rgb(136,136,136)"><font size="4" face="times new roman, serif" color="#073763"><i>Junior Software Engineer @ <a href="http://www.daynix.com" target="_blank">Daynix</a>.</i></font></div></div></div></div></div></div></div>
</div>