force exit of mouseDown?

Richard Gaskin ambassador at fourthworld.com
Fri Jun 24 12:39:13 CDT 2011


Nicolas Cueto wrote:

> mouseStillDown, for example. When part of a script set as a behavior,
> mouseStillDown would not work. But that same script with the same
> mouseStillDown handler, when actually stored as a button's script,
> worked as expected.

In a way that's kinda good news, as mouseStillDown is an anomaly among 
mouse messages.  I think you'll find the other mouse messages quite 
reliable in behavior scripts, but mouseStillDown is an oddity as noted 
in the Dictionary:

      Usually, it is easier and more efficient to use the mouseMove
      message to track the movement of the mouse while the button
      is being held down.

      Note:  If there is no mouseStillDown handler in the target
      object's script, no mouseStillDown message is sent, even if
      there is a mouseStillDown handler in an object that's
      further along the message path.

Your behavior script should work if you add this to the target object:

on mouseStillDown
    pass mouseStillDown
end mouseStillDown

Why is mouseStillDown so different from other mouse messages?

Because it's uniquely inefficient, and the mouseMove message was 
provided to provide an alternative that's far more flexible and takes 
fewer system resources for many similar needs.

Most OSes provide a message when the mouse first goes down, but not all 
of them provide a second message sent continuously while the mouse is 
being held down.  So to provide mouseStillDown for us the engine needs 
to continually poll the OS for the state of the mouse button.   It does 
this with a frequency defined in the idleRate, which is far less 
frequent than checking "if the mouse is down" in a repeat loop, but 
still not optimal.

If the message was always sent into the message path whether or not it's 
needed, anytime the user holds the mouse down it would trigger a lot of 
messaging overhead that's never used.

But what if you need it?

Like the idle message (HyperCard's message-clogging workaround for not 
having timers), all you need to do is include a mouseStillDown handler 
in any target you want it to be sent to, and the engine will then know 
to trigger that seldom-used message.

"Seldom-used?"  Yes:

Historically, mouseStillDown was most often used for dragging or other 
operations in which things need to be updated while the mouse is moving. 
  In such cases, the developer probably doesn't need to update anything 
until the location of the mouse changes, but mouseStillDown is 
continually being sent anyway, requiring a lot of redundant processing 
for things which have no visible effect.

So the mouseMove message was added, providing a way to update things 
only when the mouse is moved.

MouseMove also works when the mouse is up, which can be useful for 
update mouse position indicators in a drawing program's rulers, for example.

This additional flexibility requires us to use a few other handlers to 
substitute for mouseStillDown, but it well worth the few seconds it 
takes to set up.  You'll need a mouseDown to set a flag so the mouseMove 
can know that the mouse is down without having to poll the OS (you can 
also use this flag for other useful info, as shown below), and you'll 
need mouseUp and mouseRelease messages to clear the flag.

This example is for a splitter control that adjusts the groups on either 
side of it:

local sXOffset

on mouseDown
   -- Provide the info mouseMove will need later:
   put the mouseH - the left of me into sXOffset
end mouseDown

on mouseMove
    -- Is the flag still set?
    if sXOffset is not empty then
      -- If so, handle the splitter drag here:
      set the rect of grp "LeftGroup" to \
        0,0,the left of me, the height of this cd
      set the rect of grp "RightGroup" to \
        the right of me, 0, the width of this cd,
        the height of this cd
    end if
end mouseMove

-- Clear the flag when the mouse is released over the control:
on mouseUp
    put empty into sXOffset
end mouseUp

-- Clear the flag when the mouse is release when not over the control:
on mouseRelease
   put empty into sXOffset
end mouseRelease


In addition to handling simple drags like a splitter, drag-and-drop 
operations can be handled using the messages provided for those 
(dragStart, dragMove, dragDrop, dragEnd) far more simply than emulating 
drag-and-drop behaviors with mouseStillDown.

So once we use mouseMove for movement-related things and the 
drag-and-drop messages for those types of actions, the remaining subset 
of cases where mouseStillDown can be useful are relatively few.  And for 
those, you can still use it so long as you provide a handler for it in 
the target object.


> One other thing I noticed during development and had thought due to my
> uncertain knowledge about the various mouse-related handlers, was that
> I couldn't rely on "me" but had to be more specific. Something like
> "put the short name of the owner of me into tGroup; if the flag of
> button "theButton" of group tGroup is...", rather than simply "if the
> flag of me is...".

More good news:  the uncertainty you subjectively felt is well addressed 
by the implementation.  If you experiment a bit you'll find that "me" in 
a behavior script will always refer to the target object.

Once you've experimented to verify this, you'll become confident with 
their use and will want to use them every day.  And every night.  And on 
the weekends.  Highly addictive. :) Behaviors are one of the most 
powerful additions to the language since arrays.


> Anyway. I doubt I will ever rely on behaviors again. And I don't feel
> confident enough with my programming skills to present this to LC as
> something like a bug. Cause I have been known to be wrong -- though
> not about mouseStillDown working now when it wasn't before.

Having addressed the unique anomaly that is the mouseStillDown message, 
I hope you're inspired to give behaviors a fresh try.

While your own confidence may not be as strong as the moment, I'm 
completely confident with with just an hour or two's experimentation to 
verify how behaviors work, you'll enjoy using them going forward and 
have simpler and more robust code in the process.


Hope all is well with you and yours in Tokyo -

--
  Richard Gaskin
  Fourth World
  LiveCode training and consulting: http://www.fourthworld.com
  Webzine for LiveCode developers: http://www.LiveCodeJournal.com
  LiveCode Journal blog: http://LiveCodejournal.com/blog.irv



More information about the use-livecode mailing list