[comp.sys.amiga.tech] inputs from many windows.

tlm@pur-phy (Timothy Lee Meisenheimer) (01/28/89)

Well, I'm working on a little project which will have lots of little
windows around (1 - X where X is related to how obnoxious you're feeling)
and I'll be getting inputs (mouseclicks, gadgets, kill etc.) from them
all. What I would like to ask is for those of you who have done something
like this (like "Browser") what have you done in your event loop to read
all these messages and tell which window they come from? I haven't seen
any good examples yet (though I'm going to check out what Matt does in
DME), and would appreciate any advice from those wiser than myself. Would
you suggest looking at all the UserPorts? Replacing all the UserPorts with
that of the first one? (that sounds fishy!) Thanks for any help.

	tim.

peter@sugar.uu.net (Peter da Silva) (01/29/89)

Browser 1.2 and 1.3 just opened an IDCMP for each window, and had a loop like
this:

	while(1) {
		Wait(sigmask); /* sigmask is OR of all ports' sigbits */
		for(each window, w) {
			while(msg = GetMsg(w->UserPort->mp_SigBits)) {
				copymsg = *msg; /* structure copy */
				ReplyMsg(msg);
				switch(copymsg.Class) {
					...
				}
			}
		}
	}

Browser 1.4 and 1.5 had one IDCMP shared between all the windows, and used
CLoseWindowSafely(). Unfortunately, it wasn't safe. So 1.6 has gone back to
one IDCMP per window.
-- 
Peter "Have you hugged your wolf today" da Silva  `-_-'  Hackercorp.
...texbell!sugar!peter, or peter@sugar.uu.net      'U`

cunniff@hpfcdc.HP.COM (Ross Cunniff) (01/29/89)

In article <1918@pur-phy> tlm@pur-phy (Timothy Lee Meisenheimer) writes:
> Well, I'm working on a little project which will have lots of little
> windows around (1 - X where X is related to how obnoxious you're feeling)
> and I'll be getting inputs (mouseclicks, gadgets, kill etc.) from them
> all...
>			...what have you done in your event loop to read
> all these messages and tell which window they come from?

Well, probably the best thing is to share the same IDCMP port between
all your windows.  To do this, first get an IDCMP (from the first OpenWindow
will do nicely).  When you open subsequent windows, don't specify ANY
IDCMP events in the NewWindow structure.  Instead, do the following:

	Win = OpenWindow( &NewWin );
	Win->UserPort = OrigWin->UserPort;
	ModifyIDCMP( Win, MOUSEBUTTONS|MOUSEMOVE|... (whatever) );

You now are sharing the same IDCMP between OrigWin and Win.  You
can tell which window an event came from by examining the Msg->IDCMPWindow
field.  BE CAREFUL, however, when you close Win.  You will have to do something
like the following, or you may get gurus:

	ILock = LockIBase( 0 );

		while( Msg = GetMsg( Win->UserPort ) ) {
		    ReplyMsg( Msg );
		}
		Win->UserPort = NULL;
		CloseWindow( Win );

	UnlockIBase( ILock );

(Your mileage on actual code may vary.  Amiga Wizards???)

					Ross Cunniff
					Hewlett-Packard Colorado Languages Lab
					...{ucbvax,hplabs}!hpfcrt!cunniff
					cunniff%hpfcrt@hplabs.ARPA

jimm@amiga.UUCP (Jim Mackraz) (01/30/89)

In article <3358@sugar.uu.net> peter@sugar.uu.net (Peter da Silva) writes:
)Browser 1.4 and 1.5 had one IDCMP shared between all the windows, and used
)CLoseWindowSafely(). Unfortunately, it wasn't safe. So 1.6 has gone back to
)one IDCMP per window.

Lots and lots of programs use a single port for multiple windows, using
CloseWindowSafely() and the protocol described in the V1.2 Intuition Enhancer
document.  There is a field in the IntuiMessage to identify the window
to which the message pertains.

