Home > open-source, PlanetCDOT, programming > Done and Done, Pt. 2

Done and Done, Pt. 2

Success! I’ve managed to alter the reported location of the cursor! Here’s what I did to get it to work:

The file that I had to modify was content/events/src/nsDOMMouseEvent.cpp, this is the implementation file of the DOM MouseEvent in firefox.
The updates were as follows:

// ... snip ... line 223

NS_METHOD nsDOMMouseEvent::GetScreenX(PRInt32* aScreenX)
  //*aScreenX = GetScreenPoint().x;
  *aScreenX = 17000;
  return NS_OK;

nsDOMMouseEvent::GetScreenY(PRInt32* aScreenY)
  //*aScreenY = GetScreenPoint().y;
  *aScreenY = 18000;
  return NS_OK;

NS_METHOD nsDOMMouseEvent::GetClientX(PRInt32* aClientX)
  //*aClientX = GetClientPoint().x;
  *aClientX = 7000;
  return NS_OK;

nsDOMMouseEvent::GetClientY(PRInt32* aClientY)
  //*aClientY = GetClientPoint().y;
  *aClientY = 8000;
  return NS_OK;

// ... /snip ...

As you can see, I forced the reported values for the cursor’s position to be 17000/18000 for the screenX/screenY members and 7000/8000 for the clientX/clientY members. This is a pretty naive way to do it but it proved to produce results. Check it out!

This is what happens now when a user attempts to right click anywhere in the page. As you can see, the context menu appears far off into the right bottom corner ( since the coordinates go off screen ).

Interestingly enough, the changes to the event class do not affect the native windows right click context menu ( can be triggered by right clicking in the same vertical space as the minimize/maximize/close buttons ), as can be seen here. Also not affected is text selection and clicking buttons/links and forms.

Also interesting is that no assertion errors are usually thrown. I have managed to provoke an assertion error however simply by middle clicking ( click the wheel of your mouse if you have a mouse wheel ) somewhere inside the page; the page being used should have sufficient text for the quick drag middle click popup to appear, for an example this page should work. Scroll around a bit if you don’t first succeed.

In conclusion, it seems that it is not immediately obvious how MouseEvent is used internally. On the one hand, the values reported through the event to the js engine are the only way for the js to figure out where the cursor is; so as far as the js is concerned, whatever we return here will be where the js believes the cursor to be. On the other hand, some internals seem to use the values returned from the getter functions of the mouse event object as well; this may make updating the values to our whims possibly difficult due to the sheer size of firefox’s internals and the fact that we don’t *exactly* know what will be affected by our meddling.

P.S. The MouseEvent class also defines some longs (screenX, screenY, clientX, clientY); from what I could tell, these are only updated during initialization:

// ... snip ... line 106

nsDOMMouseEvent::InitMouseEvent(const nsAString & aType, PRBool aCanBubble, PRBool aCancelable,
                                nsIDOMAbstractView *aView, PRInt32 aDetail, PRInt32 aScreenX, 
                                PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY, 
                                PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey, 
                                PRBool aMetaKey, PRUint16 aButton, nsIDOMEventTarget *aRelatedTarget)
  nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);

    case NS_MOUSE_EVENT:
    case NS_DRAG_EVENT:
       static_cast(mEvent)->relatedTarget = aRelatedTarget;
       static_cast(mEvent)->button = aButton;
       nsInputEvent* inputEvent = static_cast(mEvent);
       inputEvent->isControl = aCtrlKey;
       inputEvent->isAlt = aAltKey;
       inputEvent->isShift = aShiftKey;
       inputEvent->isMeta = aMetaKey;
       mClientPoint.x = aClientX;
       mClientPoint.y = aClientY;
       inputEvent->refPoint.x = aScreenX;
       inputEvent->refPoint.y = aScreenY;

       if (mEvent->eventStructType == NS_MOUSE_EVENT) {
         nsMouseEvent* mouseEvent = static_cast(mEvent);
         mouseEvent->clickCount = aDetail;

  return NS_OK;

// ... /snip ...

It may also be interesting to play around with these values; I have not touched these values for this update.

  1. hungryr
    November 15, 2011 at 3:22 am

    I love your post! So much win in this post…
    It is very helpful on starting to mess in firefox codes.
    I was wondering if you can share with the rest of us on how you ended up in “content/events/src/nsDOMMouseEvent.cpp” and the functions that report the coordinates.

    Thank you so much for helping the rest of us find a place to start playing around… I am sure many classmates found this post helpful!

    • northwind87
      November 15, 2011 at 4:04 am

      Hey no problem! However I was by no means the first to find these functions. According to CDOT, I believe that at minimum Diogo Golovanevsky Monteiro hit those functions before I did. It’s kind of funny, his post is almost identical to mine in many respects even though we were working entirely in parallel with no communication imbetween!

      To answer your question, I basically hit MXR and started looking around the codebase for any mentions of MouseEvent; I got the name from the idl specification where it was called MouseEvent. Eventually after a bunch of stumbling around, I remembered @humph’s words about how all of the mouse interfaces have to do with the DOM so when I saw a couple of entries with DOM in the filename I knew that I was getting close. Beyond that, it took a little looking around to find the non-platform-specific code for event creation/dispatching and then altering the getter functions appropriately. I liken the process to stumbling around drunk in a hall of mirrors; you don’t quite know when you’ll get where you want to go but eventually you get there and think “huh, you were here all along?”

      Hahaha, this mouse stuff is gonna be fun šŸ˜‰

  1. November 15, 2011 at 2:40 am
  2. November 15, 2011 at 3:19 am
  3. November 21, 2011 at 5:09 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: