Both.  Perhaps a good way of defining it is like this: when an object  
starts receiving mouse events, it receives onmouseover.  When it  
stops receiving events (for any reason) it receives onmouseout.  So  
if the mouse moves onto A, then over B, then off of B (but still on  
A), it goes like this:

// mouse enters A
A: onmouseover

// mouse enters B
A: onmouseout
B: onmouseover

// mouse leaves B, staying on A
B: onmouseout
A: onmouseover

It appears from experimentation that when "mouse focus" changes from  
A to B, the onmouseout on A is always delivered before onmouseover on  
B, but I don't know if there's any contractual guarantee of that  
behavior.  It also seems that when switching from one object to  
another that both events are delivered in the same execution "time  
slot" (frame?), but again I couldn't say that there's any contractual  
guarantee there.

Some difficulty arises in that the runtime doesn't necessarily catch/ 
announce every mouse movement, which means that mouseout on B in no  
way guarantees a mouseover on A.  It's possible to skip right over A  
and onto objects that don't receive mouse events, or off the canvas  
entirely:

// mouse enters A
A: onmouseover

// mouse enters B
A: onmouseout
B: onmouseover

// mouse exits canvas (quickly)
B: onmouseout


Also, intervening objects can throw a curve at you.  Say there's an  
object C who is a sibling to A, overlaps and is above A, but is  
invisible.  If C becomes visible, mouse out/over events work exactly  
as described above.  For example:

// enter A
A: onmouseover

// C appears
A: onmouseout
C: onmouseover

// mouse moves to the region of C that overlaps B
// no events

// C disappears
C: onmouseout
B: onmouseover


See how this starts to get a bit confusing?  I can get a mouseout  
event for several reasons:
   1) the mouse moved away from the object,
   2) something appeared above the object, or
   3) the object itself became invisible
In the case of the widget I'm building, I want to hide in the case of  
#1 but not in the case of #2.  But with #1 if the mouse leaves the  
canvas it is indistinguishable from #2 at the moment of mouseout.

In my case, all of this is compounded by the fact that objects  
transition from visible to invisible across several hundred  
milliseconds, making any reasonably sane evaluation of the current  
"state" of affairs a bit difficult.  But that's my problem to deal  
with, since I'm an eternal perfectionist who absolute *has* to have  
glowing transition effects.  ;)

Event bubbling would be a great fix for my situation provided you're  
able to detect that the mouse has left the canvas.  Remember, the  
mouse coordinates reported by getMouse() will be at their last known  
position.  So if I mouseout from B off the canvas, the event bubbles  
up to A at which point A thinks that the mouse is still within its  
bounds and drops the event on the floor when ideally it should  
receive mouseout.

All of this reminds me of a question I've been meaning to ask: how  
are you dealing with mouse events in the DHTML runtime?  The behavior  
is vastly different between DHTML and Flash.  In thinking through it,  
the only way I've been able to conceive of compatibility between the  
two is if the DHTML runtime places an invisible "screen" over the app  
to catch all mouse events, and then the "kernel" manually determines  
which view should receive events.  Is that how you're doing it?


On May 26, 2006, at 1:01 PM, P T Withington wrote:

> I have a question:
>
> If I have a nested view B inside A, when the mouse moves from A to  
> B, does A get a mouseout, or just B gets mousein?
>
> I'm thinking along the lines of event bubbling (which we don't  
> currently do), and wondering if mouse tracking needs to be more  
> sophisticated in the platform so applications don't have to resort  
> to what you describe below.
>
> On 2006-05-26, at 13:48 EDT, Benjamin Shine wrote:
>
>> We coped with a similar problem in the rich text editor; we needed to
>> preserve the selected text before the text area loses focus, which is
>> parallel to making your mouseover-widget disappear when you mouse
>> off. I think. This might help; it's how we handle the preserve-
>> selection-on-mouseout behavior in the rich text editor in laszlo
>> mail. The code below is the core of how we do it, and it's all in
>> context at:
>> http://svn.openlaszlo.org/openlaszlo/trunk/lps/components/incubator/
>> rich-text/richtexteditarea.lzx
>>
>> (I think this implementation falls under the rubric of "For various
>> reasons, this line of thinking proved nearly impossible to sort out,"
>> as you say.)
>>
>>
>>   <!--- Forget the selection if we lose focus to a focusable  
>> widget, but
>>              keep the selection if we lose focus to a non-focusable
>> widget, like
>>              the toolbar buttons.
>>              @param view s: the view which is gaining the selection
>>          -->
>>          <method event="onblur" args="s">
>>              this._fieldhasfocus = false;
>>              // If we're blurring and the focus is going to anything
>> *but* the toolbar
>>              // widgets, set _ssel and _esel to nothing.
>>              // Semantically, we want to get rid of the selection if
>> we lose focus.
>>              if (s != null) {
>>                  // We're really giving focus to something else, so,
>> forget
>>                  // about whatever was selected while this component
>> still had focus.
>>                  // It seems to "feel" right to me to move the cursor
>> to the end of
>>                  // the text.
>>                  this._ssel = this._esel = this.getText().length;
>>              }
>>          </method>
>>
>>
>>          <!--- If the mouse down is over me or any of my children,
>> remember that,
>>              so we can listen for an onmouseup anywhere. A mouseup
>> after a mousedown
>>              indicates that the selection has changed.
>>              @param view who: the element being moused down on
>>          -->
>>          <method event="onmousedown" reference="LzGlobalMouse"
>> args="who"><![CDATA[
>>              if ((who != null) && (this._containsView(who))) {
>>                  // the mouse went down on a child of me
>>                  // Debug.write("mousedown on child of me");
>>                  this._mousedownorigin = who;
>>              } else if ((who == null) && (inp.containsPt 
>> (this.getMouse
>> ("x"), this.getMouse("y")))) {
>>                  // the mouse went down on me
>>                  // Debug.write("mousedown on me");
>>                  this._mousedownorigin = this;
>>              } else {
>>                  // the mouse went down on someone other than me; i'm
>> not interested.
>>                  this._mousedownorigin = null;
>>              }
>>              ]]>
>>          </method>
>>
>>
>>          <!--- Listen for global mouse up.
>>              We're only interested in global mouse up if the editor
>> has focus.
>>              If the editor does have focus,
>>              is there a mousedown/mouseup pair in progress?
>>              @param view who: the current mousedown element (ben  
>> shine)
>>          -->
>>          <method event="onmouseup" reference="LzGlobalMouse"  
>> args="who">
>>              if (this._fieldhasfocus) {
>>                  // Debug.write("onmouseup, field has focus, who is
>> ", who);
>>
>>                  if (this._mousedownorigin != null) {
>>                      // We have focus, and there _is_ a mousedown/
>> mouseup pair in progress.
>>                      if (this._mousedownorigin == this) {
>>
>>                          // The mouse click started on the richtext
>> editor.
>>
>>                          // If the mouse click also ended on the rich
>> text editor,
>>                          // it's just a caret move.
>>                          if (inp.containsPt(this.getMouse("x"),
>> this.getMouse("y"))) {
>>                              this._caretmove();
>>                          } else {
>>                              // If the mouseclick ended anywhere but
>> the rich text editor,
>>                              // it's a lost mousedown.
>>                              this._handleLostMouseDown();
>>                          }
>>                      } else {
>>                          // We have focus, and there's a mousedown/
>> mouseup pair in progress,
>>                          // and it started on one of the subviews of
>> the RTE.
>>                          // Debug.write("lost mousedown, origin was
>> ", this._mousedownorigin);
>>                      }
>>
>>                  } else {
>>                      // We have focus, but there's no mousedown/
>> mouseup pair in progress.
>>                      // Therefore, do nothing.
>>                      // Debug.write("No mousedown origin. The
>> mousedown didn't start on an RTE component.");
>>                  }
>>              }
>>
>>              // Clear the mousedown attribute; a mouseup means that
>> whatever
>>              // the mousedown was, it's gone now.
>>              this._mousedownorigin = null;
>>          </method>
>>
>> ...
>>        <!---
>>              Handle the case where a mouse drag began on the RTE but
>> the mouse up
>>              was not on the RTE.
>>              @keywords private
>>          -->
>>          <method name="_handleLostMouseDown">
>>              var selstart = this._field.getSelectionPosition();
>>              var selend = selstart + this._field.getSelectionSize();
>>              this.setCurrentFormat( this.getTextFormat(selstart,
>> selend), true);
>>          </method>
>>
>>          <!--- Restore last selection region.
>>              Note: this must be called from a delegate in an idle  
>> event
>>              *after* flash completes the "frame" in which the
>> selection or focus
>>              changed.
>>                @keywords private -->
>>          <method name="_restoreSelection">
>>              //------------------------------------------------------ 
>> ---
>> ---
>>              // FIXME [2005-08-16 pkang]: Need to know in which
>> direction
>>              // selection was done so as to not make scrollbar jump.
>>              //------------------------------------------------------ 
>> ---
>> ---
>>              this._shouldresettoolbar = false;
>>              this.setSelection(this._ssel, this._esel);
>>              this._shouldresettoolbar = true;
>>          </method>
>>
>>
>> On May 26, 2006, at 10:08 AM, Neil Mix wrote:
>>
>>> Thanks Benjamin.  That's some good stuff.  Way beyond me, I  
>>> think.  ;)
>>>
>>> Here's a little more info about the problem I'm facing.  It's
>>> pretty unique and edge-casey, but maybe you'll find it interesting.
>>>
>>> I'm prototyping a graphical widget that appears when you mouse over
>>> the album art on a song slide.  I want to make the widget disappear
>>> when you mouse away.  Typically, this would be as easy as catching
>>> an onmouseout and hiding the widget.  And flash supports that, even
>>> when you mouse off the canvas -- you still get an onmouseout (yet
>>> the reported mouse coordinates are still within the bounds of the
>>> object).
>>>
>>> Here's the trick: this widget contains buttons that also receive
>>> mouse events.  Those buttons (of course) have hover effects and
>>> various states, and clicking them may cause other objects to appear
>>> above the buttons.  The net result is that my widget may never
>>> receive a mouseout event, because one of the buttons contained
>>> within it may instead receive the mouseout.
>>>
>>> What I've ended up doing is attaching event handlers to
>>> LzGlobalMouse to catch all onmouseover/onmouseout events and check
>>> to see whether or not the current mouse position is within the
>>> bounds of the the widget.  This is by far the easiest and most
>>> fullproof algorithm.  (Alternative would be to catch onmouseout of
>>> the contained buttons directly, and then try to determine why a
>>> button received a mouseout, and whether the event is worthy of
>>> hiding the container widget or not.  For various reasons, this line
>>> of thinking proved nearly impossible to sort out.)
>>>
>>> As I've thought about it, I've wondered if what I need is extra
>>> info in the mouseout event that tells me which object is going to
>>> receive the subsequent mouseover (or null if no object is going to
>>> get mouseover).  For example, something like:
>>>
>>> <method event="onmousemove" reference="LzGlobalMouse"
>>> args="who,where">
>>>     // "who" is the object that received the mouseout event
>>>     // "where" is the object that the mouse has entered, or null
>>>     // if no object receives mouse events at the new location
>>>
>>>     if(who_is_the_widget_or_its_child()) {
>>>             keep_visible();
>>>     } else {
>>>             make_invisible();
>>>     }
>>> </method>
>>>
>>> I suppose I could implement this by setting a timer during
>>> onmouseout to check what the subsequent onmouseover value is.  The
>>> only problem is that I don't know what contractual guarantees the
>>> runtime provides with regard to mouse events and their proximity
>>> time-wise.  If a mouseout occurs, is any subsequent mouseover
>>> guaranteed to happen before the next onidle?  Is it possible for
>>> multiple mouseout/mouseover combos to happen before the next onidle?
>>>
>>> On May 26, 2006, at 12:43 AM, Benjamin Shine wrote:
>>>
>>>> You might try applying a predictive tracking algorithm: something
>>>> like watching every mouse move, guessing where the mouse is going,
>>>> then setting a timer to see if you get another mouse move event.
>>>> You could get into math like evaluating the rate of travel of the
>>>> mouse pointer towards a boundary of the app; moving rapidly toward
>>>> the border would predict that the border will be crossed; moving
>>>> towards the border but decelerating would predict that the border
>>>> won't be crossed.
>>>>
>>>> Patrick Baudisch, at Microsoft Research, has been doing some
>>>> really nice CHI work with user studies on this sort of thing. I
>>>> recommend checking out his work. It might not be exactly what you
>>>> need, but it's *cool*, and could get you a "+5 nifty!" rating if
>>>> you applied it to Pandora.
>>>> http://www.patrickbaudisch.com/publications/index.html
>>>>
>>>> Joe Laviola at Brown has been doing some work with this:
>>>> http://www.cs.brown.edu/people/jjl/ptracking/ptracking.html
>>>>
>>>> Is your app in a javascript wrapper, though? Seems like there
>>>> ought to be a clever way of noticing a mouse-enter in DHTML, and
>>>> sending a message to the laszlo app to let it know it's lost the
>>>> pointer.
>>>>
>>>> Please let us know what you learn.
>>>>
>>>> On May 25, 2006, at 9:38 AM, Neil Mix wrote:
>>>>
>>>>> I'd like to have some way of knowing that the mouse is no longer
>>>>> above the canvas, i.e. the Flash app is no longer able to receive
>>>>> mouse events.  Is this possible at all?  What I'm seeing is  
>>>>> that the
>>>>> last moused-over object will receive a mouseout event, but the
>>>>> getMouse() coords returned are the last known location of the  
>>>>> mouse
>>>>> before it left the canvas (which makes sense).
>>>>>
>>>>> I'm guessing I'm out of luck here, but I thought I'd check with  
>>>>> the
>>>>> experts first.  It's OK by me if the solution involves using Flash
>>>>> native or deeply private LZX stuff.
>>>>>
>>>>> TIA, -Neil
>>>>> _______________________________________________
>>>>> Laszlo-dev mailing list
>>>>> [email protected]
>>>>> http://www.openlaszlo.org/mailman/listinfo/laszlo-dev
>>>>
>>>> benjamin shine
>>>> software engineer
>>>> [EMAIL PROTECTED]
>>>>
>>>>
>>>>
>>>
>>
>> benjamin shine
>> software engineer
>> [EMAIL PROTECTED]
>>
>>
>>
>> _______________________________________________
>> Laszlo-dev mailing list
>> [email protected]
>> http://www.openlaszlo.org/mailman/listinfo/laszlo-dev
>

_______________________________________________
Laszlo-dev mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-dev

Reply via email to