Back to index

lightning-sunbird  0.9+nobinonly
nsPointerService.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Christopher Blizzard.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include <gdk/gdk.h>
00038 #include <gdk/gdkx.h>
00039 
00040 #include "nsPointerService.h"
00041 #include "nsWindow.h"
00042 
00043 NS_IMPL_ADDREF_INHERITED(nsPointerService, nsBasePointerService)
00044 NS_IMPL_RELEASE_INHERITED(nsPointerService, nsBasePointerService)
00045 NS_IMPL_QUERY_INTERFACE_INHERITED0(nsPointerService, nsBasePointerService)
00046 
00047 
00048 NS_IMETHODIMP
00049 nsPointerService::WidgetUnderPointer(nsIWidget **_retval,
00050                                  PRUint32 *aXOffset, PRUint32 *aYOffset)
00051 {
00052   *_retval = nsnull;
00053   *aXOffset = 0;
00054   *aYOffset = 0;
00055 
00056   Bool retval;
00057   Window root_return;
00058   Window child_return = None;
00059   int root_x_return, root_y_return;
00060   int win_x_return, win_y_return;
00061   unsigned int mask_return;
00062 
00063   // Flush the queue to get any pending destroys out the door.  If we
00064   // don't then we can end up with a sitution where the XQueryPointer
00065   // flushes the queue and then the XTranslateCoordinates will cause
00066   // an X error since the window doesn't exist anymore.  God,
00067   // sometimes I just hate X.
00068   XSync(GDK_DISPLAY(), False);
00069 
00070   // Query the pointer
00071   retval = XQueryPointer(GDK_DISPLAY(),
00072                       GDK_WINDOW_XWINDOW(GDK_ROOT_PARENT()),
00073                       &root_return, &child_return,
00074                       &root_x_return, &root_y_return,
00075                       &win_x_return, &win_y_return,
00076                       &mask_return);
00077 
00078   // the pointer is on a different window
00079   if (!retval || child_return == None)
00080     return NS_OK;
00081 
00082   int done = 0;
00083   Window dest_w = child_return;
00084   int    xlate_x_return;
00085   int    xlate_y_return;
00086 
00087   // loop to find the inner most window
00088   while (!done) {
00089     Window xlate_return = None;
00090     retval = XTranslateCoordinates(GDK_DISPLAY(),
00091                                GDK_WINDOW_XWINDOW(GDK_ROOT_PARENT()),
00092                                dest_w,
00093                                win_x_return, win_y_return,
00094                                &xlate_x_return, &xlate_y_return,
00095                                &xlate_return);
00096     
00097     // the pointer is on a different screen
00098     if (!retval)
00099       return NS_OK;
00100 
00101     // if xlate_return was None then we've reached the inner most window
00102     if (xlate_return == None)
00103       done = 1;
00104     // otherwise set our new destination window to the return from the
00105     // translation
00106     else
00107       dest_w = xlate_return;
00108   }
00109 
00110   GdkWindow *window;
00111   nsWindow  *widget;
00112 
00113   // get the gdk window under the pointer
00114   window = gdk_window_lookup(dest_w);
00115   // it's not a gdk window
00116   if (!window)
00117     return NS_OK;
00118   
00119   // is that an nsWindow window?
00120   gpointer data = NULL;
00121   gdk_window_get_user_data(window, &data);
00122   // nope
00123   if (!data)
00124     return NS_OK;
00125 
00126   // downcast
00127   widget = (nsWindow *)gtk_object_get_data(GTK_OBJECT(data), "nsWindow");
00128   if (!widget)
00129     return NS_OK;
00130 
00131   *_retval = NS_STATIC_CAST(nsIWidget *, widget);
00132   *aXOffset = xlate_x_return;
00133   *aYOffset = xlate_y_return;
00134 
00135   NS_ADDREF(*_retval);
00136 
00137   return NS_OK;
00138 }