text: /****************************** Module Header ******************************\
  * Module Name: mmrtl.c
  *
  * Copyright (c) 1985 - 1999, Microsoft Corporation
  *
  * Multimonitor APIs.
  *
  * History:
  * 29-Mar-1997 adams     Created.
  \***************************************************************************/
  
  #define Int32x32To32(x, y) ((x) * (y))
  
  /*
   * There is no object locking in the client, so the monitor object can
   * go away at any time. Therefore to be safe, we need an exception handler.
   */
  #ifdef _USERK_
  #define BEGIN_EXCEPTION_HANDLER
  #define END_EXCEPTION_HANDLER
  #define END_EXCEPTION_HANDLER_EMPTY
  #else // _USERK_
  #define BEGIN_EXCEPTION_HANDLER try {
  #define END_EXCEPTION_HANDLER \
      } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { \
          pMonitorResult = NULL; \
      }
  #define END_EXCEPTION_HANDLER_EMPTY \
      } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { \
      }
  #endif // _USERK_
  
  
  /***************************************************************************\
  * _MonitorFromPoint
  *
  * Calculate the monitor that a point is in or is nearest to.
  *
  * Arguments:
  *     pt      - The point.
  *     dwFlags - One of:
  *         MONITOR_DEFAULTTONULL - If the point isn't in a monitor,
  *             return NULL.
  *
  *         MONITOR_DEFAULTTOPRIMARY - If the point isn't in a monitor,
  *             return the primary monitor.
  *
  *         MONITOR_DEFAULTTONEAREST - Return the monitor nearest the point.
  *
  * History:
  * 22-Sep-1996 adams     Created.
  * 29-Mar-1997 adams     Moved to rtl.
  \***************************************************************************/
  
  PMONITOR
  _MonitorFromPoint(POINT pt, DWORD dwFlags)
  {
      PMONITOR        pMonitor, pMonitorResult;
      int             dx;
      int             dy;
  
      UserAssert(dwFlags == MONITOR_DEFAULTTONULL ||
                 dwFlags == MONITOR_DEFAULTTOPRIMARY ||
                 dwFlags == MONITOR_DEFAULTTONEAREST);
  
      if (GetDispInfo()->cMonitors == 1 && dwFlags != MONITOR_DEFAULTTONULL)
          return GetPrimaryMonitor();
  
      switch (dwFlags) {
      case MONITOR_DEFAULTTONULL:
      case MONITOR_DEFAULTTOPRIMARY:
          /*
           * Return the monitor the point is in.
           */
  
          BEGIN_EXCEPTION_HANDLER
  
          for (   pMonitor = REBASESHAREDPTRALWAYS(GetDispInfo()->pMonitorFirst);
                  pMonitor;
                  pMonitor = REBASESHAREDPTR(pMonitor->pMonitorNext)) {
  
              if (!(pMonitor->dwMONFlags & MONF_VISIBLE))
                  continue;
  
              if (PtInRect(KPRECT_TO_PRECT(&pMonitor->rcMonitor), pt)) {
                  return pMonitor;
              }
          }
  
          END_EXCEPTION_HANDLER_EMPTY
  
          /*
           * Return what the user wants if it's not found.
           */
          switch (dwFlags) {
          case MONITOR_DEFAULTTONULL:
              return NULL;
  
          case MONITOR_DEFAULTTOPRIMARY:
              return GetPrimaryMonitor();
  
          default:
              UserAssertMsg0(FALSE, "Logic error in _MonitorFromPoint");
              break;
          }
  
      case MONITOR_DEFAULTTONEAREST:
  
  #define MONITORFROMPOINTALGORITHM(SUMSQUARESMAX, SUMSQUARESTYPE, POINTMULTIPLY)     \
          SUMSQUARESTYPE  sumsquare;                                                  \
          SUMSQUARESTYPE  leastsumsquare;                                             \
          leastsumsquare = SUMSQUARESMAX;                                             \
          for (   pMonitor = REBASESHAREDPTRALWAYS(GetDispInfo()->pMonitorFirst);     \
                  pMonitor;                                                           \
                  pMonitor = REBASESHAREDPTR(pMonitor->pMonitorNext)) {               \
                                                                                      \
              if (!(pMonitor->dwMONFlags & MONF_VISIBLE))                             \
                  continue;                                                           \
                                                                                      \
              /*                                                                      \
               * Determine distance from monitor along x axis.                        \
               */                                                                     \
              if (pt.x < pMonitor->rcMonitor.left) {                                  \
                  dx = pMonitor->rcMonitor.left - pt.x;                               \
              } else if (pt.x < pMonitor->rcMonitor.right) {                          \
                  dx = 0;                                                             \
              } else {                                                                \
                  /*                                                                  \
                   * Monitor rectangles do not include the rightmost edge.            \
                   */                                                                 \
                  dx = pt.x - (pMonitor->rcMonitor.right - 1);                        \
              }                                                                       \
                                                                                      \
              /*                                                                      \
               * Skip this monitor if dx is greater than dx^2 + dy^2.                 \
               * We do this check to avoid multiplication operations.                 \
               */                                                                     \
              if ((SUMSQUARESTYPE) dx >= leastsumsquare)                              \
                  continue;                                                           \
                                                                                      \
              /*                                                                      \
               * Determine distance from monitor along y axis.                        \
               */                                                                     \
              if (pt.y < pMonitor->rcMonitor.top) {                                   \
                  dy = pMonitor->rcMonitor.top - pt.y;                                \
              } else if (pt.y < pMonitor->rcMonitor.bottom) {                         \
                  /*                                                                  \
                   * The point is in the monitor and we're done                       \
                   * if both dx and dy are zero.                                      \
                   */                                                                 \
                  if (dx == 0)                                                        \
                      return pMonitor;                                                \
                                                                                      \
                  dy = 0;                                                             \
              } else {                                                                \
                  dy = pt.y - (pMonitor->rcMonitor.bottom - 1);                       \
              }                                                                       \
                                                                                      \
              /*                                                                      \
               * Calculate dx^2. Skip this monitor if dx is greater                   \
               * than dx^2 + dy^2. We do this check to avoid                          \
               * multiplication operations.                                           \
               */                                                                     \
              sumsquare = POINTMULTIPLY(dx, dx);                                      \
              if (sumsquare >= leastsumsquare)                                        \
                  continue;                                                           \
                                                                                      \
              /*                                                                      \
               * Skip this monitor if dx^2 + y is greater than dx^2 + dy^2.           \
               * We do this check to avoid multiplication operations.                 \
               */                                                                     \
              if (sumsquare + (SUMSQUARESTYPE) dy >= leastsumsquare)                  \
                  continue;                                                           \
                                                                                      \
              /*                                                                      \
               * Compute dx^2 + dy^2. Skip this monitor if it's not the least.        \
               */                                                                     \
              sumsquare += (SUMSQUARESTYPE) POINTMULTIPLY(dy, dy);                    \
              if (sumsquare >= leastsumsquare)                                        \
                  continue;                                                           \
                                                                                      \
              /*                                                                      \
               * This is the closest monitor so far.                                  \
               */                                                                     \
              leastsumsquare = sumsquare;                                             \
              pMonitorResult = pMonitor;                                              \
          }
  
  #if DBG
          pMonitorResult = (PMONITOR) -1;
  #endif
  
          if (    pt.x < SHRT_MIN || SHRT_MAX < pt.x ||
                  pt.y < SHRT_MIN || SHRT_MAX < pt.y) {
  
              BEGIN_EXCEPTION_HANDLER
              MONITORFROMPOINTALGORITHM(_UI64_MAX, ULONGLONG, Int32x32To64)
              END_EXCEPTION_HANDLER
  
          } else {
  
              BEGIN_EXCEPTION_HANDLER
              MONITORFROMPOINTALGORITHM(UINT_MAX, UINT, Int32x32To32)
              END_EXCEPTION_HANDLER
  
          }
  
          UserAssert(pMonitorResult != (PMONITOR) -1);
          return pMonitorResult;
  
      default:
          UserAssert(0 && "Logic error in _MonitorFromPoint, shouldn't have gotten here.");
          break;
      }
  
      UserAssert(0 && "Logic error in _MonitorFromPoint, shouldn't have gotten here.");
      return NULL;
  }
  
  
  
  /***************************************************************************\
  * _MonitorFromRect
  *
  * Calculate the monitor that a rect is in or is nearest to.
  *
  * Arguments:
  *     lprc    - The rect.
  *     dwFlags - One of:
  *         MONITOR_DEFAULTTONULL - If the rect doesn't intersect a monitor,
  *             return NULL.
  *
  *         MONITOR_DEFAULTTOPRIMARY - If the rect doesn't intersect a monitor,
  *             return the primary monitor.
  *
  *         MONITOR_DEFAULTTONEAREST - Return the monitor nearest the rect.
  *
  * History:
  * 22-Sep-1996 adams     Created.
  * 29-Mar-1997 adams     Moved to rtl.
  \***************************************************************************/
  
  PMONITOR
  _MonitorFromRect(LPCRECT lprc, DWORD dwFlags)
  {
      PDISPLAYINFO    pDispInfo;
      PMONITOR        pMonitor, pMonitorResult;
      RECT            rc;
      int             area, areaMost;
  
      UserAssert(dwFlags == MONITOR_DEFAULTTONULL ||
                 dwFlags == MONITOR_DEFAULTTOPRIMARY ||
                 dwFlags == MONITOR_DEFAULTTONEAREST);
  
      /*
       * Special case the most common case - 1 monitor.
       */
      pDispInfo = GetDispInfo();
      if (pDispInfo->cMonitors == 1 && dwFlags != MONITOR_DEFAULTTONULL)
          return GetPrimaryMonitor();
  
      /*
       * If rect is empty, use topleft point.
       */
      if (IsRectEmpty(lprc)) {
          return _MonitorFromPoint(*(LPPOINT)lprc, dwFlags);
      }
  
      /*
       * Return the primary monitor if the rectangle covers the desktop.
       */
      if (    lprc->left   <= pDispInfo->rcScreen.left &&
              lprc->top    <= pDispInfo->rcScreen.top &&
              lprc->right  >= pDispInfo->rcScreen.right &&
              lprc->bottom >= pDispInfo->rcScreen.bottom) {
  
          return GetPrimaryMonitor();
      }
  
      /*
       * Calculate the nearest rectangle by determining which
       * monitor has the greatest intersection with the rectangle.
       */
  
      BEGIN_EXCEPTION_HANDLER
  
      areaMost = 0;
      for (   pMonitor = REBASESHAREDPTRALWAYS(GetDispInfo()->pMonitorFirst);
              pMonitor;
              pMonitor = REBASESHAREDPTR(pMonitor->pMonitorNext)) {
  
          if (!(pMonitor->dwMONFlags & MONF_VISIBLE))
              continue;
  
          if (IntersectRect(&rc, lprc, KPRECT_TO_PRECT(&pMonitor->rcMonitor))) {
              if (EqualRect(&rc, lprc))
                  return pMonitor;
  
              /*
               * Calculate the area of the intersection. Note that
               * the intersection must be in 16bit coordinats, since
               * we limit monitor rects to 16bit coordinate space.
               * So the result of any area calculation will fit in
               * in an int.
               */
              area = (rc.right - rc.left) * (rc.bottom - rc.top);
              if (area > areaMost) {
                  areaMost = area;
                  pMonitorResult = pMonitor;
              }
          }
      }
  
      END_EXCEPTION_HANDLER
  
      UserAssert(areaMost >= 0);
      if (areaMost > 0)
          return pMonitorResult;
  
  
      switch (dwFlags) {
      case MONITOR_DEFAULTTONULL:
          return NULL;
  
      case MONITOR_DEFAULTTOPRIMARY:
          return GetPrimaryMonitor();
  
      case MONITOR_DEFAULTTONEAREST:
          {
              int dx, dy;
  
  #define MONITORFROMRECTALGORITHM(SUMSQUARESMAX, SUMSQUARESTYPE, POINTMULTIPLY)      \
              SUMSQUARESTYPE  sumsquare;                                              \
              SUMSQUARESTYPE  leastsumsquare;                                         \
              leastsumsquare = SUMSQUARESMAX;                                         \
              for (   pMonitor = REBASESHAREDPTRALWAYS(GetDispInfo()->pMonitorFirst); \
                      pMonitor;                                                       \
                      pMonitor = REBASESHAREDPTR(pMonitor->pMonitorNext)) {           \
                                                                                      \
                  if (!(pMonitor->dwMONFlags & MONF_VISIBLE))                         \
                      continue;                                                       \
                                                                                      \
                  /*                                                                  \
                   * Determine distance from monitor along x axis.                    \
                   */                                                                 \
                  if (lprc->right <= pMonitor->rcMonitor.left) {                      \
                      /*                                                              \
                       * Add 1 because rectangles do not include the rightmost edge.  \
                       */                                                             \
                      dx = pMonitor->rcMonitor.left - lprc->right + 1;                \
                  } else if (lprc->left < pMonitor->rcMonitor.right) {                \
                      dx = 0;                                                         \
                  } else {                                                            \
                      /*                                                              \
                       * Add 1 because rectangles do not include the rightmost edge.  \
                       */                                                             \
                      dx = lprc->left - (pMonitor->rcMonitor.right - 1);              \
                  }                                                                   \
                                                                                      \
                  /*                                                                  \
                   * Skip this monitor if dx is greater than dx^2 + dy^2.             \
                   * We do this check to avoid multiplication operations.             \
                   */                                                                 \
                  if ((SUMSQUARESTYPE) dx >= leastsumsquare)                          \
                      continue;                                                       \
                                                                                      \
                  /*                                                                  \
                   * Determine distance from monitor along y axis.                    \
                   */                                                                 \
                  if (lprc->bottom <= pMonitor->rcMonitor.top) {                      \
                      /*                                                              \
                       * Add 1 because rectangles do not include the bottommost edge. \
                       */                                                             \
                      dy = pMonitor->rcMonitor.top - lprc->bottom + 1;                \
                  } else if (lprc->top < pMonitor->rcMonitor.bottom) {                \
                      UserAssert(dx != 0 && "This rectangle intersects a monitor, so we shouldn't be here."); \
                      dy = 0;                                                         \
                  } else {                                                            \
                      /*                                                              \
                       * Add 1 because rectangles do not include the bottommost edge. \
                       */                                                             \
                      dy = lprc->top - pMonitor->rcMonitor.bottom + 1;                \
                  }                                                                   \
                                                                                      \
                  /*                                                                  \
                   * Calculate dx^2. Skip this monitor if dx is greater               \
                   * than dx^2 + dy^2. We do this check to avoid                      \
                   * multiplication operations.                                       \
                   */                                                                 \
                  sumsquare = POINTMULTIPLY(dx, dx);                                  \
                  if (sumsquare >= leastsumsquare)                                    \
                      continue;                                                       \
                                                                                      \
                  /*                                                                  \
                   * Skip this monitor if dx^2 + y is greater than dx^2 + dy^2.       \
                   * We do this check to avoid multiplication operations.             \
                   */                                                                 \
                  if (sumsquare + (SUMSQUARESTYPE) dy >= leastsumsquare)              \
                      continue;                                                       \
                                                                                      \
                  /*                                                                  \
                   * Compute dx^2 + dy^2. Skip this monitor if it's not the least.    \
                   */                                                                 \
                  sumsquare += (SUMSQUARESTYPE) POINTMULTIPLY(dy, dy);                \
                  if (sumsquare >= leastsumsquare)                                    \
                      continue;                                                       \
                                                                                      \
                  /*                                                                  \
                   * This is the closest monitor so far.                              \
                   */                                                                 \
                  leastsumsquare = sumsquare;                                         \
                  pMonitorResult = pMonitor;                                          \
              }
  
  #if DBG
              pMonitorResult = (PMONITOR) -1;
  #endif
  
              if (    lprc->left < SHRT_MIN || SHRT_MAX < lprc->left ||
                      lprc->top < SHRT_MIN || SHRT_MAX < lprc->top ||
                      lprc->right < SHRT_MIN || SHRT_MAX < lprc->right ||
                      lprc->bottom < SHRT_MIN || SHRT_MAX < lprc->bottom) {
  
                  BEGIN_EXCEPTION_HANDLER
                  MONITORFROMRECTALGORITHM(_UI64_MAX, ULONGLONG, Int32x32To64)
                  END_EXCEPTION_HANDLER
  
              } else {
  
                  BEGIN_EXCEPTION_HANDLER
                  MONITORFROMRECTALGORITHM(UINT_MAX, UINT, Int32x32To32)
                  END_EXCEPTION_HANDLER
  
              }
  
              UserAssert(pMonitorResult != (PMONITOR) -1);
              return pMonitorResult;
          }
  
      default:
          UserAssertMsg0(0, "Logic error in _MonitorFromWindow, shouldn't have gotten here.");
          break;
      }
  
      UserAssertMsg0(0, "Logic error in _MonitorFromWindow, shouldn't have gotten here.");
      return NULL;
  }
  
  
  
  /***************************************************************************\
  * _MonitorFromWindow
  *
  * Calculate the monitor that a window is in or is nearest to. We use
  * the center of the window to determine its location. If the window
  * is minimized, use its normal position.
  *
  * Arguments:
  *     pwnd    - The window.
  *     dwFlags - One of:
  *         MONITOR_DEFAULTTONULL - If the window doesn't intersect a monitor,
  *             return NULL.
  *
  *         MONITOR_DEFAULTTOPRIMARY - If the window doesn't intersect a monitor,
  *             return the primary monitor.
  *
  *         MONITOR_DEFAULTTONEAREST - Return the monitor nearest the window.
  *
  * History:
  * 22-Sep-1996 adams     Created.
  * 29-Mar-1997 adams     Moved to rtl.
  \***************************************************************************/
  
  PMONITOR
  _MonitorFromWindow(PWND pwnd, DWORD dwFlags)
  {
      PWND            pwndParent;
  
      UserAssert(dwFlags == MONITOR_DEFAULTTONULL ||
                 dwFlags == MONITOR_DEFAULTTOPRIMARY ||
                 dwFlags == MONITOR_DEFAULTTONEAREST);
  
      if (GetDispInfo()->cMonitors == 1 && dwFlags != MONITOR_DEFAULTTONULL) {
          return GetPrimaryMonitor();
      }
  
      if (!pwnd)
          goto NoWindow;
  
      /*
       * Handle minimized windows.
       */
      if (TestWF(pwnd, WFMINIMIZED))
      {
  #ifdef _USERK_
          CHECKPOINT *    pcp;
  
          pcp = (CHECKPOINT *)_GetProp(pwnd, PROP_CHECKPOINT, PROPF_INTERNAL);
          if (pcp) {
              return _MonitorFromRect(&pcp->rcNormal, dwFlags);
          }
  #else
          WINDOWPLACEMENT wp;
          HWND            hwnd;
  
          wp.length = sizeof(wp);
          hwnd = (HWND)PtoH(pwnd);
          if (GetWindowPlacement(hwnd, &wp)) {
              return _MonitorFromRect(&wp.rcNormalPosition, dwFlags);
          }
  
          /*
           * (adams) If GetWindowPlacement fails, then either there was not enough
           * memory to allocate a CHECKPOINT, or the window was destroyed
           * and the API failed. If the later, the following code my be
           * playing with invalid memory. Although on the client side we
           * can never guarantee that a window is valid, it seems especially
           * likely that it is invalid here. So do another revalidation
           * by calling IsWindow.
           */
          if (!IsWindow(hwnd))
              goto NoWindow;
  #endif
  
          UserAssert(GETFNID(pwnd) != FNID_DESKTOP);
          pwndParent = REBASEPWND(pwnd, spwndParent);
          if (GETFNID(pwndParent) == FNID_DESKTOP) {
              return GetPrimaryMonitor();
          }
  
          /*
           * Otherwise, if we are a child window, fall thru below to use the
           * window rect, which actually means something for non-toplevel dudes.
           */
      }
  
      return _MonitorFromRect(KPRECT_TO_PRECT(&pwnd->rcWindow), dwFlags);
  
  NoWindow:
      if (dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) {
          return GetPrimaryMonitor();
      }
  
      return NULL;
  }
  