[comp.sys.mac.programmer] why does a ModalDialog filter proc get empty update events?

mikem@uhccux.uhcc.hawaii.edu (Mike Morton) (08/01/89)

The filterproc passed to ModalDialog sometimes seems to get an endless
stream of update events with an empty event region.  Anyone know why?

This is annoying, because I'd like to use update events to redraw the
outline around the default item, making sure that the item reappears
if a screen-saver or nested dialog obscures it.

I can check for the case where the update region is empty, and avoid
doing updating (thus avoiding some cursor flickering) but I'm curious
about why these events come in.  The code below is a full application
which demonstrates the phenomenon.  If I take out a NewWindow call
(see below), the update events stop.

This happens within LSC and as a standalone application, under both
Uni- and MultiFinder.  System 6.0.3 on an SE/30.

 -- Mike Morton // P.O. Box 11378, Honolulu, HI  96828, (808) 676-6966 HST
      Internet: mikem@uhccux.uhcc.hawaii.edu
    (anagrams): Mr. Machine Tool; Ethical Mormon; Chosen Immortal; etc.
----------------------------------------------------------------------
/*  The project contains: MacTraps, sprintf, strings, this file.
    The project's resource file contains a single DLOG and DITL, both ID #128.
      DLOG info: bounds (100,100,200,200); procID 1; itemsID 128; visible)
      DITL info: one item; button, text "OK", enabled, bounds (32,24,48,80)
*/

pascal Boolean dlStdFilter (DialogPtr theDialog, EventRecord *evt, short *item);

void main ()
{ Rect bounds;
  WindowRecord wind;
  DialogPtr theDialog;
  short itemHit;

  SetApplLimit (CurStackBase - 32000L); MaxApplZone (); MoreMasters ();
  InitGraf (&thePort); InitFonts (); FlushEvents (everyEvent, 0);
  InitWindows (); InitMenus (); TEInit (); InitDialogs (0L); InitCursor ();

  SetRect (& bounds, 32, 32, 64, 64);
#if 1 /* commenting the next line out fixes the bug! */
  NewWindow (& wind, & bounds, "\p", true, altDBoxProc, -1L, false, 0L);
#endif

  theDialog = GetNewDialog (128, 0L, -1L);
  SetPort (theDialog);                  /* not sure this is necessary */
  ShowWindow (theDialog);
  ModalDialog (dlStdFilter, & itemHit); /* await item hit */
  DisposDialog (theDialog);             /* chuck the dialog's record */
}                                       /* end of main () */

pascal Boolean dlStdFilter (theDialog, evt, item)
  DialogPtr theDialog; EventRecord *evt; short *item;
{ RgnHandle upd;

  if (evt->what == updateEvt)           /* anything being updated? */
  { upd = ((WindowPeek) theDialog) -> updateRgn;

    if (! upd)
      DebugStr ("\p update event with no handle");
    else if (EmptyRgn (upd))
      DebugStr ("\p empty update");
    else
      DebugStr ("\p real update");
  }                                     /* end of handling update event */
  return false;
}                                       /* end of dlStdFilter () */

jerryg@Apple.COM (Jerry Godes) (08/01/89)

In article <4468@uhccux.uhcc.hawaii.edu> mikem@uhccux.uhcc.hawaii.edu (Mike Morton) writes:
>
>The filterproc passed to ModalDialog sometimes seems to get an endless
>stream of update events with an empty event region.  Anyone know why?
[...]
> -- Mike Morton // P.O. Box 11378, Honolulu, HI  96828, (808) 676-6966 HST
>      Internet: mikem@uhccux.uhcc.hawaii.edu
>
[Other code deleted]
>pascal Boolean dlStdFilter (theDialog, evt, item)
>  DialogPtr theDialog; EventRecord *evt; short *item;
>{ RgnHandle upd;
>
>  if (evt->what == updateEvt)           /* anything being updated? */
>  { upd = ((WindowPeek) theDialog) -> updateRgn;
>
>    if (! upd)
>      DebugStr ("\p update event with no handle");
>    else if (EmptyRgn (upd))
>      DebugStr ("\p empty update");
>    else
>      DebugStr ("\p real update");
>  }                                     /* end of handling update event */
>  return false;
>}                                       /* end of dlStdFilter () */

