[comp.sys.amiga.programmer] How to do a "MovePointer

bratt@csli.Stanford.EDU (Harry Bratt) (06/18/91)

I need to change the position of Intuition's mouse pointer.  I
don't need lots of low-level control (like recording mouse movements
and playing them back), I just need a single re-positioning once
in a while.
Currently I'm doing:

IntuitionBase->MouseX = x;
IntuitionBase->MouseY = y;
SetPointer(...);

This appears to work....  but...
Is it legal to be writing to those IntuitionBase variables?  And
is there a better way to be doing this?

 -Harry
  bratt@csli.stanford.edu

peterk@cbmger.UUCP (Peter Kittel GERMANY) (06/18/91)

In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt) writes:
>I need to change the position of Intuition's mouse pointer.  I
>don't need lots of low-level control (like recording mouse movements
>and playing them back), I just need a single re-positioning once
>in a while.

Look into the RKMs with the Input device. You can create Input events
of the Pointerpos kind. This will do exactly what you want.

-- 
Best regards, Dr. Peter Kittel  // E-Mail to  \\  Only my personal opinions... 
Commodore Frankfurt, Germany  \X/ {uunet|pyramid|rutgers}!cbmvax!cbmger!peterk

mks@cbmvax.commodore.com (Michael Sinz) (06/18/91)

In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt) writes:
>I need to change the position of Intuition's mouse pointer.  I
>don't need lots of low-level control (like recording mouse movements
>and playing them back), I just need a single re-positioning once
>in a while.
>Currently I'm doing:
>
>IntuitionBase->MouseX = x;
>IntuitionBase->MouseY = y;
>SetPointer(...);
>
>This appears to work....  but...
>Is it legal to be writing to those IntuitionBase variables?  And
>is there a better way to be doing this?

You are lucky that it almost worked...

To move the mouse, you need to send a mouse event down the input
food chain.  There is full documentation of this in the RKM (1.3)

The example code given here moves the mouse pointer in a circle...

/*
 * InputDevice example
 *
 * This example adds a few mouse movements to the input chain...
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/input.h>
#include <devices/inputevent.h>

#include <proto/all.h>

VOID main(VOID)
{
struct IOStdReq   *inputReqBlk;
struct MsgPort    *inputPort;
struct InputEvent *FakeEvent;
       short      loop;
       short      num;
       short      numloop;

    if (inputPort=CreatePort(NULL,NULL))
    {
        if (FakeEvent=AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC))
        {
            if (inputReqBlk=(struct IOStdReq *)CreateExtIO(inputPort,
                                                     sizeof(struct IOStdReq)))
            {
                if (!OpenDevice("input.device",NULL,
                                 (struct IORequest *)inputReqBlk,NULL))
                {
                    for (numloop=0;numloop<4;numloop++)
                     for (loop=0;loop<8;loop++)
                      for (num=0;num<20;num++)
                    {
			/*
			 * Note that events are trashed after they finish
			 * from the input food chain.  All fields must
			 * be set up before submitting the event again
			 */
                        FakeEvent->ie_NextEvent=NULL;
                        FakeEvent->ie_Class=IECLASS_RAWMOUSE;
                        FakeEvent->ie_Code=IECODE_NOBUTTON;
                        FakeEvent->ie_Qualifier=IEQUALIFIER_RELATIVEMOUSE;
                        FakeEvent->ie_X=0;
                        FakeEvent->ie_Y=0;

                        switch (loop)
                        {
                        case 0: FakeEvent->ie_X=1;
                        case 1: FakeEvent->ie_Y=1;  break;
                        case 2: FakeEvent->ie_Y=1;
                        case 3: FakeEvent->ie_X=-1; break;
                        case 4: FakeEvent->ie_X=-1;
                        case 5: FakeEvent->ie_Y=-1; break;
                        case 6: FakeEvent->ie_Y=-1;
                        case 7: FakeEvent->ie_X=1;  break;
                        }

                        inputReqBlk->io_Data=(APTR)FakeEvent;
                        inputReqBlk->io_Command=IND_WRITEEVENT;
                        inputReqBlk->io_Flags=0;
                        inputReqBlk->io_Length=sizeof(struct InputEvent);
                        DoIO((struct IORequest *)inputReqBlk);
                    }
                    CloseDevice((struct IORequest *)inputReqBlk);
                }
                DeleteExtIO((struct IORequest *)inputReqBlk);
            }
            FreeMem(FakeEvent,sizeof(struct InputEvent));
        }
        DeletePort(inputPort);
    }
}

