Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Public Attributes | Private Member Functions | Private Attributes
nsSpatialNavigation Class Reference

#include <nsSpatialNavigationPrivate.h>

Inheritance diagram for nsSpatialNavigation:
Inheritance graph
[legend]
Collaboration diagram for nsSpatialNavigation:
Collaboration graph
[legend]

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSISPATIALNAVIGATION
NS_DECL_NSIDOMEVENTLISTENER
NS_IMETHOD 
KeyDown (nsIDOMEvent *aKeyEvent)
 Processes a key pressed event.
NS_IMETHOD KeyUp (nsIDOMEvent *aKeyEvent)
 Processes a key release event.
NS_IMETHOD KeyPress (nsIDOMEvent *aKeyEvent)
 Processes a key typed event.
 nsSpatialNavigation (nsSpatialNavigationService *aService)
void init (in nsIDOMWindow aWindow)
void shutdown ()
void up ()
void down ()
void left ()
void right ()
void handleEvent (in nsIDOMEvent event)
 This method is called whenever an event occurs of the type for which the EventListener interface was registered.

Public Attributes

readonly attribute nsIDOMWindow attachedWindow

Private Member Functions

 ~nsSpatialNavigation ()
nsPresContextgetPresContext (nsIContent *aContent)
PRInt64 spatialDistance (int direction, nsRect &a, nsRect &b)
nsIDOMWindowgetContentWindow ()
void setFocusedContent (nsIContent *aContent)
void getFocusedContent (int direction, nsIContent **aContent)
nsresult handleMove (int direction)
nsresult getContentInDirection (int direction, nsPresContext *presContext, nsRect &focusedRect, nsIFrame *focusedFrame, PRBool aFocusDocuments, PRBool isAREA, nsIContent **aContent)

Private Attributes

nsCOMPtr< nsIDOMWindowmTopWindow
nsSpatialNavigationServicemService
PRBool mNavigationFramesState

Detailed Description

Definition at line 134 of file nsSpatialNavigationPrivate.h.


Constructor & Destructor Documentation

Definition at line 52 of file nsSpatialNavigation.cpp.

{
  NS_ASSERTION(aService, "Should not create this object without a valid service");

  mService = aService; // back pointer -- no reference

  mNavigationFramesState = PR_FALSE;
}

Definition at line 61 of file nsSpatialNavigation.cpp.

{
}

Member Function Documentation

nsresult nsSpatialNavigation::getContentInDirection ( int  direction,
nsPresContext presContext,
nsRect focusedRect,
nsIFrame focusedFrame,
PRBool  aFocusDocuments,
PRBool  isAREA,
nsIContent **  aContent 
) [private]

Definition at line 578 of file nsSpatialNavigation.cpp.

