[comp.sys.amiga.tech] Sharing a window's IDCMP between tasks

svermeulen@Janus.MRC.AdhocNet.CA (Steve Vermeulen) (01/20/89)

To All,

    I have a question regarding windows and their IDCMP ports.

    I am developing an application where I would like to share
    access to a window among several independent programs.
    Access to the window will be granted on an exclusive
    basis, the recepient will do its thing and no one else
    will access the window until the recepient has released
    its control.  Only the original creator of the window
    will be closing the window.

    As far as I can see the only potentially hazardous part
    about doing this is associated with the IDCMP messages
    and ports.  Since the message ports must know which
    task to signal when a message is arrived one cannot
    just pass a window pointer to another task and then
    have that task wait on the window's UserPort for
    messages with a line like:

              Wait(1L << w->UserPort->mp_SigBit);

    What I have tried to do (and have been completely
    successful at doing so far) is to have the recepient
    task (the one that is being granted usage of an
    already opened window) save the various window
    message port pointers, NULL out these fields
    and then do a ModifyIDCMP() to have a new message
    port created for it.  Before the recepient returns
    control of the window to the window's owner (the
    program that called OpenWindow() in the first place)
    it calls ModifyIDCMP(w, NULL) to close its ports
    and then restores the original pointers.

    The actual code that I am using looks like this:

-------------------------------------------------------------------------

            wind = (struct Window *) msg->Data[6];
            rp = wind->RPort;
            w = msg->Data[2];
            h = msg->Data[3];
            mode = rp->DrawMode;
            oldpen = rp->FgPen;

            /** now take over the window's IDCMP port
                note the positioning of Forbid()/Permit()
                is this secure enough?
             **/

            Forbid();
            oldUP = wind->UserPort;
            oldWP = wind->WindowPort;
            oldIDCMP = wind->IDCMPFlags;
            oldFlags = wind->Flags & REPORTMOUSE;

            wind->UserPort = NULL;
            wind->WindowPort = NULL;
            wind->IDCMPFlags = NULL;
            Permit();

            /** the original owner of the window has already
                removed its menus from the screen, so now we
                attach our menus and set up our IDCMP port...

                You can probably ignore most of the stuff in
                the middle, its just a simple event response
                loop that rubberbands a box on the window to
                show that we really can get away with doing
                this.
             **/

            SetMenuStrip(wind, &firstmenu);
            ModifyIDCMP(wind, MOUSEBUTTONS | MOUSEMOVE | MENUPICK);
            wind->Flags |= REPORTMOUSE;
            SetDrMd(rp, COMPLEMENT);

            /** now we go into the message processing loop, here we
                look for select button downs and mouse moves
             **/

            qflag = TRUE;
            pendown = FALSE;
            while (qflag)
            {
              Wait(1L << wind->UserPort->mp_SigBit);
              while (imess = (struct IntuiMessage *) GetMsg(wind->UserPort))
              {
                class = imess->Class;
                code  = imess->Code;
                ReplyMsg(imess);
                switch (class)
                {
                  case MENUPICK:
                    switch (ITEMNUM(code))
                    {
                      case 3:
                        /** user wants to shut down this
                         **/
                        flag = TRUE;
                      case 2:
                        /** user wants to return to the window's owner
                         **/
                        qflag = FALSE;
                        break;
                    }
                    break;

                  case MOUSEMOVE:
                    if (pendown)
                    {
                      box(rp, x1, y1, x2, y2);
                      x2 = mx; y2 = my;
                      box(rp, x1, y1, x2, y2);
                    }
                    break;
                  case MOUSEBUTTONS:
                    switch (code)
                    {
                      case SELECTDOWN:
                        if (pendown)
                        {
                          /** currently rubberbanding so stop now!
                           **/
                          box(rp, x1, y1, x2, y2);
                          pendown = FALSE;
                          SetDrMd(rp, JAM1);
                          do_wizzy_stuff_in_box(rp, psx, psy, x1, y1, x2, y2);
                          SetDrMd(rp, COMPLEMENT);
                        }
                        else
                        {
                          x2 = x1 = mx;
                          y2 = y1 = my;
                          pendown = TRUE;
                          box(rp, x1, y1, x2, y2);
                        }
                        break;
                    }
                    break;
                }
              }
            } /** end of message processing **/
            if (pendown) box(rp, x1, y1, x2, y2); /** erase rubberband **/

            SetDrMd(rp, (long) mode);
            SetAPen(rp, (long) oldpen);

            /**  START READING HERE AGAIN

                now restore the old IDCMP...  We kill our port
                and then restore the original ports...
             **/

            ModifyIDCMP(wind, NULL);
            Forbid();
            wind->UserPort = oldUP;
            wind->WindowPort = oldWP;
            wind->IDCMPFlags = oldIDCMP;
            wind->Flags |= oldFlags;
            Permit();
            ClearMenuStrip(wind); /** this should probably be before
                                      the ModifyIDCMP() line.
                                   **/

--------------------------------------------------------------------------

    So any thoughts on this?  Is this kosher, or should I go give
    myself 40 lashes with a wet floppy disk to attone for my sins?
    Have I missed an obvious bug that will bite back when I least
    expect it? ...



Stephen Vermeulen
Author: Express Paint
Newsletter Editor of AMUC
SVermeulen%Janus.MRC.AdhocNet.CA@Uncaedu.BITnet