Back to index

lightning-sunbird  0.9+nobinonly
nsScreenManagerGtk.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 "nsScreenManagerGtk.h"
00039 #include "nsScreenGtk.h"
00040 #include "nsIComponentManager.h"
00041 #include "nsRect.h"
00042 #include "nsAutoPtr.h"
00043 
00044 #include <gdk/gdkx.h>
00045 
00046 #ifdef MOZ_ENABLE_XINERAMA
00047 // this header rocks!
00048 extern "C"
00049 {
00050 #include <X11/extensions/Xinerama.h>
00051 }
00052 #endif /* MOZ_ENABLE_XINERAMA */
00053 
00054 nsScreenManagerGtk :: nsScreenManagerGtk ( )
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   mNumScreens = 0;
00060 }
00061 
00062 
00063 nsScreenManagerGtk :: ~nsScreenManagerGtk()
00064 {
00065   // nothing to see here.
00066 }
00067 
00068 
00069 // addref, release, QI
00070 NS_IMPL_ISUPPORTS1(nsScreenManagerGtk, nsIScreenManager)
00071 
00072 
00073 // this function will make sure that everything has been initialized.
00074 nsresult
00075 nsScreenManagerGtk :: EnsureInit(void)
00076 {
00077   if (!mCachedScreenArray) {
00078     mCachedScreenArray = do_CreateInstance("@mozilla.org/supports-array;1");
00079     if (!mCachedScreenArray) {
00080       return NS_ERROR_OUT_OF_MEMORY;
00081     }
00082 #ifdef MOZ_ENABLE_XINERAMA
00083     // get the number of screens via xinerama
00084     XineramaScreenInfo *screenInfo;
00085     if (XineramaIsActive(GDK_DISPLAY())) {
00086       screenInfo = XineramaQueryScreens(GDK_DISPLAY(), &mNumScreens);
00087     }
00088     else {
00089       screenInfo = NULL;
00090       mNumScreens = 1;
00091     }
00092 #else
00093     mNumScreens = 1;
00094 #endif
00095     // there will be < 2 screens if we are either not building with
00096     // xinerama support or xinerama isn't running on the current
00097     // display.
00098     if (mNumScreens < 2) {
00099       mNumScreens = 1;
00100       nsRefPtr<nsScreenGtk> screen = new nsScreenGtk();
00101       if (!screen)
00102         return NS_ERROR_OUT_OF_MEMORY;
00103 
00104       screen->Init();
00105 
00106       nsISupports *supportsScreen = screen;
00107       mCachedScreenArray->AppendElement(supportsScreen);
00108     }
00109     // If Xinerama is enabled and there's more than one screen, fill
00110     // in the info for all of the screens.  If that's not the case
00111     // then nsScreenGTK() defaults to the screen width + height
00112 #ifdef MOZ_ENABLE_XINERAMA
00113     else {
00114 #ifdef DEBUG
00115       printf("Xinerama superpowers activated for %d screens!\n", mNumScreens);
00116 #endif
00117       int i;
00118       for (i=0; i < mNumScreens; i++) {
00119         nsRefPtr<nsScreenGtk> screen = new nsScreenGtk();
00120         if (!screen) {
00121           return NS_ERROR_OUT_OF_MEMORY;
00122         }
00123 
00124         // initialize this screen object
00125         screen->Init(&screenInfo[i]);
00126 
00127         nsISupports *screenSupports = screen;
00128         mCachedScreenArray->AppendElement(screenSupports);
00129       }
00130     }
00131 #endif /* MOZ_ENABLE_XINERAMA */
00132   }
00133 
00134   return NS_OK;;
00135 }
00136 
00137 
00138 //
00139 // ScreenForRect 
00140 //
00141 // Returns the screen that contains the rectangle. If the rect overlaps
00142 // multiple screens, it picks the screen with the greatest area of intersection.
00143 //
00144 // The coordinates are in pixels (not twips) and in screen coordinates.
00145 //
00146 NS_IMETHODIMP
00147 nsScreenManagerGtk :: ScreenForRect ( PRInt32 aX, PRInt32 aY,
00148                                       PRInt32 aWidth, PRInt32 aHeight,
00149                                       nsIScreen **aOutScreen )
00150 {
00151   nsresult rv;
00152   rv = EnsureInit();
00153   if (NS_FAILED(rv)) {
00154     NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForRect\n");
00155     return rv;
00156   }
00157   // which screen ( index from zero ) should we return?
00158   PRUint32 which = 0;
00159   // Optimize for the common case.  If the number of screens is only
00160   // one then this will fall through with which == 0 and will get the
00161   // primary screen.
00162   if (mNumScreens > 1) {
00163     // walk the list of screens and find the one that has the most
00164     // surface area.
00165     PRUint32 count;
00166     mCachedScreenArray->Count(&count);
00167     PRUint32 i;
00168     PRUint32 area = 0;
00169     nsRect   windowRect(aX, aY, aWidth, aHeight);
00170     for (i=0; i < count; i++) {
00171       PRInt32  x, y, width, height;
00172       x = y = width = height = 0;
00173       nsCOMPtr<nsIScreen> screen;
00174       mCachedScreenArray->GetElementAt(i, getter_AddRefs(screen));
00175       screen->GetRect(&x, &y, &width, &height);
00176       // calculate the surface area
00177       nsRect screenRect(x, y, width, height);
00178       screenRect.IntersectRect(screenRect, windowRect);
00179       PRUint32 tempArea = screenRect.width * screenRect.height;
00180       if (tempArea >= area) {
00181         which = i;
00182         area = tempArea;
00183       }
00184     }
00185   }
00186   nsCOMPtr<nsIScreen> outScreen;
00187   mCachedScreenArray->GetElementAt(which, getter_AddRefs(outScreen));
00188   *aOutScreen = outScreen.get();
00189   NS_IF_ADDREF(*aOutScreen);
00190   return NS_OK;
00191     
00192 } // ScreenForRect
00193 
00194 
00195 //
00196 // GetPrimaryScreen
00197 //
00198 // The screen with the menubar/taskbar. This shouldn't be needed very
00199 // often.
00200 //
00201 NS_IMETHODIMP 
00202 nsScreenManagerGtk :: GetPrimaryScreen(nsIScreen * *aPrimaryScreen) 
00203 {
00204   nsresult rv;
00205   rv =  EnsureInit();
00206   if (NS_FAILED(rv)) {
00207     NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from GetPrimaryScreen\n");
00208     return rv;
00209   }
00210   nsCOMPtr <nsIScreen> screen;
00211   mCachedScreenArray->GetElementAt(0, getter_AddRefs(screen));
00212   *aPrimaryScreen = screen.get();
00213   NS_IF_ADDREF(*aPrimaryScreen);
00214   return NS_OK;
00215   
00216 } // GetPrimaryScreen
00217 
00218 
00219 //
00220 // GetNumberOfScreens
00221 //
00222 // Returns how many physical screens are available.
00223 //
00224 NS_IMETHODIMP
00225 nsScreenManagerGtk :: GetNumberOfScreens(PRUint32 *aNumberOfScreens)
00226 {
00227   nsresult rv;
00228   rv = EnsureInit();
00229   if (NS_FAILED(rv)) {
00230     NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from GetNumberOfScreens\n");
00231     return rv;
00232   }
00233   *aNumberOfScreens = mNumScreens;
00234   return NS_OK;
00235   
00236 } // GetNumberOfScreens
00237