Back to index

lightning-sunbird  0.9+nobinonly
nsScreenManagerWin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 //
00039 // We have to do this in order to have access to the multiple-monitor
00040 // APIs that are only defined when WINVER is >= 0x0500. Don't worry,
00041 // these won't actually be called unless they are present.
00042 //
00043 #undef WINVER
00044 #define WINVER 0x0500
00045 #undef _WIN32_WINNT
00046 #define _WIN32_WINNT 0x0500
00047 
00048 #include "nsScreenManagerWin.h"
00049 #include "nsScreenWin.h"
00050 
00051 // needed because there are unicode/ansi versions of this routine
00052 // and we need to make sure we get the correct one.
00053 #ifdef UNICODE
00054 #define GetMonitorInfoQuoted "GetMonitorInfoW"
00055 #else
00056 #define GetMonitorInfoQuoted "GetMonitorInfoA"
00057 #endif
00058 
00059 
00060 #if defined(__MINGW32__) || _MSC_VER >= 1200
00061 typedef HMONITOR (WINAPI *MonitorFromRectProc)(LPCRECT inRect, DWORD inFlag); 
00062 typedef BOOL (WINAPI *EnumDisplayMonitorsProc)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
00063 
00064 BOOL CALLBACK CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioCount ) ;
00065 #else
00066 typedef void* HMONITOR;
00067 #endif
00068 
00069 
00070 class ScreenListItem
00071 {
00072 public:
00073   ScreenListItem ( HMONITOR inMon, nsIScreen* inScreen )
00074     : mMon(inMon), mScreen(inScreen) { } ;
00075   
00076   HMONITOR mMon;
00077   nsCOMPtr<nsIScreen> mScreen;
00078 };
00079 
00080 
00081 nsScreenManagerWin :: nsScreenManagerWin ( )
00082   : mHasMultiMonitorAPIs(PR_FALSE), mNumberOfScreens(0),
00083     mGetMonitorInfoProc(nsnull), mMonitorFromRectProc(nsnull),
00084     mEnumDisplayMonitorsProc(nsnull)
00085 {
00086   // figure out if we can call the multiple monitor APIs that are only
00087   // available on Win98/2000.
00088   HMODULE lib = GetModuleHandle("user32.dll");
00089   if ( lib ) {
00090     mGetMonitorInfoProc = GetProcAddress ( lib, GetMonitorInfoQuoted );
00091     mMonitorFromRectProc = GetProcAddress ( lib, "MonitorFromRect" );
00092     mEnumDisplayMonitorsProc = GetProcAddress ( lib, "EnumDisplayMonitors" );
00093     if ( mGetMonitorInfoProc && mMonitorFromRectProc && mEnumDisplayMonitorsProc )
00094       mHasMultiMonitorAPIs = PR_TRUE;
00095   }
00096 
00097   // nothing else to do. I guess we could cache a bunch of information
00098   // here, but we want to ask the device at runtime in case anything
00099   // has changed.
00100 }
00101 
00102 
00103 nsScreenManagerWin :: ~nsScreenManagerWin()
00104 {
00105   // walk our list of cached screens and delete them.
00106   for ( int i = 0; i < mScreenList.Count(); ++i ) {
00107     ScreenListItem* item = NS_REINTERPRET_CAST(ScreenListItem*, mScreenList[i]);
00108     delete item;
00109   }
00110 }
00111 
00112 
00113 // addref, release, QI
00114 NS_IMPL_ISUPPORTS1(nsScreenManagerWin, nsIScreenManager)
00115 
00116 
00117 //
00118 // CreateNewScreenObject
00119 //
00120 // Utility routine. Creates a new screen object from the given device handle
00121 //
00122 // NOTE: For this "single-monitor" impl, we just always return the cached primary
00123 //        screen. This should change when a multi-monitor impl is done.
00124 //
00125 nsIScreen* 
00126 nsScreenManagerWin :: CreateNewScreenObject ( void* inScreen )
00127 {
00128   nsIScreen* retScreen = nsnull;
00129   
00130   // look through our screen list, hoping to find it. If it's not there,
00131   // add it and return the new one.
00132   for ( int i = 0; i < mScreenList.Count(); ++i ) {
00133     ScreenListItem* curr = NS_REINTERPRET_CAST(ScreenListItem*, mScreenList[i]);
00134     if ( inScreen == curr->mMon ) {
00135       NS_IF_ADDREF(retScreen = curr->mScreen.get());
00136       return retScreen;
00137     }
00138   } // for each screen.
00139  
00140   retScreen = new nsScreenWin(inScreen);
00141   ScreenListItem* listItem = new ScreenListItem ( (HMONITOR)inScreen, retScreen );
00142   mScreenList.AppendElement ( listItem );
00143 
00144   NS_IF_ADDREF(retScreen);
00145   return retScreen;
00146 }
00147 
00148 
00149 //
00150 // ScreenForRect 
00151 //
00152 // Returns the screen that contains the rectangle. If the rect overlaps
00153 // multiple screens, it picks the screen with the greatest area of intersection.
00154 //
00155 // The coordinates are in pixels (not twips) and in screen coordinates.
00156 //
00157 NS_IMETHODIMP
00158 nsScreenManagerWin :: ScreenForRect ( PRInt32 inLeft, PRInt32 inTop, PRInt32 inWidth, PRInt32 inHeight,
00159                                         nsIScreen **outScreen )
00160 {
00161   if ( !(inWidth || inHeight) ) {
00162     NS_WARNING ( "trying to find screen for sizeless window, using primary monitor" );
00163     *outScreen = CreateNewScreenObject ( nsnull );    // addrefs
00164     return NS_OK;
00165   }
00166 
00167   RECT globalWindowBounds = { inLeft, inTop, inLeft + inWidth, inTop + inHeight };
00168 
00169   void* genScreen = nsnull;
00170 #if defined(__MINGW32__) || _MSC_VER >= 1200
00171   if ( mHasMultiMonitorAPIs ) {
00172     MonitorFromRectProc proc = (MonitorFromRectProc)mMonitorFromRectProc;
00173     HMONITOR screen = (*proc)( &globalWindowBounds, MONITOR_DEFAULTTOPRIMARY );
00174     genScreen = screen;
00175 
00176     //XXX find the DC for this screen??
00177   }
00178 #endif
00179 
00180   *outScreen = CreateNewScreenObject ( genScreen );    // addrefs
00181   
00182   return NS_OK;
00183     
00184 } // ScreenForRect
00185 
00186 
00187 //
00188 // GetPrimaryScreen
00189 //
00190 // The screen with the menubar/taskbar. This shouldn't be needed very
00191 // often.
00192 //
00193 NS_IMETHODIMP 
00194 nsScreenManagerWin :: GetPrimaryScreen(nsIScreen** aPrimaryScreen) 
00195 {
00196   *aPrimaryScreen = CreateNewScreenObject ( nsnull );    // addrefs  
00197   return NS_OK;
00198   
00199 } // GetPrimaryScreen
00200 
00201 
00202 #if defined(__MINGW32__) || _MSC_VER >= 1200
00203 //
00204 // CountMonitors
00205 //
00206 // Will be called once for every monitor in the system. Just 
00207 // increments the parameter, which holds a ptr to a PRUin32 holding the
00208 // count up to this point.
00209 //
00210 BOOL CALLBACK
00211 CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioParam )
00212 {
00213   PRUint32* countPtr = NS_REINTERPRET_CAST(PRUint32*, ioParam);
00214   ++(*countPtr);
00215 
00216   return TRUE; // continue the enumeration
00217 
00218 } // CountMonitors
00219 #endif
00220 
00221 
00222 //
00223 // GetNumberOfScreens
00224 //
00225 // Returns how many physical screens are available.
00226 //
00227 NS_IMETHODIMP
00228 nsScreenManagerWin :: GetNumberOfScreens(PRUint32 *aNumberOfScreens)
00229 {
00230   if ( mNumberOfScreens )
00231     *aNumberOfScreens = mNumberOfScreens;
00232 #if defined(__MINGW32__) || _MSC_VER >= 1200
00233   else if ( mHasMultiMonitorAPIs ) {
00234       PRUint32 count = 0;
00235       EnumDisplayMonitorsProc proc = (EnumDisplayMonitorsProc)mEnumDisplayMonitorsProc;
00236       BOOL result = (*proc)(nsnull, nsnull, (MONITORENUMPROC)CountMonitors, (LPARAM)&count);
00237       if (!result)
00238         return NS_ERROR_FAILURE;
00239       *aNumberOfScreens = mNumberOfScreens = count;      
00240   } // if there can be > 1 screen
00241 #endif
00242   else
00243     *aNumberOfScreens = mNumberOfScreens = 1;
00244 
00245   return NS_OK;
00246   
00247 } // GetNumberOfScreens