/* * DMOUSE-HANDLER.C compile 32 bit integers (+L), c32.lib * AZTEC COMPILATION * 28 June 1988 * * Note on upping the handler process priority. This is done to cause the * handler task to get CPU before the current input event completes its * processing so intuition calls made by the process are executed before * the event is propogated. If said intuition calls block, it's ok * because they are not blocking the input handler process. */ #include "dmouse.h" #define IBASE IntuitionBase DMS *Dms; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; long *LayersBase; NS Ns = { 0, 0, 64, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET }; IE DummyIE = { 0 }; IE *handler(); short NRMe; /* Don't Repeat Mouse Events */ _main() { register DMS *dms; IOR *ior; INT addhand; { register PROC *proc = (PROC *)FindTask(NULL); proc->pr_ConsoleTask = NULL; } NRMe = 0; dms = Dms = FindPort(PORTNAME); if (!dms) _exit(0); dms->Port.mp_Flags = PA_SIGNAL; dms->Port.mp_SigBit = AllocSignal(-1); dms->Port.mp_SigTask = FindTask(NULL); dms->HandTask = dms->Port.mp_SigTask; ior = CreateStdIO(&dms->Port); IntuitionBase = OpenLibrary("intuition.library", 0); GfxBase = OpenLibrary("graphics.library", 0); LayersBase = OpenLibrary("layers.library", 0); if (!IntuitionBase || !GfxBase || !LayersBase) goto startupfail; addhand.is_Node.ln_Pri = dms->IPri; addhand.is_Code = (FPTR)handler; addhand.is_Data = NULL; if (OpenDevice("input.device", 0, ior, 0)) { goto startupfail; } else { SCR *scr = NULL; uword *SprSavePtr = NULL; Signal(dms->ShakeTask, 1 << dms->ShakeSig); ior->io_Command = IND_ADDHANDLER; ior->io_Data = (APTR)&addhand; ior->io_Message.mn_Node.ln_Type = NT_MESSAGE; DoIO(ior); for (;;) { register long sigs = Wait(SBF_C|(1<Port.mp_SigBit)); if (sigs & (1 << dms->Port.mp_SigBit)) { register REQ *msg; while (msg = GetMsg(&dms->Port)) { switch((long)msg->Msg.mn_Node.ln_Name) { case REQ_SCREENON: if (scr) CloseScreen(scr); scr = NULL; break; case REQ_SCREENOFF: if (scr) { ScreenToFront(scr); } else { if (scr = OpenScreen(&Ns)) SetRGB4(&scr->ViewPort, 0, 0, 0, 0); } break; case REQ_MOUSEON: if (SprSavePtr) { register COPINIT *ci = GfxBase->copinit; ci->sprstrtup[1] = (ulong)SprSavePtr >> 16; ci->sprstrtup[3] = (uword)(long)SprSavePtr; SprSavePtr = NULL; } break; case REQ_MOUSEOFF: { register COPINIT *ci = GfxBase->copinit; if (!SprSavePtr) SprSavePtr = (uword *)((ci->sprstrtup[1] << 16) | ci->sprstrtup[3]); ci->sprstrtup[1] = (ulong)dms->NoSprData >> 16; ci->sprstrtup[3] = (uword)(long)dms->NoSprData; } break; case REQ_DOCMD: { long fh = Open("nil:", 1006); Execute(dms->Cmd, NULL, fh); if (fh) Close(fh); } break; case REQ_RAWMOUSE: { register LAYER *layer; NRMe = 0; Forbid(); layer = WhichMouseLayer(); if (msg->ie_Code == IECODE_RBUTTON && dms->LMBEnable && (msg->ie_Qualifier & dms->RQual)) { register WIN *win; if (layer && (win = (WIN *)layer->Window) && !(win->Flags & BACKDROP) && (win->NextWindow || win->WScreen->FirstWindow != win)) { if (dms->Workbench) WindowToBack(win); else BehindLayer(0, layer); } else if (IBASE->FirstScreen) ScreenToBack(IBASE->FirstScreen); } if (layer && layer->Window) { if (msg->ie_Code == IECODE_LBUTTON && !(((WIN *)layer->Window)->Flags & BACKDROP) && dms->LMBEnable && layer->ClipRect && layer->ClipRect->Next) { /* * Note: Case where it is the 'first' click in a series, where dms->CTime is * garbage, works properly no matter what DoubleClick returns. */ if (dms->LQual == 0 || (msg->ie_Qualifier & dms->LQual)) { if ((APTR)dms->CWin == layer->Window && DoubleClick(dms->CTime.tv_secs, dms->CTime.tv_micro, msg->ie_TimeStamp.tv_secs, msg->ie_TimeStamp.tv_micro)) --dms->CLeft; else dms->CLeft = dms->Clicks - 1; dms->CTime = msg->ie_TimeStamp; dms->CWin = (WIN *)layer->Window; if (dms->CLeft == 0) { dms->CLeft = dms->Clicks; if (dms->Workbench) WindowToFront(layer->Window); else UpfrontLayer(0, layer); } } } if (dms->AAEnable && layer->Window != IBASE->ActiveWindow && msg->ie_Code == IECODE_NOBUTTON && !(msg->ie_Qualifier & 0x7000)) ActivateWindow(layer->Window); } Permit(); } break; case REQ_RAWKEY: { register LAYER *layer; Forbid(); layer = WhichMouseLayer(); if (layer && layer->Window && layer->Window != IBASE->ActiveWindow) ActivateWindow(layer->Window); Permit(); } break; } FreeMem(msg, msg->Msg.mn_Length); } } if (sigs & SBF_C) break; } ior->io_Command = IND_REMHANDLER; ior->io_Data = (APTR)&addhand; ior->io_Message.mn_Node.ln_Type = NT_MESSAGE; DoIO(ior); ior->io_Command = IND_WRITEEVENT; /* NULL EVENT */ ior->io_Length = sizeof(IE); ior->io_Data = (APTR)&DummyIE; ior->io_Message.mn_Node.ln_Type = NT_MESSAGE; DoIO(ior); CloseDevice(ior); { register MSG *msg; while (msg = GetMsg(&dms->Port)) FreeMem(msg, msg->mn_Length); } if (scr) CloseScreen(scr); if (SprSavePtr) { register COPINIT *ci = GfxBase->copinit; ci->sprstrtup[1] = (ulong)SprSavePtr >> 16; ci->sprstrtup[3] = (uword)(long)SprSavePtr; SprSavePtr = NULL; } } goto closedown; startupfail: dms->StartupError = 1; Signal(dms->ShakeTask, 1 << dms->ShakeSig); Wait(SBF_C); closedown: DeleteStdIO(ior); fail: if (IntuitionBase) CloseLibrary(IntuitionBase); if (GfxBase) CloseLibrary(GfxBase); if (LayersBase) CloseLibrary(LayersBase); Forbid(); Signal(dms->ShakeTask, 1 << dms->ShakeSig); } #asm ; A0 = pointer to event linked list ; A1 = pointer to my data segment ; return new event linked list in D0 public _CHandler _handler: movem.l D2/D3/A0/A1/A4/A6,-(sp) jsr _CHandler movem.l (sp)+,D2/D3/A0/A1/A4/A6 rts #endasm /* * (1) Accellerate mouse movements. * (2) Auto-Select window */ IE * CHandler(scr0, scr1, Ev) IE *Ev; { register IE *ev; register DMS *dms; static char STimedout; static char MTimedout; static long STime, MTime; geta4(); dms = Dms; for (ev = Ev; ev; ev = Ev->ie_NextEvent) { switch(ev->ie_Class) { case IECLASS_RAWMOUSE: /* * Mouse events restore both the screen and mouse pointer. */ STime = ev->ie_TimeStamp.tv_secs + dms->STo; MTime = ev->ie_TimeStamp.tv_secs + dms->MTo; if (STimedout) sendrequest(REQ_SCREENON, ev); if (MTimedout) sendrequest(REQ_MOUSEON, ev); STimedout = MTimedout = 0; /* * Mouse Acceleration */ { register short n; register short s; if (dms->Acc != 1) { n = ev->ie_X; s = 1; if (n < 0) { n = -n; s = -1; } if (n > dms->AThresh) ev->ie_X = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1); n = ev->ie_Y; s = 1; if (n < 0) { n = -n; s = -1; } if (n > dms->AThresh) ev->ie_Y = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1); } } /* * Auto Activate and LMB (win/scrn front/bak) */ if (dms->LMBEnable && ev->ie_Code == IECODE_RBUTTON && (ev->ie_Qualifier & dms->RQual)) ev->ie_Class = IECLASS_NULL; /* remove event */ if (NRMe == 0 && ((dms->AAEnable & 1) || dms->LMBEnable)) { register short old; NRMe = 1; if (ev->ie_Code != IECODE_NOBUTTON) old = SetTaskPri(dms->Port.mp_SigTask, 21); sendrequest(REQ_RAWMOUSE, ev); if (ev->ie_Code != IECODE_NOBUTTON) SetTaskPri(dms->Port.mp_SigTask, old); } break; case IECLASS_RAWKEY: /* * Keyboard events will kill the screen timeout but not * the mouse timeout. Note that the priority of the * co-process must be upped to ensure it is able to make the * window active before the keystroke is passed further. */ if (dms->AAEnable & 2) { register short old = SetTaskPri(dms->Port.mp_SigTask, 21); sendrequest(REQ_RAWKEY, ev); SetTaskPri(dms->Port.mp_SigTask, old); } STime = ev->ie_TimeStamp.tv_secs + dms->STo; if (STimedout) { sendrequest(REQ_SCREENON, ev); if (dms->MTo == 0) sendrequest(REQ_MOUSEON, ev); } STimedout = 0; if (ev->ie_Code == dms->Code && ev->ie_Qualifier == dms->Qual) { sendrequest(REQ_DOCMD, ev); ev->ie_Class = IECLASS_NULL; /* remove event */ } break; case IECLASS_TIMER: /* * On a timer event, if timeout has occured execute the operation * and reset the timeout. Note that this will cause continuous * timeouts every STo and MTo seconds... required because at any * time Intuition might turn the mouse back on or open a screen or * something and I want the blanker's to work in the long run. */ { register long old; if (dms->Reset) { dms->Reset = 0; STime = ev->ie_TimeStamp.tv_secs + dms->STo; MTime = ev->ie_TimeStamp.tv_secs + dms->MTo; } if (dms->STo && (old = STime - ev->ie_TimeStamp.tv_secs) < 0) { STime = ev->ie_TimeStamp.tv_secs + dms->STo + 10; STimedout = 1; MTimedout = 1; if (old > -10) { sendrequest(REQ_SCREENOFF, ev); sendrequest(REQ_MOUSEOFF, ev); } } if (dms->MTo && (old = MTime - ev->ie_TimeStamp.tv_secs) < 0) { MTime = ev->ie_TimeStamp.tv_secs + dms->MTo + 1; MTimedout = 1; if (old > -10) sendrequest(REQ_MOUSEOFF, ev); } } break; } } return(Ev); } sendrequest(creq, ev) long creq; register IE *ev; { register REQ *req = AllocMem(sizeof(REQ), MEMF_PUBLIC); if (req) { req->Msg.mn_Node.ln_Name = (char *)creq; req->Msg.mn_ReplyPort = NULL; req->Msg.mn_Length = sizeof(REQ); req->ie_Code = ev->ie_Code; req->ie_Qualifier = ev->ie_Qualifier; req->ie_TimeStamp = ev->ie_TimeStamp; PutMsg(&Dms->Port, req); } } LAYER * WhichMouseLayer() { register struct IntuitionBase *ib = IBASE; register LAYER *layer = NULL; register SCR *scr = ib->FirstScreen; for (scr = ib->FirstScreen; scr; scr = scr->NextScreen) { register short mousey = ib->MouseY; register short mousex = ib->MouseX; if (!(scr->ViewPort.Modes & LACE)) mousey >>= 1; if (!(scr->ViewPort.Modes & HIRES)) mousex >>= 1; if (layer = WhichLayer(&scr->LayerInfo, mousex, mousey - scr->ViewPort.DyOffset)) break; if (mousey >= scr->ViewPort.DyOffset) break; } return(layer); }