If there are problems, let them be known.  If you think the problems might
have been your own or you don't understand what was going on, don't post
to the contrary.  Please be specific or don't bother answering.  The original
poster would now think that ports cannot be shared, when indeed they can and
are for many programs, including the Workbench.

	jimm
-- 
Jim Mackraz, I and I Computing	   	"Like you said when we crawled down
{cbmvax,well,oliveb}!amiga!jimm          from the trees: We're in transition."
							- Gang of Four
Opinions are my own.  Comments are not to be taken as Commodore official policy.

jesup@cbmvax.UUCP (Randell Jesup) (01/30/89)

In article <3358@sugar.uu.net> peter@sugar.uu.net (Peter da Silva) writes:
>			while(msg = GetMsg(w->UserPort->mp_SigBits)) {

	Now Peter, you know better than that!  :-)	^^^^^^^^^^

>Browser 1.4 and 1.5 had one IDCMP shared between all the windows, and used
>CLoseWindowSafely(). Unfortunately, it wasn't safe. So 1.6 has gone back to
>one IDCMP per window.

	What was unsafe about it?

-- 
Randell Jesup, Commodore Engineering {uunet|rutgers|allegra}!cbmvax!jesup

peter@sugar.uu.net (Peter da Silva) (01/30/89)

In article <5844@cbmvax.UUCP>, jesup@cbmvax.UUCP (Randell Jesup) writes:
> In article <3358@sugar.uu.net> peter@sugar.uu.net (Peter da Silva) writes:
> >			while(msg = GetMsg(w->UserPort->mp_SigBits)) {
> 	Now Peter, you know better than that!  :-)	^^^^^^^^^^

Yeh, what a bozo. "while(msg = GetMsg(w->UserPort))..."

> >Browser 1.4 and 1.5 had one IDCMP shared between all the windows, and used
> >CLoseWindowSafely(). Unfortunately, it wasn't safe. So 1.6 has gone back to
> >one IDCMP per window.

> 	What was unsafe about it?

I don't know, but under heavy use I got Gurus.
-- 
Peter "Have you hugged your wolf today" da Silva  `-_-'  Hackercorp.
...texbell!sugar!peter, or peter@sugar.uu.net      'U`

peter@sugar.uu.net (Peter da Silva) (01/30/89)

In article <3290@amiga.UUCP>, jimm@amiga.UUCP (Jim Mackraz) writes:
> If there are problems, let them be known.  If you think the problems might
> have been your own or you don't understand what was going on, don't post
> to the contrary.  Please be specific or don't bother answering.  The original
> poster would now think that ports cannot be shared, when indeed they can and
> are for many programs, including the Workbench.

Well, when I use Browser I open and close windows a lot faster, and with
more pending messages, than just about any other program that I can think of.
And I found that very rarely Browser would guru on closing a window. I
tried tracing it under SDB, but it seemed timing dependent. It never happened
under SDB. It was definitely Browser doing it... and it wasn't any obvious
booboos like replying to messages from a closed window. I eventually gave up
on it because I wanted to get 1.6 out. I'll probably try again at a later date.

I asked about it on this group when I had the problems, without any useful
responses (got half a dozen copies of CloseWindowSafely. Thanks, folks).

Anyway, while it's possible to share IDCMPs it's certainly not easy. You have
to be VERY careful... when I figure out just how careful I'll be sure to let
you know. I suspect there are programs out there with the same problems I had
that just haven't been exersized enough (how often do you close windows? How
about 6 at once with pending mouse clicks and resize messages?).
-- 
Peter "Have you hugged your wolf today" da Silva  `-_-'  Hackercorp.
...texbell!sugar!peter, or peter@sugar.uu.net      'U`

billk@pnet01.cts.com (Bill W. Kelly) (01/30/89)

