rosenkra@hall.cray.com (Bill Rosenkranz) (06/17/89)
a while back i had this question as well, called up atari, and got this
suggestion which works fine for my application. someone has asked me to
post it so here goes...
-bill
rosenkra@boston.cray.com
/*
* this is the code i use to reset the mouse position. the application
* involves sort of a "mouse drag window scroller" which works pretty
* well. the new position is set as soon as the mouse moves again,
* NOT (unfortunately) RIGHT NOW! this is ok for me but may not be for
* you. this is, however, 100% legal and does not rely on any version-
* specific code. there may be better ways of doing this but this is
* what atari suggested. i am not a wiz at assembler so the .s file
* could be optimized possibly. the regs d0 and d1 store the current
* mous position (before the normal AES/VDI handler gets them so you
* can stuff anything there you want.
*
* there is an assembler file at the bottom. this works with alcyon
* 4.14 but should be readily portable to other compilers... (int is
* 16 bit)
*/
#define BEG_MCTRL 2
#define END_MCTRL 3
/*------------------------------*/
/* track_it */
/*------------------------------*/
track_it ()
{
/*
* this is just a skeleton of my routine. what i do is wait for the
* x coord to exceed a certain value (move out of a box) then redraw
* the window and finally move the mouse to the other (left) side of
* the box. it works like sort of a "mouse scroll"
*/
extern _NEW_MOT (); /* our new handler */
extern int new_mouse_position ();
extern int wind_update ();
extern int vex_motv ();
extern int graf_mkstate ();
extern long _AES_MOT; /* "normal" handler */
extern int vdi_handle_G; /* device handle */
long dummy;
int but,
key;
int mx,
my,
new_x,
new_y;
/*
* capture mouse
*/
wind_update (BEG_MCTRL);
/*
* setup new motion vector
*/
vex_motv (vdi_handle_G, &_NEW_MOT, &_AES_MOT);
new_mouse_position (-1, -1, -1);
/*
* track mouse. when button comes up, stop and use last mx, my
* to calc new position
*/
while (graf_mkstate (&mx, &my, &but, &key), !(but & 0x0001))
{
/*
* if some condition is met, reset the mouse position...
*/
if (!new_mouse_position (-1, -1, 0)
&& some_condition_met (mx, my))
{
new_x = mx, new_y = my;
calc_new_xy (&new_x, &new_y); /* your routine... */
new_mouse_position (new_x, new_y, 1);
}
}
/*
* reset normal AES/VDI mouse movement vector
*/
vex_motv (vdi_handle_G, _AES_MOT, &dummy);
/*
* release mouse to GEM
*/
wind_update (END_MCTRL);
}
/*------------------------------*/
/* new_mouse_position */
/*------------------------------*/
new_mouse_position (newx, newy, opt)
int newx,
newy;
int opt;
{
/*
* this works with the new mouse movement vector, _NEW_MOT. we set the
* globals here to the new (desired) mouse position and then flag the
* routine to reset (via _mot_flg). the new mouse vector reads these
* values and clears _mot_flg. if _mot_flg is 1, it resets the mouse
* coord to _mot_x,_mot_y before calling the VDI handler (which will
* redraw the cursor, if !hidden).
*
* opt=1 do it ret=1
* opt=0 inquire status ret=_mot_flg
* opt=-1 reset _mot_flg to 0 ret=0
*
* ret=-1 if error
*
* note: the new mouse routine is called only after there is mouse
* movement, not continuously.
*/
extern int _mot_flg; /* these are in the .s file */
extern int _mot_x;
extern int _mot_y;
switch (opt)
{
case 1: /* new coord */
if (newx >= 0 && newy >= 0)
{
_mot_x = newx;
_mot_y = newy;
_mot_flg = 1; /* tell it to change on next ms move */
return (1);
}
break;
case 0: /* inquire status */
return ((_mot_flg == 1) ? 1 : 0);
case -1: /* reset */
_mot_flg = 0;
return (0);
default: /* error */
break;
}
/*
* error...
*/
return (-1);
}
* NAME
* _NEW_MOT - new mouse motion detector handler (passes on to normal one)
*
* SYNOPSIS
* extern _NEW_MOT ();
* extern int _mot_flg;
* extern int _mot_x;
* extern int _mot_y;
* extern long _AES_MOT;
* long dummy;
*
* vex_motv (handle, &_NEW_MOT, &_AES_MOT); (set new handler)
*
* (loop here looking for events, say evnt_multi())
*
* _mot_x = new_x; (set new coord)
* _mot_y = new_y;
* _mot_flg = 1; (tell hndlr to change
* on next mouse move)
* vex_motv (handle, _AES_MOT, &dummy); (reset AES handler)
*
* DESCRIPTION
* The routine looks for _mot_flg set. If it is, it moves the new
* coords (_mot_x -> d0.w, _mot_y -> d1.w), unsets _mot_flg, then
* jumps to the normal AES/VDI routine. If unset, it just jumps to
* the normal routine (which redraws the mouse cursor).
*
* the vex_motv () calls set/get pointers to the routines.
*
* _AES_MOT contains the address of the AES interrupt routine
* that deals with mouse motion. It is saved during the first vex_butv
* and restored with the last
*
* _mot_flg contains 1 if the program wants to change coordinates.
* This routine then resets it to 0.
*
.globl __NEW_MOT
.globl __AES_MOT
.globl __mot_flg
.globl __mot_x
.globl __mot_y
.text
__NEW_MOT:
move.l d2,-(a7) * save reg (just in case)
move.w __mot_flg,d2 * test semaphore flag
tst d2
beq bypass * if not set, bypass
move.w __mot_x,d0 * set new position
move.w __mot_y,d1
clr.w __mot_flg * clear the flag
bypass:
move.l (a7)+,d2 * restore reg
move.l __AES_MOT,-(sp)
rts * jmp to AES subroutine
.even
.bss
__AES_MOT: ds.l 1 * place to store normal AES routine
__mot_flg: ds.w 1 * semaphore
__mot_x: ds.w 1 * new coords
__mot_y: ds.w 1
.endrosenkra@hall.cray.com (Bill Rosenkranz) (06/17/89)
oops... just notices a bug in the posting i just made. here is the correction:
while (graf_mkstate (&mx, &my, &but, &key), !(but & 0x0001))
_SHOULD_ be:
while (graf_mkstate (&mx, &my, &but, &key), (but & 0x0001))
or (the way i actually wrote it):
while (1)
{
graf_mkstate (&mx, &my, &but, &key);
if (!(but & 0x0001))
break;
sorry...(so much for ignoring KISS, temporary insanity)
-bill