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 .end
rosenkra@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