Inital checkin of Spatial Navigation. Not part of the default build.
git-svn-id: svn://10.0.0.236/trunk@173382 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
13
mozilla/extensions/spatialnavigation/Makefile.in
Executable file
13
mozilla/extensions/spatialnavigation/Makefile.in
Executable file
@@ -0,0 +1,13 @@
|
||||
DEPTH=../..
|
||||
topsrcdir=@top_srcdir@
|
||||
srcdir=@srcdir@
|
||||
VPATH=@srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = snav
|
||||
|
||||
DIRS = public src
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
51
mozilla/extensions/spatialnavigation/public/Makefile.in
Executable file
51
mozilla/extensions/spatialnavigation/public/Makefile.in
Executable file
@@ -0,0 +1,51 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Spatial Navigation
|
||||
#
|
||||
# The Initial Developer of the Original Code is Douglas F. Turner II
|
||||
# Portions created by the Initial Developer are Copyright (C) 2004
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
DEPTH=../../..
|
||||
topsrcdir=@top_srcdir@
|
||||
srcdir=@srcdir@
|
||||
VPATH=@srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE=snav
|
||||
XPIDL_MODULE=snav
|
||||
|
||||
XPIDLSRCS = nsISpatialNavigation.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
54
mozilla/extensions/spatialnavigation/public/nsISpatialNavigation.idl
Executable file
54
mozilla/extensions/spatialnavigation/public/nsISpatialNavigation.idl
Executable file
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Spatial Navigation
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Douglas F. Turner II
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, uuid(ef7cb437-9eb3-47c7-9d89-71679bfefcc1)]
|
||||
interface nsISpatialNavigation: nsISupports
|
||||
{
|
||||
void init(in nsIDOMWindow aWindow);
|
||||
void shutdown();
|
||||
|
||||
void up();
|
||||
void down();
|
||||
void left();
|
||||
void right();
|
||||
|
||||
readonly attribute nsIDOMWindow attachedWindow;
|
||||
};
|
||||
82
mozilla/extensions/spatialnavigation/src/Makefile.in
Executable file
82
mozilla/extensions/spatialnavigation/src/Makefile.in
Executable file
@@ -0,0 +1,82 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Spatial Navigation
|
||||
#
|
||||
# The Initial Developer of the Original Code is Douglas F. Turner II
|
||||
# Portions created by the Initial Developer are Copyright (C) 2004
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
DEPTH=../../..
|
||||
topsrcdir=@top_srcdir@
|
||||
srcdir=@srcdir@
|
||||
VPATH=@srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = snav
|
||||
LIBRARY_NAME = snav
|
||||
IS_COMPONENT = 1
|
||||
|
||||
REQUIRES = xpcom \
|
||||
string \
|
||||
pref \
|
||||
js \
|
||||
dom \
|
||||
dom_base \
|
||||
gfx \
|
||||
layout \
|
||||
content \
|
||||
widget \
|
||||
locale \
|
||||
necko \
|
||||
docshell \
|
||||
view \
|
||||
webshell \
|
||||
windowwatcher \
|
||||
webbrwsr \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS= \
|
||||
nsSpatialNavigation.cpp \
|
||||
nsSpatialNavigationUtils.cpp \
|
||||
nsSpatialNavigationService.cpp \
|
||||
$(NULL)
|
||||
|
||||
DEFINES = -DMOZILLA_INTERNAL_API
|
||||
|
||||
EXTRA_DSO_LIBS = gkgfx
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(LIBS_DIR) \
|
||||
$(EXTRA_DSO_LIBS) \
|
||||
$(MOZ_COMPONENT_LIBS)\
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
737
mozilla/extensions/spatialnavigation/src/nsSpatialNavigation.cpp
Executable file
737
mozilla/extensions/spatialnavigation/src/nsSpatialNavigation.cpp
Executable file
@@ -0,0 +1,737 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Spatial Navigation
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Douglas F. Turner II <dougt@meer.net>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004-2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsSpatialNavigationPrivate.h"
|
||||
|
||||
PRInt32 gRectFudge = 20;
|
||||
PRInt32 gDirectionalBias = 3;
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsSpatialNavigation)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISpatialNavigation)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMKeyListener)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(nsSpatialNavigation)
|
||||
NS_IMPL_RELEASE(nsSpatialNavigation)
|
||||
|
||||
|
||||
nsSpatialNavigation::nsSpatialNavigation(nsSpatialNavigationService* aService)
|
||||
{
|
||||
NS_ASSERTION(aService, "Should not create this object without a valid service");
|
||||
|
||||
mService = aService; // back pointer -- no reference
|
||||
|
||||
mNavigationFramesState = PR_FALSE;
|
||||
}
|
||||
|
||||
nsSpatialNavigation::~nsSpatialNavigation()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::KeyDown(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::KeyUp(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::KeyPress(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
||||
// check to see if we are in a text field.
|
||||
|
||||
if (!mService->mIgnoreTextFields)
|
||||
{
|
||||
// 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::eHTML_FORM_CONTROL))
|
||||
{
|
||||
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(targetContent));
|
||||
PRInt32 controlType = formControl->GetType();
|
||||
|
||||
if (controlType == NS_FORM_TEXTAREA ||
|
||||
controlType == NS_FORM_INPUT_TEXT ||
|
||||
controlType == NS_FORM_INPUT_PASSWORD ||
|
||||
controlType == NS_FORM_INPUT_FILE)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else if (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)
|
||||
{
|
||||
// We're using this key, no one else should
|
||||
aEvent->StopPropagation();
|
||||
aEvent->PreventDefault();
|
||||
return Left();
|
||||
}
|
||||
|
||||
if (keyCode == mService->mKeyCodeRight)
|
||||
{
|
||||
aEvent->StopPropagation();
|
||||
aEvent->PreventDefault();
|
||||
return Right();
|
||||
}
|
||||
|
||||
if (keyCode == mService->mKeyCodeUp)
|
||||
{
|
||||
aEvent->StopPropagation();
|
||||
aEvent->PreventDefault();
|
||||
return Up();
|
||||
}
|
||||
|
||||
if (keyCode == mService->mKeyCodeDown)
|
||||
{
|
||||
aEvent->StopPropagation(); // We're using this key, no one else should
|
||||
aEvent->PreventDefault();
|
||||
return Down();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::Init(nsIDOMWindow *aWindow)
|
||||
{
|
||||
mTopWindow = aWindow;
|
||||
|
||||
nsCOMPtr<nsIDOM3EventTarget> target;
|
||||
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||
nsresult rv = getEventTargetFromWindow(aWindow, getter_AddRefs(target), getter_AddRefs(systemGroup));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
target->AddGroupedEventListener(NS_LITERAL_STRING("keypress"),
|
||||
NS_STATIC_CAST(nsIDOMKeyListener*, this),
|
||||
PR_FALSE,
|
||||
systemGroup);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::Shutdown()
|
||||
{
|
||||
nsCOMPtr<nsIDOM3EventTarget> target;
|
||||
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||
nsresult rv = getEventTargetFromWindow(mTopWindow, getter_AddRefs(target), getter_AddRefs(systemGroup));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
target->RemoveGroupedEventListener(NS_LITERAL_STRING("keypress"),
|
||||
NS_STATIC_CAST(nsIDOMKeyListener*, this),
|
||||
PR_FALSE,
|
||||
systemGroup);
|
||||
mTopWindow = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::Up()
|
||||
{
|
||||
return handleMove(eNavUp);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::Down()
|
||||
{
|
||||
return handleMove(eNavDown);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::Left()
|
||||
{
|
||||
return handleMove(eNavLeft);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::Right()
|
||||
{
|
||||
return handleMove(eNavRight);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigation::GetAttachedWindow(nsIDOMWindow * *aAttachedWindow)
|
||||
{
|
||||
NS_IF_ADDREF(*aAttachedWindow = mTopWindow);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void DoTraversal(int aDirection,
|
||||
nsIBidirectionalEnumerator* aFrameTraversal,
|
||||
nsIFrame* aFocusedFrame,
|
||||
nsRect& aFocusedRect,
|
||||
PRBool isAREA,
|
||||
PRBool focusDocuments,
|
||||
nsPresContext* aPresContext,
|
||||
PRInt64* aDSoFar,
|
||||
nsIContent** aCurrentContent)
|
||||
{
|
||||
|
||||
*aCurrentContent = nsnull;
|
||||
|
||||
// There are some rects with zero width or height.
|
||||
// calculating distance from a non point is troublesome.
|
||||
// we will fix this up here by setting such a point to at
|
||||
// least 1 px.
|
||||
|
||||
if (aFocusedRect.width == 0) {
|
||||
aFocusedRect.width = 1;
|
||||
}
|
||||
|
||||
if (aFocusedRect.height == 0) {
|
||||
aFocusedRect.height = 1;
|
||||
}
|
||||
|
||||
nsIFrame* frame;
|
||||
nsRect frameRect;
|
||||
|
||||
PRInt64 d;
|
||||
|
||||
while (1)
|
||||
{
|
||||
aFrameTraversal->Next();
|
||||
|
||||
nsISupports* currentItem;
|
||||
aFrameTraversal->CurrentItem(¤tItem);
|
||||
frame = NS_STATIC_CAST(nsIFrame*, currentItem);
|
||||
|
||||
if (!frame)
|
||||
break;
|
||||
|
||||
printf("got frame %x\n", frame);
|
||||
|
||||
// So, here we want to make sure that the frame that we
|
||||
// nav to isn't part of the flow of the currently
|
||||
// focused frame
|
||||
|
||||
if (!isAREA)
|
||||
{
|
||||
nsIFrame* flowFrame = aFocusedFrame;
|
||||
PRBool currentFrameIsFocusedFrame = PR_FALSE;
|
||||
while (flowFrame)
|
||||
{
|
||||
if (flowFrame == frame)
|
||||
{
|
||||
currentFrameIsFocusedFrame = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
flowFrame = flowFrame->GetNextInFlow();
|
||||
}
|
||||
if (currentFrameIsFocusedFrame)
|
||||
continue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// a special case for area's which are not enumerated by the nsIFrameTraversal
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
if (isMap(frame))
|
||||
{
|
||||
nsIContent* c = frame->GetContent();
|
||||
nsCOMPtr<nsIDOMHTMLMapElement> element = do_QueryInterface(c);
|
||||
if (!element)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLCollection> mapAreas;
|
||||
element->GetAreas(getter_AddRefs(mapAreas));
|
||||
if (!mapAreas)
|
||||
continue;
|
||||
|
||||
PRUint32 length;
|
||||
mapAreas->GetLength(&length);
|
||||
|
||||
for (PRUint32 i = 0; i < length; i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> domNode;
|
||||
mapAreas->Item(i,getter_AddRefs(domNode));
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLAreaElement> e = do_QueryInterface(domNode);
|
||||
nsCOMPtr<nsIContent> content= do_QueryInterface(domNode);
|
||||
getFrameForContent(content, &frame);
|
||||
|
||||
getRectOfAreaElement(frame, e, &frameRect);
|
||||
|
||||
if (!isRectInDirection(aDirection, aFocusedRect, frameRect))
|
||||
continue;
|
||||
|
||||
d = spatialDistance(aDirection, aFocusedRect, frameRect);
|
||||
|
||||
if ((*aDSoFar) > d)
|
||||
{
|
||||
(*aDSoFar) = d;
|
||||
NS_IF_RELEASE(*aCurrentContent);
|
||||
NS_ADDREF(*aCurrentContent = content);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// we don't want to worry about the same frame if we
|
||||
// aren't an area
|
||||
if (frame == aFocusedFrame ||
|
||||
(aFocusedFrame && (frame->GetContent() == aFocusedFrame->GetContent())))
|
||||
continue;
|
||||
|
||||
// make sure the frame is targetable for focus
|
||||
if (!isTargetable(focusDocuments, frame))
|
||||
continue;
|
||||
|
||||
// RECT !!
|
||||
frameRect = makeRectRelativeToGlobalView(frame);
|
||||
|
||||
// no frames without size and be navigated to
|
||||
// successfully.
|
||||
if (frameRect.width == 0 || frameRect.height == 0)
|
||||
continue;
|
||||
|
||||
// deflate the rect to avoid overlapping with other
|
||||
// rects.
|
||||
frameRect.Deflate(gRectFudge, gRectFudge);
|
||||
|
||||
if (!isRectInDirection(aDirection, aFocusedRect, frameRect))
|
||||
continue;
|
||||
|
||||
d = spatialDistance(aDirection, aFocusedRect, frameRect);
|
||||
|
||||
if ((*aDSoFar) >= d)
|
||||
{
|
||||
#ifdef DEBUG_dougt
|
||||
if (d == 0)
|
||||
{
|
||||
printf("there is overlapping content;\n");
|
||||
}
|
||||
#endif
|
||||
(*aDSoFar) = d;
|
||||
NS_IF_RELEASE(*aCurrentContent);
|
||||
NS_ADDREF(*aCurrentContent = frame->GetContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void centerRect(int aDirection, nsRect& aRect)
|
||||
{
|
||||
if (aDirection == eNavLeft)
|
||||
aRect.x = 1000000;
|
||||
else if (aDirection == eNavRight)
|
||||
aRect.x = 0;
|
||||
else if (aDirection == eNavUp)
|
||||
aRect.y = 1000000;
|
||||
else
|
||||
aRect.y = 0;
|
||||
|
||||
aRect.height = 1;
|
||||
aRect.width = 1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSpatialNavigation::getContentInDirection(int aDirection,
|
||||
nsPresContext* aPresContext,
|
||||
nsRect& aFocusedRect,
|
||||
nsIFrame* aFocusedFrame,
|
||||
PRBool aIsAREA,
|
||||
PRBool aFocusDocuments,
|
||||
nsIContent** aContent)
|
||||
{
|
||||
|
||||
// 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,
|
||||
¤tDistance,
|
||||
aContent);
|
||||
|
||||
|
||||
if ( (hhElement || iFrameElement) && mNavigationFramesState)
|
||||
{
|
||||
mNavigationFramesState = PR_FALSE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsSpatialNavigation::handleMove(int direction)
|
||||
{
|
||||
PRUint32 type = FOCUS;
|
||||
|
||||
if (!mService->mEnabled)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> focusedContent;
|
||||
getFocusedContent(direction, getter_AddRefs(focusedContent));
|
||||
|
||||
if (!focusedContent)
|
||||
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) {
|
||||
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);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
nsSpatialNavigation::getFocusedContent(int direction, nsIContent** aContent)
|
||||
{
|
||||
*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));
|
||||
}
|
||||
|
||||
void
|
||||
nsSpatialNavigation::setFocusedContent(nsIContent* c)
|
||||
{
|
||||
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();
|
||||
|
||||
DisableJSScope foopy (contentWindow);
|
||||
|
||||
//#ifdef OLDER_LAYOUT
|
||||
nsPresContext* presContext = getPresContext(c);
|
||||
|
||||
nsIFrame* frame = nsnull;
|
||||
nsIPresShell *presShell = presContext->PresShell();
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
nsIDOMWindow*
|
||||
nsSpatialNavigation::getContentWindow()
|
||||
{
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
nsPresContext*
|
||||
nsSpatialNavigation::getPresContext(nsIContent* content)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
273
mozilla/extensions/spatialnavigation/src/nsSpatialNavigationPrivate.h
Executable file
273
mozilla/extensions/spatialnavigation/src/nsSpatialNavigationPrivate.h
Executable file
@@ -0,0 +1,273 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Spatial Navigation
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Douglas F. Turner II <dougt@meer.net>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004-2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "memory.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "nspr.h"
|
||||
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsISpatialNavigation.h"
|
||||
|
||||
#include "nsArray.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsFrameTraversal.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIChromeEventHandler.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDOM3EventTarget.h"
|
||||
#include "nsIDOMAbstractView.h"
|
||||
#include "nsIDOMCSSStyleDeclaration.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocumentView.h"
|
||||
#include "nsIDOMElementCSSInlineStyle.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsIDOMHTMLAreaElement.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLFrameElement.h"
|
||||
#include "nsIDOMHTMLHtmlElement.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMHTMLMapElement.h"
|
||||
#include "nsIDOMHTMLOptionElement.h"
|
||||
#include "nsIDOMHTMLSelectElement.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
#include "nsIDOMKeyListener.h"
|
||||
#include "nsIDOMNSEvent.h"
|
||||
#include "nsIDOMNSHTMLElement.h"
|
||||
#include "nsIDOMNSUIEvent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFocusController.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIFrameFrame.h"
|
||||
#include "nsIFrameLoader.h"
|
||||
#include "nsIFrameTraversal.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIImageFrame.h"
|
||||
#include "nsIImageMap.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsILineIterator.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIPrefBranchInternal.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIProperties.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISound.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIWebBrowser.h"
|
||||
#include "nsIWebBrowserChrome.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsStyleContext.h"
|
||||
|
||||
|
||||
class nsSpatialNavigationService;
|
||||
class nsSpatialNavigation;
|
||||
|
||||
class nsSpatialNavigation : public nsISpatialNavigation, public nsIDOMKeyListener
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISPATIALNAVIGATION
|
||||
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
// ----- nsIDOMKeyListener ----------------------------
|
||||
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
|
||||
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
|
||||
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
|
||||
|
||||
nsSpatialNavigation(nsSpatialNavigationService* aService);
|
||||
|
||||
private:
|
||||
~nsSpatialNavigation();
|
||||
|
||||
nsPresContext* getPresContext(nsIContent* aContent);
|
||||
|
||||
PRInt64 spatialDistance(int direction, nsRect& a, nsRect& b);
|
||||
|
||||
nsIDOMWindow* getContentWindow();
|
||||
|
||||
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);
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> mTopWindow;
|
||||
|
||||
nsSpatialNavigationService* mService;
|
||||
|
||||
PRBool mNavigationFramesState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class nsSpatialNavigationService: public nsIObserver
|
||||
{
|
||||
public:
|
||||
nsSpatialNavigationService();
|
||||
virtual ~nsSpatialNavigationService();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsCOMArray<nsISpatialNavigation> mObjects;
|
||||
|
||||
PRBool mEnabled;
|
||||
PRBool mIgnoreTextFields;
|
||||
PRBool mDisableJSWhenFocusing;
|
||||
|
||||
PRInt32 mKeyCodeLeft;
|
||||
PRInt32 mKeyCodeRight;
|
||||
PRInt32 mKeyCodeUp;
|
||||
PRInt32 mKeyCodeDown;
|
||||
PRInt32 mKeyCodeModifier;
|
||||
|
||||
};
|
||||
|
||||
extern PRInt32 gRectFudge;
|
||||
extern PRInt32 gDirectionalBias;
|
||||
|
||||
enum {
|
||||
eNavLeft = 0,
|
||||
eNavUp,
|
||||
eNavRight,
|
||||
eNavDown
|
||||
};
|
||||
|
||||
|
||||
// Utils
|
||||
|
||||
PRBool is_space (char c);
|
||||
nscoord* lo_parse_coord_list (char *str, PRInt32* value_cnt);
|
||||
nsresult createFrameTraversal (PRUint32 type, nsPresContext* presContext, nsIBidirectionalEnumerator** outTraversal);
|
||||
nsresult getEventTargetFromWindow (nsIDOMWindow* aWindow, nsIDOM3EventTarget** aEventTarget, nsIDOMEventGroup** aSystemGroup);
|
||||
void getContentFromFrame (nsIContent* c, nsIContent** outContent);
|
||||
nsresult getFrameForContent (nsIContent* aContent, nsIFrame** aFrame);
|
||||
PRBool isContentOfType (nsIContent* content, const char* type);
|
||||
PRBool isArea (nsIContent* content);
|
||||
PRBool isMap (nsIFrame* frame);
|
||||
PRBool isTargetable (PRBool focusDocuments, nsIFrame* frame);
|
||||
nsRect makeRectRelativeToGlobalView (nsIFrame *aFrame);
|
||||
void poly2Rect (int sides, nscoord* coord, nsRect* rect);
|
||||
void getRectOfAreaElement (nsIFrame* f, nsIDOMHTMLAreaElement* e, nsRect* r);
|
||||
PRBool isRectInDirection (int direction, nsRect& focusedRect, nsRect& frameRect);
|
||||
PRInt64 spatialDistance (int direction, nsRect& a, nsRect& b);
|
||||
void GetWindowFromDocument (nsIDOMDocument* aDocument, nsIDOMWindowInternal** aWindow);
|
||||
|
||||
|
||||
|
||||
class DisableJSScope
|
||||
{
|
||||
public:
|
||||
DisableJSScope(nsIDOMWindow* window) :
|
||||
isEnabled(PR_FALSE), scriptContext(nsnull)
|
||||
{
|
||||
// My passing null, we don't do a thing
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
// so, we want to set the focus to the next element, but
|
||||
// we do not want onFocus to fire. The reason for this is
|
||||
// that we want to have the "enter" key be able to trigger
|
||||
// the targeted link after we have focused it. However,
|
||||
// we have found a popular portal has a toolbar that, on
|
||||
// onFocus, decides to move the focus as if the targeted
|
||||
// content was clicked. The only way that I know how to
|
||||
// do this is to disable javascript during this call.
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo (do_QueryInterface(window));
|
||||
if (!sgo)
|
||||
return;
|
||||
|
||||
scriptContext = sgo->GetContext();
|
||||
if (!scriptContext)
|
||||
return;
|
||||
|
||||
isEnabled = scriptContext->GetScriptsEnabled();
|
||||
|
||||
if (isEnabled)
|
||||
scriptContext->SetScriptsEnabled(PR_FALSE, PR_TRUE);
|
||||
}
|
||||
|
||||
~DisableJSScope()
|
||||
{
|
||||
if (isEnabled && scriptContext)
|
||||
{
|
||||
// enable javascript again..
|
||||
scriptContext->SetScriptsEnabled(PR_TRUE, PR_TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
PRBool isEnabled;
|
||||
nsIScriptContext *scriptContext;
|
||||
};
|
||||
|
||||
|
||||
267
mozilla/extensions/spatialnavigation/src/nsSpatialNavigationService.cpp
Executable file
267
mozilla/extensions/spatialnavigation/src/nsSpatialNavigationService.cpp
Executable file
@@ -0,0 +1,267 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Spatial Navigation
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Douglas F. Turner II <dougt@meer.net>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004-2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsSpatialNavigationPrivate.h"
|
||||
|
||||
nsSpatialNavigationService::nsSpatialNavigationService()
|
||||
{
|
||||
mEnabled = PR_TRUE;
|
||||
mIgnoreTextFields = PR_TRUE;
|
||||
mDisableJSWhenFocusing = PR_TRUE;
|
||||
|
||||
mKeyCodeLeft = nsIDOMKeyEvent::DOM_VK_LEFT;
|
||||
mKeyCodeRight = nsIDOMKeyEvent::DOM_VK_RIGHT;
|
||||
mKeyCodeUp = nsIDOMKeyEvent::DOM_VK_UP;
|
||||
mKeyCodeDown = nsIDOMKeyEvent::DOM_VK_DOWN;
|
||||
|
||||
mKeyCodeModifier = 0x00000012 | 0x00100000; // By default ALT and SHIFT
|
||||
}
|
||||
|
||||
nsSpatialNavigationService::~nsSpatialNavigationService()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSpatialNavigationService, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSpatialNavigationService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!strcmp(aTopic,"domwindowopened"))
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> chromeWindow = do_QueryInterface(aSubject);
|
||||
|
||||
nsSpatialNavigation* sn = new nsSpatialNavigation(this);
|
||||
|
||||
if (!sn)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
sn->Init(chromeWindow);
|
||||
|
||||
mObjects.AppendObject(sn); // the array owns the only reference to sn.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic,"domwindowclosed"))
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> chromeWindow = do_QueryInterface(aSubject);
|
||||
// need to find it in our array
|
||||
|
||||
PRInt32 count = mObjects.Count();
|
||||
for (PRInt32 i = 0; i < count; i++)
|
||||
{
|
||||
nsISpatialNavigation* sn = mObjects[i];
|
||||
nsCOMPtr<nsIDOMWindow> attachedWindow;
|
||||
sn->GetAttachedWindow(getter_AddRefs(attachedWindow));
|
||||
|
||||
if (attachedWindow == chromeWindow)
|
||||
{
|
||||
sn->Shutdown();
|
||||
mObjects.RemoveObjectAt(i);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic,"xpcom-startup"))
|
||||
{
|
||||
nsCOMPtr<nsIWindowWatcher> windowWatcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
windowWatcher->RegisterNotification(this);
|
||||
|
||||
nsCOMPtr<nsIPrefBranchInternal> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
prefBranch->AddObserver("snav.", this, PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID))
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject);
|
||||
nsXPIDLCString cstr;
|
||||
|
||||
const char* pref = NS_ConvertUCS2toUTF8(aData).get();
|
||||
|
||||
if (!strcmp(pref, "snav.enabled"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mEnabled);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.ignoreTextFields"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mIgnoreTextFields);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.directionalBias"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &gDirectionalBias);
|
||||
if (gDirectionalBias == 0)
|
||||
gDirectionalBias = 1;
|
||||
}
|
||||
else if (!strcmp(pref, "snav.disableJS"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mDisableJSWhenFocusing);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.rectFudge"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &gRectFudge);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.keyCode.left"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mKeyCodeLeft);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.keyCode.right"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mKeyCodeRight);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.keyCode.up"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mKeyCodeUp);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.keyCode.down"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mKeyCodeDown);
|
||||
}
|
||||
else if (!strcmp(pref, "snav.keyCode.modifier"))
|
||||
{
|
||||
prefBranch->GetIntPref(pref, &mKeyCodeModifier);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// XPCOM REGISTRATION BELOW
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#define SpatialNavigation_CID \
|
||||
{ 0xd1b91385, 0xe1c1, 0x46ec, \
|
||||
{0x8d, 0x15, 0x88, 0x0c, 0x45, 0xbe, 0x8e, 0x0e} }
|
||||
|
||||
#define SpatialNavigation_ContractID "@mozilla.org/spatialNavigation/service;1"
|
||||
|
||||
#define SpatialNavigationService_CID \
|
||||
{ 0x4125624b, 0xaf22, 0x4d50, \
|
||||
{ 0x87, 0xf6, 0x40, 0x19, 0xc9, 0x85, 0x7b, 0x58} }
|
||||
|
||||
#define SpatialNavigationService_ContractID "@mozilla.org/spatialnavigation/service"
|
||||
|
||||
|
||||
static NS_METHOD SpatialNavigationServiceRegistration(nsIComponentManager *aCompMgr,
|
||||
nsIFile *aPath,
|
||||
const char *registryLocation,
|
||||
const char *componentType,
|
||||
const nsModuleComponentInfo *info)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
||||
nsCOMPtr<nsICategoryManager> catman;
|
||||
servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
|
||||
NS_GET_IID(nsICategoryManager),
|
||||
getter_AddRefs(catman));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
char* previous = nsnull;
|
||||
rv = catman->AddCategoryEntry("xpcom-startup",
|
||||
"SpatialNavigationService",
|
||||
SpatialNavigationService_ContractID,
|
||||
PR_TRUE,
|
||||
PR_TRUE,
|
||||
&previous);
|
||||
if (previous)
|
||||
nsMemory::Free(previous);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static NS_METHOD SpatialNavigationServiceUnregistration(nsIComponentManager *aCompMgr,
|
||||
nsIFile *aPath,
|
||||
const char *registryLocation,
|
||||
const nsModuleComponentInfo *info)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsICategoryManager> catman;
|
||||
servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
|
||||
NS_GET_IID(nsICategoryManager),
|
||||
getter_AddRefs(catman));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = catman->DeleteCategoryEntry("xpcom-startup",
|
||||
"SpatialNavigationService",
|
||||
PR_TRUE);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSpatialNavigationService)
|
||||
|
||||
|
||||
static const nsModuleComponentInfo components[] =
|
||||
{
|
||||
{ "SpatialNavigationService",
|
||||
SpatialNavigationService_CID,
|
||||
SpatialNavigationService_ContractID,
|
||||
nsSpatialNavigationServiceConstructor,
|
||||
SpatialNavigationServiceRegistration,
|
||||
SpatialNavigationServiceUnregistration
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE(SpatialNavigationModule, components)
|
||||
774
mozilla/extensions/spatialnavigation/src/nsSpatialNavigationUtils.cpp
Executable file
774
mozilla/extensions/spatialnavigation/src/nsSpatialNavigationUtils.cpp
Executable file
@@ -0,0 +1,774 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Spatial Navigation
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Douglas F. Turner II <dougt@meer.net>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004-2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsSpatialNavigationPrivate.h"
|
||||
#include "nsIFrameDebug.h"
|
||||
|
||||
PRBool is_space(char c)
|
||||
{
|
||||
return (c == ' ' || c == '\f' || c == '\n' ||
|
||||
c == '\r' || c == '\t' || c == '\v');
|
||||
}
|
||||
|
||||
nscoord* lo_parse_coord_list(char *str, PRInt32* value_cnt)
|
||||
{
|
||||
char *tptr;
|
||||
char *n_str;
|
||||
PRInt32 i, cnt;
|
||||
PRInt32 *value_list;
|
||||
|
||||
/*
|
||||
* Nothing in an empty list
|
||||
*/
|
||||
*value_cnt = 0;
|
||||
if (!str || *str == '\0')
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip beginning whitespace, all whitespace is empty list.
|
||||
*/
|
||||
n_str = str;
|
||||
while (is_space(*n_str))
|
||||
{
|
||||
n_str++;
|
||||
}
|
||||
if (*n_str == '\0')
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a pass where any two numbers separated by just whitespace
|
||||
* are given a comma separator. Count entries while passing.
|
||||
*/
|
||||
cnt = 0;
|
||||
while (*n_str != '\0')
|
||||
{
|
||||
PRBool has_comma;
|
||||
|
||||
/*
|
||||
* Skip to a separator
|
||||
*/
|
||||
tptr = n_str;
|
||||
while (!is_space(*tptr) && *tptr != ',' && *tptr != '\0')
|
||||
{
|
||||
tptr++;
|
||||
}
|
||||
n_str = tptr;
|
||||
|
||||
/*
|
||||
* If no more entries, break out here
|
||||
*/
|
||||
if (*n_str == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip to the end of the separator, noting if we have a
|
||||
* comma.
|
||||
*/
|
||||
has_comma = PR_FALSE;
|
||||
while (is_space(*tptr) || *tptr == ',')
|
||||
{
|
||||
if (*tptr == ',')
|
||||
{
|
||||
if (has_comma == PR_FALSE)
|
||||
{
|
||||
has_comma = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
tptr++;
|
||||
}
|
||||
/*
|
||||
* If this was trailing whitespace we skipped, we are done.
|
||||
*/
|
||||
if ((*tptr == '\0')&&(has_comma == PR_FALSE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Else if the separator is all whitespace, and this is not the
|
||||
* end of the string, add a comma to the separator.
|
||||
*/
|
||||
else if (has_comma == PR_FALSE)
|
||||
{
|
||||
*n_str = ',';
|
||||
}
|
||||
|
||||
/*
|
||||
* count the entry skipped.
|
||||
*/
|
||||
cnt++;
|
||||
|
||||
n_str = tptr;
|
||||
}
|
||||
/*
|
||||
* count the last entry in the list.
|
||||
*/
|
||||
cnt++;
|
||||
|
||||
/*
|
||||
* Allocate space for the coordinate array.
|
||||
*/
|
||||
value_list = new nscoord[cnt];
|
||||
if (!value_list)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second pass to copy integer values into list.
|
||||
*/
|
||||
tptr = str;
|
||||
for (i=0; i<cnt; i++)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = strchr(tptr, ',');
|
||||
if (ptr)
|
||||
{
|
||||
*ptr = '\0';
|
||||
}
|
||||
/*
|
||||
* Strip whitespace in front of number because I don't
|
||||
* trust atoi to do it on all platforms.
|
||||
*/
|
||||
while (is_space(*tptr))
|
||||
{
|
||||
tptr++;
|
||||
}
|
||||
if (*tptr == '\0')
|
||||
{
|
||||
value_list[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
value_list[i] = (nscoord) ::atoi(tptr);
|
||||
}
|
||||
if (ptr)
|
||||
{
|
||||
*ptr = ',';
|
||||
tptr = ptr + 1;
|
||||
}
|
||||
}
|
||||
|
||||
*value_cnt = cnt;
|
||||
return value_list;
|
||||
}
|
||||
|
||||
nsresult createFrameTraversal(PRUint32 type, nsPresContext* presContext,
|
||||
nsIBidirectionalEnumerator** outTraversal)
|
||||
{
|
||||
nsresult result;
|
||||
if (!presContext)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIPresShell* presShell = presContext->PresShell();
|
||||
if (!presShell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIFrame* frame = presShell->GetRootFrame();
|
||||
|
||||
if (!frame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
||||
|
||||
nsIFrameDebug* fd;
|
||||
frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**) &fd);
|
||||
if (fd)
|
||||
fd->List(frame->GetPresContext(), stdout, 0);
|
||||
|
||||
nsCOMPtr<nsIBidirectionalEnumerator> frameTraversal;
|
||||
|
||||
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
|
||||
nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID,&result));
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
result = trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
|
||||
type,
|
||||
presContext,
|
||||
frame);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
NS_IF_ADDREF(*outTraversal = frameTraversal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult getEventTargetFromWindow(nsIDOMWindow* aWindow, nsIDOM3EventTarget** aEventTarget, nsIDOMEventGroup** aSystemGroup)
|
||||
{
|
||||
*aEventTarget = nsnull;
|
||||
nsCOMPtr<nsPIDOMWindow> privateWindow = do_QueryInterface(aWindow);
|
||||
|
||||
if (!privateWindow)
|
||||
return NS_ERROR_UNEXPECTED; // assert
|
||||
|
||||
nsIChromeEventHandler *chromeEventHandler = privateWindow->GetChromeEventHandler();
|
||||
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(chromeEventHandler));
|
||||
if (!receiver)
|
||||
return NS_ERROR_UNEXPECTED; // assert
|
||||
|
||||
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||
nsCOMPtr<nsIDOM3EventTarget> target(do_QueryInterface(receiver));
|
||||
|
||||
if (!target || !systemGroup)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ADDREF(*aEventTarget = target);
|
||||
NS_ADDREF(*aSystemGroup = systemGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void getContentFromFrame(nsIContent* c, nsIContent** outContent)
|
||||
{
|
||||
*outContent = nsnull;
|
||||
|
||||
nsCOMPtr<nsIContent> result;
|
||||
nsCOMPtr<nsIDOMDocument> contentDocument;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLFrameElement> domFrameElement = do_QueryInterface(c);
|
||||
|
||||
if (domFrameElement) {
|
||||
domFrameElement->GetContentDocument(getter_AddRefs(contentDocument));
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDOMHTMLIFrameElement> domIFrameElement = do_QueryInterface(c);
|
||||
if (domIFrameElement)
|
||||
domIFrameElement->GetContentDocument(getter_AddRefs(contentDocument));
|
||||
}
|
||||
|
||||
if (contentDocument) {
|
||||
nsCOMPtr<nsIDOMElement> documentElement;
|
||||
contentDocument->GetDocumentElement(getter_AddRefs(documentElement));
|
||||
result = do_QueryInterface(documentElement);
|
||||
}
|
||||
NS_IF_ADDREF(*outContent = result);
|
||||
}
|
||||
|
||||
nsresult getFrameForContent(nsIContent* aContent, nsIFrame** aFrame)
|
||||
{
|
||||
*aFrame = nsnull;
|
||||
|
||||
if (!aContent)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIDocument* doc = aContent->GetDocument();
|
||||
if (!doc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIFrame* frame;
|
||||
nsIPresShell *presShell = doc->GetShellAt(0);
|
||||
presShell->GetPrimaryFrameFor(aContent, &frame);
|
||||
|
||||
if (!frame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aFrame = frame;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
isContentOfType(nsIContent* content, const char* type)
|
||||
{
|
||||
if (!content)
|
||||
return PR_FALSE;
|
||||
|
||||
nsINodeInfo *nodeInfo = content->GetNodeInfo();
|
||||
if (nodeInfo)
|
||||
{
|
||||
nsIAtom* atom = nodeInfo->NameAtom();
|
||||
if (atom)
|
||||
return atom->EqualsUTF8(nsDependentCString(type));
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
isArea(nsIContent* content)
|
||||
{
|
||||
if (!content || !content->IsContentOfType(nsIContent::eHTML))
|
||||
return PR_FALSE;
|
||||
|
||||
return isContentOfType(content, "area");
|
||||
}
|
||||
|
||||
PRBool
|
||||
isDocument(nsIFrame* frame)
|
||||
{
|
||||
nsIContent* content = frame->GetContent();
|
||||
|
||||
if (!content || !content->IsContentOfType(nsIContent::eHTML))
|
||||
return PR_FALSE;
|
||||
|
||||
return isContentOfType(content, "map");
|
||||
}
|
||||
|
||||
PRBool
|
||||
isMap(nsIFrame* frame)
|
||||
{
|
||||
nsIContent* content = frame->GetContent();
|
||||
|
||||
if (!content || !content->IsContentOfType(nsIContent::eHTML))
|
||||
return PR_FALSE;
|
||||
|
||||
return isContentOfType(content, "map");
|
||||
}
|
||||
|
||||
PRBool
|
||||
isTargetable(PRBool focusDocuments, nsIFrame* frame)
|
||||
{
|
||||
nsIContent* currentContent = frame->GetContent();
|
||||
|
||||
if (!currentContent)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!currentContent->IsContentOfType(nsIContent::eHTML))
|
||||
return PR_FALSE;
|
||||
|
||||
if (isContentOfType(currentContent, "map"))
|
||||
return PR_TRUE;
|
||||
|
||||
if (isContentOfType(currentContent, "a"))
|
||||
{
|
||||
// an anchor isn't targetable unless it has a non-null href.
|
||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement = do_QueryInterface(currentContent);
|
||||
nsAutoString uri;
|
||||
anchorElement->GetHref(uri);
|
||||
if (uri.IsEmpty()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFrameFrame> frameFrame(do_QueryInterface(frame));
|
||||
if (frameFrame)
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLIFrameElement> iFrameElement = do_QueryInterface(currentContent);
|
||||
if (iFrameElement)
|
||||
return PR_TRUE;
|
||||
|
||||
if (focusDocuments) {
|
||||
nsCOMPtr<nsIDOMHTMLHtmlElement> hhElement(do_QueryInterface(currentContent));
|
||||
if (hhElement)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// need to figure out how to determine if a element is
|
||||
// either disabled, hidden, or it is inaccessible due to
|
||||
// its parent being one of these.
|
||||
|
||||
PRBool disabled = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement = do_QueryInterface(currentContent);
|
||||
if (selectElement && NS_SUCCEEDED(selectElement->GetDisabled(&disabled)))
|
||||
return !disabled;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLOptionElement> optionElement = do_QueryInterface(currentContent);
|
||||
if (optionElement && NS_SUCCEEDED(optionElement->GetDisabled(&disabled)))
|
||||
return !disabled;
|
||||
|
||||
nsAutoString inputType;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(currentContent);
|
||||
if (inputElement && NS_SUCCEEDED(inputElement->GetDisabled(&disabled)) && NS_SUCCEEDED(inputElement->GetType(inputType)))
|
||||
return !disabled && (! inputType.EqualsIgnoreCase("hidden"));
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsRect makeRectRelativeToGlobalView(nsIFrame *aFrame)
|
||||
{
|
||||
nsRect result;
|
||||
result.SetRect(0,0,0,0);
|
||||
|
||||
nsPoint offset;
|
||||
|
||||
if (!aFrame)
|
||||
return result;
|
||||
|
||||
result = aFrame->GetRect();
|
||||
|
||||
nsIView* view;
|
||||
aFrame->GetOffsetFromView(offset, &view);
|
||||
|
||||
nsIView* rootView = nsnull;
|
||||
if (view) {
|
||||
nsIViewManager* viewManager = view->GetViewManager();
|
||||
NS_ASSERTION(viewManager, "View must have a viewmanager");
|
||||
viewManager->GetRootView(rootView);
|
||||
}
|
||||
while (view) {
|
||||
offset += view->GetPosition();
|
||||
if (view == rootView) {
|
||||
break;
|
||||
}
|
||||
view = view->GetParent();
|
||||
}
|
||||
|
||||
result.MoveTo(offset);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void poly2Rect(int sides, nscoord* coord, nsRect* rect)
|
||||
{
|
||||
nscoord x1, x2, y1, y2, xtmp, ytmp;
|
||||
x1 = x2 = coord[0];
|
||||
y1 = y2 = coord[1];
|
||||
for (PRInt32 i = 2; i < sides; i += 2)
|
||||
{
|
||||
xtmp = coord[i];
|
||||
ytmp = coord[i+1];
|
||||
x1 = x1 < xtmp ? x1 : xtmp;
|
||||
y1 = y1 < ytmp ? y1 : ytmp;
|
||||
x2 = x2 > xtmp ? x2 : xtmp;
|
||||
y2 = y2 > ytmp ? y2 : ytmp;
|
||||
}
|
||||
rect->SetRect(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void getRectOfAreaElement(nsIFrame* f, nsIDOMHTMLAreaElement* e, nsRect* r)
|
||||
{
|
||||
if (!f || !e || !r)
|
||||
return;
|
||||
|
||||
// RECT !!
|
||||
nsRect frameRect = makeRectRelativeToGlobalView(f);
|
||||
|
||||
if (frameRect.width == 0)
|
||||
frameRect.width = 1;
|
||||
if (frameRect.height == 0)
|
||||
frameRect.height = 1;
|
||||
|
||||
nsPoint offset;
|
||||
offset.x = frameRect.x;
|
||||
offset.y = frameRect.y;
|
||||
|
||||
|
||||
nsAutoString coordstr;
|
||||
e->GetCoords(coordstr);
|
||||
|
||||
NS_ConvertUTF16toUTF8 cp (coordstr);
|
||||
|
||||
PRInt32 count;
|
||||
nscoord* coords = lo_parse_coord_list((char*) cp.get(), &count);
|
||||
|
||||
// FIX what about other shapes?
|
||||
|
||||
if (count == 4)
|
||||
{
|
||||
// x y width height
|
||||
frameRect.SetRect(coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1]);
|
||||
|
||||
frameRect.x += offset.x;
|
||||
frameRect.y += offset.y;
|
||||
}
|
||||
else if (count >=6)
|
||||
poly2Rect(count, coords, &frameRect);
|
||||
else
|
||||
printf("area count not supported!! %d\n", count);
|
||||
|
||||
// find the center of the rect.
|
||||
|
||||
frameRect.x = frameRect.x + (frameRect.width / 2) - 1;
|
||||
frameRect.width = 2;
|
||||
frameRect.y = frameRect.y + (frameRect.height / 2) - 1;
|
||||
frameRect.height = 2;
|
||||
|
||||
*r = frameRect;
|
||||
}
|
||||
|
||||
// we want to determine if going in the |direction|
|
||||
// direction from focusedRect will intercept the frameRect
|
||||
|
||||
PRBool isRectInDirection(int direction, nsRect& focusedRect, nsRect& frameRect)
|
||||
{
|
||||
if (direction == eNavLeft)
|
||||
{
|
||||
return (frameRect.x < focusedRect.x);
|
||||
}
|
||||
|
||||
if (direction == eNavRight)
|
||||
{
|
||||
return (frameRect.x + frameRect.width > focusedRect.x + focusedRect.width);
|
||||
}
|
||||
|
||||
if (direction == eNavUp)
|
||||
{
|
||||
return (frameRect.y < focusedRect.y);
|
||||
}
|
||||
|
||||
if (direction == eNavDown)
|
||||
{
|
||||
return (frameRect.y + frameRect.height > focusedRect.y + focusedRect.height);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRInt64 spatialDistance(int direction, nsRect& a, nsRect& b)
|
||||
{
|
||||
PRBool inlineNavigation = PR_FALSE;
|
||||
nsPoint m, n;
|
||||
|
||||
if (direction == eNavLeft)
|
||||
{
|
||||
// |---|
|
||||
// |---|
|
||||
//
|
||||
// |---| |---|
|
||||
// |---| |---|
|
||||
//
|
||||
// |---|
|
||||
// |---|
|
||||
//
|
||||
|
||||
if (a.y > b.y + b.height)
|
||||
{
|
||||
// the b rect is above a.
|
||||
m.x = a.x;
|
||||
m.y = a.y;
|
||||
n.x = b.x + b.width;
|
||||
n.y = b.y + b.height;
|
||||
}
|
||||
else if (a.y + a.height < b.y)
|
||||
{
|
||||
// the b rect is below a.
|
||||
m.x = a.x;
|
||||
m.y = a.y + a.height;
|
||||
n.x = b.x + b.width;
|
||||
n.y = b.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.x = a.x;
|
||||
m.y = 0;
|
||||
n.x = b.x + b.width;
|
||||
n.y = 0;
|
||||
|
||||
// m.x = (a.x + (a.width / 2));
|
||||
// m.y = (a.y + (a.height / 2));
|
||||
// n.x = (b.x + (b.width / 2));
|
||||
// n.y = (b.y + (b.height / 2));
|
||||
|
||||
}
|
||||
}
|
||||
else if (direction == eNavRight)
|
||||
{
|
||||
|
||||
// |---|
|
||||
// |---|
|
||||
//
|
||||
// |---| |---|
|
||||
// |---| |---|
|
||||
//
|
||||
// |---|
|
||||
// |---|
|
||||
//
|
||||
|
||||
if (a.y > b.y + b.height)
|
||||
{
|
||||
// the b rect is above a.
|
||||
m.x = a.x + a.width;
|
||||
m.y = a.y;
|
||||
n.x = b.x;
|
||||
n.y = b.y + b.height;
|
||||
}
|
||||
else if (a.y + a.height < b.y)
|
||||
{
|
||||
// the b rect is below a.
|
||||
m.x = a.x + a.width;
|
||||
m.y = a.y + a.height;
|
||||
n.x = b.x;
|
||||
n.y = b.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.x = a.x + a.width;
|
||||
m.y = 0;
|
||||
n.x = b.x;
|
||||
n.y = 0;
|
||||
|
||||
// m.x = (a.x + (a.width / 2));
|
||||
// m.y = (a.y + (a.height / 2));
|
||||
// n.x = (b.x + (b.width / 2));
|
||||
// n.y = (b.y + (b.height / 2));
|
||||
}
|
||||
}
|
||||
else if (direction == eNavUp)
|
||||
{
|
||||
|
||||
// |---| |---| |---|
|
||||
// |---| |---| |---|
|
||||
//
|
||||
// |---|
|
||||
// |---|
|
||||
//
|
||||
|
||||
if (a.x > b.x + b.width)
|
||||
{
|
||||
// the b rect is to the left of a.
|
||||
m.x = a.x;
|
||||
m.y = a.y;
|
||||
n.x = b.x + b.width;
|
||||
n.y = b.y + b.height;
|
||||
}
|
||||
else if (a.x + a.width < b.x)
|
||||
{
|
||||
// the b rect is to the right of a
|
||||
m.x = a.x + a.width;
|
||||
m.y = a.y;
|
||||
n.x = b.x;
|
||||
n.y = b.y + b.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
// both b and a share some common x's.
|
||||
m.x = 0;
|
||||
m.y = a.y;
|
||||
n.x = 0;
|
||||
n.y = b.y + b.height;
|
||||
|
||||
// m.x = (a.x + (a.width / 2));
|
||||
// m.y = (a.y + (a.height / 2));
|
||||
// n.x = (b.x + (b.width / 2));
|
||||
// n.y = (b.y + (b.height / 2));
|
||||
}
|
||||
}
|
||||
else if (direction == eNavDown)
|
||||
{
|
||||
// |---|
|
||||
// |---|
|
||||
//
|
||||
// |---| |---| |---|
|
||||
// |---| |---| |---|
|
||||
//
|
||||
|
||||
if (a.x > b.x + b.width)
|
||||
{
|
||||
// the b rect is to the left of a.
|
||||
m.x = a.x;
|
||||
m.y = a.y + a.height;
|
||||
n.x = b.x + b.width;
|
||||
n.y = b.y;
|
||||
}
|
||||
else if (a.x + a.width < b.x)
|
||||
{
|
||||
// the b rect is to the right of a
|
||||
m.x = a.x + a.width;
|
||||
m.y = a.y + a.height;
|
||||
n.x = b.x;
|
||||
n.y = b.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// both b and a share some common x's.
|
||||
m.x = 0;
|
||||
m.y = a.y + a.height;
|
||||
n.x = 0;
|
||||
n.y = b.y;
|
||||
|
||||
// m.x = (a.x + (a.width / 2));
|
||||
// m.y = (a.y + (a.height / 2));
|
||||
// n.x = (b.x + (b.width / 2));
|
||||
// n.y = (b.y + (b.height / 2));
|
||||
}
|
||||
}
|
||||
|
||||
// a is always the currently focused rect.
|
||||
|
||||
nsRect scopedRect = a;
|
||||
scopedRect.Inflate(gRectFudge, gRectFudge);
|
||||
|
||||
if (direction == eNavLeft)
|
||||
{
|
||||
scopedRect.x = 0;
|
||||
scopedRect.width = nscoord_MAX;
|
||||
if (scopedRect.Intersects(b))
|
||||
inlineNavigation = PR_TRUE;
|
||||
}
|
||||
else if (direction == eNavRight)
|
||||
{
|
||||
scopedRect.width = nscoord_MAX;
|
||||
if (scopedRect.Intersects(b))
|
||||
inlineNavigation = PR_TRUE;
|
||||
}
|
||||
else if (direction == eNavUp)
|
||||
{
|
||||
scopedRect.y = 0;
|
||||
scopedRect.height = nscoord_MAX;
|
||||
if (scopedRect.Intersects(b))
|
||||
inlineNavigation = PR_TRUE;
|
||||
}
|
||||
else if (direction == eNavDown)
|
||||
{
|
||||
scopedRect.height = nscoord_MAX;
|
||||
if (scopedRect.Intersects(b))
|
||||
inlineNavigation = PR_TRUE;
|
||||
}
|
||||
|
||||
PRInt64 d = ((m.x-n.x)*(m.x-n.x)) + ((m.y-n.y)*(m.y-n.y));
|
||||
|
||||
if(d<0)
|
||||
d=d*(-1);
|
||||
|
||||
if (inlineNavigation)
|
||||
d /= gDirectionalBias;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void GetWindowFromDocument(nsIDOMDocument* aDocument, nsIDOMWindowInternal** aWindow)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocumentView> docview = do_QueryInterface(aDocument);
|
||||
|
||||
nsCOMPtr<nsIDOMAbstractView> view;
|
||||
docview->GetDefaultView(getter_AddRefs(view));
|
||||
if (!view) return;
|
||||
|
||||
nsCOMPtr<nsIDOMWindowInternal> window = do_QueryInterface(view);
|
||||
NS_IF_ADDREF(*aWindow = window);
|
||||
}
|
||||
272
mozilla/extensions/spatialnavigation/test/Spatial_Navigation_Test_Cases.html
Executable file
272
mozilla/extensions/spatialnavigation/test/Spatial_Navigation_Test_Cases.html
Executable file
@@ -0,0 +1,272 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type"
|
||||
content="text/html; charset=ISO-8859-1">
|
||||
<title>Spatial Navigation Test Cases</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="margin-left: 40px; text-align: center;">
|
||||
<h1 style="text-align: left;"><a name="mozTocId276802" class="mozTocH1"></a>Spatial
|
||||
Navigation Fun</h1>
|
||||
<h2 style="text-align: left;"><br>
|
||||
</h2>
|
||||
<div style="text-align: left;"><br>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<h2 style="text-align: left;"><a name="mozTocId192805" class="mozTocH2"></a>3x3
|
||||
Centered Table Test</h2>
|
||||
</div>
|
||||
<table
|
||||
style="text-align: left; width: 100%; margin-left: auto; margin-right: auto;"
|
||||
border="1" cellpadding="2" cellspacing="2">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
<td style="vertical-align: top; text-align: center;"><a href="a">test</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="margin-left: 40px; text-align: center;"><br>
|
||||
<br>
|
||||
<div style="text-align: left;">
|
||||
<h2><a name="mozTocId557796" class="mozTocH2"></a>Vertical Sine Test</h2>
|
||||
<br>
|
||||
</div>
|
||||
<div style="text-align: left;"><a href="a">test<br>
|
||||
</a>
|
||||
<div style="margin-left: 40px;"><a href="a">test<br>
|
||||
</a></div>
|
||||
<div style="margin-left: 80px;"><a href="a">test<br>
|
||||
</a></div>
|
||||
<div style="margin-left: 40px;"><a href="a">test<br>
|
||||
</a></div>
|
||||
<a href="a">test<br>
|
||||
</a>
|
||||
<div style="margin-left: 40px;"><a href="a">test<br>
|
||||
</a></div>
|
||||
<div style="margin-left: 80px;"><a href="a">test<br>
|
||||
</a></div>
|
||||
<div style="margin-left: 40px;"><a href="a">test<br>
|
||||
</a></div>
|
||||
<a href="a">test<br>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="a">test<br>
|
||||
</a><br>
|
||||
<br>
|
||||
<br>
|
||||
<h2><a name="mozTocId261391" class="mozTocH2"></a>Increasing sentence
|
||||
length</h2>
|
||||
<br>
|
||||
<a href="a">H</a><br>
|
||||
<a href="p">Ho<br>
|
||||
</a><a href="p">How<br>
|
||||
</a><a href="p">How <br>
|
||||
</a><a href="p">How N</a><br>
|
||||
<a href="p">How No</a><br>
|
||||
<a href="p">How Now</a><br>
|
||||
<a href="p">How Now </a><br>
|
||||
<a href="p">How Now B</a><br>
|
||||
<a href="p">How Now Br</a><br>
|
||||
<a href="p">How Now Bro</a><br>
|
||||
<a href="p">How Now Brow</a><br>
|
||||
<a href="p">How Now Brown</a><br>
|
||||
<a href="p">How Now Brown </a><br>
|
||||
<a href="p">How Now Brown C</a><br>
|
||||
<a href="p">How Now Brown Co</a><br>
|
||||
<a href="p">How Now Brown Cow</a><br>
|
||||
<br>
|
||||
<h2><a name="mozTocId100946" class="mozTocH2"></a>Split sentence<br>
|
||||
</h2>
|
||||
<br>
|
||||
<a href="p">H</a>
|
||||
|
||||
<a href="p">ow Now Brown Cow</a><br>
|
||||
<a href="p">Ho</a>
|
||||
|
||||
<a href="p">w
|
||||
Now Brown Cow</a><br>
|
||||
<a href="p">How</a>
|
||||
|
||||
<a href="p">Now Brown Cow</a><br>
|
||||
<a href="p">How N</a>
|
||||
<a
|
||||
href="p">ow Brown Cow</a><br>
|
||||
<a href="p">How No</a>
|
||||
|
||||
<a href="p">w Brown Cow</a><br>
|
||||
<a href="p">How Now </a>
|
||||
|
||||
<a href="p">Brown Cow</a><br>
|
||||
<a href="p">How Now B</a>
|
||||
|
||||
<a href="p">rown Cow</a><br>
|
||||
<a href="p">How Now Br</a>
|
||||
|
||||
<a href="p">own Cow</a><br>
|
||||
<a href="p">How Now Bro</a>
|
||||
|
||||
<a href="p">wn Cow</a><br>
|
||||
<a href="p">How Now Brow</a>
|
||||
<a href="p">n Cow</a><br>
|
||||
<a href="p">How Now Brown</a>
|
||||
|
||||
<a href="p">Cow</a><br>
|
||||
<a href="p">How Now Brown C</a>
|
||||
|
||||
<a href="p">ow</a><br>
|
||||
<a href="p">How Now Brown Co</a>
|
||||
|
||||
<a href="p">w</a><br>
|
||||
<a href="p">How Now Brown Cow</a><br>
|
||||
<br>
|
||||
<br>
|
||||
<h2>Line Wrap Test</h2>
|
||||
<br>
|
||||
<table style="text-align: left; width: 393px; height: 72px;" border="1"
|
||||
cellpadding="2" cellspacing="2">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="vertical-align: top;"><span class="huge"><a href="a">Which
|
||||
of the following constanst do you like the most, one is g, one is pi,
|
||||
and the other is e. </a><br>
|
||||
</span></td>
|
||||
<td style="vertical-align: top;"><a href="a">3.14</a><br>
|
||||
<a href="a">2.71</a><br>
|
||||
<a href="a">6.67</a><br>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h2><a name="mozTocId625391" class="mozTocH2"></a>Javascript Hover Test</h2>
|
||||
When going from any link to the following link, you should NOT get an
|
||||
alert dialog. However, if you mouse over this link, you should
|
||||
see a dialog.<br>
|
||||
<br>
|
||||
<a href="a" onmouseover='alert("onMouseOver")'
|
||||
onmouseout='alert("onMouseOut")'>Test</a><br>
|
||||
<br>
|
||||
<h2><a name="mozTocId272030" class="mozTocH2"></a>Overlapped Anchors</h2>
|
||||
<br>
|
||||
<table style="text-align: left; width: 100%;" border="1" cellpadding="2"
|
||||
cellspacing="2">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="vertical-align: top;">
|
||||
<div style="text-align: left;"><a href="a"><img
|
||||
src="mozilla-star.png"
|
||||
title="" alt="" style="border: 0px solid ; width: 57px; height: 57px;"></a><a
|
||||
href="a"><img
|
||||
src="mozilla-star.png"
|
||||
title="" alt="" style="border: 0px solid ; width: 57px; height: 57px;"
|
||||
hspace="0"></a><br>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<br>
|
||||
<h2><a name="mozTocId16012" class="mozTocH2"></a>Area Tag (Rect)<br>
|
||||
</h2>
|
||||
<br>
|
||||
<br>
|
||||
<img src="mozilla-star.png" title="" alt=""
|
||||
style="width: 513px; height: 513px;"><br>
|
||||
<br>
|
||||
<h2><a name="mozTocId922752" class="mozTocH2"></a>Area Tag (Circle)<br>
|
||||
</h2>
|
||||
<br>
|
||||
<br>
|
||||
<img
|
||||
src="mozilla-star.png"
|
||||
title="" alt="" style="width: 513px; height: 513px;"><br>
|
||||
<br>
|
||||
<h2><a name="mozTocId216319" class="mozTocH2"></a>Area Tag (Polygon)<br>
|
||||
</h2>
|
||||
<br>
|
||||
<br>
|
||||
<img
|
||||
src="mozilla-star.png"
|
||||
title="" alt="" style="height: 513px; width: 513px;"><br>
|
||||
<br>
|
||||
<br>
|
||||
<a href="http://www.visa.com/globalgateway/gg_map.html">A
|
||||
nice poly test case</a>
|
||||
<br>
|
||||
<h2>FrameSets</h2>
|
||||
<br>
|
||||
<frameset cols="25%,25%,*">
|
||||
<frame src="links.html" />
|
||||
<frame src="links.html" />
|
||||
<frame src="links.html" />
|
||||
</frameset>
|
||||
<br>
|
||||
<br>
|
||||
<h2>IFrames</h2>
|
||||
<br>
|
||||
<iframe src="links.html"></iframe> <br>
|
||||
<br>
|
||||
<br>
|
||||
<h2>DIVs</h2>
|
||||
<br>
|
||||
<div id=v>
|
||||
<a href="a">a</a>
|
||||
<div id="Div1">
|
||||
<a href="a">a</a>
|
||||
</div>
|
||||
<a href="a">a</a>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
<a href="last">last</a>
|
||||
|
||||
|
||||
<p>
|
||||
<p> A select example
|
||||
<FORM ACTION="SelectExample" METHOD="POST">
|
||||
<SELECT NAME="parameter" SIZE=1>
|
||||
<OPTION VALUE="value1" SELECTED> first setting </OPTION>
|
||||
<OPTION VALUE="value2"> second setting </OPTION>
|
||||
</SELECT>
|
||||
<INPUT TYPE="Submit" NAME="Submit" VALUE="Evaluate">
|
||||
</FORM>
|
||||
<p>
|
||||
<p> A option example
|
||||
|
||||
<FORM ACTION="OptionExample" METHOD="POST">
|
||||
<SELECT NAME="a" SIZE=10>
|
||||
<OPTION>a
|
||||
<OPTION>b
|
||||
<OPTION>c
|
||||
<OPTION>d
|
||||
<OPTION>e
|
||||
<OPTION>f
|
||||
<OPTION>g
|
||||
</SELECT>
|
||||
<p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
2
mozilla/extensions/spatialnavigation/test/a.html
Executable file
2
mozilla/extensions/spatialnavigation/test/a.html
Executable file
@@ -0,0 +1,2 @@
|
||||
<iframe src="links.html"></iframe> <br>
|
||||
<a href="a">a</a>
|
||||
9
mozilla/extensions/spatialnavigation/test/links.html
Executable file
9
mozilla/extensions/spatialnavigation/test/links.html
Executable file
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<p>
|
||||
<a href="a">a</a>
|
||||
<a href="a">a</a>
|
||||
<a href="a">a</a>
|
||||
</body>
|
||||
</html>
|
||||
BIN
mozilla/extensions/spatialnavigation/test/mozilla-star.png
Executable file
BIN
mozilla/extensions/spatialnavigation/test/mozilla-star.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
107
mozilla/extensions/spatialnavigation/test/prefs.txt
Executable file
107
mozilla/extensions/spatialnavigation/test/prefs.txt
Executable file
@@ -0,0 +1,107 @@
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.enabled
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.ignoreTextFields
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
This preference when enabled will ensure that text fields
|
||||
and inputs retain focus even if spatial navigation was
|
||||
requested.
|
||||
|
||||
Default: TRUE
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.directionalBias
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
When calculating distances between elements on the screen,
|
||||
elements may be given a bias if the elements are in the
|
||||
direction of navigation. The bias is a given by a fraction
|
||||
such that:
|
||||
|
||||
bias distance = true distance / directional bias
|
||||
|
||||
DEFAULT: 3
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.disableJS
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
Disable onFocus event that an element may recieve during
|
||||
spatial navigation. On some pages we have found that the
|
||||
page decides to move the focus as if the targeted content
|
||||
was clicked. This may lead to an undesirable behavior.
|
||||
|
||||
DEFAULT: TRUE
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.rectFudge
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
To reduce the chance that a element overlaps with another
|
||||
element, we reduce the elements height and width by this
|
||||
value.
|
||||
|
||||
DEFAULT: 20
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.keyCode.left
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
This preference is the key code which corresponds to the
|
||||
left direction.
|
||||
|
||||
DEFAULT: DOM_VK_LEFT
|
||||
SEE: nsIDOMKeyEvent
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.keyCode.right
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
This preference is the key code which corresponds to the
|
||||
right direction.
|
||||
|
||||
DEFAULT: DOM_VK_RIGHT
|
||||
SEE: nsIDOMKeyEvent
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.keyCode.up
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
This preference is the key code which corresponds to the
|
||||
up direction.
|
||||
|
||||
DEFAULT: DOM_VK_UP
|
||||
SEE: nsIDOMKeyEvent
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.keyCode.down
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
This preference is the key code which corresponds to the
|
||||
down direction.
|
||||
|
||||
DEFAULT: DOM_VK_DOWN
|
||||
SEE: nsIDOMKeyEvent
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// snav.keyCode.modifier
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
This preference is the key code which corresponds to the
|
||||
required modifier keys. These values are given as follows:
|
||||
|
||||
NONE = 0
|
||||
SHIFT = 0x00100000
|
||||
CONTROL = 0x00001100
|
||||
ALT = 0x00000012
|
||||
|
||||
|
||||
DEFAULT: ALT | SHIFT
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user