{  

  // Check to see if we should decend into subdoc
  nsIContent* subFrameContent = aFocusedFrame->GetContent();
  nsCOMPtr<nsIDOMHTMLHtmlElement> hhElement = do_QueryInterface(subFrameContent);
  nsCOMPtr<nsIDOMHTMLIFrameElement> iFrameElement = do_QueryInterface(subFrameContent);

  if ( (hhElement || iFrameElement) && mNavigationFramesState)
  {
    aPresContext = getPresContext(subFrameContent);
    centerRect(aDirection, aFocusedRect);
  }

  
  nsCOMPtr<nsIBidirectionalEnumerator> frameTraversal;
  nsresult result = createFrameTraversal(FOCUS, aPresContext, getter_AddRefs(frameTraversal));  
  if (NS_FAILED(result))
    return result;
  
  nsCOMPtr<nsIContent> currentContent;
  PRInt64 currentDistance = LL_MaxInt();

  DoTraversal(aDirection,
              frameTraversal, 
              aFocusedFrame,
              aFocusedRect,
              aIsAREA,
              aFocusDocuments,
              aPresContext, 
              &currentDistance,
              aContent);


  if ( (hhElement || iFrameElement) && mNavigationFramesState)
  {
    mNavigationFramesState = PR_FALSE;
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 861 of file nsSpatialNavigation.cpp.

{

  nsIDOMWindow* resultWindow = nsnull;

  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTopWindow);
  nsIDOMWindowInternal *rootWindow = window->GetPrivateRoot();
  
  nsCOMPtr<nsIDOMWindow> windowContent;
  rootWindow->GetContent(getter_AddRefs(windowContent));
  
  if (!windowContent)
       return nsnull;

  NS_ADDREF(resultWindow = windowContent);
  return resultWindow;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsSpatialNavigation::getFocusedContent ( int  direction,
nsIContent **  aContent 
) [private]

Definition at line 776 of file nsSpatialNavigation.cpp.

{
  *aContent = nsnull;
  
  nsCOMPtr<nsIDOMWindow> contentWindow = getContentWindow();
  if (!contentWindow)
    return;
  
  nsCOMPtr<nsPIDOMWindow> privateWindow = do_QueryInterface(contentWindow);
  nsIFocusController *focusController = privateWindow->GetRootFocusController();
  
  if (!focusController)
    return;
  
  nsCOMPtr<nsIDOMElement> element;
  focusController->GetFocusedElement(getter_AddRefs(element));
  
  if (element)
  {
    nsCOMPtr<nsIContent> content = do_QueryInterface(element);
    NS_IF_ADDREF(*aContent = content);
    return;
  }

  //xxxx should/can we prevent it from going into chrome???
  if (direction == eNavLeft || direction == eNavUp)
    focusController->MoveFocus(PR_FALSE, nsnull);
  else
    focusController->MoveFocus(PR_TRUE, nsnull);
  
  // so there is no focused content -- lets make some up, hightlight it and return.  
  focusController->GetFocusedElement(getter_AddRefs(element));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 881 of file nsSpatialNavigation.cpp.

{
  if (!content) return nsnull;
  
  nsCOMPtr<nsIDocument> doc = content->GetDocument();
  if (!doc) return nsnull;
  
  // the only case where there could be more shells in printpreview
  nsIPresShell *shell = doc->GetShellAt(0);
  if (!shell) return nsnull;
  
  nsPresContext *presContext = shell->GetPresContext();
  return presContext;
}

Here is the call graph for this function:

Here is the caller graph for this function:

This method is called whenever an event occurs of the type for which the EventListener interface was registered.

Parameters:
evtThe Event contains contextual information about the event. It also contains the stopPropagation and preventDefault methods which are used in determining the event's flow and default action.
nsresult nsSpatialNavigation::handleMove ( int  direction) [private]

Definition at line 628 of file nsSpatialNavigation.cpp.

{
  PRUint32 type = FOCUS;

  nsCOMPtr<nsIContent> focusedContent;
  getFocusedContent(direction, getter_AddRefs(focusedContent));

  // there are some websites which have no focusable elements,
  // only text, for example. In these cases, scrolling have to be
  // performed by snav.
  if (!focusedContent) {
     ScrollWindow(direction, getContentWindow());
     return NS_OK;
  }
  nsPresContext* presContext = getPresContext(focusedContent);
  if(!presContext)
    return NS_ERROR_NULL_POINTER;

  nsIFrame* focusedFrame;
  getFrameForContent(focusedContent, &focusedFrame);

  nsRect focusedRect;
  PRBool isAREA = isArea(focusedContent);
  if (!isAREA) 
  {
    // RECT !!
    focusedRect = makeRectRelativeToGlobalView(focusedFrame);

    // deflate the rect to avoid overlapping with other
    // rects.
    focusedRect.Deflate(gRectFudge, gRectFudge);
  }
  else
  {
    nsCOMPtr<nsIDOMHTMLAreaElement> e = do_QueryInterface(focusedContent);
    getRectOfAreaElement(focusedFrame, e, &focusedRect);
  }

  nsCOMPtr<nsIContent> c;
  getContentInDirection(direction, presContext, focusedRect, focusedFrame, PR_FALSE, isAREA, getter_AddRefs(c));
  
  if (c) {
   
    nsIDocument* doc = c->GetDocument();
    if (!doc)
      return NS_ERROR_FAILURE;
    
/*    nsIPresShell *presShell = doc->GetShellAt(0);

    nsIFrame* cframe;
    presShell->GetPrimaryFrameFor(c, &cframe);
    
    PRBool b = IsPartiallyVisible(presShell, cframe); 
    
    if (b)
      setFocusedContent(c);
    else
      ScrollWindow(direction, getContentWindow());*/

    setFocusedContent(c);
    return NS_OK;
  }

  // do it all again at the parent document

  {
    nsCOMPtr<nsIDOMWindow> contentWindow = getContentWindow();
    if (!contentWindow)
      return NS_OK;

    nsCOMPtr<nsIDOMDocument> domDoc;
    contentWindow->GetDocument(getter_AddRefs(domDoc));
    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);

    nsIPresShell *shell = doc->GetShellAt(0);
    if (!shell) return NS_OK;
  
    presContext = shell->GetPresContext();

       nsIFrame* parentFrame = shell->GetRootFrame();

    nsCOMPtr<nsIDocument> subdoc = focusedContent->GetDocument();
    if (!subdoc) return NS_OK;
    
    nsCOMPtr<nsIDOMDocument> subdomdoc = do_QueryInterface(subdoc);

    nsCOMPtr<nsIDOMWindowInternal> domWindowInternal;
    GetWindowFromDocument(subdomdoc, getter_AddRefs(domWindowInternal));
    if (!domWindowInternal) return NS_OK;

    nsCOMPtr<nsIDOMWindowInternal> domWindowInternal2 = domWindowInternal;
       domWindowInternal2->GetOpener(getter_AddRefs(domWindowInternal));
    if (!domWindowInternal) 
      domWindowInternal = domWindowInternal2;

    nsCOMPtr<nsIDOMWindow> subdocWindow = do_QueryInterface(domWindowInternal);
    if (!subdocWindow) return NS_OK;

    subdocWindow->GetDocument(getter_AddRefs(subdomdoc));
    if (!subdoc) return NS_OK;

    nsIPresShell *subdocShell = subdoc->GetShellAt(0);
    if (!subdocShell) return NS_OK;
  
    nsPresContext *subdocPresContext = subdocShell->GetPresContext();

    nsIFrame* subdocFrame = subdocShell->GetRootFrame();

    nsRect subdocRect = subdocFrame->GetRect();

    nsPoint frame_offset = subdocFrame->GetOffsetToExternal(parentFrame);
       
       subdocRect.x = frame_offset.x;
       subdocRect.y = frame_offset.y;

    getContentInDirection(direction, presContext, subdocRect, subdocFrame, PR_TRUE, PR_FALSE, getter_AddRefs(c));
  }

  if (c) {
    nsCOMPtr<nsIContent> subdocContent;
    getContentFromFrame(c, getter_AddRefs(subdocContent));

    if (subdocContent) {
      mNavigationFramesState = PR_TRUE;
      setFocusedContent(c);
      return NS_OK;
    }

    setFocusedContent(c);
    return NS_OK;
  }
  
  // if everything fails, default is to move the focus just as if the user hit tab.
  //  presContext->EventStateManager()->ShiftFocus(PR_TRUE, focusedContent);

  // how about this, if we find anything, we just scroll the
  // page in the direction of the navigation??
  ScrollWindow(direction, getContentWindow());


  return NS_OK;

}

Here is the call graph for this function:

void nsISpatialNavigation::init ( in nsIDOMWindow  aWindow) [inherited]

Processes a key pressed event.

Parameters:
aKeyEvent
See also:
nsIDOMEvent.h
Returns:
whether the event was consumed or ignored.
See also:
nsresult

Implements nsIDOMKeyListener.

Definition at line 84 of file nsSpatialNavigation.cpp.

{
  nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
  PRBool enabled;
  prefBranch->GetBoolPref("snav.enabled", &enabled);
  if (!enabled) //  this doesn't work.  wtf? if (!mService->mEnabled)
    return NS_OK;
 

  nsCOMPtr<nsIDOMNSUIEvent> uiEvent(do_QueryInterface(aEvent));
  if (uiEvent)
  {
    // If a web page wants to use the keys mapped to our
    // move, they have to use evt.preventDefault() after
    // they get the key

    PRBool preventDefault;
    uiEvent->GetPreventDefault(&preventDefault);
    if (preventDefault)
      return NS_OK;
  }

  PRInt32 formControlType = -1;
  // check to see if we are in a text field.
  // based on nsTypeAheadFind.
    
  //nsEvent should be renamed.
  nsCOMPtr<nsIDOMNSEvent> nsEvent = do_QueryInterface(aEvent);
  if (!nsEvent)
    return NS_ERROR_FAILURE;
  
  nsCOMPtr<nsIDOMEventTarget> domEventTarget;
  nsEvent->GetOriginalTarget(getter_AddRefs(domEventTarget));
  
  nsCOMPtr<nsIContent> targetContent = do_QueryInterface(domEventTarget);

  if (targetContent->IsContentOfType(nsIContent::eXUL))
    return NS_OK;
  
  if (targetContent->IsContentOfType(nsIContent::eHTML_FORM_CONTROL)) 
  {
      nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(targetContent));
      formControlType = formControl->GetType();
      
      if (mService->mIgnoreTextFields)
      {
        if (formControlType == NS_FORM_TEXTAREA ||
            formControlType == NS_FORM_INPUT_TEXT ||
            formControlType == NS_FORM_INPUT_PASSWORD ||
            formControlType == NS_FORM_INPUT_FILE) 
        {
          return NS_OK;
        }
      }
  }
  else if (mService->mIgnoreTextFields && targetContent->IsContentOfType(nsIContent::eHTML)) 
  {
    // Test for isindex, a deprecated kind of text field. We're using a string 
    // compare because <isindex> is not considered a form control, so it does 
    // not support nsIFormControl or eHTML_FORM_CONTROL, and it's not worth 
    // having a table of atoms just for it. 
    
      if (isContentOfType(targetContent, "isindex"))
        return NS_OK;
  }

  PRUint32 keyCode;
  PRBool isModifier;
  nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aEvent));
  
  if (!keyEvent)
    return NS_ERROR_FAILURE;

  if (NS_FAILED(keyEvent->GetKeyCode(&keyCode)))
       return NS_ERROR_FAILURE;
  
  // figure out what modifier to use  
  
  /************************************************
    Value of the keyCodeModifier is
  
    SHIFT          = 0x00100000
    CONTROL        = 0x00001100
    ALT            = 0x00000012
  *************************************************/
  
  
  if (mService->mKeyCodeModifier & 0x00100000)
  {
    if (NS_FAILED(keyEvent->GetShiftKey(&isModifier)))
      return NS_ERROR_FAILURE;
    if (!isModifier)
      return NS_OK;  
  }
  
  if (mService->mKeyCodeModifier & 0x00001100)
  {
    if (NS_FAILED(keyEvent->GetCtrlKey(&isModifier)))
      return NS_ERROR_FAILURE;
    if (!isModifier)
      return NS_OK;  
  }
  
  if (mService->mKeyCodeModifier & 0x00000012)
  {
    if (NS_FAILED(keyEvent->GetAltKey(&isModifier)))
      return NS_ERROR_FAILURE;
    if (!isModifier)
      return NS_OK;  
  }

  if (keyCode == mService->mKeyCodeLeft)
  {
    //************************************************************************************
    // NS_FORM_TEXTAREA & (NS_FORM_INPUT_TEXT | NS_FORM_INPUT_PASSWORD | NS_FORM_INPUT_FILE) cases

    PRInt32 selectionStart = 0, textLength = 0;
    if (formControlType == NS_FORM_INPUT_TEXT || 
        formControlType == NS_FORM_INPUT_PASSWORD ||
        formControlType == NS_FORM_INPUT_FILE)
    {
      nsCOMPtr<nsIDOMNSHTMLInputElement> input = do_QueryInterface(targetContent);
      if (input) {
        input->GetSelectionStart (&selectionStart);
        input->GetTextLength (&textLength);
      }
    } else if (formControlType == NS_FORM_TEXTAREA) {

      nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textArea = do_QueryInterface(targetContent);
      if (textArea) {
        textArea->GetSelectionStart (&selectionStart);
        textArea->GetTextLength (&textLength);
      }
    }

    if (textLength != 0 && selectionStart != 0)
      return NS_OK;

    // We're using this key, no one else should
    aEvent->StopPropagation();
    aEvent->PreventDefault();
    return Left();
  }

  if (keyCode == mService->mKeyCodeRight)
  {
    //************************************************************************************
    // NS_FORM_TEXTAREA & (NS_FORM_INPUT_TEXT | NS_FORM_INPUT_PASSWORD | NS_FORM_INPUT_FILE) cases

    PRInt32 selectionEnd = 0, textLength = 0;

    if (formControlType == NS_FORM_INPUT_TEXT || 
        formControlType == NS_FORM_INPUT_PASSWORD ||
        formControlType == NS_FORM_INPUT_FILE)
    {
      nsCOMPtr<nsIDOMNSHTMLInputElement> input = do_QueryInterface(targetContent);
      if (input) {
        input->GetSelectionEnd (&selectionEnd);
        input->GetTextLength (&textLength);
      }
    } else if (formControlType == NS_FORM_TEXTAREA) {

      nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textArea = do_QueryInterface(targetContent);
      if (textArea) {
        textArea->GetSelectionEnd (&selectionEnd);
        textArea->GetTextLength (&textLength);
      }
    }

    if (textLength  != selectionEnd)
      return NS_OK;

    aEvent->StopPropagation();
    aEvent->PreventDefault();
    return Right();
  }

  if (keyCode == mService->mKeyCodeUp)
  {

    // If we are going up or down, in a select, lets not
    // navigate.
    //
    // FIX: What we really want to do is determine if we are
    // at the start or the end fo the form element, and
    // based on the selected position we decide to nav. or
    // not.

    // ************************************************************************************
    // NS_FORM_SELECT cases:
    // * if it is a select form of 'size' attr != than '1' then we do as above.

    // * if it is a select form of 'size' attr == than '1', snav can take care of it.
    // if (formControlType == NS_FORM_SELECT)
    //   return NS_OK;

    //************************************************************************************
    // NS_FORM_TEXTAREA & (NS_FORM_INPUT_TEXT | NS_FORM_INPUT_PASSWORD | NS_FORM_INPUT_FILE) cases

    if (formControlType == NS_FORM_TEXTAREA) {

      PRInt32 selectionStart = 0, textLength = 0;
      nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textArea = do_QueryInterface(targetContent);
      if (textArea) {
        textArea->GetSelectionStart (&selectionStart);
        textArea->GetTextLength (&textLength);
      }

      if (textLength != 0 && selectionStart != 0)
        return NS_OK;
    }

    // We're using this key, no one else should
    aEvent->StopPropagation();
    aEvent->PreventDefault();
    return Up();
  }

  if (keyCode == mService->mKeyCodeDown)
  {
    // If we are going up or down, in a select, lets not
    // navigate.
    //
    // FIX: What we really want to do is determine if we are
    // at the start or the end fo the form element, and
    // based on the selected position we decide to nav. or
    // not.

    // ************************************************************************************
    // NS_FORM_SELECT cases:
    // * if it is a select form of 'size' attr != than '1' then we do as above.

    // * if it is a select form of 'size' attr == than '1', snav can take care of it.
    // if (formControlType == NS_FORM_SELECT)
    //   return NS_OK;

    if (formControlType == NS_FORM_TEXTAREA) {

      PRInt32 selectionEnd = 0, textLength = 0;
      nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textArea = do_QueryInterface(targetContent);
      if (textArea) {
        textArea->GetSelectionEnd (&selectionEnd);
        textArea->GetTextLength (&textLength);
      }

      if (textLength  != selectionEnd)
        return NS_OK;
    }

    aEvent->StopPropagation();  // We're using this key, no one else should
    aEvent->PreventDefault();
    return Down();
  }
  
  return NS_OK;
}

