[comp.sys.mac.hypercard] How to tell when really idle?

kenw@skyler.arc.ab.ca (Ken Wallewein) (04/23/91)

  One of the things that's always bugged me about HyperCard is that,
although it updates most stuff to disk automatically, it won't do the same
for the current card -- at least, not doing the things I do.  A person can
loose a lot of text in a hurry if you crash without saving first.

  A while ago I decided to try to address that by writing an idle handler
that would detect how long HyperCard had been sitting idle, and if it was
longer than, say, five minutes, it would execute a "keep" (custom, of
course).

  I discovered that there appears to be no reasonable way to tell how long
HyperCard has been "consecutively" idle.  Oh, sure, one can count "idle"
messages.  Unfortunately, one needs a way to _reset_ that counter if
_anything_ _else_ happens.  Oops.  About the only way to address this right
now, as far as I can see, is to set up handlers for all the system
messages, and have them all clear a global variable.  I don't like the
overhead, and it's not foolproof.

  Does anybody have a better way to address this problem?

--
/kenw

Ken Wallewein                                                     A L B E R T A
kenw@noah.arc.ab.ca  <-- replies (if mailed) here, please       R E S E A R C H
(403)297-2660                                                     C O U N C I L

maurits@neon.Stanford.EDU (A. Maurits van der Veen) (04/23/91)

In article <KENW.91Apr22200900@skyler.arc.ab.ca> kenw@skyler.arc.ab.ca (Ken Wallewein) writes:
>
>  One of the things that's always bugged me about HyperCard is that,
>although it updates most stuff to disk automatically, it won't do the same
>for the current card -- at least, not doing the things I do.  A person can
>loose a lot of text in a hurry if you crash without saving first.
>
>  Does anybody have a better way to address this problem?
>
>Ken Wallewein                                                     A L B E R T A
>kenw@noah.arc.ab.ca  <-- replies (if mailed) here, please       R E S E A R C H
>(403)297-2660                                                     C O U N C I L

I am not sure this would qualify as a better way, but here goes:

Hypercard does update stuff to disk when you move to another card.
So you might have an idle handler that accumulates idle-counts,
and at a certain count just quickly to the next card and back.

Of course, a problem arises if the person is just then typing into a field.
Possible solutions to that:

- reset the idle-count to 0 every time someone types into a field
- when you are going to go to the next card, save the name of the current
  field and the selected position (selectedChunk, I think, might work,
  put you should probably look that up in the manual), and upon your
  return select the same chunk of the same field.

- You would want to lock screen before going to the next card, of course.
- You would reset idle-count to 0 on openCard.

Hope this helps,

Maurits van der Veen
maurits@neon.stanford.edu

- 

robertw@informix.com (Robert Weinberg) (04/23/91)

In article <KENW.91Apr22200900@skyler.arc.ab.ca> kenw@skyler.arc.ab.ca (Ken Wallewein) writes:
>
>  One of the things that's always bugged me about HyperCard is that,
>although it updates most stuff to disk automatically, it won't do the same
>for the current card -- at least, not doing the things I do.  A person can
>loose a lot of text in a hurry if you crash without saving first.

I think your text will be saved to disk whenever you click out lf
the field you are working in.

>  A while ago I decided to try to address that by writing an idle handler
>that would detect how long HyperCard had been sitting idle, and if it was
>longer than, say, five minutes, it would execute a "keep" (custom, of
>course).
>
>  I discovered that there appears to be no reasonable way to tell how long
>HyperCard has been "consecutively" idle.  Oh, sure, one can count "idle"
>messages.  Unfortunately, one needs a way to _reset_ that counter if
>_anything_ _else_ happens.  Oops.  About the only way to address this right
>now, as far as I can see, is to set up handlers for all the system
>messages, and have them all clear a global variable.  I don't like the
>overhead, and it's not foolproof.
>
>  Does anybody have a better way to address this problem?

How about an idle handler that just checks the number of ticks
since the last time it was invoked? Like: "if the ticks - SavedTicks >
whatever, then IdleWasInterrupted; put the ticks into SavedTicks."
You can figure out how long the handler takes, and determine the proper
constant to let you know if something else has happened between
invocations of your handler. Then you need to handle IdleWasInterrupted
with something like:  "if the ticks - SavedInterrupt > fiveMinutesWorth
then KeepHandler; put the ticksinto SavedInterrupt."

Well, just a thought.


-- 
* Rob Weinberg, graphics & publishing ***** Does a falling tree make a sound *
*  {uunet,pyramid}!infmx!robertw      *****   if  1: no one hears it         * 
*  => Ask me about me.                *****   BUT 2: it is not known that    * 
*  => Ask Informix about Informix.    *****          no one hears it?        * 

