Back to index

lightning-sunbird  0.9+nobinonly
nsDOMMouseEvent.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) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Steve Clark (buster@netscape.com)
00024  *   Ilya Konstantinov (mozilla-code@future.shiny.co.il)
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 "nsDOMMouseEvent.h"
00041 #include "nsGUIEvent.h"
00042 #include "nsIContent.h"
00043 #include "nsIEventStateManager.h"
00044 #include "nsContentUtils.h"
00045 
00046 nsDOMMouseEvent::nsDOMMouseEvent(nsPresContext* aPresContext,
00047                                  nsInputEvent* aEvent)
00048   : nsDOMUIEvent(aPresContext, aEvent ? aEvent :
00049                  new nsMouseEvent(PR_FALSE, 0, nsnull,
00050                                   nsMouseEvent::eReal)),
00051     mButton(-1)
00052 {
00053   // There's no way to make this class' ctor allocate an nsMouseScrollEvent.
00054   // It's not that important, though, since a scroll event is not a real
00055   // DOM event.
00056   
00057   if (aEvent) {
00058     mEventIsInternal = PR_FALSE;
00059   }
00060   else {
00061     mEventIsInternal = PR_TRUE;
00062     mEvent->time = PR_Now();
00063     mEvent->refPoint.x = mEvent->refPoint.y = mEvent->point.x = mEvent->point.y = 0;
00064   }
00065 
00066   switch (mEvent->eventStructType)
00067   {
00068     case NS_MOUSE_EVENT:
00069       mDetail = NS_STATIC_CAST(nsMouseEvent*, mEvent)->clickCount;
00070       break;
00071     case NS_MOUSE_SCROLL_EVENT:
00072       mDetail = NS_STATIC_CAST(nsMouseScrollEvent*, mEvent)->delta;
00073       break;
00074     default:
00075       break;
00076   }
00077 }
00078 
00079 NS_IMPL_ADDREF_INHERITED(nsDOMMouseEvent, nsDOMUIEvent)
00080 NS_IMPL_RELEASE_INHERITED(nsDOMMouseEvent, nsDOMUIEvent)
00081 
00082 NS_INTERFACE_MAP_BEGIN(nsDOMMouseEvent)
00083   NS_INTERFACE_MAP_ENTRY(nsIDOMMouseEvent)
00084   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(MouseEvent)
00085 NS_INTERFACE_MAP_END_INHERITING(nsDOMUIEvent)
00086 
00087 NS_IMETHODIMP
00088 nsDOMMouseEvent::InitMouseEvent(const nsAString & aType, PRBool aCanBubble, PRBool aCancelable,
00089                                 nsIDOMAbstractView *aView, PRInt32 aDetail, PRInt32 aScreenX, 
00090                                 PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY, 
00091                                 PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey, 
00092                                 PRBool aMetaKey, PRUint16 aButton, nsIDOMEventTarget *aRelatedTarget)
00093 {
00094   nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
00095   NS_ENSURE_SUCCESS(rv, rv);
00096   
00097   switch(mEvent->eventStructType)
00098   {
00099     case NS_MOUSE_EVENT:
00100     case NS_MOUSE_SCROLL_EVENT:
00101     {
00102        nsInputEvent* inputEvent = NS_STATIC_CAST(nsInputEvent*, mEvent);
00103        inputEvent->isControl = aCtrlKey;
00104        inputEvent->isAlt = aAltKey;
00105        inputEvent->isShift = aShiftKey;
00106        inputEvent->isMeta = aMetaKey;
00107        inputEvent->point.x = aClientX;
00108        inputEvent->point.y = aClientY;
00109        inputEvent->refPoint.x = aScreenX;
00110        inputEvent->refPoint.y = aScreenY;
00111        mButton = aButton;
00112        // Now fix up mEvent->message, since nsDOMUIEvent::InitUIEvent
00113        // doesn't have enough information to set it right.
00114        // XXXbz AARGH.  No useful constants for the buttons!
00115        if (mEvent->message == NS_MOUSE_LEFT_CLICK) {
00116          if (mButton == 1) {  // Middle button
00117            mEvent->message = NS_MOUSE_MIDDLE_CLICK;
00118          }
00119          else if (mButton == 2) {  // Right button
00120            mEvent->message = NS_MOUSE_RIGHT_CLICK;
00121          }
00122        }
00123        if (mEvent->message == NS_MOUSE_LEFT_DOUBLECLICK) {
00124          if (mButton == 1) {  // Middle button
00125            mEvent->message = NS_MOUSE_MIDDLE_DOUBLECLICK;
00126          }
00127          else if (mButton == 2) {  // Right button
00128            mEvent->message = NS_MOUSE_RIGHT_DOUBLECLICK;
00129          }
00130        }
00131        if (mEvent->eventStructType == NS_MOUSE_SCROLL_EVENT) {
00132          nsMouseScrollEvent* scrollEvent = NS_STATIC_CAST(nsMouseScrollEvent*, mEvent);
00133          scrollEvent->delta = aDetail;
00134        } else {
00135          nsMouseEvent* mouseEvent = NS_STATIC_CAST(nsMouseEvent*, mEvent);
00136          mouseEvent->clickCount = aDetail;
00137        }
00138        break;
00139     }
00140     default:
00141        break;
00142   }
00143 
00144   return NS_OK;
00145 }   
00146 
00147 NS_IMETHODIMP
00148 nsDOMMouseEvent::GetButton(PRUint16* aButton)
00149 {
00150   NS_ENSURE_ARG_POINTER(aButton);
00151   if (!mEvent || mEvent->eventStructType != NS_MOUSE_EVENT) {
00152     NS_WARNING("Tried to get mouse button for null or non-mouse event!");
00153     *aButton = (PRUint16)-1;
00154     return NS_OK;
00155   }
00156 
00157   // If button has been set then use that instead.
00158   if (mButton >= 0) {
00159     *aButton = (PRUint16)mButton;
00160   }
00161   else {
00162     switch (mEvent->message) {
00163     case NS_MOUSE_LEFT_BUTTON_UP:
00164     case NS_MOUSE_LEFT_BUTTON_DOWN:
00165     case NS_MOUSE_LEFT_CLICK:
00166     case NS_MOUSE_LEFT_DOUBLECLICK:
00167       *aButton = 0;
00168       break;
00169     case NS_MOUSE_MIDDLE_BUTTON_UP:
00170     case NS_MOUSE_MIDDLE_BUTTON_DOWN:
00171     case NS_MOUSE_MIDDLE_CLICK:
00172     case NS_MOUSE_MIDDLE_DOUBLECLICK:
00173       *aButton = 1;
00174       break;
00175     case NS_MOUSE_RIGHT_BUTTON_UP:
00176     case NS_MOUSE_RIGHT_BUTTON_DOWN:
00177     case NS_MOUSE_RIGHT_CLICK:
00178     case NS_MOUSE_RIGHT_DOUBLECLICK:
00179     case NS_CONTEXTMENU:
00180       *aButton = 2;
00181       break;
00182     default:
00183       // This event doesn't have a mouse button associated with it
00184       *aButton = (PRUint16)0;
00185       break;
00186     }
00187   }
00188   return NS_OK;
00189 }
00190 
00191 NS_IMETHODIMP
00192 nsDOMMouseEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
00193 {
00194   NS_ENSURE_ARG_POINTER(aRelatedTarget);
00195   *aRelatedTarget = nsnull;
00196 
00197   if (!mPresContext) {
00198     return NS_OK;
00199   }
00200 
00201   nsCOMPtr<nsIContent> relatedContent;
00202   mPresContext->EventStateManager()->
00203     GetEventRelatedContent(getter_AddRefs(relatedContent));
00204   if (!relatedContent) {
00205     return NS_OK;
00206   }
00207 
00208   return CallQueryInterface(relatedContent, aRelatedTarget);
00209 }
00210 
00211 NS_METHOD nsDOMMouseEvent::GetScreenX(PRInt32* aScreenX)
00212 {
00213   NS_ENSURE_ARG_POINTER(aScreenX);
00214   *aScreenX = GetScreenPoint().x;
00215   return NS_OK;
00216 }
00217 
00218 NS_IMETHODIMP
00219 nsDOMMouseEvent::GetScreenY(PRInt32* aScreenY)
00220 {
00221   NS_ENSURE_ARG_POINTER(aScreenY);
00222   *aScreenY = GetScreenPoint().y;
00223   return NS_OK;
00224 }
00225 
00226 
00227 NS_METHOD nsDOMMouseEvent::GetClientX(PRInt32* aClientX)
00228 {
00229   NS_ENSURE_ARG_POINTER(aClientX);
00230   *aClientX = GetClientPoint().x;
00231   return NS_OK;
00232 }
00233 
00234 NS_IMETHODIMP
00235 nsDOMMouseEvent::GetClientY(PRInt32* aClientY)
00236 {
00237   NS_ENSURE_ARG_POINTER(aClientY);
00238   *aClientY = GetClientPoint().y;
00239   return NS_OK;
00240 }
00241 
00242 NS_IMETHODIMP
00243 nsDOMMouseEvent::GetAltKey(PRBool* aIsDown)
00244 {
00245   NS_ENSURE_ARG_POINTER(aIsDown);
00246   *aIsDown = ((nsInputEvent*)mEvent)->isAlt;
00247   return NS_OK;
00248 }
00249 
00250 NS_IMETHODIMP
00251 nsDOMMouseEvent::GetCtrlKey(PRBool* aIsDown)
00252 {
00253   NS_ENSURE_ARG_POINTER(aIsDown);
00254   *aIsDown = ((nsInputEvent*)mEvent)->isControl;
00255   return NS_OK;
00256 }
00257 
00258 NS_IMETHODIMP
00259 nsDOMMouseEvent::GetShiftKey(PRBool* aIsDown)
00260 {
00261   NS_ENSURE_ARG_POINTER(aIsDown);
00262   *aIsDown = ((nsInputEvent*)mEvent)->isShift;
00263   return NS_OK;
00264 }
00265 
00266 NS_IMETHODIMP
00267 nsDOMMouseEvent::GetMetaKey(PRBool* aIsDown)
00268 {
00269   NS_ENSURE_ARG_POINTER(aIsDown);
00270   *aIsDown = ((nsInputEvent*)mEvent)->isMeta;
00271   return NS_OK;
00272 }
00273 
00274 NS_IMETHODIMP
00275 nsDOMMouseEvent::GetWhich(PRUint32* aWhich)
00276 {
00277   NS_ENSURE_ARG_POINTER(aWhich);
00278   PRUint16 button;
00279   (void) GetButton(&button);
00280   *aWhich = button + 1;
00281   return NS_OK;
00282 }
00283 
00284 nsresult NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult,
00285                              nsPresContext* aPresContext,
00286                              nsInputEvent *aEvent) 
00287 {
00288   nsDOMMouseEvent* it = new nsDOMMouseEvent(aPresContext, aEvent);
00289   if (nsnull == it) {
00290     return NS_ERROR_OUT_OF_MEMORY;
00291   }
00292 
00293   return CallQueryInterface(it, aInstancePtrResult);
00294 }