[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    Re: [PATCH]  various nodeAtPoint() fixes
From:       Germain Garand <germain () ebooksfrance ! com>
Date:       2002-07-15 6:04:53
[Download RAW message or body]

Le Samedi 13 Juillet 2002 19:19, Dirk Mueller a écrit :
[..]
> > - 1°: relative coordinates change don't propagate recursively to
> > childrens. (I posted this last week on kfm-devel but noone replied so
> > it's still pending)
>
> Yes, this was partly intended. I think I remember an interaction with
> absolute positioned containers in relative positioned parents.

I've tried to do something like that here :
http://www.phoenix-library.org/germain/testcases/bug_khtml_abs_child_in_rel_parent.html

Oddly enough, in such a case, the absolute translation is not rendered, but 
nodeAtPoint() still think the link is were it should be : in the small golden 
box.

>
> Personally i think khtml is behaving correct in this case, although it is
> very annoying for the example page you mentioned (I've spend some hours on
> that page already)
>

Frankly I think not... I've been haunted all the WE by that...

I'll elaborate, still on the http://www.w3.org/Style/CSS/ example :

When you hover the invisibly covered part of "What's New ?", the innermost 
node is indeed, formally, <P>.

But how is it that the tree walking continues and finally elects "What's New" 
as a good candidate for the hand cursor ?
From the formal point of view, the search should stop at <P>...
A striking illustration of that is when you hover "nearby" in the fixed menu. 
Should we really get "What's New"'s hand cursor ?

What I want to advocate here is : there is a need to distinguish between two 
kind of inner nodes :

- formal ones ("P" is indeed the innermost node, may it be invisible or 
opaque) [owner: innerNode] 
- visual ones ( for human sight, the innermost node is the "A" tag. If "P" was 
overriding something on "A", it would be "P") [owner: visualNode]

In fact, khtml already does this distinction with URLElement, since it can be 
different from the innerNode (too bad it's only for URLs).

I've implemented roughly such a mechanism in the attached patch,
and it looks promizing...
For instance, try comparing the behaviour on this slightly modified version :
http://www.phoenix-library.org/germain/testcases/www.w3.org/Style/CSS/          
 
Anyway, feel free to have a look or simply throw it to the overcrowded Hell of 
Lame ! ;-)

Germain

["render_object.patch" (text/x-diff)]

Index: render_object.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_object.h,v
retrieving revision 1.127
diff -u -p -r1.127 render_object.h
--- render_object.h	2002/06/16 15:23:47	1.127
+++ render_object.h	2002/07/15 05:53:25
@@ -281,19 +281,22 @@ public:
         friend class DOM::HTMLAreaElementImpl;
     public:
         NodeInfo(bool readonly, bool active)
-            : m_innerNode(0), m_innerURLElement(0), m_readonly(readonly), \
m_active(active) +            : m_innerNode(0), m_visualNode(0), \
m_innerURLElement(0), m_readonly(readonly), m_active(active)  { }
 
         DOM::NodeImpl* innerNode() const { return m_innerNode; }
+        DOM::NodeImpl* visualNode() const { return m_visualNode; }
         DOM::NodeImpl* URLElement() const { return m_innerURLElement; }
         bool readonly() const { return m_readonly; }
         bool active() const { return m_active; }
 
     private:
         void setInnerNode(DOM::NodeImpl* n) { m_innerNode = n; }
+        void setVisualNode(DOM::NodeImpl* n) { m_visualNode = n; }
         void setURLElement(DOM::NodeImpl* n) { m_innerURLElement = n; }
-
+        
         DOM::NodeImpl* m_innerNode;
+        DOM::NodeImpl* m_visualNode;
         DOM::NodeImpl* m_innerURLElement;
         bool m_readonly;
         bool m_active;
Index: render_object.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_object.cpp,v
retrieving revision 1.177
diff -u -p -r1.177 render_object.cpp
--- render_object.cpp	2002/06/16 15:23:47	1.177
+++ render_object.cpp	2002/07/15 05:53:25
@@ -837,24 +837,40 @@ bool RenderObject::nodeAtPoint(NodeInfo&
 
     bool inside = (style()->visibility() != HIDDEN && ((_y >= ty) && (_y < \
                ty + height()) &&
                   (_x >= tx) && (_x < tx + width()))) || isBody() || \
                isHtml();
-    bool inner = !info.innerNode();
-
+    
     // ### table should have its own, more performant method
     if (overhangingContents() || isInline() || isRoot() || isTableRow() || \
                isTableSection() || inside || mouseInside() ) {
         for (RenderObject* child = lastChild(); child; child = \
                child->previousSibling())
-            if (!child->isPositioned() && child->nodeAtPoint(info, _x, _y, \
_tx+xPos(), _ty+yPos())) +            if (!child->isPositioned() && \
child->nodeAtPoint(info, _x, _y, tx, ty))  inside = true;
     }
 
     if (inside && element()) {
-        if (!info.innerNode())
+        if (!info.innerNode()){
+            kdDebug() << "iNode: "<< information() << endl;
             info.setInnerNode(element());
-
-        if (!info.URLElement()) {
+        }
+        if ( !info.visualNode() && 
+             ( isRoot() || element()->hasAnchor() || 
+               ( style() && 
+                 ( style()->hasHover() || (info.active() && \
style()->hasActive()) || +                   style()->hasBorder() || 
+                   ( container() && container()->style() && 
+                     ( container()->style()->backgroundColor() != \
style()->backgroundColor() || +                       \
container()->style()->backgroundImage() != style()->backgroundImage() +     \
) +                   )
+                 )
+               )
+             )  
+           ) {
+            info.setVisualNode(element());
+            kdDebug() << "vNode: "<< information() << endl;
             RenderObject* p = this;
             while (p) {
                 if (p->element() && p->element()->hasAnchor()) {
                     info.setURLElement(p->element());
+                    kdDebug() << "URL: " << information() << endl;
                     break;
                 }
                 if (!isSpecial()) break;
@@ -866,14 +882,23 @@ bool RenderObject::nodeAtPoint(NodeInfo&
     if (!info.readonly()) {
         // lets see if we need a new style
         bool oldinside = mouseInside();
-        setMouseInside(inside && inner);
+        setMouseInside(false);
         if (element()) {
             bool oldactive = element()->active();
-            if (oldactive != (inside && info.active() && element() == \
                info.innerNode()))
-                element()->setActive(inside && info.active() && element() \
== info.innerNode()); +            if (oldactive != (inside && \
info.active() && element() == info.visualNode())) +                \
element()->setActive(inside && info.active() && element() == \
info.visualNode());  if ( ((oldinside != mouseInside()) && \
                style()->hasHover()) ||
                  ((oldactive != element()->active()) && \
style()->hasActive()))  element()->setChanged();
+        }
+        if(isRoot() && info.visualNode()) {
+            RenderObject* p = info.visualNode()->renderer();
+            while(p && !p->isRoot()){
+                p->setMouseInside(true);
+                if (p->style() && p->style()->hasHover()) 
+                    element()->setChanged();
+                p = p->parent();
+            }    
         }
     }
 



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic