implementation module osevent import StdInt, StdBool, StdList, StdTuple import events, desk, pointer import StdClass, StdMisc import code from "cTCP." import osrgn,commondef,ostime from quickdraw import QRectRgn, QLocalToGlobal, QNewRgn //import StdDebug //import dodebug DebugTraceEvents msg osEvent state :== state /* = case isIgnoreEvent osEvent of True -> state False -> DebugStr (msg +++ showEvent osEvent) state where isIgnoreEvent (_,what,_,_,_,_,_) = what == NullEvent || what == OsEvent */ oseventFatalError :: String String -> .x oseventFatalError function error = fatalError function "osevent" error :: *OSEvents // = Event Int // The event stream :== [OSEvent] // The empty event stream: osNewEvents :: OSEvents osNewEvents = [] //Event 0 /* PA: does not seem to be used. osCopyEvents :: !OSEvents -> (!OSEvents,!OSEvents) //OScopyEvents (Event e) // = (Event e, Event e) osCopyEvents [] = ([],[]) osCopyEvents [e:es] = ([e:es1],[e:es2]) where (es1,es2) = osCopyEvents es */ osAppendEvents :: !*[OSEvent] !OSEvents -> OSEvents osAppendEvents newEvents osEvents = osEvents ++ newEvents osInsertEvents :: !*[OSEvent] !OSEvents -> OSEvents osInsertEvents newEvents osEvents = newEvents ++ osEvents osIsEmptyEvents :: !OSEvents -> (!Bool,!OSEvents) osIsEmptyEvents [] = (True, []) osIsEmptyEvents osEvents = (False, osEvents) osRemoveEvent :: !OSEvents -> (!OSEvent,!OSEvents) osRemoveEvent [osEvent:osEvents] = (osEvent,osEvents) osRemoveEvent [] = oseventFatalError "osRemoveEvent" "OSEvents argument is empty" :: OSEvent :== (!Bool,!Int,!Int,!Int,!Int,!Int,!Int) //:: CrossCallInfo = CCI // Dummy to keep imports happy (PA: not required anymore) :: OSSleepTime :== Int // The max time the process allows multi-tasking osNullEvent :: OSEvent osNullEvent = (True,NullEvent,0,0,0,0,0) // ??? //OSLongSleep :== 2147483647 // The application requires no timing (2^31-1) //OSLongSleep :== 65535 // The application requires no timing (2^16-1) OSLongSleep :== 60//1//60 OSNoSleep :== 0//1//0 mRgn =: rgn rgn # (rgn,tb) = QNewRgn OSNewToolbox # (x,y,tb) = GetMouse tb # (x,y,tb) = QLocalToGlobal x y tb # tb = QRectRgn rgn (x,y,inc x,inc y) tb | tb == OSNewToolbox = rgn = abort "initialising mouseRegion failed" osHandleEvents :: !(.s -> (Bool,.s)) !(.s -> (OSEvents,.s)) !((OSEvents,.s) -> .s) !(.s -> (Int,.s)) !(OSEvent -> .s -> ([Int],.s)) !(!.s,!*OSToolbox) -> (!.s,!*OSToolbox) osHandleEvents isFinalState getOSEvents setOSEvents getSleepTime handleOSEvent (state,tb) # (terminate,state) = isFinalState state # (now,tb) = TickCount tb | terminate = (state,tb) # (osEvents,state) = getOSEvents state # (noDelayEvents,osEvents) = osIsEmptyEvents osEvents | noDelayEvents # (sleep,state) = getSleepTime state # (tracking,tb) = loadTracking tb # (sleep,tb) = case tracking of 0 -> (min OSLongSleep sleep,tb) -1 -> (max 1 sleep,stopTracking tb) _ -> (sleep,tb) # (x,y,tb) = GetMouse tb # (x,y,tb) = QLocalToGlobal x y tb # (osEvent,osEvents,tb) = EventsWaitEvent sleep mRgn osEvents tb # tb = case osEvent of (b,OsEvent,message,_,x,y,_) -> if ((message >> 24) bitand 0xFF == MouseMovedMessage) (QRectRgn mRgn (x,y,inc x,inc y) tb) tb _ -> tb # state = setOSEvents (osEvents,state) # state = DebugTraceEvents ("Event["+++toString (now,sleep,tracking)+++"]:\t") osEvent state # (_,state) = handleOSEvent osEvent state = osHandleEvents isFinalState getOSEvents setOSEvents getSleepTime handleOSEvent (state,tb) # (osEvent,osEvents) = osRemoveEvent osEvents # state = setOSEvents (osEvents,state) # state = DebugTraceEvents ("Delayed["+++toString now+++"]:\t") osEvent state # (_,state) = handleOSEvent osEvent state = osHandleEvents isFinalState getOSEvents setOSEvents getSleepTime handleOSEvent (state,tb) showEvent :: !OSEvent -> {#Char} showEvent (_,what,mess,when,_,_,_) = case what of NullEvent -> "NullEvent@"+++toString when MouseDownEvent -> "MouseDownEvent" MouseUpEvent -> "MouseUpEvent" KeyDownEvent -> "KeyDownEvent" KeyUpEvent -> "KeyUpEvent" AutoKeyEvent -> "AutoKeyEvent" UpdateEvent -> "UpdateEvent" DiskEvent -> "DiskEvent" ActivateEvent -> "ActivateEvent" NetworkEvent -> "NetworkEvent" DriverEvent -> "DriverEvent" OsEvent | (mess >> 24) bitand 0xFF == MouseMovedMessage -> "MouseMovedEvent" | (mess >> 24) bitand 0xFF == SuspendResumeMessage -> "SuspendResumeEvent" -> "OsEvent" HighLevelEvent -> "HighLevelEvent" InetEvent -> "InetEvent" _ -> "unknown event: " +++ toString what osEventIsUrgent :: !OSEvent -> Bool osEventIsUrgent osEvent=:(_,what,_,when,_,_,_) | what == NullEvent # (time,_) = loadTracking OSNewToolbox | time == 0 = False | when - 2 < time = False = True = True //setReplyInOSEvent :: ![Int] -> OSEvent //setReplyInOSEvent createOSActivateWindowEvent :: !OSWindowPtr !*OSToolbox -> (!OSEvent,!*OSToolbox) createOSActivateWindowEvent wPtr tb # event = (True,ActivateEvent,wPtr,0,0,0,1) // dummy implementation = // trace_n "createOSActivateWindowEvent: dummy" (event,tb) createOSDeactivateWindowEvent :: !OSWindowPtr !*OSToolbox -> (!OSEvent,!*OSToolbox) createOSDeactivateWindowEvent wPtr tb # event = (True,ActivateEvent,wPtr,0,0,0,0) // dummy implementation = // trace_n "createOSDeactivateWindowEvent: dummy" (event,tb) // dummy implementation createOSActivateControlEvent :: !OSWindowPtr !OSWindowPtr !*OSToolbox -> (!OSEvent,!*OSToolbox) createOSActivateControlEvent wPtr cPtr tb = // trace_n "createOSActivateControlEvent: dummy" (osNullEvent,tb) // dummy implementation createOSDeactivateControlEvent :: !OSWindowPtr !OSWindowPtr !*OSToolbox -> (!OSEvent,!*OSToolbox) createOSDeactivateControlEvent wPtr cPtr tb = // trace_n "createOSDeactivateControlEvent: dummy" (osNullEvent,tb) // dummy implementation createOSLooseMouseEvent :: !OSWindowPtr !OSWindowPtr !*OSToolbox -> (!OSEvent,!*OSToolbox) createOSLooseMouseEvent wPtr cPtr tb = // trace_n "createOSLooseMouseEvent: dummy" (osNullEvent,tb) // dummy implementation createOSLooseKeyEvent :: !OSWindowPtr !OSWindowPtr !*OSToolbox -> (!OSEvent,!*OSToolbox) createOSLooseKeyEvent wPtr cPtr tb = // trace_n "createOSLooseKeyEvent: dummy" (osNullEvent,tb) // dummy implementation /* createOSKeyDownEvent :: !OSWindowPtr !*OSToolbox -> (!OSEvent,!*OSToolbox) createOSKeyDownEvent wPtr tb = ((True,what,message,when,wherex,wherey,modifiers),tb) where what = KeyDownEvent message = when = 0 wherex = 0 wherey = 0 modifiers = mods m2i :: !Modifiers -> Int m2i flags = a + b + c + d + e where a | flags.shiftDown = 512 = 0 b | flags.optionDown = 2048 = 0 c | flags.commandDown = 256 = 0 d | flags.controlDown = 4096 , altDown = False } */ createOSZeroTimerEvent :: !OSTime -> OSEvent createOSZeroTimerEvent (OSTime zeroStart) = (True,NullEvent,0,zeroStart,0,0,0) getOSZeroTimerStartTime :: !OSEvent -> Maybe OSTime getOSZeroTimerStartTime (interesting,what,message,i,h,v,mods) | interesting && what == NullEvent = Just (OSTime i) = Nothing // Two ways to retrieve events from the event stream: DeviceMaskGetNextEvent :== 383 // UpdateMask+ActivMask+KeyboardMask+MouseMask+1 DeviceMaskWaitNextEvent :== -32385 // OsMask+DeviceMaskGetNextEvent DeviceMaskWNHEvent :== -31361 // HighLevelEventMask+DeviceMaskWaitNextEvent // On a non multi-tasking Macintosh (using GetNextEvent): /* EventsGetEvent :: !*OSEvents !*OSToolbox -> (!OSEvent,!*OSEvents,!*OSToolbox) EventsGetEvent events tb # (event,tb) = GetEvent tb = (event,events,tb) GetEvent :: !*OSToolbox -> (!OSEvent,!*OSToolbox) GetEvent tb | True = abort "event.icl: GetEvent used" # (interesting,what,message,i,h,v,mods,tb) = GetNextEvent DeviceMaskGetNextEvent tb | interesting || what==NullEvent = ((interesting,what,message,i,h,v,mods), tb) = GetEvent (SystemTask tb) */ // On a multi-tasking Macintosh (using WaitNextEvent): EventsWaitEvent :: !Int !OSRgnHandle !*OSEvents !*OSToolbox -> (!OSEvent,!*OSEvents,!*OSToolbox) EventsWaitEvent sleep mouseRgn events tb # (event, tb) = WaitEvent sleep mouseRgn tb = (event,events,tb) /* MW: it was: WaitEvent :: !Int !OSRgnHandle !*OSToolbox -> (!OSEvent,!*OSToolbox) WaitEvent sleep mouseRgn tb # (interesting,what,message,i,h,v,mods,tb) = WaitNextEvent DeviceMaskWaitNextEvent sleep mouseRgn tb | interesting || what==NullEvent = ((interesting,what,message,i,h,v,mods), tb) = WaitEvent sleep mouseRgn tb */ WaitEvent :: !Int !OSRgnHandle !*OSToolbox -> (!OSEvent,!*OSToolbox) WaitEvent sleep mouseRgn tb // MW: WaitNextEventC also returns TCP events //# (interesting,what,message,i,h,v,mods,tb) = WaitNextEvent DeviceMaskWaitNextEvent 0 mouseRgn tb //# event = (interesting,what,message,i,h,v,mods) # (caret,tb) = GetCaretTime tb // <= kan je in osLongSleep regelen... //# tb = abort`` tb "WaitEvent: after GetCaretTime" # sleep = min sleep caret //# (event=:(interesting,what,message,i,h,v,mods),tb) = WaitNextEventC DeviceMaskWaitNextEvent sleep mouseRgn tb # (event=:(interesting,what,message,i,h,v,mods),tb) = WaitNextEventC DeviceMaskWNHEvent sleep mouseRgn tb //# (interesting,what,message,i,h,v,mods,tb) = WaitNextEvent DeviceMaskWNHEvent sleep mouseRgn tb //# event = (interesting,what,message,i,h,v,mods) //# tb = abort`` tb "WaitEvent: after WaitNextEventC" | interesting || what==NullEvent = (event, tb) = WaitEvent sleep mouseRgn tb WaitNextEventC :: !Int !Int !OSRgnHandle !*OSToolbox -> (!OSEvent, !*OSToolbox) WaitNextEventC _ _ _ _ = code { ccall WaitNextEventC "IIII-IIIIIIII" } //=== import memory,pointer tracking =: iniTrack iniTrack # (ptr,err,tb) = NewPtr 4 OSNewToolbox | err <> 0 || tb <> OSNewToolbox = abort "initialising tracking info failed..." # ptr = StoreLong ptr 0 tb // | tb <> OSNewToolbox = abort "initialising tracking info failed..." = ptr startTracking :: !OSTime !*OSToolbox -> *OSToolbox startTracking (OSTime time) tb = StoreLong tracking time tb stopTracking :: !*OSToolbox -> *OSToolbox stopTracking tb = StoreLong tracking 0 tb loadTracking :: !*OSToolbox -> (!Int,!*OSToolbox) loadTracking tb = LoadLong tracking tb