cunniff@hpfcdc.HP.COM (Ross Cunniff) writes:
>In article <1918@pur-phy> tlm@pur-phy (Timothy Lee Meisenheimer) writes:
>> Well, I'm working on a little project which will have lots of little
>> windows around (1 - X where X is related to how obnoxious you're feeling)
>> and I'll be getting inputs (mouseclicks, gadgets, kill etc.) from them
>> all...
>>			...what have you done in your event loop to read
>> all these messages and tell which window they come from?
>
>Well, probably the best thing is to share the same IDCMP port between
>all your windows.  To do this, first get an IDCMP (from the first OpenWindow
>will do nicely).  When you open subsequent windows, don't specify ANY
>IDCMP events in the NewWindow structure.  Instead, do the following:
>
>	Win = OpenWindow( &NewWin );
>	Win->UserPort = OrigWin->UserPort;
>	ModifyIDCMP( Win, MOUSEBUTTONS|MOUSEMOVE|... (whatever) );
>
[rest of message and sample code for closing window deleted]

Ok, I give up.  

What's the _probem_ with allowing these poor little windows to each have their
own IDCMP's?  

It doesn't seem as though it would require more code for each window to have
its own IDCMP -- in fact, it seems like a much simpler/safer way to go than
the alternative.

Am I missing something?

bill
--
Bill W. Kelly                                         billk@pnet01.cts.com
{nosc ucsd hplabs!hp-sdd}!crash!pnet01!billk   crash!pnet01!billk@nosc.mil

aaron@madnix.UUCP (Aaron Avery) (01/30/89)

In article <1918@pur-phy> tlm@newton.physics.purdue.edu.UUCP (Timothy Lee Meisenheimer) writes:
>you suggest looking at all the UserPorts? Replacing all the UserPorts with
>that of the first one? (that sounds fishy!) Thanks for any help.

Well, that may sound fishy, but it's what the manual says to do and what works.
Well, a variant anyway.
What you want to do is to only define any IDCMPFlags in one of the windows
before you open it. This window will then have a UserPort allocated for it.
Now, after you open other windows with IDCMPFlags set to NULL, you set their
UserPort variables to the one allocated for the first window. Now, call
ModifyIDCMP() on those windows, saying which flags you want them to respond
to. Now, all IDCMP messages for all windows will come in to that one UserPort.
The IntuiMessage structure you are passed contains a pointer to which
window the message pertains to (IDCMPWindow, a pointer to its Window
structure). Later, when you go to close the windows, set all but one of the
UserPort's to NULL before closing them. I'd suggest calling ModifyIDCMP()
and clearing all flags before putting NULL in the UserPort. That's probably
safest, but wasn't mentioned in my manual.
Also note that you could just as well allocate your own message port and
use that one, not having Intuition allocate even that one. If the
IDCMPFlags variable is NULL when you call OpenWindow(), Intuition won't
allocate a port. If the IDCMPFlags variable is non-NULL when you call
ModifyIDCMP(), intuition won't allocate a port. That's how we controlled the
port's allocation above.

-- 
Aaron Avery, ASDG Inc.         "A mime is a terrible thing to waste."
                                                             -- Robin Williams
ARPA: madnix!aaron@cs.wisc.edu   {uunet|ncoast}!marque!
UUCP:   {harvard|rutgers|ucbvax}!uwvax!astroatc!nicmad!madnix!aaron

phil@titan.rice.edu (William LeFebvre) (01/31/89)

In article <3778@crash.cts.com> billk@pnet01.cts.com (Bill W. Kelly) writes:
>What's the _probem_ with allowing these poor little windows to each have their
>own IDCMP's?  
>...
>Am I missing something?

This is my thinking (and it might be wrong---I'm not sure).  Separate
IDCMPs means separate message ports.  Separate ports means separate signal
bits.  And you can only have 32 sigbits, right (only 32 bits in a long)?
That would imply to me that you can have, at the most, 32 open windows in
your task, if you use a separate IDCMP for each window.

This leads to something for which I don't know the answer:  are sigbits
allocated on a per-task basis or do they need to be unique throughout the
entire system?  In other words, can two separate tasks both be using the
same signal bit for two separate ports?  Seems to me that it would just be
too restrictive if they couldn't.

			William LeFebvre
			Department of Computer Science
			Rice University
			<phil@Rice.edu>

jesup@cbmvax.UUCP (Randell Jesup) (02/01/89)

In article <2509@kalliope.rice.edu> phil@Rice.edu (William LeFebvre) writes:
>This is my thinking (and it might be wrong---I'm not sure).  Separate
>IDCMPs means separate message ports.  Separate ports means separate signal
>bits.  And you can only have 32 sigbits, right (only 32 bits in a long)?
>That would imply to me that you can have, at the most, 32 open windows in
>your task, if you use a separate IDCMP for each window.

	Actually less, since a number of signals (like ^C-F, plus others)
are pre-allocated to the system.

>This leads to something for which I don't know the answer:  are sigbits
>allocated on a per-task basis or do they need to be unique throughout the
>entire system?  In other words, can two separate tasks both be using the
>same signal bit for two separate ports?  Seems to me that it would just be
>too restrictive if they couldn't.

	Yes, signal allocations are on a per-task basis.

-- 
Randell Jesup, Commodore Engineering {uunet|rutgers|allegra}!cbmvax!jesup

shf@well.UUCP (Stuart H. Ferguson) (02/01/89)

+-- tlm@newton.physics.purdue.edu.UUCP (Timothy Lee Meisenheimer) writes:
| Well, I'm working on a little project which will have lots of little
| windows 
|  [...] what have you done in your event loop to read
| all these messages and tell which window they come from? I haven't seen
| any good examples yet (though I'm going to check out what Matt does in

Modeler 3D lets you open an unlimited number of windows, and I just let
Intuition create a new UserPort for each one.  Modeler just waits on the
logical-or of the waitmask for each window.  Works fine.

One thing that caused me some trouble, however, is the fact that Intuition
will start to re-use SigBit's once you've used them all.  This means that
two windows can share the same signal bit -- not a terrible problem, but
something to be aware of so you don't assume that all signal bits are unique.
I made this assumption initially and found that windows stopped working
in stress-testing (multi-dozens of windows).  It wasn't hard to fix.
-- 
		Stuart Ferguson		(shf@well.UUCP)
		Action by HAVOC

shf@well.UUCP (Stuart H. Ferguson) (02/01/89)

+-- shf@well.UUCP (Stuart H. Ferguson) writes:
| logical-or of the waitmask for each window.  Works fine.
  ^^^^^^^

I meant "bitwise," obviously.  The code Peter Da.S. posted looked like
about what I do.
-- 
		Stuart Ferguson		(shf@well.UUCP)
		Action by HAVOC

billk@pnet01.cts.com (Bill W. Kelly) (02/01/89)

phil@titan.rice.edu (William LeFebvre) writes:
>In article <3778@crash.cts.com> billk@pnet01.cts.com (Bill W. Kelly) writes:
>>What's the _probem_ with allowing these poor little windows to each have their
>>own IDCMP's?  
>>...
>>Am I missing something?
>
>This is my thinking (and it might be wrong---I'm not sure).  Separate
>IDCMPs means separate message ports.  Separate ports means separate signal
>bits.  And you can only have 32 sigbits, right (only 32 bits in a long)?
>That would imply to me that you can have, at the most, 32 open windows in
>your task, if you use a separate IDCMP for each window.
 
For some reason, that completely slipped my mind.  (Someone else also reminded
me of this via email.)  Each task has 16 (sixteen) user sigbits available to
it.  The other 16 sigbits are reserved for system use.  (For example, bits
12-15 are for ^C, ^D, ^E, and ^F.  For instance if from the CLI you type:
'break 3 C', process number three gets signaled with bit 12 --
SIGBREAKF_CTRL_C.)

>This leads to something for which I don't know the answer:  are sigbits
>allocated on a per-task basis or do they need to be unique throughout the
>entire system?  In other words, can two separate tasks both be using the
>same signal bit for two separate ports?  Seems to me that it would just be
>too restrictive if they couldn't.

Each task has its own set of sigbits.  The signals you have allocated, are
waiting for, and have received are kept track of in the tc_SigAlloc,
tc_SigWait, and tc_SigRecvd fields of each task structure.  (This is the
structure you get the address of when you call FindTask(0).)

--
Bill W. Kelly                                         billk@pnet01.cts.com
{nosc ucsd hplabs!hp-sdd}!crash!pnet01!billk   crash!pnet01!billk@nosc.mil

aaron@madnix.UUCP (Aaron Avery) (02/01/89)

In article <2509@kalliope.rice.edu> phil@Rice.edu (William LeFebvre) writes:
)This is my thinking (and it might be wrong---I'm not sure).  Separate
)IDCMPs means separate message ports.  Separate ports means separate signal
)bits.  And you can only have 32 sigbits, right (only 32 bits in a long)?
)That would imply to me that you can have, at the most, 32 open windows in
)your task, if you use a separate IDCMP for each window.

That's my impression of what the problem is. Also, it's worse than that. The
system pre-allocates 16 sigbits for you, so you only have 16 more to allocate
yourself.
 
)This leads to something for which I don't know the answer:  are sigbits
)allocated on a per-task basis or do they need to be unique throughout the
)entire system?  In other words, can two separate tasks both be using the
)same signal bit for two separate ports?  Seems to me that it would just be
)too restrictive if they couldn't.

