[comp.sys.mac.programmer] MultiFinder & Modal Dialogs

jackiw@cs.swarthmore.edu (Nick Jackiw) (01/12/89)

In article <482@pyuxf.UUCP> asg@pyuxf.UUCP (alan geller) writes:
> 
> My question, though, is:
> 	WHY can't layer switches happen when a modal dialog is displayed?
> 	Or, alternatively, would it be possible to create a type of dialog
> 		that would be 'layer modal' rather than 'system modal'; 
> 		that is, if such a dialog were displayed, then no other
> 		window/dialog/menu/control/etc. in the owning layer and
> 		task would be available to the user, but the user could
> 		switch layers (to a different task) if so desired?
> 
> Alan Geller
> Bellcore
> ...!{princeton|rutgers}!bcr!asg

Mostly the answer to (A) concerns the event-driven programming model of
Mac programs.  Someone else has already pointed out that (B) is easy to do
IF you're writing your own programs, but it's difficult to modify existing
programs to give you what you want (layer-switching from beneath modals).

Well-written Mac programs have a "main event loop" from which they can
dispatch to various operating system or user requests to take some action,
including (and this is a biggie for MultiFinder) redrawing their windows
if necessary (because some other window's blocked them). At the beginning
of the event loop, the program asks the system for an event.  This is where
MultiFinder might switch the layer out: the event-request never returns.
Then, when MultiF needs to switch the layer back in, either to resume its
topmost status or just to force it to redraw its corrupted windows, this
pending event-request returns, and the program never needs to know it just
spent some time in limbo.

Enter the modal dialog difficulty.  Modal dialogs are treated differently
by apps than other windows, because there is a toolbox call (_ModalDialog)
which will process all events pertaining TO THAT DIALOG ALONE.  A mini-event
loop, as it were. Now, imagine if MF were to snatch control out from the
get-event-requests which are presumably buried in the call to _ModalDialog.
There are no problems giving time to other tasks, and this is what MF does.
If, however, it allowed another layer to come frontmost, that would corrupt
the windows in the _ModalDialog layer.  Now if User drags or resizes or closes
a top-layer window, portions of the windows in the layer with the modal are
going to be exposed, and consequently require updating in their back layer.
Normally, MultiFinder would (TASK-)switch the app in, feed it its update
events, and (TASK-)switch back to the frontmost layer. THE WHOLE PROBLEM:
The modal app CAN'T PROCESS ITS UPDATES, or provide other key functionality,
because it's not in its main event loop, it's only in the mini-event loop
of the specific call to _ModalDialog. (Remember, this loop can't do anything
but maintain the dialog.)  So, if MF switched out from under a modal, that
layer's windows would progressively deteriorate, until they were all just
empty window frames (except for the modal window, which would get updated
because _ModalDialog can process THOSE updates).

Time for my disclaimer: this is all guesswork. I've never traced the code,
and I have only a dim knowledge of the bowels of MultiFinder. I DO know
that MF can't access your main-event-loop from within the ModalEventLoop,
however: programs have to be explicitly coded to support that sort of
re-entrancy, and most aren't.

Programmers could easily design layer-switchable modals that
resembled real ones, it would just require integrating modal-event handling
with regular-event handling (and maintaining an internal flag indicating
that USER- [vs. SYSTEM-] events which don't pertain to the pseudomodalwindow
should be ignored.  

Sorry to be so longwinded.  I knew there had to be a better reason than
"it was a user-interface decision."  This is my guess at one.

No flames, thank you.









-- 
+-------------------+-jackiw@cs.swarthmore.edu / !rutgers!bpa!swatsun!jackiw-+
|  nicholas jackiw  | jackiw%campus.swarthmore.edu@swarthmr.bitnet           |
+-------------------+-VGP/MathDept/Swarthmore College, Swarthmore, PA 19081--+
                          PER ASPERA AD ASTRA


-- 
+-------------------+-jackiw@cs.swarthmore.edu / !rutgers!bpa!swatsun!jackiw-+
|  nicholas jackiw  | jackiw%campus.swarthmore.edu@swarthmr.bitnet           |
+-------------------+-VGP/MathDept/Swarthmore College, Swarthmore, PA 19081--+
                          PER ASPERA AD ASTRA

beard@ux1.lbl.gov (Patrick C Beard) (01/13/89)

In article <2299@ilium.cs.swarthmore.edu> jackiw@swatsun.UUCP () writes:
>In article <482@pyuxf.UUCP> asg@pyuxf.UUCP (alan geller) writes:
>> 
>> My question, though, is:
>> 	WHY can't layer switches happen when a modal dialog is displayed?
>
>Now, imagine if MF were to snatch control out from the
>get-event-requests which are presumably buried in the call to _ModalDialog.
>There are no problems giving time to other tasks, and this is what MF does.
>If, however, it allowed another layer to come frontmost, that would corrupt
>the windows in the _ModalDialog layer.  Now if User drags or resizes or closes
>a top-layer window, portions of the windows in the layer with the modal are
>going to be exposed, and consequently require updating in their back layer.
>Normally, MultiFinder would (TASK-)switch the app in, feed it its update
>events, and (TASK-)switch back to the frontmost layer. THE WHOLE PROBLEM:
>The modal app CAN'T PROCESS ITS UPDATES...

Untrue.  You are forgetting the parameters that are passed to ModalDialog:

	pascal void filterProc();
	short int itemHit;

	ModalDialog(filterProc, &itemHit);
                ^^^^^^^^^^

All normal event processing can be done from within this code.  If you
write your application like this:

	main()
	{
		EventRecord evt;

		StartupMac();	/* init managers */

		do {
			if(GetNextEvent(everyEvent, &evt)) {
				ProcessEvents(&evt);
			} else {
				IdleAwayTheHours();
			}
			SystemTask();
			/* of course it's easier to call WaitNextEvent... */
		} while(!quit);

		CloseUpShop();	/* deallocate everything */
	}

Then from within your filterProc you just call ProcessEvents() when
appropriate.

Sorry for my longwindedness.

Patrick Beard
Berkeley Systems, Berkeley CA

jackiw@cs.swarthmore.edu (Nick Jackiw) (01/17/89)

In article <1678@helios.ee.lbl.gov> beard@ux1.lbl.gov (Patrick C Beard) writes:
> In article <2299@ilium.cs.swarthmore.edu> jackiw@swatsun.UUCP () writes:
> >In article <482@pyuxf.UUCP> asg@pyuxf.UUCP (alan geller) writes:
> >> 	WHY can't layer switches happen when a modal dialog is displayed?
> >THE WHOLE PROBLEM:
> >The modal app CAN'T PROCESS ITS UPDATES...
> Untrue.  You are forgetting the parameters that are passed to ModalDialog:
> 	pascal void filterProc();
> 	short int itemHit;
> 	ModalDialog(filterProc, &itemHit);
>                 ^^^^^^^^^^
> Then from within your filterProc you just call ProcessEvents() when
> appropriate.
> Patrick Beard

You're right, but what I wrote IS true.  Of course it's possible to code an
app so that MF can switch out from modal situations.  Elsewhere in my article
I mentioned exactly that possibility.  The vast majority of apps written in
Multifinder times and ALL apps written before it, however, are NOT going to
implement a filterProc to process updates for non-modal windows. Before 
Multifinder, this was considered an impossible occurence.  We were talking
about why MFinder's backward-compatibility enforces total modality, not about
what tricks wonder-boy can teach wonder-app with total retrospective knowledge
of the inner workings of an elaborate and elegant multiprocessing kludge. 

Follow before ya flame.


-- 
+-------------------+-jackiw@cs.swarthmore.edu / !rutgers!bpa!swatsun!jackiw-+
|  nicholas jackiw  | jackiw%campus.swarthmore.edu@swarthmr.bitnet           |
+-------------------+-VGP/MathDept/Swarthmore College, Swarthmore, PA 19081--+
                          PER ASPERA AD ASTRA

wdh@well.UUCP (Bill Hofmann) (01/19/89)

In article <2311@ilium.cs.swarthmore.edu> jackiw@ilium.UUCP (Nick Jackiw) writes:
>In article <1678@helios.ee.lbl.gov> beard@ux1.lbl.gov (Patrick C Beard) writes:
>> In article <2299@ilium.cs.swarthmore.edu> jackiw@swatsun.UUCP () writes:
>> >In article <482@pyuxf.UUCP> asg@pyuxf.UUCP (alan geller) writes:
>> >> 	WHY can't layer switches happen when a modal dialog is displayed?

Because Multifinder won't switch when a window of type dBoxProc, the
standard modal dialog or alert window, is frontmost.  As I understand it,
this was a deliberate decision to improve backward compatability.

>You're right, but what I wrote IS true.  Of course it's possible to code an
>app so that MF can switch out from modal situations.  Elsewhere in my article
>I mentioned exactly that possibility.  The vast majority of apps written in
>Multifinder times and ALL apps written before it, however, are NOT going to
>implement a filterProc to process updates for non-modal windows. Before 
>Multifinder, this was considered an impossible occurence.  

Beg to differ.  If your modal dialog does something like put up an SFGet
or SFPut, you could easily have to deal (or want to deal) with update
events.  My standard filterproc handles updates.

-Bill Hofmann