/----------------------------------------------------------------------\
|      /// Michael Sinz  -  Amiga Software Engineer                    |
|     ///                   Operating System Development Group         |
|    ///   BIX:  msinz      UUNET:  rutgers!cbmvax!mks                 |
|\\\///                                                                |
| \XX/     Quantum Physics:  The Dreams that Stuff is made of.         |
\----------------------------------------------------------------------/

GUTEST8@cc1.kuleuven.ac.be (Ives Aerts) (06/20/91)

In article <1382@cbmger.UUCP>, peterk@cbmger.UUCP (Peter Kittel GERMANY) says:
>
>In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt)
>writes:
>>I need to change the position of Intuition's mouse pointer.  I
>>don't need lots of low-level control (like recording mouse movements
>>and playing them back), I just need a single re-positioning once
>>in a while.
>
>Look into the RKMs with the Input device. You can create Input events
>of the Pointerpos kind. This will do exactly what you want.

That's the way to do it. But are you really *SURE* you have to do it ?
I don't like other programs to mess around with the mouse pointer.
And if you do, set it back to it's original position afterwards.
Again: think twice before doing such a thing. If there exists another
(legal) way to do what you want then do it that way, even it that
method needs more code.


------------------------------------------------------------------------
      Ives Aerts           |          IBM definition SY-34378
GUTEST8@BLEKUL11.BITNET    |   A signature consists of sequences of
gutest8@cc1.kuleuven.ac.be | non-blank characters separated by blanks.
------------------------------------------------------------------------

caw@miroc.Chi.IL.US (Christopher A. Wichura) (06/20/91)

In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt) writes:
>I need to change the position of Intuition's mouse pointer.  I

>Currently I'm doing:
>
>IntuitionBase->MouseX = x;
>IntuitionBase->MouseY = y;
>SetPointer(...);
>
>This appears to work....  but...

The above looks kinda illegal to me.  What you might consider is doing
something like this:

	lock = LockIBase(0);
	CurX = IntuitionBase->MouseX;
	CurY = IntuitionBase->MouseY;
	<calculate delta to where you want the mouse to be>
	<create an input event and send it to input.device>
	UnlockIBase(lock);

-=> CAW

Christopher A. Wichura                Multitasking.  Just DO it.
caw@miroc.chi.il.us  (my amiga)                          ...the Amiga way...
u12401@uicvm.uic.edu (school account)

bratt@csli.Stanford.EDU (Harry Bratt) (06/20/91)

In <91170.181652GUTEST8@cc1.kuleuven.ac.be> GUTEST8@cc1.kuleuven.ac.be (Ives Aerts) writes:
>In article <1382@cbmger.UUCP>, peterk@cbmger.UUCP (Peter Kittel GERMANY):
>>
>>In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt):
>>>I need to change the position of Intuition's mouse pointer.
>>
>>Look into the RKMs with the Input device. You can create Input events
>>of the Pointerpos kind. This will do exactly what you want.

>That's the way to do it. But are you really *SURE* you have to do it ?
>I don't like other programs to mess around with the mouse pointer.
>And if you do, set it back to it's original position afterwards.

Actually, I've been wondering about that problem for a while.  The program
I'm writing is using a RMB-pop-up-menu.  The need to move the pointer
comes when 2 things conflict:
 1) I want the menu to pop up under the mouse on a specific item
 2) Doing #1 would place some of the menu off-screen

Now I've used other systems which use pop-up menus as standard, but I
don't have access to them now and I didn't notice well enough what
they did in this case.  Possibly they just don't care about #1.  I
know Iff2Pcs on an early fish disk uses pop-up menus (which it got from
somewhere else - I don't remember where), but the way it handles the
problem is by leaving the pointer alone and moving the menu within screen
bounds - this means if the mouse pointer is high or low on the screen,
you may get the menu popping up on an undesired default.  I've ended up
inadvertantly selecting "quit" a few times because of this. :-(

What I'm doing now is moving both the pointer and the menu by the
amount needed to put the menu within screen bounds.

So I'd be interested in knowing what people think the solution to this
should be.  I guess many people dislike pop-up menus partially for
just this reason - but I think I need them (I'm using title bar menus
as well - if the mouse pointer is on the title bar, like in DPaint).

And more specifically, if I do move the pointer like I am now, should
I attempt to move it back after they release the RMB?  I see 3 possibilities:
1) don't move it back
2) move it back exactly to where it was when the RMB was pressed
   (or, since they'll be moving the pointer to do menu selection,)
3) move it the same distance I had to move it when the RMB was pressed,
   but in the opposite direction

 -Harry
  bratt@csli.stanford.edu