kenw@skyler.arc.ab.ca (Ken Wallewein) (04/26/91)

In article <1991Apr23.153901.5618@informix.com> robertw@informix.com (Robert Weinberg) writes:

   >  One of the things that's always bugged me about HyperCard is that,
   >although it updates most stuff to disk automatically, it won't do the same
   >for the current card -- at least, not doing the things I do.  A person can
   >loose a lot of text in a hurry if you crash without saving first.

   I think your text will be saved to disk whenever you click out lf
   the field you are working in.

Nope, it doesn't.

   >  A while ago I decided to try to address that by writing an idle handler
   >that would detect how long HyperCard had been sitting idle, and if it was
   >longer than, say, five minutes, it would execute a "keep" (custom, of
   >course).
   >....

   How about an idle handler that just checks the number of ticks
   since the last time it was invoked? Like: "if the ticks - SavedTicks >
   whatever, then IdleWasInterrupted; put the ticks into SavedTicks."

I'd prefer not to have it try to save when I'm in the middle of doing stuff.

   You can figure out how long the handler takes, and determine the proper
   constant to let you know if something else has happened between
   invocations of your handler. 

Love to. Got any ideas how I can check if "something else has happened"?
Like a somethingWasChanged message?
--
/kenw

Ken Wallewein                                                     A L B E R T A
kenw@noah.arc.ab.ca  <-- replies (if mailed) here, please       R E S E A R C H
(403)297-2660                                                     C O U N C I L

Eric.J.Baumgartner@dartmouth.edu (Eric J. Baumgartner) (05/06/91)

This routine won't always work but unless the user is pounding away in
a text field and never makes a mistake (or fixes mistakes with the
arrow keys) it'll do OK.  If nothing else, it's a starting place for a
better idle checker, because mouse activity tends to be a good test to
"non-idleness".

on idle
  global lastMouseLoc, idleSinceWhen

  put 5*60*60 into idleTicksThreshold -- 5 minute threshold
  if (the mouseLoc <> lastMouseLoc) then
    if (the ticks - idleSinceWhen) > idleTicksThreshold then
      doYourIdleRoutine
    end if
  else
    put the mouseLoc into lastMouseLoc
    put the ticks into idleSinceWhen
  end if

  -- pass idle -- if necessary
end idle

If someone figures out how to deal with keystrokes as well, I'd love to
see it.  * lightbulb suddenly appears over head... BING * Actually,
what might work is in addition to checking that the mouse is in the
same place, check to see if the selectedChunk is the same as it was
before.  If the user is typing merrily along the selectedChunk should
change.  I'll leave that one as an exercise for the reader, who can
then tell me if it works. :-)

Eric Baumgartner
Interactive Media Lab
Dartmouth Medical School

kenw@skyler.arc.ab.ca (Ken Wallewein) (05/08/91)

  Here's what I finaly came up with.  It saves after 2.5 minutes of no menu
or keyboard activity -- mousing isn't likely to cause problems if menus
aren't involved.  It has occured to me that this is only needed if a text
field is actually open, because closing a field writes it, but I haven't
optimized for that yet; it doesn't seem needed.

on openStack -- initialize globals; s/b "on startUp"?
  global active,lastAction,shortIdle
  put false into active
  put false into shortIdle
  put the seconds into lastAction
  pass openStack
end openStack

-- based on idle checker idea from Frank Vernon, 9to5 S/ware
on idle
  global active,lastAction,lastOnIdle,shortIdle
  if the seconds-lastOnIdle >60 then -- only check occasionally
    get the seconds
    put it into lastOnIdle
    if active then  -- remember when (approx) if active in last minute
      put true into shortIdle
      put it into lastAction
      put false into active
    end if
    if shortIdle then -- do stuff once when short idle times out
      if it-lastAction >150 then -- if no activity last 2.5 minutes
        doKeep
        put false into shortIdle
      end if
    end if
  end if
end idle

on keyDown -- do minimum amount of work here
  global active
  put true into active
  -- put "keyDown handled"
  pass keyDown
end keyDown

on doMenu -- some changes do not involve keys down
  global active
  put true into active
  -- put "doMenu handled"
  pass doMenu
end doMenu

on doKeep -- force the stack to write down to disk
  get the selectedChunk
  -- set cantModify of this stack to true
  -- set cantModify of this stack to false
  push card -- this is quicker
  pop card
  put the name of this stack && "KEEP done at" && the time
  select it
end doKeep


--
/kenw

Ken Wallewein                                                     A L B E R T A
kenw@noah.arc.ab.ca  <-- replies (if mailed) here, please       R E S E A R C H
(403)297-2660                                                     C O U N C I L