Mike - 

What you are forgetting to check is which window the update event is for.  I
doctored your program to work in MPW, so I could see what was going on in
MacsBug.  As I thought, the update event you are getting is for the other
window.  So, to solve your problem, just check the update event for the dialog
window, but not for any other windows.

My question now is why is an update event being generated for the other
window?  Maybe I'll go snooping in MacsBug a bit later and see what's going
on.

Jerry Godes
Communications Product Development
Apple Computer Inc.
(Nothing interesting to add here).

tim@hoptoad.uucp (Tim Maroney) (08/01/89)

In article <4468@uhccux.uhcc.hawaii.edu> mikem@uhccux.uhcc.hawaii.edu
(Mike Morton) writes:
>The filterproc passed to ModalDialog sometimes seems to get an endless
>stream of update events with an empty event region.  Anyone know why?

I don't know what an event region is.  Do you mean that your dialog
window's update region is empty?  If that's so, then the update event
must be for another window.  Have you checked to see if the update
event is for your window or not?

>This is annoying, because I'd like to use update events to redraw the
>outline around the default item, making sure that the item reappears
>if a screen-saver or nested dialog obscures it.

The correct way to do this is to create a disabled user item which
surrounds the button four pixels out, then bind to that item a drawing
procedure which does a FrameOval on the item rectangle.  (It may also
be possible to just set the default button field in the DialogPeek, but
I haven't tried that yet.)

>I can check for the case where the update region is empty, and avoid
>doing updating (thus avoiding some cursor flickering) but I'm curious
>about why these events come in.  The code below is a full application
>which demonstrates the phenomenon.  If I take out a NewWindow call
>(see below), the update events stop.

This demonstrates that the update events are for the other window.  You
should either service the events as normal for the other window, or ignore
them inside your filter procedure.

>  if (evt->what == updateEvt)           /* anything being updated? */
>  { upd = ((WindowPeek) theDialog) -> updateRgn;

Try adding:
	if ((DialogPtr)(evt->message) != theDialog) return false;
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"Gorbachev is returning to the heritage of the great Lenin" - Ronald Reagan

tim@hoptoad.uucp (Tim Maroney) (08/01/89)

Sorry, I said "FrameOval" in the previous message when I meant
"FrameRoundRect".  Also note that the pen width should be set to 3,
then restored to nromal after the outline is drawn.
-- 
Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com

"The negro slaves of the South are the happiest, and, in some sense, the
 freest people in the world.  The children and the aged and infirm work not
 at all, and yet have all the comforts and neccessaries of life provided for
 them." -- George Fitzhugh, CANNIBALS ALL! OR, SLAVES WITHOUT MASTERS, 1857

pratt@boulder.Colorado.EDU (Jonathan Pratt) (08/01/89)

In article <3257@internal.Apple.COM> jerryg@Apple.COM (Jerry Godes) writes:
[Notes that ModalDialog passes update events for other windows]

>My question now is why is an update event being generated for the other
>window?  Maybe I'll go snooping in MacsBug a bit later and see what's going
>on.
>
This is a pretty common gotcha.  I guess we just assume that ModalDialog
is going to do some pre-filtering for us so that we only receive events
related to the dialog window, but in fact I believe you get the event
pretty much straight from GetNextEvent (which means of course that you'll
hear if *any* of your windows needs updating).

Jonathan

/* Jonathan Pratt          Internet: pratt@boulder.colorado.edu     *
 * Campus Box 525              uucp: ..!{ncar|nbires}!boulder!pratt *
 * University of Colorado                                           *
 * Boulder, CO 80309          Phone: (303) 492-4293                 */