peter@cbmvax.commodore.com (Peter Cherna) (06/21/91)

In article <caw.2099@miroc.Chi.IL.US> caw@miroc.Chi.IL.US (Christopher A. Wichura) writes:
>In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt) writes:
>>I need to change the position of Intuition's mouse pointer.  I
>
>>Currently I'm doing:
>>
>>IntuitionBase->MouseX = x;
>>IntuitionBase->MouseY = y;
>>SetPointer(...);
>>
>>This appears to work....  but...

That is illegal.
>
>The above looks kinda illegal to me.  What you might consider is doing
>something like this:
>
>	lock = LockIBase(0);
>	CurX = IntuitionBase->MouseX;
>	CurY = IntuitionBase->MouseY;
>	<calculate delta to where you want the mouse to be>
>	<create an input event and send it to input.device>
>	UnlockIBase(lock);

I don't think I'd do a DoIO() to input.device while inside LockIBase().
In any case, you can't guarantee that there aren't other input events
(from the hardware) moving the mouse.  All you want to do is get
an atomic reading of MouseX and MouseY.  That is to say, if the
mouse-coords change from (100,50) to (120,40) at one time, you
want to avoid reading (100,40) or (120,50).  Since MouseX and
MouseY are both words, you can grab them in one shot:

sturct MouseCoords
{
    WORD MouseY;
    WORD MouseX;
} mouse;

	(* (ULONG *)(&mouse)) = (* (ULONG *)(&IntuitionBase->MouseY) )
	/* set-up event and perform DoIO() */

That horrible expression basically reads:  pretend there is a ULONG
value starting at IntuitionBase->MouseY, and copy it into the ULONG
we're pretending is located at 'mouse'.

>Christopher A. Wichura                Multitasking.  Just DO it.

     Peter
--
Peter Cherna, Operating Systems Development Group, Commodore-Amiga, Inc.
{uunet|rutgers}!cbmvax!peter    peter@cbmvax.commodore.com
My opinions do not necessarily represent the opinions of my employer.
"Gosh, didn't he have anything positive to say at all?"

steve@wildcat.UUCP (Steve Holland) (06/22/91)

>In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt) writes:
>I need to change the position of Intuition's mouse pointer.  I
>don't need lots of low-level control (like recording mouse movements
>and playing them back), I just need a single re-positioning once
>in a while.
>Currently I'm doing:
>
>IntuitionBase->MouseX = x;
>IntuitionBase->MouseY = y;
>SetPointer(...);
  If you do it that way, remember to LockIBase() first. The correct way to
do this is to send the input.device a pointer-positioning message.
>
>This appears to work....  but...
>Is it legal to be writing to those IntuitionBase variables?  And
>is there a better way to be doing this?
>
> -Harry
>  bratt@csli.stanford.edu

--
 ----------->Steve Holland<-----------
 Internet: wildcat!steve@alphalpha.com| "I never let my schooling get in the
 USENET:  ...!alphalpha!wildcat!steve | way of my education" -Mark Twain

