[comp.sys.sun] Need help with Sunview programming

jmb%warwick.uucp@nss.cs.ucl.ac.uk (James M Beckett) (02/10/89)

I'm trying to write a tool-based program for a workstation running under
sunview(4.0.1), which creates and draws fractal landscapes.  My 3D
plotting routines are cheap and nasty and it takes a frog of a long time
to complete a 256^2 landscape.  I want to have the 'plot' button change to
a 'stop' button, which I can select to stop the fractal while it's drawing
if it doesn't look too good.

Changing the button I can do, however the notifier and I seem to be having
a breakdown of communications: I can't persuade it to let me do anything
(including resize, move, close etc, let alone select items) while the draw
routine is doing its work.

The draw routine is itself initially called from the notifier using the
PANEL_NOTIFY_PROC argument to panel_create_item, (followed eventually by a
window_main_loop(); ) and while drawing the fractal I want to give the
notifier a look-in (so that on selection of the 'stop' button it will call
a function which sets a global variable which is tested in the draw
routine which causes the loop(s) to end etc etc...)

On the advice of section 17.6 of the Sunview Programmer's Guide, I've
tried dropping a 'notify_dispatch();' inside the drawing loop, but it gets
ignored completely; any selections made while the drawing is going on just
get queued, and executed when it's done.

Other windows on the screen are unaffected, except in that the tool
doesn't auto-repaint over them when they are removed from in front of it
(understandable, if the notifier isn't getting a chance), nor does it
even, in continuing plotting, draw over where a window was, except in the
case of some canvases.  (not sure of workings..)

My theory at the moment is that once a function has been called via the
notifier, other events are disabled until the function ends.

Is this so?  What the zarking fardwarks can I do to enable the action I
want, or must I invert my program structure even further?

Thanks,

-James

 James Beckett, Computer Science,   JANET:  jmb@uk.ac.warwick.cs
 University of Warwick,              UUCP:  ...!mcvax!ukc!warwick!jmb
 Coventry CV4 7AL,  England.        PHONE:  +44 203 520995

eswara@deervax.concordia.ca (Srinivas Eswara) (02/16/89)

James M Beckett writes
>Changing the button I can do, however the notifier and I seem to be having
>a breakdown of communications...

You could probably use window_release_event_lock(window) - page 97 in
Handling Input - to take care of other events you are interested in. 

-Srinivas Eswara
eswara@deervax.concordia.ca

jsb@uunet.uu.net (The Invisible Man) (02/23/89)

In article <961@ubu.warwick.UUCP> jmb%warwick.uucp@nss.cs.ucl.ac.uk (James M Beckett) writes:

)The draw routine is itself initially called from the notifier using the
)PANEL_NOTIFY_PROC argument to panel_create_item, (followed eventually by a
)window_main_loop(); ) and while drawing the fractal I want to give the
)notifier a look-in (so that on selection of the 'stop' button it will call
)a function which sets a global variable which is tested in the draw
)routine which causes the loop(s) to end etc etc...)...

Well, there are a couple of things I'd try here: First, don't use
window_main_loop() at all.  Use explicit dispatching.  I think its
described in the same section (17.6) or thereabouts.  Secondly, instead of
using the draw routine as a notify proc, try having the notify proc merely
set a flag and return.  Then, each time through your dispatching loop,
check this flag and call your draw routine if its set, making sure that
the draw routine also checks occasionally for pending events (or nothing
will change!)  If this sort of approach doesn't work, you can always have
the draw routine run as a separate process.  I've had to do something like
that once...

				jim (uunet!actnyc!jsb)

paisley@cme.nbs.gov (Scott Paisley) (02/28/89)

jmb%warwick.uucp@nss.cs.ucl.ac.uk (James M Beckett) writes:
>Changing the button I can do, however the notifier and I seem to be having
>a breakdown of communications: I can't persuade it to let me do anything
>(including resize, move, close etc, let alone select items) while the draw
>routine is doing its work.

