DIRECTORY InputFocus, MultiCursors, Process, Rope, TIPPrivate, TIPUser, UserInputOps, UserInputGetActions, ViewerClasses, ViewerEvents, ViewerOps, ViewerPrivate, ViewersWorld, ViewersWorldInstance, ViewersWorldRefType, ViewersWorldTypes, WindowManager; InputFocusImpl: CEDAR MONITOR IMPORTS MultiCursors, Process, TIPPrivate, TIPUser, UserInputOps, UserInputGetActions, ViewerEvents, ViewerOps, ViewerPrivate, ViewersWorld, ViewersWorldInstance, WindowManager EXPORTS InputFocus, ViewersWorldRefType, ViewerPrivate SHARES ViewerEvents = BEGIN Focus: TYPE = InputFocus.Focus; FocusRec: TYPE = InputFocus.FocusRec; LORA: TYPE = LIST OF REF ANY; Viewer: TYPE = ViewerClasses.Viewer; ViewersWorldRef: TYPE = REF ViewersWorldObj; ViewersWorldObj: PUBLIC TYPE = ViewersWorldTypes.ViewersWorldObj; WindowManagerTIPTable: PUBLIC TIPUser.TIPTable ¬ TIPUser.InstantiateNewTIPTable["WindowMgr.tip"]; vWorld: ViewersWorldRef ¬ ViewersWorldInstance.GetWorld[]; NewWorld: ViewersWorldInstance.SetNotifyProc = { vWorld ¬ viewersWorld }; SetInputFocus: PUBLIC ENTRY PROC [self: Viewer ¬ NIL, info: REF ¬ NIL] = { ENABLE UNWIND => NULL; -- release lock ModifyInputFocus[kill]; vWorld.currentFocus.owner ¬ self; -- note that we don't flush any CaptureButtons! vWorld.currentFocus.info ¬ info; vWorld.currentFocus.link ¬ NIL; ModifyInputFocus[set]; IF vWorld.currentFocus.owner # NIL THEN ChangeTIPContext[vWorld.currentFocus.owner]; }; GetInputFocus: PUBLIC PROC RETURNS [Focus] = { RETURN [vWorld.currentFocus]; }; PushInputFocus: PUBLIC ENTRY PROC [self: Viewer ¬ NIL, info: REF ¬ NIL] = { ENABLE UNWIND => NULL; -- release lock ModifyInputFocus[push]; vWorld.currentFocus ¬ NEW[FocusRec ¬ [owner: self, info: info, link: vWorld.currentFocus]]; ModifyInputFocus[set]; ChangeTIPContext[vWorld.currentFocus.owner]; }; NotifyProc: TYPE = InputFocus.NotifyProc; CaptureButtons: PUBLIC ENTRY PROC [proc: NotifyProc, tip: TIPUser.TIPTable, viewer: Viewer ¬ NIL, captureKeyboard: BOOL ¬ FALSE] = { ENABLE UNWIND => NULL; -- release lock vWorld.captureProc ¬ proc; vWorld.captureTIP ¬ tip; vWorld.captureViewer ¬ viewer; }; PopInputFocus: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; -- release lock IF vWorld.currentFocus.link = NIL THEN RETURN; ModifyInputFocus[kill]; vWorld.currentFocus ¬ vWorld.currentFocus.link; ModifyInputFocus[pop]; ChangeTIPContext[vWorld.currentFocus.owner]; }; ModifyInputFocus: INTERNAL PROC [action: ViewerClasses.ModifyAction] = { owner: ViewerClasses.Viewer ¬ vWorld.currentFocus.owner; -- good for the whole invocation modify: ViewerClasses.ModifyProc ¬ NIL; SELECT action FROM set => IF ViewerEvents.ProcessEvent[setInputFocus, owner, TRUE] THEN RETURN; kill => IF ViewerEvents.ProcessEvent[killInputFocus, owner, TRUE] THEN RETURN; ENDCASE; SELECT TRUE FROM owner = NIL => {}; owner.iconic => ViewerPrivate.IconModify[owner, action]; (modify ¬ owner.class.modify) # NIL => modify[owner, action]; ENDCASE; SELECT action FROM set => [] ¬ ViewerEvents.ProcessEvent[setInputFocus, owner, FALSE]; kill => [] ¬ ViewerEvents.ProcessEvent[killInputFocus, owner, FALSE]; ENDCASE; }; transparentTIP: TIPUser.TIPTable ~ TIPUser.TransparentTIPTable[]; ChangeTIPContext: INTERNAL PROC [self: Viewer, interrupt: BOOL ¬ FALSE] = { table: TIPUser.TIPTable ¬ NIL; IF self#NIL THEN SELECT TRUE FROM self.iconic => table ¬ ViewerPrivate.iconTIP; self.transparentTIP => table ¬ transparentTIP; ENDCASE => table ¬ self.tipTable; TIPPrivate.ResetTIPContext[vWorld.focusTIP, table, MasterNotifyProc, interrupt]; }; MapCoordinateResults: PROC [results: LORA, coords: TIPUser.TIPScreenCoords ¬ NIL] = { FOR lst: LORA ¬ results, lst.rest UNTIL lst = NIL DO SELECT lst.first FROM TIPPrivate.stdCoords => IF coords # NIL THEN TIPPrivate.stdCoords­ ¬ coords­ ELSE [] ¬ ViewerOps.MouseInViewer[TIPPrivate.stdCoords]; ENDCASE; ENDLOOP; }; MasterNotifyProc: PUBLIC TIPPrivate.TIPNotifyProc ~ { InnerMasterNotifyProc: PROC ~ { owner: Viewer ~ vWorld.currentFocus.owner; IF owner.iconic THEN ViewerPrivate.IconNotify[owner, results] ELSE { MapCoordinateResults[results]; owner.class.notify[vWorld.currentFocus.owner, results, device, user, display]; }; }; IF vWorld.inputEnabled AND vWorld.currentFocus.owner#NIL THEN InnerMasterNotifyProc[]; }; parseInfo: TIPPrivate.TIPParseInfo ¬ TIPPrivate.CreateParseInfo[NIL, "InputFocus"]; MasterButtonProc: PUBLIC TIPPrivate.TIPButtonProc ~ { InnerMasterButtonProc: PROC RETURNS [consume: BOOL ¬ FALSE] ~ { results: LORA ¬ NIL; viewer: ViewerClasses.Viewer ¬ NIL; client: BOOL ¬ FALSE; device, user, display: REF; TIPParse: PROC [table: TIPUser.TIPTable, mapCoords: BOOL ¬ TRUE] = { actionBody: UserInputGetActions.InputActionBody; parseInfo.inCreek ¬ state; -- OK since we only ever do one parse parseInfo.tableHead ¬ table; actionBody ¬ UserInputGetActions.GetInputActionBody[handle: parseInfo.inCreek, waitMode: forever, acceptance: clicksAndMotion]; results ¬ TIPPrivate.WideMatchEvent[parseInfo, actionBody]; device ¬ actionBody.device; user ¬ actionBody.user; display ¬ actionBody.display; UserInputOps.Close[parseInfo.localCreek]; IF mapCoords THEN MapCoordinateResults[results, screenXY]; }; IF NOT vWorld.inputEnabled THEN RETURN [FALSE]; IF vWorld.captureProc # NIL THEN { -- someone is capturing all input events TIPParse[vWorld.captureTIP, FALSE]; IF results # NIL THEN { captureProc: InputFocus.NotifyProc ¬ vWorld.captureProc; --sample just once IF captureProc # NIL THEN captureProc[vWorld.captureViewer, results, device, user, display]; }; RETURN [TRUE]; }; [viewer, client] ¬ ViewerOps.MouseInViewer[screenXY]; SELECT TRUE FROM viewer = NIL => { cursorName: ATOM; TIPParse[NIL, FALSE]; -- consume event (and find out what device produced it) cursorName ¬ IF ISTYPE[device, ATOM] THEN NARROW[device] ELSE NIL; IF WindowManager.waitCount=0 AND MultiCursors.GetACursor[cursorName] # textPointer THEN MultiCursors.SetACursor[textPointer, cursorName]; }; viewer.iconic => { TIPParse[ViewerPrivate.iconTIP, FALSE]; IF results # NIL THEN ViewerPrivate.IconNotifyMouse[viewer, results, device, user, display]; }; client => { cursor: ViewerClasses.CursorType ¬ viewer.cursor; cursorName: ATOM; TIPParse[IF viewer.transparentTIP THEN transparentTIP ELSE viewer.tipTable]; -- sets both "results" and "device" IF cursor=none THEN cursor ¬ viewer.class.cursor; IF cursor#last THEN { cursorName ¬ IF ISTYPE[device, ATOM] THEN NARROW[device] ELSE NIL; IF WindowManager.waitCount=0 AND cursor#MultiCursors.GetACursor[cursorName] THEN MultiCursors.SetACursor[cursor, cursorName]; }; IF results # NIL THEN viewer.class.notify[viewer, results, device, user, display]; }; ENDCASE => { TIPParse[WindowManagerTIPTable]; IF results # NIL THEN ViewerPrivate.ProcessWindowManagerInput[viewer, results, device, user, display]; }; RETURN [TRUE]; }; consume ¬ InnerMasterButtonProc[]; }; PrivateUnWedgeNotifier: PROC = { ViewerOps.BlinkDisplay[]; vWorld.currentFocus ¬ NEW[FocusRec]; ViewersWorld.RestartInput[vWorld]; }; WaitingCursor: PROC = { aWhile: Process.Ticks = Process.MsecToTicks[170]; ViewerPrivate.InitializeHourglass[56]; UNTIL vWorld # NIL AND vWorld.inputEnabled DO ViewerPrivate.TickHourglass[]; Process.Pause[aWhile]; ENDLOOP; WindowManager.RestoreCursor[]; }; <> -- doesn't work in the portable world. Needs to know what the hardware is too early CreateDebugButton: PUBLIC PROC = { }; wideViewers: BOOL ¬ TRUE; ViewersWorldInstance.CallWhenSet[NewWorld]; END. Ύ InputFocusImpl.mesa Copyright Σ 1985, 1986, 1987, 1988, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) March 3, 1987 7:04:40 pm PST Pier, November 17, 1988 5:03:14 pm PST Bier, March 5, 1991 8:04 pm PST Doug Wyatt, January 2, 1990 3:43:00 pm PST Willie-s, October 29, 1991 6:32 pm PST Christian Jacobi, March 3, 1992 12:16 pm PST Michael Plass, March 13, 1992 10:54 am PST Global variables Public procedures Private procedures PROC [results: LIST OF REF ANY, clientData: REF ANY]; convert a TIPNotify into an InputFocusNotify. MasterNotifyProc is called for keyboard input. See MasterButtonProc below for mouse actions. InnerMasterNotifyProc[ ! AMEvents2.Debugging => IF vWorld.forkNewNotifier THEN PrivateUnWedgeNotifier[] ]; PROC [screenXY: TIPScreenCoords, mouseEvent: MouseEvent, state: UserInput.Handle, clientData: REF ANY] RETURNS [consume: BOOL _ FALSE]; Applications that would like the cursor left alone can set the cursor to last consume ¬ InnerMasterButtonProc[ ! AMEvents2.Debugging => IF vWorld.forkNewNotifier THEN PrivateUnWedgeNotifier[] ]; exciting code to make a new notifier when ours is dying <> cursor for amusement during start-up Κ ‹–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœU™`K™0K™&K™K™*K™&K™,K™*—K˜šΟk ˜ K˜ςK˜—šΡblnœžœž˜Kšžœ©˜°Kšžœ/˜6Kšžœ ˜Kšœž˜K˜Kšœžœ˜Kšœ žœ˜%Kš žœžœžœžœžœžœ˜Kšœžœ˜$Kšœžœžœ˜,Kšœžœžœ%˜A—head2™šΟnœžœ˜0K˜0K˜—K˜:š œ(˜0K˜Kšœ˜——šœ™š  œžœžœžœžœžœžœ˜JKšžœžœžœΟc˜&K˜Kšœ"‘/˜QKšœ ˜ Kšœžœ˜K˜Kšžœžœžœ-˜TKšœ˜K˜—š  œžœžœžœ ˜.Kšžœ˜Kšœ˜—K˜š œžœžœžœžœžœžœ˜KKšžœžœžœ‘˜&K˜KšœžœB˜[K˜Kšœ,˜,Kšœ˜K˜—Kšœ žœ˜)š œžœžœžœ<žœžœžœ˜„Kšžœžœžœ‘˜&Kšœ˜K˜K˜Kšœ˜K˜—š  œžœžœžœ˜$Kšžœžœžœ‘˜&Kšžœžœžœžœ˜.K˜K˜/K˜K˜,Kšœ˜—K˜—™š œžœžœ)˜HKšœ:‘ ˜ZKšœ#žœ˜'šžœž˜Kš œžœ1žœžœžœ˜LKš œžœ2žœžœžœ˜NKšžœ˜—šžœžœž˜Kšœžœ˜Kšœ8˜8Kšœ žœ˜=Kšžœ˜—šžœž˜Kšœ<žœ˜CKšœ>žœ˜EKšžœ˜—Kšœ˜K˜—KšœA˜AK˜š  œžœžœžœžœ˜KKšœžœ˜š žœžœžœžœžœž˜!Kšœ-˜-KšΟbœ’˜.Kšžœ˜!—KšœP˜Pšœ˜K˜——š œžœ žœ$žœ˜Uš žœžœžœžœž˜4šžœ ž˜šœ˜šžœ ž˜Kšžœ ˜$Kšžœ4˜8——Kšžœ˜—Kšžœ˜—Kšœ˜—K˜š œžœ˜5Kšžœ žœžœžœžœžœžœ™5Kšœ-™-Kšœ]™]š œžœ˜Kšœ*˜*šžœ ˜Kšžœ)˜-šžœ˜K˜KšœN˜NKšœ˜——K˜—šžœžœžœž˜=šœ™Kšœžœžœ™PKšœ™—Kšœ˜—Kšœ˜K˜—Kšœ@žœ˜SK˜š œžœ˜5Kš žœZžœžœžœ žœžœ™‡š  œžœžœ žœžœ˜?Kšœ žœžœ˜Kšœžœ˜#Kšœžœžœ˜Kšœžœ˜K˜š œžœ&žœžœ˜DKšœ0˜0Kšœ‘%˜@˜Kšœ˜Kšœ;˜;Kšœ˜Kšœ˜Kšœ˜—K˜)Kšžœ žœ)˜:Kšœ˜K˜—Kš žœžœžœžœžœ˜/K˜šžœžœžœ‘(˜KKšœžœ˜#šžœ žœžœ˜Kšœ9‘˜KKšžœžœžœC˜\K˜—KšΠbk’£’˜Kšœ˜K˜—K˜5K˜šžœžœž˜šœ žœ˜Kšœ žœ˜Kšœ žœžœ‘7˜MKšœ žœžœ žœžœžœ žœžœ˜Bšžœžœ3ž˜WKšœ1˜1—K˜—šœ˜Kšœ žœ˜'Kšžœ žœžœG˜\K˜—šœ ˜ Kšœ1˜1Kšœ žœ˜Kšœ žœžœžœ‘#˜pKšžœ žœ˜1šžœ žœ˜K™MKšœ žœžœ žœžœžœ žœžœ˜Bšžœžœ+˜KKšžœ-˜1—K˜—Kšžœ žœžœ=˜RK˜—šžœ˜ K˜ Kšžœ žœžœQ˜fK˜——Kšžœžœ˜K˜—šœ ™ Kšœžœžœ™PKšœ™—Kšœ"˜"Kšœ˜K˜—š œžœ˜ Kšœ7™7Kšœ˜Kšœžœ ˜$Kšœ"˜"Kšœ˜K˜—š  œžœ˜K˜1Kšœ&˜&šžœ žœžœž˜-Kšœ˜Kšœ˜Kšžœ˜—K˜Kšœ˜——™˜ Kšœ$™$Kšœžœ˜#Kšœ˜Kšœ‘T˜WK˜——š œžœžœ˜"K˜K˜—Kšœ žœžœ˜šœ+˜+K˜—Kšžœ˜—…—(+q