<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>