Apple II
Technical Notes
_____________________________________________________________________________
                                                  Developer Technical Support

Apple IIgs
#84:    TaskMaster Madness

Written by:    C.K. Haun <TR>                                       July 1990

This Technical Note discusses the enhancements made to TaskMaster in System 
Software 5.0.
_____________________________________________________________________________

TaskMaster has been expanded to handle extended control actions and give you 
more information about events in System Software 5.0.  This Note discusses 
some features of the expanded TaskMaster and TaskMasterDA, and how you can 
best exploit the new features in your applications.


Stop Making It So Difficult

Developers just want to work too hard.  You get a neat new thing like the 
expanded TaskMaster, and you still want to do all the work yourself.  The new 
TaskMaster does nearly everything for you, as long as you treat it correctly.

What this means is you do not have to call FindControl, TrackControl, TEIdle, 
LEKey, handle keystrokes for controls, keep track of click counts, or any of 
the other mundane event management tasks unless you specifically want to 
perform actions that TaskMaster does not perform.  For the standard controls 
and situations this means that you do not have to do anything.

The magic keys to this life of freedom and ease are the five newly defined 
taskMask flag bits, labeled in the interfaces as tmContentControls, 
tmControlKey, tmControlMenu, tmMultiClick and tmIdleEvents.  This Note looks 
at what the new bits do for you, but first a word of warning.

Warning:  If you set any of these new bits, TaskMaster assumes you are 
          using the new extended task record.  This means that you 
          cannot just go into an older program and set these bits and 
          expect your program to work successfully.  You also must 
          allocate the additional space for the extended portion of 
          the task record.  If you do not, TaskMaster puts task data 
          in areas that you do not expect, and Bad Things happen.


Bits 'o This, Bits 'o That

Click Bits

tmMultiClick tells TaskMaster to keep the new "click information" fields in 
the extended task record updated.  This allows you to have TaskMaster keep 
track of multiclick events; the wmClickCount field is one, two or three 
depending on whether the last action was a single, double, or triple click.  
In fact, if you can click your mouse button fast enough, you can time 
quadruple clicks, sextuple clicks, or as high as you want, although anything 
over triple-clicking is nearly impossible for users to consistently manage.  
wmClickCount just gets incremented by one when the click falls within the 
double time interval.  wmLastClickTick is updated with the system tick value 
at last click.  wmLastClickPt contains the location of the last mouse click.  
TaskMaster calls GetDblTime internally to determine the correct time intervals 
for these values.

Idle Bits

tmIdleEvents tells TaskMaster to call the idle routines for controls that need 
idle events, like TextEdit controls and LineEdit controls.  This also means 
that only the active control is blinking a cursor, since TaskMaster is working 
with the target bits of the extended control records to keep track of which 
TextEdit or LineEdit control is active and switching the target control in 
response to mouse clicks and Tab keypresses.  This is also the area where you 
tell TaskMaster how to highlight your window controls.  Using the Control 
Manager calls MakeNextCtlTarget and MakeThisCtlTarget allows you to specify 
which LineEdit or TextEdit control is active.  You can use these calls to 
highlight input errors the user has made.  For example, if someone has entered 
text in a LineEdit control that requires a number, you can alert the user if 
he enters non-numeric characters with an Alert or AlertWindow call.  You can 
then direct the user to the LineEdit control that contains the bad entry by 
calling MakeThisCtlTarget with the handle of that LineEdit control.  This 
deactivates any other target control and moves the insertion point to the 
LineEdit control that needs the correction.

Contentious Bits

tmContentControls, tmControlMenu and tmControlKey bits are the real workhorses 
of the expanded TaskMaster.

When the tmContentControls and tmControlMenu bits are set, TaskMaster handles 
the mouse activity side of events--tracking, highlighting or popping-up the 
selected control.  If the control is a radio button, check box, pop-up menu or 
list control, TaskMaster also performs the correct action for the click, 
either setting the control value, scrolling the list, setting the pop-up menu 
to the selected item, and so on.  TaskMaster then returns a taskCode of 
wInControl ($21).  The control handle is stored in wmTaskData2, the part code 
of the part selected in wmTaskData3 and the control ID is in wmTaskData4.  For 
many of the controls in your windows your application needs to take no further 
actions, TaskMaster has set the control values.  When the user closes the 
window or clicks on a button that causes an action, you can then read the 
values of all the controls you care about at that point and do what you need 
to do, instead of keeping track as the user manipulates controls.

The last new bit, tmControlKey, works with the tmControlMenu bit to handle key 
events for your extended controls.

When a key event occurs, TaskMaster sends the event to the internal routine 
TaskMasterKey.  TaskMasterKey first looks at the tmMenuKey bit (which has been 
in TaskMaster since the Window Manager was implemented).  If it is set, then 
TaskMaster tries to handle the event as a menu event, calling MenuKey for the 
current menu bar.

Note:  This also means that any key equivalents in your main menu bar 
       (across the top of the desktop) take precedence over key 
       equivalents in your window controls.