Yes, they're on a per-task basis. 32 signals for the whole system would be a
TAD restrictive!-)

-- 
Aaron Avery, ASDG Inc.         "A mime is a terrible thing to waste."
                                                             -- Robin Williams
ARPA: madnix!aaron@cs.wisc.edu   {uunet|ncoast}!marque!
UUCP:   {harvard|rutgers|ucbvax}!uwvax!astroatc!nicmad!madnix!aaron

janhen@wn2.sci.kun.nl (Jan Hendrikx) (02/02/89)

In article <439@madnix.UUCP>, aaron@madnix.UUCP (Aaron Avery) writes:
> structure). Later, when you go to close the windows, set all but one of the
> UserPort's to NULL before closing them. I'd suggest calling ModifyIDCMP()
> and clearing all flags before putting NULL in the UserPort. That's probably
> safest, but wasn't mentioned in my manual.

Noooo! If you have a non-NULL UserPort when you use ModifyIDCMP to
clear all the flags, the port will be de-allocated. (Thats what the
Intuition manual and autodocs say about it). So you must FIRST NULL out
the userports on all windows but the last, and THEN use ModifyIDCMP to
clear the flags. (This is safe to do for all

By the way, the version of CloseWindowSafely() that I got here uses
Forbit()/Permit() around its message Remove()ing loop.  What I say on
the net uses LockIBase()/UnLockIBase(). Is that sufficient for the
purpose (of making sure no new IntuiMessages are PutMsg()ed to the
port)?

> Aaron Avery, ASDG Inc.         "A mime is a terrible thing to waste."

-Olaf Seibert (using Jan's account)

peter@sugar.uu.net (Peter da Silva) (02/02/89)

In article <10549@well.UUCP>, shf@well.UUCP (Stuart H. Ferguson) writes:
> One thing that caused me some trouble, however, is the fact that Intuition
> will start to re-use SigBit's once you've used them all.

This is *terrible*! It should either only ever use one SigBit, or it should
refuse to open windows once it's run out. I can't believe this...

> I made this assumption initially and found that windows stopped working
> in stress-testing (multi-dozens of windows).  It wasn't hard to fix.

Oh well, expect occasional oddnesses if you habitually use in excess of 24
windows in Browser. It may lock up if you open 30 windows and then close them
all... my first bug fix for 1.7, I guess.
-- 
Peter "Have you hugged your wolf today" da Silva  `-_-'  Hackercorp.
...texbell!sugar!peter, or peter@sugar.uu.net      'U`

dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) (02/03/89)

	Another solution to the signal-bit problem which I have yet to
try, but which also seems workable, is to just open up a lot of windows
w/ independant IDCMP ports.

	But nobody ever said they had to have *different* signal bits!!

	That's right, once you get the port back, simply modify SigBit
to some common signal bit and then FreeSignal() the one that came with the
port.

	When you CloseWindow() a window, first replace SigBit with a newly
allocated one (which the workbench will immediately deallocate when it
deletes the port).  I.E.:

	Short MasterSigBit;

	main()
	{
	    short tmp;
	    MasterSigBit = AllocSignal(-1);

	    ...
	    win = OpenWindow(&Nw);
	    tmp = win->UserPort->mp_SigBit;
	    win->UserPort->mp_SigBit = MasterSigBit;
	    FreeSignal(tmp);

	    ...
	    win->UserPort->mp_SigBit = AllocSignal(-1);
	    CloseWindow(win);
	}

	Now, this isn't quite as nice as sharing a single IDCMP port because
you now have to poll all the active window's ports whenever you get a signal,
but neither do you have to screw around much either.

	Note that a simple 'window cache' .. I.E. remembering the last window
that an IDCMP came from and checking that first .. will yield almost the same
efficiency as sharing an IDCMP port.

					-Matt

shf@well.UUCP (Stuart H. Ferguson) (02/03/89)

+-- aaron@madnix.UUCP (Aaron Avery) writes:
| In article <2509@kalliope.rice.edu> phil@Rice.edu (William LeFebvre) writes:
| )bits.  And you can only have 32 sigbits, right (only 32 bits in a long)?
| )That would imply to me that you can have, at the most, 32 open windows in
| )your task, if you use a separate IDCMP for each window.
| That's my impression of what the problem is. Also, it's worse than that. The
| system pre-allocates 16 sigbits for you, so you only have 16 more to allocate
| yourself.

