Back to index

lightning-sunbird  0.9+nobinonly
nsCairoScreen.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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  * mozilla.org.
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Stuart Parmenter <pavlov@pavlov.net>
00024  *   Joe Hewitt <hewitt@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsCairoScreen.h"
00041 
00042 #ifdef MOZ_ENABLE_GTK2
00043 #include <gdk/gdk.h>
00044 #include <gdk/gdkx.h>
00045 #include <gtk/gtk.h>
00046 #include <X11/Xatom.h>
00047 #endif
00048 
00049 NS_IMPL_ISUPPORTS1(nsCairoScreen, nsIScreen)
00050 
00051 nsCairoScreen::nsCairoScreen()
00052   :
00053     mScreenNum(0), mRect(0, 0, 0, 0), mAvailRect(0, 0, 0, 0)
00054 
00055 {
00056     NS_INIT_ISUPPORTS();
00057 }
00058 
00059 
00060 nsCairoScreen::~nsCairoScreen()
00061 {
00062 }
00063 
00064 NS_IMETHODIMP
00065 nsCairoScreen::GetRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth, PRInt32 *outHeight)
00066 {
00067     *outLeft = mRect.x;
00068     *outTop = mRect.y;
00069     *outWidth = mRect.width;
00070     *outHeight = mRect.height;
00071 
00072     return NS_OK;
00073 }
00074 
00075 
00076 NS_IMETHODIMP
00077 nsCairoScreen::GetAvailRect(PRInt32 *outLeft, PRInt32 *outTop, PRInt32 *outWidth, PRInt32 *outHeight)
00078 {
00079     *outLeft = mAvailRect.x;
00080     *outTop = mAvailRect.y;
00081     *outWidth = mAvailRect.width;
00082     *outHeight = mAvailRect.height;
00083 
00084     return NS_OK;
00085 } 
00086 
00087 NS_IMETHODIMP 
00088 nsCairoScreen::GetPixelDepth(PRInt32 *aPixelDepth)
00089 {
00090     *aPixelDepth = 24;
00091     return NS_OK;
00092 }
00093 
00094 NS_IMETHODIMP 
00095 nsCairoScreen::GetColorDepth(PRInt32 *aColorDepth)
00096 {
00097     return 24;
00098 }
00099 
00100 
00101 void
00102 nsCairoScreen::Init ()
00103 {
00104 #ifdef MOZ_ENABLE_GTK2
00105     mAvailRect = mRect = nsRect(0, 0, gdk_screen_width(), gdk_screen_height());
00106     // We need to account for the taskbar, etc in the available rect.
00107     // See http://freedesktop.org/Standards/wm-spec/index.html#id2767771
00108 
00109     // XXX It doesn't change that often, but we should probably
00110     // listen for changes to _NET_WORKAREA.
00111     // XXX do we care about _NET_WM_STRUT_PARTIAL?  That will
00112     // add much more complexity to the code here (our screen
00113     // could have a non-rectangular shape), but should
00114     // lead to greater accuracy.
00115 
00116 #if GTK_CHECK_VERSION(2,2,0)
00117     GdkWindow *root_window = gdk_get_default_root_window();
00118 #else
00119     GdkWindow *root_window = GDK_ROOT_PARENT();
00120 #endif // GTK_CHECK_VERSION(2,2,0)
00121 
00122     long *workareas;
00123     GdkAtom type_returned;
00124     int format_returned;
00125     int length_returned;
00126 
00127 #if GTK_CHECK_VERSION(2,0,0)
00128     GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
00129 #else
00130     GdkAtom cardinal_atom = (GdkAtom) XA_CARDINAL;
00131 #endif
00132 
00133     gdk_error_trap_push();
00134 
00135     // gdk_property_get uses (length + 3) / 4, hence G_MAXLONG - 3 here.
00136     if (!gdk_property_get(root_window,
00137                           gdk_atom_intern ("_NET_WORKAREA", FALSE),
00138                           cardinal_atom,
00139                           0, G_MAXLONG - 3, FALSE,
00140                           &type_returned,
00141                           &format_returned,
00142                           &length_returned,
00143                           (guchar **) &workareas)) {
00144         // This window manager doesn't support the freedesktop standard.
00145         // Nothing we can do about it, so assume full screen size.
00146         return;
00147     }
00148 
00149     // Flush the X queue to catch errors now.
00150     gdk_flush();
00151 
00152     if (!gdk_error_trap_pop() &&
00153         type_returned == cardinal_atom &&
00154         length_returned && (length_returned % 4) == 0 &&
00155         format_returned == 32) {
00156         int num_items = length_returned / sizeof(long);
00157 
00158         for (int i = 0; i < num_items; i += 4) {
00159             nsRect workarea(workareas[i],     workareas[i + 1],
00160                             workareas[i + 2], workareas[i + 3]);
00161             if (!mRect.Contains(workarea)) {
00162                 NS_WARNING("Invalid bounds");
00163                 continue;
00164             }
00165 
00166             mAvailRect.IntersectRect(mAvailRect, workarea);
00167         }
00168     }
00169 
00170 #elif MOZ_ENABLE_XLIB
00171     mScreenNum = 0;
00172     mRect.x = mAvailRect.x = 0;
00173     mRect.y = mAvailRect.y = 0;
00174     mRect.width = mAvailRect.width = 1600;
00175     mRect.height = mAvailRect.height = 1200;
00176 #endif
00177 }