test: multimon.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# multimon.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: multimon.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * Multimonitor APIs.
    00007 *
    00008 * History:
    00009 * 27-Sep-1996 adams     Stub implementation for NT 5.
    00010 * 20-Feb-1997 adams     Port from NT4 SP3.
    00011 \***************************************************************************/
    00012
    00013 #include "precomp.h"
    00014 #pragma hdrstop
    00015
    00016 /* last monitor the cursor was clipped to */
    00017 PMONITOR gpMonitorMouse;
    00018
    00019 /***************************************************************************\
    00020 * ClipPointToDesktop
    00021 *
    00022 * Clips the point the nearest monitor on the desktop.
    00023 *
    00024 * Arguments:
    00025 *     lppt - The point to clip.
    00026 *
    00027 * History:
    00028 * 22-Sep-1996 adams     Created.
    00029 * 04-Sep-1998 MCostea   Use _MonitorFromPoint()
    00030 \***************************************************************************/
    00031
    00032 void
    00033 ClipPointToDesktop(LPPOINT lppt)
    00034 {
    00035     PMONITOR        pMonitor;
    00036
    00037     UserAssert(!gpDispInfo->fDesktopIsRect &&
    00038                "You shouldn't call this function if the desktop is a rectangle.\n"
    00039                "Just clip to gpsi->rcScreen instead.");
    00040
    00041     /*
    00042      * Optimization: The cursor is likely to be on the monitor it was last on,
    00043      * so check for that case.
    00044      */
    00045     if (gpMonitorMouse != NULL && PtInRect(&gpMonitorMouse->rcMonitor, *lppt)) {
    00046         return;
    00047     }
    00048
    00049     pMonitor = _MonitorFromPoint(*lppt, MONITOR_DEFAULTTONEAREST);
    00050
    00051     /*
    00052      * Remember the monitor the cursor is on.
    00053      */
    00054     gpMonitorMouse = pMonitor;
    00055
    00056     if (lppt->x < pMonitor->rcMonitor.left) {
    00057         lppt->x = pMonitor->rcMonitor.left;
    00058     } else if (lppt->x >= pMonitor->rcMonitor.right) {
    00059         lppt->x = pMonitor->rcMonitor.right-1;
    00060     }
    00061     if (lppt->y < pMonitor->rcMonitor.top) {
    00062         lppt->y = pMonitor->rcMonitor.top;
    00063     } else if (lppt->y >= pMonitor->rcMonitor.bottom) {
    00064         lppt->y = pMonitor->rcMonitor.bottom-1;
    00065     }
    00066 }
    00067
    00068 /***************************************************************************\
    00069 * xxxEnumDisplayMonitors
    00070 *
    00071 * Enumerates the monitors in a display.
    00072 *
    00073 * Arguments:
    00074 *     hdcPaint  - An HDC with a particular visible region. The HDC
    00075 *         passed to lpfnEnum will have the capabilities of that monitor,
    00076 *         with its visible region clipped to the monitor and hdcPaint.
    00077 *         If hdcPaint is NULL, the hdcMonitor passed to lpfnEnum will be NULL.
    00078 *
    00079 *     lprcClip  - A rectangle to clip the area to. If hdcPaint is non-NULL,
    00080 *         the coordinates have the origin of hdcPaint. If hdcPaint is NULL,
    00081 *         the coordinates are virtual screen coordinates. If lprcClip is NULL,
    00082 *         no clipping is performed.
    00083 *
    00084 *     lpfnEnum  - The enumeration function.
    00085 *
    00086 *     dwData    - Application-defined data that is passed through to the
    00087 *         enumeration function.
    00088 *
    00089 *     fInternal - TRUE if the callback is in the kernel, FALSE otherwise.
    00090 *
    00091 * BUGBUG: This function is only a skeleton for the real thing. It needs
    00092 * to handle different displays and possibly different bit depths.
    00093 *
    00094 * History:
    00095 * 22-Sep-1996 adams     Created.
    00096 \***************************************************************************/
    00097
    00098 BOOL
    00099 xxxEnumDisplayMonitors(
    00100     HDC             hdcPaint,
    00101     LPRECT          lprcPaint,
    00102     MONITORENUMPROC lpfnEnum,
    00103     LPARAM          lData,
    00104     BOOL            fInternal)
    00105 {
    00106     RECT            rcPaint;
    00107     POINT           ptOrg;
    00108     RECT            rcMonitorPaint;
    00109     BOOL            fReturn;
    00110     PMONITOR        pMonitor;
    00111     TL              tlpMonitor;
    00112     PTHREADINFO     ptiCurrent = PtiCurrent();
    00113     PDCE            pdcePaint;
    00114     HDC             hdcMonitor;
    00115     PWND            pwndOrg;
    00116
    00117     /*
    00118      * Validate the DC passed in.
    00119      */
    00120     if (hdcPaint) {
    00121
    00122         if ((pdcePaint = LookupDC(hdcPaint)) == NULL) {
    00123             RIPMSG0(RIP_WARNING, "EnumDisplayMonitors: LookupDC failed");
    00124             return FALSE;
    00125         }
    00126
    00127         pwndOrg = pdcePaint->pwndOrg;
    00128
    00129         /*
    00130          * Intersect the painting area with the clipbox.  If there
    00131          * isn't anything, bail out now.
    00132          */
    00133         if (GreGetClipBox(hdcPaint, &rcPaint, FALSE) == NULLREGION)
    00134             return TRUE;
    00135
    00136         if (lprcPaint && !IntersectRect(&rcPaint, &rcPaint, lprcPaint))
    00137             return TRUE;
    00138
    00139         /*
    00140          * rcPaint is in dc coordinates.  We must convert to screen
    00141          * coords so we can intersect with monitors.
    00142          */
    00143         GreGetDCOrg(hdcPaint, &ptOrg);
    00144         OffsetRect(&rcPaint, ptOrg.x, ptOrg.y);
    00145     } else {
    00146         CopyRect(&rcPaint, &gpDispInfo->rcScreen);
    00147         if (lprcPaint && !IntersectRect(&rcPaint, &rcPaint, lprcPaint))
    00148             return TRUE;
    00149     }
    00150
    00151     fReturn = TRUE;
    00152
    00153     for (pMonitor = gpDispInfo->pMonitorFirst; pMonitor != NULL;
    00154                 pMonitor = pMonitor->pMonitorNext) {
    00155
    00156         /*
    00157          * Note: the check for MONF_VISIBLE was removed to allow mirror drivers
    00158          * to see monitor specific updates.
    00159          */
    00160         if (!IntersectRect(&rcMonitorPaint, &rcPaint, &pMonitor->rcMonitor)) {
    00161             continue;
    00162         }
    00163
    00164         if (hdcPaint) {
    00165
    00166             if ((hdcMonitor = GetMonitorDC(pdcePaint, pMonitor)) == NULL) {
    00167                 RIPMSG0(RIP_WARNING, "EnumDisplayMonitors: GetMonitorDC failed");
    00168                 return FALSE;
    00169             }
    00170
    00171             OffsetRect(&rcMonitorPaint, -ptOrg.x, -ptOrg.y);
    00172             GreIntersectClipRect(
    00173                     hdcMonitor,
    00174                     rcMonitorPaint.left,
    00175                     rcMonitorPaint.top,
    00176                     rcMonitorPaint.right,
    00177                     rcMonitorPaint.bottom);
    00178         } else {
    00179
    00180             hdcMonitor = NULL;
    00181         }
    00182
    00183         ThreadLockAlwaysWithPti(ptiCurrent, pMonitor, &tlpMonitor);
    00184
    00185         if (fInternal) {
    00186             fReturn = (*lpfnEnum) (
    00187                     (HMONITOR) pMonitor,
    00188                     hdcMonitor,
    00189                     &rcMonitorPaint,
    00190                     lData);
    00191
    00192         } else {
    00193             fReturn = xxxClientMonitorEnumProc(
    00194                     PtoH(pMonitor),
    00195                     hdcMonitor,
    00196                     &rcMonitorPaint,
    00197                     lData,
    00198                     lpfnEnum);
    00199         }
    00200
    00201         /*
    00202          * We just called back and the monitor has been freed if
    00203          * ThreadUnlock returns NULL. The entire monitor configuration may
    00204          * have changed, the monitors may have been rearranged, so just stop
    00205          * enumerating at this point.
    00206          */
    00207         if (ThreadUnlock(&tlpMonitor) == NULL) {
    00208             fReturn = FALSE;
    00209         }
    00210
    00211         if (hdcMonitor)
    00212             ReleaseCacheDC(hdcMonitor, FALSE);
    00213
    00214         if (!fReturn)
    00215             break;
    00216
    00217         /*
    00218          * Revalidate hdcPaint, since it could have been messed with
    00219          * in the callback.
    00220          */
    00221         if (hdcPaint) {
    00222             if ((pdcePaint = LookupDC(hdcPaint)) == NULL) {
    00223                 RIPMSG0(RIP_WARNING, "EnumDisplayMonitors: LookupDC failed");
    00224                 return FALSE;
    00225             }
    00226
    00227             if (pdcePaint->pwndOrg != pwndOrg) {
    00228                 RIPMSG0(RIP_WARNING, "EnumDisplayMonitors: wrong window");
    00229                 return FALSE;
    00230             }
    00231         }
    00232     }
    00233
    00234     return fReturn;
    00235 }
    00236
    00237 /***************************************************************************\
    00238 * DestroyMonitor
    00239 *
    00240 * This function doesn't keep track of the visible monitors count because
    00241 * it assumes that after it was called the count will be recalculated, such
    00242 * as the case during mode changes. For a final unlock the monitor will have
    00243 * been removed from the monitor list already, so the count doesn't need to
    00244 * be recalculated.
    00245 *
    00246 * 5-May-1998    vadimg      created
    00247 \***************************************************************************/
    00248
    00249 void DestroyMonitor(PMONITOR pMonitor)
    00250 {
    00251     UserAssert(pMonitor);
    00252
    00253     /*
    00254      * Remove references to this monitor from the global data.
    00255      */
    00256     if (pMonitor == gpMonitorMouse) {
    00257         gpMonitorMouse = NULL;
    00258     }
    00259
    00260     /*
    00261      * Remove from the monitor list.
    00262      */
    00263     REMOVE_FROM_LIST(MONITOR, gpDispInfo->pMonitorFirst, pMonitor, pMonitorNext);
    00264
    00265     /*
    00266      * Make sure the primary monitor points to a valid monitor. During the
    00267      * mode changes the primary monitor will be recalculated as appropriate.
    00268      */
    00269     if (pMonitor == gpDispInfo->pMonitorPrimary) {
    00270         gpDispInfo->pMonitorPrimary = gpDispInfo->pMonitorFirst;
    00271     }
    00272
    00273     if (HMMarkObjectDestroy(pMonitor)) {
    00274
    00275         if (pMonitor->hrgnMonitor) {
    00276            GreDeleteObject(pMonitor->hrgnMonitor);
    00277         }
    00278
    00279         HMFreeObject(pMonitor);
    00280     }
    00281 }