In case no one caught it the first time through -- Intuition re-uses signal
bits to create new IDCMP ports _once all the unique ones_ are used up.  In 
other words, if you want to open 50 windows, fine, but the last 34 or so
will use the same signal bit for incoming messages.  As long as you
allocate all the signals you need up front, you can open mass quantities
of windows and Intuition will take care of its own.
-- 
		Stuart Ferguson		(shf@well.UUCP)
		Action by HAVOC

shimoda@infohh.rmi.de (Markus Schmidt) (02/04/89)

>IDCMPs means separate message ports.  Separate ports means separate signal
>bits.  And you can only have 32 sigbits, right (only 32 bits in a long)?
>That would imply to me that you can have, at the most, 32 open windows in
>your task, if you use a separate IDCMP for each window.
>
Not quite right. The OS reserves 16 Signals for internal use, so you
only have 16 for yourself.


Shimoda

jimm@amiga.UUCP (Jim Mackraz) (02/04/89)

In article <327@wn2.sci.kun.nl> janhen@wn2.sci.kun.nl (Jan Hendrikx) writes:
)By the way, the version of CloseWindowSafely() that I got here uses
)Forbit()/Permit() around its message Remove()ing loop.  What I say on
)the net uses LockIBase()/UnLockIBase(). Is that sufficient for the
)purpose (of making sure no new IntuiMessages are PutMsg()ed to the
)port)?

It is very incorrect.  Let me quote from the autodocs of LockIBase:

*       Grabs Intuition internal semaphore so that caller may examine
*       IntuitionBase safely.

This has nothing to do with messaging, nothing to do with millions of other
pretend uses of LockIBase().  We reserve the right to assume that uses of
LockIBase() are exactly as documented.

Apart from this, Olaf, your interpretation of ModifyIDCMP() was sound.

)-Olaf Seibert (using Jan's account)

	jimm
-- 
Jim Mackraz, I and I Computing	   	"Like you said when we crawled down
{cbmvax,well,oliveb}!amiga!jimm          from the trees: We're in transition."
							- Gang of Four
Opinions are my own.  Comments are not to be taken as Commodore official policy.