I found a solution to this problem, (without doing explicit dispatching)
but I'm sure that this method could be refined quite a bit.  One way
around this problem is to fork the draw routine so that it has it's own
process.  That way you still can move the window, quit, close it or
whatever else you want to do.  Here is a code frag that will do the job.

...
if ((pid = fork()) == -1) {	/* get me another process */
    perror("fork failed");
    exit(-1);
}
if (pid == 0) {		/* this identifies the child process */
    draw_routine();	/* call the draw routine  */
    exit(1);		/* exit the child process */
}
...

Barry Warsaw and I actually tried this piece of code, and it does in fact
work.  However, we noticed that while in the draw routine, the drawing was
somewhat jumpy. BUT you can click on the frame and get the frame menu
while the program draws.  Another method that we haven't tried was to fork
off the window_main_loop call itself and then go about your business.  I
would think that this would yield similar results to the above code.  I
would be interested in hearing from any other solutions that people come
up with.

Scott Paisley        paisley@cme.nbs.gov        ..!uunet!cme-durer!paisley

bickel@nprdc.navy.mil (Steven Bickel) (03/01/89)

jmb%warwick.uucp@nss.cs.ucl.ac.uk (James M Beckett) writes:
>...I want to have the 'plot' button change to
>a 'stop' button, which I can select to stop the fractal while it's drawing
>if it doesn't look too good....
>My theory at the moment is that once a function has been called via the
>notifier, other events are disabled until the function ends.

True.

Have the panels notify proc call notify_set_itimer_func(). Below is a
routine that can act as a nice interface to notify_set_itimer_func().
notify_set_itimer_func() will have the system clock (via signal - don't
use this unix function with notify_set_itimer_func()) call the designated
routine and all panel buttons within your frame will still be active.
These button will be capable of settings flags for stopping your routine.
Also, your routine should immediately reset notify_set_itimer_func() with
no function so that your function is not repeated.  This type of procedure
should also be used for panel buttons that destroy their own panel. ( I
modified this code after extracting it from our application, it may need
some slight modifications ie. for resetting the timer_func to NULL - I did
not test it).


/*--  v1.0 
     set_the_notify_itimer: 

     Sets the systems interrupt routine (layer above unix signal() )
     to call the timer node functions update function.

     Returns:  void
*/

void  set_the_notify_itimer(timer_func)
void   (*timer_func) ();

{
/*    ----- Variables -----		*/
    static char *me = (char *) &me;
    struct itimerval timer;
    float update_interval = 0.005; /* minimal time between repeated calls */

/** BEGIN set_the_notify_itimer     */

    /** set the tim interval structure to pass to the system timer interrupt */
    timer.it_interval.tv_usec = (int) (1000000 *
		    (update_interval - (float) ((int) update_interval)));
    timer.it_interval.tv_sec = (int) update_interval;
    timer.it_interval.tv_sec = 0;
    timer.it_value.tv_usec = 1;
    timer.it_value.tv_sec = 0;

    /** set the system timer interrupt routine to be the routine passed in */
    notify_set_itimer_func(me, timer_func, ITIMER_REAL, &timer, NULL);

/** END   set_the_notify_itimer     */
}

          Steve Bickel                          bickel@nprdc.arpa
	  Systems Engineering Assoc.            (619) 553-9306
	  Naval Personel R & D Center.

knudsen@ihlpl.att.com (Knudsen) (03/09/89)

I used another solution to the problem of halting a lengthy plot process.
By fooling with event masks and other things (excuse the foggy details,
this was a few weeks ago), I was able to steer the signal from the L1 key
("stop" key in the Keyboard Accelarators table) to a routine that sets a
global variable that the plodding plotting routine checks inside its loop.

Works very well, tho not as user-friendly and self-documenting as a panel
button labeled STOP.  So the first thing my plot routine does is a
pw_text(pw, "Hit L1 to Halt Plot.").

Mike Knudsen  Bell Labs(AT&T)   att!ihlpl!knudsen
"Anyone can build a conservative design, given liberal resources." -- MJK