Here is the call graph for this function:

Processes a key typed event.

Parameters:
aKeyEvent
See also:
nsIDOMEvent.h
Returns:
whether the event was consumed or ignored.
See also:
nsresult

Implements nsIDOMKeyListener.

Definition at line 78 of file nsSpatialNavigation.cpp.

{
  return NS_OK;
}

Processes a key release event.

Parameters:
aKeyEvent
See also:
nsIDOMEvent.h
Returns:
whether the event was consumed or ignored.
See also:
nsresult

Implements nsIDOMKeyListener.

Definition at line 72 of file nsSpatialNavigation.cpp.

{
  return NS_OK;
}

Definition at line 811 of file nsSpatialNavigation.cpp.

{
  if (!c)
    return;

  nsCOMPtr<nsIContent> subdocContent;
  getContentFromFrame(c, getter_AddRefs(subdocContent));

  if (subdocContent) {
    c = subdocContent;
  }

  nsIContent* currentContent = c;
  nsCOMPtr<nsIDOMElement> element = do_QueryInterface(currentContent);
  nsCOMPtr<nsIDOMNode> node(do_QueryInterface(element));

  nsCOMPtr<nsIDOMWindow> contentWindow;
  if (mService->mDisableJSWhenFocusing)
    contentWindow = getContentWindow();

  // We do not want to have JS disable at anytime - see bug 51075
  // DisableJSScope foopy (contentWindow);

  //#ifdef OLDER_LAYOUT  
  nsPresContext* presContext = getPresContext(c);
  
  nsIPresShell *presShell = presContext->PresShell();
  nsIFrame* frame;
  presShell->GetPrimaryFrameFor(c, &frame);
  
  if (frame) {
    presContext->EventStateManager()->SetContentState(c, NS_EVENT_STATE_FOCUS);
    
    presShell->ScrollFrameIntoView(frame, 
                                   NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
                                   NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
    
    presContext->EventStateManager()->MoveCaretToFocus();
  }

  //#else
  nsCOMPtr<nsIDOMNSHTMLElement> nsElement = do_QueryInterface(element);
  if (nsElement) 
    nsElement->Focus();
  //#endif

}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt64 nsSpatialNavigation::spatialDistance ( int  direction,
nsRect a,
nsRect b 
) [private]
void nsISpatialNavigation::up ( ) [inherited]

Member Data Documentation

Definition at line 53 of file nsISpatialNavigation.idl.

Definition at line 169 of file nsSpatialNavigationPrivate.h.

Definition at line 167 of file nsSpatialNavigationPrivate.h.

Definition at line 165 of file nsSpatialNavigationPrivate.h.


The documentation for this class was generated from the following files: