Back to index

lightning-sunbird  0.9+nobinonly
nsScreenManagerMac.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 #include "nsScreenManagerMac.h"
00039 #include "nsScreenMac.h"
00040 #include "nsCOMPtr.h"
00041 
00042 
00043 class ScreenListItem
00044 {
00045 public:
00046   ScreenListItem ( GDHandle inGD, nsIScreen* inScreen )
00047     : mGD(inGD), mScreen(inScreen) { } ;
00048   
00049   GDHandle mGD;
00050   nsCOMPtr<nsIScreen> mScreen;
00051 };
00052 
00053 
00054 nsScreenManagerMac :: nsScreenManagerMac ( )
00055 {
00056   // nothing else to do. I guess we could cache a bunch of information
00057   // here, but we want to ask the device at runtime in case anything
00058   // has changed.
00059 }
00060 
00061 
00062 nsScreenManagerMac :: ~nsScreenManagerMac()
00063 {
00064   // walk our list of cached screens and delete them.
00065   for ( int i = 0; i < mScreenList.Count(); ++i ) {
00066     ScreenListItem* item = NS_REINTERPRET_CAST(ScreenListItem*, mScreenList[i]);
00067     delete item;
00068   }
00069 }
00070 
00071 
00072 // addref, release, QI
00073 NS_IMPL_ISUPPORTS1(nsScreenManagerMac, nsIScreenManager)
00074 
00075 
00076 //
00077 // CreateNewScreenObject
00078 //
00079 // Utility routine. Creates a new screen object from the given device handle
00080 //
00081 nsIScreen* 
00082 nsScreenManagerMac :: CreateNewScreenObject ( GDHandle inDevice )
00083 {
00084   nsIScreen* retScreen = nsnull;
00085   
00086   // look through our screen list, hoping to find it. If it's not there,
00087   // add it and return the new one.
00088   for ( int i = 0; i < mScreenList.Count(); ++i ) {
00089     ScreenListItem* curr = NS_REINTERPRET_CAST(ScreenListItem*, mScreenList[i]);
00090     if ( inDevice == curr->mGD ) {
00091       NS_IF_ADDREF(retScreen = curr->mScreen.get());
00092       return retScreen;
00093     }
00094   } // for each screen.
00095   
00096   // didn't find it in the list, so add it and return that item.
00097   retScreen = new nsScreenMac ( inDevice );
00098   ScreenListItem* listItem = new ScreenListItem ( inDevice, retScreen );
00099   mScreenList.AppendElement ( listItem );
00100   
00101   NS_IF_ADDREF(retScreen);
00102   return retScreen;
00103 }
00104 
00105 
00106 //
00107 // ScreenForRect 
00108 //
00109 // Returns the screen that contains the rectangle. If the rect overlaps
00110 // multiple screens, it picks the screen with the greatest area of intersection.
00111 //
00112 // The coordinates are in pixels (not twips) and in screen coordinates.
00113 //
00114 NS_IMETHODIMP
00115 nsScreenManagerMac :: ScreenForRect ( PRInt32 inLeft, PRInt32 inTop, PRInt32 inWidth, PRInt32 inHeight,
00116                                         nsIScreen **outScreen )
00117 {
00118   if ( !(inWidth || inHeight) ) {
00119     NS_WARNING ( "trying to find screen for sizeless window, using primary monitor" );
00120     *outScreen = CreateNewScreenObject ( ::GetMainDevice() );    // addrefs
00121     return NS_OK;
00122   }
00123 
00124   Rect globalWindowBounds = { inTop, inLeft, inTop + inHeight, inLeft + inWidth };
00125 
00126   GDHandle currDevice = ::GetDeviceList();
00127   GDHandle deviceWindowIsOn = ::GetMainDevice();
00128   PRInt32 greatestArea = 0;
00129   while ( currDevice ) {
00130     if ( ::TestDeviceAttribute(currDevice, screenDevice) && ::TestDeviceAttribute(currDevice, screenActive) ) {
00131       // calc the intersection.
00132       Rect intersection;
00133       Rect devRect = (**currDevice).gdRect;
00134       ::SectRect ( &globalWindowBounds, &devRect, &intersection );
00135       PRInt32 intersectArea = (intersection.right - intersection.left) * 
00136                                   (intersection.bottom - intersection.top);
00137       if ( intersectArea > greatestArea ) {
00138         greatestArea = intersectArea;
00139         deviceWindowIsOn = currDevice;
00140      }      
00141     } // if device is a screen and visible
00142     currDevice = ::GetNextDevice(currDevice);
00143   } // foreach device in list
00144 
00145   *outScreen = CreateNewScreenObject ( deviceWindowIsOn );    // addrefs
00146   return NS_OK;
00147     
00148 } // ScreenForRect
00149 
00150 
00151 //
00152 // GetPrimaryScreen
00153 //
00154 // The screen with the menubar/taskbar. This shouldn't be needed very
00155 // often.
00156 //
00157 NS_IMETHODIMP 
00158 nsScreenManagerMac :: GetPrimaryScreen(nsIScreen * *aPrimaryScreen) 
00159 {
00160   *aPrimaryScreen = CreateNewScreenObject ( ::GetMainDevice() );    // addrefs  
00161   return NS_OK;
00162   
00163 } // GetPrimaryScreen
00164 
00165 
00166 //
00167 // GetNumberOfScreens
00168 //
00169 // Returns how many physical screens are available.
00170 //
00171 NS_IMETHODIMP
00172 nsScreenManagerMac :: GetNumberOfScreens(PRUint32 *aNumberOfScreens)
00173 {
00174   *aNumberOfScreens = 0;
00175   GDHandle currDevice = ::GetDeviceList();
00176   while ( currDevice ) {
00177     if ( ::TestDeviceAttribute(currDevice, screenDevice) && ::TestDeviceAttribute(currDevice, screenActive) )
00178       ++(*aNumberOfScreens);
00179     currDevice = ::GetNextDevice(currDevice);
00180   }
00181   return NS_OK;
00182   
00183 } // GetNumberOfScreens
00184