jpotter@ucs.adelaide.edu.au (Jonathan Potter) (06/22/91)

 In article <22627@cbmvax.commodore.com> peter@cbmvax.commodore.com (Peter Cherna) writes:
 >In article <caw.2099@miroc.Chi.IL.US> caw@miroc.Chi.IL.US (Christopher A. Wichura) writes:
 >>In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt) writes:
 >>>I need to change the position of Intuition's mouse pointer.  I
 >>
 >>>Currently I'm doing:
 >>>
 >>>IntuitionBase->MouseX = x;
 >>>IntuitionBase->MouseY = y;
 >>>SetPointer(...);
 >>>
 >>>This appears to work....  but...
 >
 >That is illegal.
 >>
 >>The above looks kinda illegal to me.  What you might consider is doing
 >>something like this:
 >>
 >>      lock = LockIBase(0);
 >>      CurX = IntuitionBase->MouseX;
 >>      CurY = IntuitionBase->MouseY;
 >>      <calculate delta to where you want the mouse to be>
 >>      <create an input event and send it to input.device>
 >>      UnlockIBase(lock);
 >
 >I don't think I'd do a DoIO() to input.device while inside LockIBase().
 >In any case, you can't guarantee that there aren't other input events
 >(from the hardware) moving the mouse.  All you want to do is get
 >an atomic reading of MouseX and MouseY.  That is to say, if the
 >mouse-coords change from (100,50) to (120,40) at one time, you
 >want to avoid reading (100,40) or (120,50).  Since MouseX and
 >MouseY are both words, you can grab them in one shot:
 >
 >sturct MouseCoords
 >{
 >    WORD MouseY;
 >    WORD MouseX;
 >} mouse;
 >
 >       (* (ULONG *)(&mouse)) = (* (ULONG *)(&IntuitionBase->MouseY) )
 >       /* set-up event and perform DoIO() */
 >
 >That horrible expression basically reads:  pretend there is a ULONG
 >value starting at IntuitionBase->MouseY, and copy it into the ULONG
 >we're pretending is located at 'mouse'.
 >
 >>Christopher A. Wichura                Multitasking.  Just DO it.
 >
 >     Peter

Going through the input device is the proper way to do it, but you don't
need to LockIBase() - your DoIO() to the input device goes in before
intuition sees it, so Intuition acts as if nothing unusual has happened.

Another way to do it is to use the Intuition() function, passing it an
input event. This saves having to setup an IORequest, but can cause some
problems. The RKM discourages you from using this.

Jon
-- 
| Jon Potter      |                              | I'd really like to      |
| P.O. Box 289    | jpotter@itd.adelaide.edu.au  |   change the world...   |
| Goodwood, SA    | FidoNet : 3:680/829          | But they won't give me  |
| Australia  5034 |                              |   the source code.      |

eeh@public.BTR.COM (Eduardo E. Horvath eeh@btr.com) (06/23/91)

In article <20052@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt) writes:
>In <91170.181652GUTEST8@cc1.kuleuven.ac.be> GUTEST8@cc1.kuleuven.ac.be (Ives Aerts) writes:
>>In article <1382@cbmger.UUCP>, peterk@cbmger.UUCP (Peter Kittel GERMANY):
>>>
>>>In article <19997@csli.Stanford.EDU> bratt@csli.Stanford.EDU (Harry Bratt):
>>>>I need to change the position of Intuition's mouse pointer.

>Actually, I've been wondering about that problem for a while.  The program
>I'm writing is using a RMB-pop-up-menu.  The need to move the pointer
>comes when 2 things conflict:
> 1) I want the menu to pop up under the mouse on a specific item
> 2) Doing #1 would place some of the menu off-screen

>Now I've used other systems which use pop-up menus as standard, but I
>don't have access to them now and I didn't notice well enough what
>they did in this case.

	Motif, at least, will place the menu entirely on the screen
near the pointer.

[description of problems with iff2pcs deleted]

>So I'd be interested in knowing what people think the solution to this
>should be.

	Moving the mouse pointer is impolite, and confusing to the
user.  Don't do it unless it is absolutely necessary.  It is extremely
irritating to be forced to lift up the mouse and re-center it on the
pad.  It is even worse if the mouse is near one edge of the mouse pad,
and a button has been pressed to access the menu, but the mouse must be
positioned off the pad to make the proper selection.

>And more specifically, if I do move the pointer like I am now, should
>I attempt to move it back after they release the RMB?  I see 3 possibilities:
>1) don't move it back
	No, don't do this.

>2) move it back exactly to where it was when the RMB was pressed
>   (or, since they'll be moving the pointer to do menu selection,)
	So now I might need to lift the mouse twice?

>3) move it the same distance I had to move it when the RMB was pressed,
>   but in the opposite direction
	What if it falls off the screen?

4) pop the menu up a few pixels away from the mouse.
	This is what Motif will do with pop-up menus.  Unless the're 
	extremely large, that little bit ov movement will not be noticed.
	It also has the advantage that if you accidentally tap the button,
	decide not to make a selection, or cannot proceed with a selection
	(i.e. must first re-position the mouse) releasing the menu button
	does not result in a selection.

> -Harry
>  bratt@csli.stanford.edu


-- 
=========================================================================
Eduardo Horvath				eeh@btr.com
					..!{decwrl,mips,fernwood}!btr!eeh
	"Trust me, I am cognizant of what I am doing." - Hammeroid