If this fails (or that bit is not set) and tmControlKey is set, then 
TaskMasterKey polls the controls in the currently open window for any controls 
that would like this keystroke, either for controls with a keyEquivalent field 
or a pop-up menu control with key equivalents for menu items.  If it finds a 
control that wants the key event, it is handled very much like a mouse event.  
The action for the control is performed (checking a check box, for example) 
and the wmTaskData fields are filled as they would be for a mouse click, and 
an event code of wInControl ($21) is returned. If a key event did occur, you 
can differentiate it from a mouse event by looking at the wmWhat field of the 
taskRecord.  Even though a wInControl event code was passed back by 
TaskMaster, the wmWhat field is either $0001 or $0003, the former for a mouse 
down event and the latter if a keystroke stimulated the wInControl event.

Even More Bits

All these new features rely very heavily on the changes made to the Control 
Manager in System Software 5.0.  Many of the TaskMaster features, keystrokes, 
target controls, and so on only work if you have the moreFlags bits set 
correctly in your control definitions.  If you are having difficulty with new 
TaskMaster features, check your control definitions against the information in 
the Control Manager chapter of Volume 3 of the Apple IIgs Toolbox Reference 
and Apple IIgs Technical Note #81, Extended Control Ecstasy.


Don't Get Goofy

There are some dangers in these new features, of course.  By allowing built-in 
key equivalencies for almost all the controls that can exist in a window, it 
may be tempting to define key equivalents for everything, and create weird and 
unusual key combinations for your controls.  Please remember the Human 
Interface Guidelines (specifically Human Interface Note #8, Keyboard 
Equivalents) and keep your use of keystroke equivalents to a minimum.  
Multimodifier keystrokes (Command-Option-Shift, for example) do not enhance 
the user's experience and can be very confusing.


NDAs Can Have Fun Too

TaskMasterDA has also been added to the Window Manager, providing your new 
desk accessories (NDAs) with the same kind of TaskMaster support your 
applications have.  This lets you easily use extended controls inside NDAs, 
following the same basic rules as in an application.  There are only a few 
things to worry about.

What Does That Stack Picture Really Mean?

The input to TaskMasterDA, as shown in Volume 3 of the Apple IIgs Toolbox 
Reference, is as follows:

        |_____________|
        |             |
        |    space    |  word, return space
        |_____________|
        |             |
        |  eventMask  |  word, eventMask, ignore
        |_____________|
        |             |
        |             |
        | taskRecord  |  long, pointer to taskRecord
        |   pointer   |
        |             |
        |_____________|

        Figure 1-TaskMasterDA Stack Picture

The call returns a word value, the taskCode.  The space and eventMask are 
self-explanatory.  The book tells you that the eventMask is ignored, which 
makes sense since the host application has already gotten the event and you 
have already specified an eventMask in your NDA header, so you can use any 
value here.  The taskRecPointer causes the confusion.

You do not pass a blank event record.  When your NDA's action routine is 
called, the Y and X registers contain a pointer to the current event record 
with which the NDA is working.  TaskMasterDA is filling that taskRecord with 
some information, so you want to move it into your NDA's data area so you can 
work with it later:

    phy
    phx                   ; push the pointer that was passed to us
    pushlong  #NDArecord  ; the space in my NDA for the extended event record
    pea       0
    pea       16          ; only 16 bytes, the original taskRecord size
    _BlockMove

It is very important that you only move 16 bytes.  TaskMasterDA can act 
erratically if the extended portion of the event record has been filled with 
nonsense values.  This can happen if your NDA is running in an application 
that does not use the extended task record and you are copying non-task data 
into the extended portion of the task record.  By the way, as you are 
debugging your NDA and you run into situations where the wmTaskData field 
values are weird, this is more than likely the problem.

Also remember to make sure the wmTaskMask field in your NDA's TaskRecord is 
set and the extended portions of the TaskRecord are zeroed out before your NDA 
starts running; you want to set all these fields in your NDA's INIT routine.

Now you can call TaskMasterDA:

    pea       0           ; return space
    pea       $FFFF       ; eventMask, ignored
    pushlong  #nDArecord  ; our NDA event record
    _TaskMasterDA
    pla                   ; event code returned

You can then process the event in a convenient way.  Remember again that 
TaskMaster has already done the control tracking for the controls in your NDA 
window.  You have the same multiclick information, control handles and IDs.


Conclusion

TaskMaster is a wonderful thing that makes any programmer's job easier.  So 
let it work for you.  Learn the capabilities of the new fields and new 
controls, and take advantage of them.  Let TaskMaster take care of the system 
details, while you concentrate on the features that make your application 
special.

Further Reference
_____________________________________________________________________________
  o  Apple IIgs Toolbox Reference, Volumes 1 through 3
  o  Apple IIgs Technical Note #81, Extended Control Ecstasy
  o  Human Interface Note #8, Keyboard Equivalents

