DisplayManagerWin.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. //
  2. // DisplayManagerWin.cpp
  3. // konvergo
  4. //
  5. // Created by Lionel CHAZALLON on 18/06/2015.
  6. //
  7. //
  8. #include <QRect>
  9. #include <math.h>
  10. #include "QsLog.h"
  11. #include "DisplayManagerWin.h"
  12. ///////////////////////////////////////////////////////////////////////////////////////////////////
  13. static DMVideoMode convertDevMode(const DEVMODEW& devmode)
  14. {
  15. DMVideoMode mode = {};
  16. mode.m_height = devmode.dmPelsHeight;
  17. mode.m_width = devmode.dmPelsWidth;
  18. mode.m_refreshRate = devmode.dmDisplayFrequency;
  19. mode.m_bitsPerPixel = devmode.dmBitsPerPel;
  20. mode.m_interlaced = !!(devmode.dmDisplayFlags & DM_INTERLACED);
  21. // Windows just returns integer refresh rate so let's fudge it
  22. if (mode.m_refreshRate == 59 ||
  23. mode.m_refreshRate == 29 ||
  24. mode.m_refreshRate == 23)
  25. mode.m_refreshRate = (float)(mode.m_refreshRate + 1) / 1.001f;
  26. return mode;
  27. }
  28. ///////////////////////////////////////////////////////////////////////////////////////////////////
  29. static bool modeEquals(const DMVideoMode& m1, const DMVideoMode& m2)
  30. {
  31. return m1.m_height == m2.m_height &&
  32. m1.m_width == m2.m_width &&
  33. fabs(m1.m_refreshRate - m2.m_refreshRate) < 1e-9 &&
  34. m1.m_bitsPerPixel == m2.m_bitsPerPixel &&
  35. m1.m_interlaced == m2.m_interlaced;
  36. }
  37. ///////////////////////////////////////////////////////////////////////////////////////////////////
  38. bool DisplayManagerWin::initialize()
  39. {
  40. DISPLAY_DEVICEW displayInfo;
  41. int displayId = 0;
  42. m_displayAdapters.clear();
  43. m_displays.clear();
  44. while (getDisplayInfo(displayId, displayInfo))
  45. {
  46. if (displayInfo.StateFlags & (DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED))
  47. {
  48. DEVMODEW modeInfo;
  49. int modeId = 0;
  50. // add the display
  51. DMDisplayPtr display = DMDisplayPtr(new DMDisplay);
  52. display->m_id = displayId;
  53. display->m_name = QString::fromWCharArray(displayInfo.DeviceString);
  54. m_displays[display->m_id] = DMDisplayPtr(display);
  55. m_displayAdapters[display->m_id] = QString::fromWCharArray(displayInfo.DeviceName);
  56. while (getModeInfo(displayId, modeId, modeInfo))
  57. {
  58. // add the videomode to the display
  59. DMVideoModePtr videoMode = DMVideoModePtr(new DMVideoMode);
  60. *videoMode = convertDevMode(modeInfo);
  61. videoMode->m_id = modeId;
  62. display->m_videoModes[videoMode->m_id] = videoMode;
  63. modeId++;
  64. }
  65. }
  66. displayId++;
  67. }
  68. if (m_displays.isEmpty())
  69. {
  70. QLOG_DEBUG() << "No display found.";
  71. return false;
  72. }
  73. else
  74. return DisplayManager::initialize();
  75. }
  76. ///////////////////////////////////////////////////////////////////////////////////////////////////
  77. bool DisplayManagerWin::setDisplayMode(int display, int mode)
  78. {
  79. DEVMODEW modeInfo;
  80. if (!isValidDisplayMode(display, mode))
  81. return false;
  82. if (getModeInfo(display, mode, modeInfo))
  83. {
  84. QLOG_DEBUG() << "Switching to mode" << mode << "on display" << display << ":" << m_displays[display]->m_videoModes[mode]->getPrettyName();
  85. modeInfo.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
  86. LONG rc = ChangeDisplaySettingsExW((LPCWSTR)m_displayAdapters[display].utf16(), &modeInfo, NULL,
  87. CDS_FULLSCREEN, NULL);
  88. if (rc != DISP_CHANGE_SUCCESSFUL)
  89. {
  90. QLOG_ERROR() << "Failed to changed DisplayMode, error" << rc;
  91. return false;
  92. }
  93. else
  94. {
  95. return true;
  96. }
  97. }
  98. return false;
  99. }
  100. ///////////////////////////////////////////////////////////////////////////////////////////////////
  101. int DisplayManagerWin::getCurrentDisplayMode(int display)
  102. {
  103. if (!isValidDisplay(display))
  104. return -1;
  105. // grab current mode
  106. DEVMODEW modeInfo;
  107. ZeroMemory(&modeInfo, sizeof(modeInfo));
  108. modeInfo.dmSize = sizeof(modeInfo);
  109. // grab current mode info
  110. if (!EnumDisplaySettingsW((LPCWSTR)m_displayAdapters[display].utf16(), ENUM_CURRENT_SETTINGS,
  111. &modeInfo))
  112. {
  113. QLOG_ERROR() << "Failed to retrieve current mode";
  114. return -1;
  115. }
  116. DMVideoMode mode = convertDevMode(modeInfo);
  117. // check if current mode info matches on of our modes
  118. for (int modeId = 0; modeId < m_displays[display]->m_videoModes.size(); modeId++)
  119. {
  120. if (modeEquals(mode, * m_displays[display]->m_videoModes[modeId]))
  121. return modeId;
  122. }
  123. return -1;
  124. }
  125. ///////////////////////////////////////////////////////////////////////////////////////////////////
  126. int DisplayManagerWin::getMainDisplay()
  127. {
  128. DISPLAY_DEVICEW displayInfo;
  129. int displayId = 0;
  130. while (getDisplayInfo(displayId, displayInfo))
  131. {
  132. if (displayInfo.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
  133. return displayId;
  134. displayId++;
  135. }
  136. return -1;
  137. }
  138. ///////////////////////////////////////////////////////////////////////////////////////////////////
  139. DisplayManagerWin::~DisplayManagerWin()
  140. {
  141. }
  142. ///////////////////////////////////////////////////////////////////////////////////////////////////
  143. int DisplayManagerWin::getDisplayFromPoint(int x, int y)
  144. {
  145. for(int displayId : m_displays.keys())
  146. {
  147. QString dispName = m_displayAdapters[displayId];
  148. DEVMODEW modeInfo = {};
  149. modeInfo.dmSize = sizeof(modeInfo);
  150. QLOG_DEBUG() << "Looking at display" << displayId << dispName;
  151. if (!EnumDisplaySettingsW((LPCWSTR)dispName.utf16(), ENUM_CURRENT_SETTINGS,
  152. &modeInfo))
  153. {
  154. QLOG_ERROR() << "Failed to retrieve current mode.";
  155. }
  156. else
  157. {
  158. QRect displayRect(modeInfo.dmPosition.x, modeInfo.dmPosition.y, modeInfo.dmPelsWidth,
  159. modeInfo.dmPelsHeight);
  160. QLOG_DEBUG() << "Position on virtual desktop:" << displayRect;
  161. if (displayRect.contains(x, y))
  162. return displayId;
  163. }
  164. }
  165. return -1;
  166. }
  167. ///////////////////////////////////////////////////////////////////////////////////////////////////
  168. bool DisplayManagerWin::getDisplayInfo(int display, DISPLAY_DEVICEW& info)
  169. {
  170. ZeroMemory(&info, sizeof(info));
  171. info.cb = sizeof(info);
  172. return EnumDisplayDevicesW(NULL, display, &info, 0);
  173. }
  174. ///////////////////////////////////////////////////////////////////////////////////////////////////
  175. bool DisplayManagerWin::getModeInfo(int display, int mode, DEVMODEW& info)
  176. {
  177. if (m_displayAdapters.contains(display))
  178. {
  179. ZeroMemory(&info, sizeof(info));
  180. info.dmSize = sizeof(info);
  181. return EnumDisplaySettingsExW((LPCWSTR)m_displayAdapters[display].utf16(), mode, &info, 0);
  182. }
  183. return false;
  184. }