[webkit-reviews] review requested: [Bug 18662] Extend keyboard navigation to allow directional navigation : [Attachment 49463] Add directional navigation to WebCore (v15)

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Wed Feb 24 19:59:31 PST 2010


Antonio Gomes (tonikitoo) <tonikitoo at webkit.org> has asked  for review:
Bug 18662: Extend keyboard navigation to allow directional navigation
https://bugs.webkit.org/show_bug.cgi?id=18662

Attachment 49463: Add directional navigation to WebCore (v15)
https://bugs.webkit.org/attachment.cgi?id=49463&action=review

------- Additional Comments from Antonio Gomes (tonikitoo)
<tonikitoo at webkit.org>
Addressed most of Simon's comments.

(In reply to comment #63)
> (From update of attachment 49074 [details])
> > +	 FocusDirection focusDirectionForKey(const AtomicString&);
> 
> This method should be |const|

Fixed.
 
> > +	     FocusDirection tabDirection = (FocusDirectionUp || direction ==
FocusDirectionLeft) ?
> > +					    FocusDirectionForward :
FocusDirectionBackward;
> 
> Shouldn't this be:
> 
>   FocusDirection tabDirection = ( direction == FocusDirectionUp || direction
==
> FocusDirectionLeft)
> ?

Fixed. Not sure how I miss that for so long.

> > +	 // Move up in the chain of nested frames.
> > +	 frame = frame->tree()->top();
> 
> I don't undersand this. Why jump to the topmost frame?

Simon, the logic used here relies on a top-down traversal algorithm
to walk through all keyboard focusable elements in the dom tree,
looking the "closest" node. That is why it goes to the top one
in before all.

> > +	     if (!(isMovingToRootDocument(focusedNode, candidate)
> > +		 && (closestFocusCandidate.node
> > +		 && (focusedNode->document() ==
closestFocusCandidate.node->document())))) {
> 
> You don't need so many parens here.

Fixed.

> >  namespace WebCore {
> >	 enum FocusDirection {
> >	     FocusDirectionForward = 0,
> > -	     FocusDirectionBackward
> > +	     FocusDirectionBackward,
> > +	     FocusDirectionNone,
> > +	     FocusDirectionUp,
> > +	     FocusDirectionDown,
> > +	     FocusDirectionLeft,
> > +	     FocusDirectionRight
> >	 };
> 
> Would making FocusDirectionNone have value 0 break anything? It would be
> preferable.

Fixed. It does not break anything, and indeed looks better.

> > +++ b/WebCore/page/SpatialNavigation.cpp
> 
> > +namespace WebCore {
> > +
> > +long long spatialDistance(FocusDirection, const IntRect&, const IntRect&);

> > +IntRect renderRectRelativeToRootDocument(RenderObject*);
> > +RectsAlignment alignmentForRects(FocusDirection, const IntRect&, const
IntRect&);
> > +bool areRectsFullyAligned(FocusDirection, const IntRect&, const IntRect&);

> > +bool areRectsPartiallyAligned(FocusDirection, const IntRect&, const
IntRect&);
> > +bool isRectInDirection(FocusDirection, const IntRect&, const IntRect&);
> 
> I'm not sure if we normally declare file-local functions as 'static'. Take a
> look at some other files to see.

Fixed. Made all file-local functions static.

> 
> > +// FIXME_tonikitoo: FocusCandidate distanceDataForNode(start, dest,
direction)
> It's not clear what the action item is.

Fixed. Comment removed.

> > +long long distanceInDirection(Node* start, Node* dest, FocusDirection
direction, FocusCandidate& candidate)
> > +{
> > +	 long long& distance = candidate.distance;
> 
> You set distance to be a reference to candidate.distance here...
> 
> > +	     // Reset distance if we are now in higher precedence case.
> > +	     if (candidate.alignment < alignment && candidate.parentAlignment <
alignment)
> > +		 distance = cMaxDistance;
> 
> and then assign to it lower down. Why use the reference at all? This is hard
to
> follow.

Right the logic here is: in case we find a node with a higher focus precedence
than the current best focus candidate (e.g. totally or partially aligned), 
we want to take that node regardless its distance. So I set current best
candidate
node's current distance to the maximum possible value, which makes me sure that
any
distance we get from |spatialDistance| later on is shorter.

I modified to comment in the code to better reflect that.

> > +	     // FIXME_tonikitoo: make this assignment in the caller method ?
> 
> Either do it, or remove the FIXME.

Removed.

> We would normally put braces at if (useScrollOffset) {

Fixed.

> > +#define MIDDLE(direction, rect)	   \
> > +	 isHorizontalMove(direction) ?	   \
> > +	     rect.y() + rect.height() / 2: \
> > +	     rect.x() + rect.width()  / 2;
> > +
> > +#define END(direction, rect)	   \
> > +	 isHorizontalMove(direction) ?	   \
> > +	     rect.y() + rect.height() :    \
> > +	     rect.x() + rect.width();
> > +
> > +#define START(direction, rect)	   \
> > +	 isHorizontalMove(direction) ? rect.y() : rect.x();
> 
> Please convert these into inline functions.

Fixed. static inline functions added.

> > +// This method checks if rects |a| and |b| are fully aligned either
vertical or
> 
> vertically

Fixed.

> > +// In essence, targets whose middle falls between the top or bottom of the
current rect.
> 
> This isn't a complete sentence.

Fixed.

> > +	 // About the logic below:
> 
> What about it?

Fixed. Comment added in the code.

> > +// * a = Current focused node.
> > +// * b = Focus candidate node.
> 
> In all these methods, rather than commenting what a and b are, you should
just
> name them appropriately: curRect, targetRect, or something.

I agree w/ you, but it could make code harder to read, imho.
And comment is used three times, not much, again imho.
So in this round, I opted to leave it was it was, but if you
really prefer I can fix it as you wish. 
 
> > +	     if (a.y() > b.y() + b.height()) {
> 
> use IntRect:bottom(), IntRect:right() here and in all these methods.

Fixed.

> You could also define some inline methods like:
> 
> bool below(const IntRect& r, int pos)
> {
>   return pos > r.bottom();
> }

Added:
   static inline bool belowOf(const intrect& rect a , const intrect& rect b)
and a correspondent |rightOf| function. is that ok ?

> to make this code more readable. You could also add IntPoint
IntRect::center()
> const if you like (FloatRect has one).

Done in bug 35346.

> > +bool isMovingToRootDocument(Node* from, Node* to)
> > +{
> > +	 if (!from || !to)
> > +	     return false;
> > +
> > +	 Document* rootDocument =
to->document()->page()->mainFrame()->document();
> > +	 return (to->document() == rootDocument && from->document() !=
to->document());
> > +}
> 
> The 'moving to' terminology is confusing. I think this would be clearer with:

> 
> bool isInRootDocument(Node*)
> and then put the other logic at the call site.

Fixed. Done.

> > +void deflateIfNeeded(IntRect& a, IntRect& b, int fudgeFactor)
> If needed for what?

I think comments in the caller site says it. See:

    // The bounding rectangle of two consecutive nodes can overlap. In such
cases,
    // deflate both.
    deflateIfOverlapped(curRect, targetRect);

btw, i renamed function to |deflateIfOverlapped|.

> I think this needs one more round of changes.

very helpful review. thx


More information about the webkit-reviews mailing list