123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
- MODULE Inputs; (** AUTHOR "pjm"; PURPOSE "Abstract input device"; *)
- (* Based on SemInput.Mod by Marc Frei *)
- IMPORT Machine, Kernel, Plugins;
- CONST
- (** KeyboardMsg flags. *)
- Release* = 0; (** a key release event, otherwise a key press or repeat. *)
- (** shift key states. *)
- LeftShift* = 1; RightShift* = 2; LeftCtrl* = 3; RightCtrl* = 4;
- LeftAlt* = 5; RightAlt* = 6; LeftMeta* = 7; RightMeta* = 8;
- (** combined shift key states. *)
- Shift* = {LeftShift, RightShift}; Ctrl* = {LeftCtrl, RightCtrl};
- Alt* = {LeftAlt, RightAlt}; Meta* = {LeftMeta, RightMeta};
- (** flags for KeyState *)
- SHIFT* = 0; CTRL* = 1; ALT* = 2;
- (** keysym values, similar to X11 keysyms *)
- KsNil* = 0FFFFFFH; (** no key *)
- (** TTY Functions, cleverly chosen to map to ascii *)
- KsBackSpace* = 0FF08H; (** back space, back char *)
- KsTab* = 0FF09H;
- KsReturn* = 0FF0DH; (** Return, enter *)
- KsPause* = 0FF13H; (** Pause, hold *)
- KsScrollLock* = 0FF14H;
- KsSysReq* = 0FF15H;
- KsEscape* = 0FF1BH;
- KsDelete* = 0FFFFH; (** Delete, rubout *)
- (** Cursor control & motion *)
- KsHome* = 0FF50H;
- KsLeft* = 0FF51H; (** Move left, left arrow *)
- KsUp* = 0FF52H; (** Move up, up arrow *)
- KsRight* = 0FF53H; (** Move right, right arrow *)
- KsDown* = 0FF54H; (** Move down, down arrow *)
- KsPageUp* = 0FF55H; (** Prior, previous *)
- KsPageDown* = 0FF56H; (** Next *)
- KsEnd* = 0FF57H; (** EOL *)
- (** Misc Functions *)
- KsPrint* = 0FF61H;
- KsInsert* = 0FF63H; (** Insert, insert here *)
- KsMenu* = 0FF67H; (** Windows menu *)
- KsBreak* = 0FF6BH;
- KsNumLock* = 0FF7FH;
- (** Keypad functions *)
- KsKPEnter* = 0FF8DH; (** enter *)
- KsKPMultiply* = 0FFAAH;
- KsKPAdd* = 0FFABH;
- KsKPSubtract* = 0FFADH;
- KsKPDecimal* = 0FFAEH;
- KsKPDivide* = 0FFAFH;
- (** Function keys *)
- KsF1* = 0FFBEH; KsF2* = 0FFBFH; KsF3* = 0FFC0H; KsF4* = 0FFC1H; KsF5* = 0FFC2H; KsF6* = 0FFC3H;
- KsF7* = 0FFC4H; KsF8* = 0FFC5H; KsF9* = 0FFC6H; KsF10* = 0FFC7H; KsF11* = 0FFC8H; KsF12* = 0FFC9H;
- (** Modifiers *)
- KsShiftL* = 0FFE1H; (** Left shift *)
- KsShiftR* = 0FFE2H; (** Right shift *)
- KsControlL* = 0FFE3H; (** Left control *)
- KsControlR* = 0FFE4H; (** Right control *)
- KsCapsLock* = 0FFE5H; (** Caps lock *)
- KsMetaL* = 0FFE7H; (** Left meta, Left Windows *)
- KsMetaR* = 0FFE8H; (** Right meta, Right Windows *)
- KsAltL* = 0FFE9H; (** Left alt *)
- KsAltR* = 0FFEAH; (** Right alt *)
- (** HID Consumer Keys**)
- KsScanPreviousTrack*= 0FF0000H;
- KsScanNextTrack*= 0FF0001H;
- KsALConsumerControl*= 0FF0002H;
- KsMute*= 0FF0003H;
- KsVolumeDecrement*= 0FF0004H;
- KsVolumeIncrement*= 0FF0005H;
- KsPlayPause*= 0FF0006H;
- KsStopOSC*= 0FF0007H;
- KsALEmailReader*= 0FF0008H;
- KsALCalculator*= 0FF0009H;
- KsACSearch*= 0FF000AH;
- KsACHome*= 0FF000BH;
- KsACBack*= 0FF000CH;
- KsACForward*= 0FF000DH;
- KsACBookmarks*= 0FF000EH;
- KsConsumerButtons*= 0FFF000H;
- TYPE
- Message* = RECORD END; (** generic message. *)
- KeyboardMsg* = RECORD (Message)
- ch*: CHAR; (** extended ASCII key code, or 0X if not relevant *)
- flags*: SET; (** key flags *)
- keysym*: LONGINT (** X11-compatible key code *)
- END;
- MouseMsg* = RECORD (Message)
- keys*: SET; (** mouse key state. *)
- dx*, dy*, dz*: LONGINT (** mouse movement vector. *)
- END;
- AbsMouseMsg*= RECORD(Message);
- keys*: SET;
- x*,y*,z*,dx*,dy*,dz*: LONGINT;
- END;
- PointerMsg* = RECORD (Message)
- keys*: SET; (** pointer key state. *)
- x*, y*, z*: LONGINT; (** pointer position. *)
- mx*, my*, mz*: LONGINT (** pointer max values. *)
- END;
- TYPE
- Sink* = OBJECT (** a message receiver. *)
- (** Handle is overriden by a concrete receiver. *)
- PROCEDURE Handle*(VAR msg: Message);
- BEGIN HALT(301) END Handle;
- END Sink;
- Group* = OBJECT (** a group of message receivers. *)
- (** Add a receiver to a group. *)
- PROCEDURE Register*(s: Sink);
- BEGIN HALT(301) END Register;
- (** Remove a receiver from a group. *)
- PROCEDURE Unregister*(s: Sink);
- BEGIN HALT(301) END Unregister;
- (** Send a message to all receivers currently in the group. *)
- PROCEDURE Handle*(VAR msg: Message);
- BEGIN HALT(301) END Handle;
- END Group;
- TYPE
- Pointer* = OBJECT (Sink) (** convert incremental movements into absolute positions *)
- VAR
- cur: PointerMsg;
- threshold, speedup: LONGINT;
- fixedKeys: SET;
- PROCEDURE Update;
- VAR p: PointerMsg;
- BEGIN
- IF cur.x < 0 THEN cur.x := 0
- ELSIF cur.x > cur.mx THEN cur.x := cur.mx
- END;
- IF cur.y < 0 THEN cur.y := 0
- ELSIF cur.y > cur.my THEN cur.y := cur.my
- END;
- IF cur.z < 0 THEN cur.z := 0
- ELSIF cur.z > cur.mz THEN cur.z := cur.mz
- END;
- p := cur; p.keys := p.keys + fixedKeys;
- pointer.Handle(p)
- END Update;
- PROCEDURE SetKeys(keys: SET);
- BEGIN {EXCLUSIVE}
- fixedKeys := keys; Update
- END SetKeys;
- PROCEDURE Handle*(VAR m: Message);
- VAR dx, dy: LONGINT;
- BEGIN {EXCLUSIVE}
- IF m IS MouseMsg THEN
- WITH m: MouseMsg DO
- dx := m.dx; dy := m.dy;
- IF (ABS(dx) > threshold) OR (ABS(dy) > threshold) THEN
- dx := dx*speedup DIV 10; dy := dy*speedup DIV 10
- END;
- INC(cur.x, dx); INC(cur.y, dy); INC(cur.z, m.dz);
- cur.keys := m.keys;
- Update;
- END;
- ELSIF m IS AbsMouseMsg THEN
- WITH m: AbsMouseMsg DO
- cur.x := m.x; cur.y := m.y; cur.z := m.z;
- cur.keys := m.keys;
- Update
- END;
- END
- END Handle;
- PROCEDURE SetLimits*(mx, my, mz: LONGINT);
- BEGIN {EXCLUSIVE}
- cur.mx := mx; cur.my := my; cur.mz := mz;
- Update
- END SetLimits;
- PROCEDURE &Init*(t, s: LONGINT);
- BEGIN
- threshold := t; speedup := s;
- cur.x := 0; cur.y := 0; cur.z := 0;
- cur.mx := 1; cur.my := 1; cur.mz := 1;
- cur.keys := {}; fixedKeys := {};
- mouse.Register(SELF)
- END Init;
- END Pointer;
- TYPE
- List = POINTER TO RECORD
- next: List;
- s: Sink
- END;
- Broadcaster = OBJECT (Group)
- VAR sentinel: List;
- PROCEDURE Register*(s: Sink);
- VAR n: List;
- BEGIN {EXCLUSIVE}
- NEW(n); n.s := s; n.next := sentinel.next; sentinel.next := n
- END Register;
- PROCEDURE Unregister*(s: Sink);
- VAR n: List;
- BEGIN {EXCLUSIVE}
- n := sentinel;
- WHILE (n.next # NIL) & (n.next.s # s) DO n := n.next END;
- IF n.next # NIL THEN n.next := n.next.next END
- END Unregister;
- PROCEDURE Handle*(VAR msg: Message);
- VAR n: List;
- BEGIN {EXCLUSIVE}
- n := sentinel.next;
- WHILE n # NIL DO n.s.Handle(msg); n := n.next END
- END Handle;
- END Broadcaster;
- TYPE
- OberonInput* = OBJECT (Plugins.Plugin)
- VAR timer-: Kernel.Timer;
- PROCEDURE Mouse*(VAR x, y: INTEGER; VAR keys:SET);
- BEGIN
- HALT(99) (* abstract *)
- END Mouse;
- PROCEDURE Read*(VAR ch: CHAR; VAR break: BOOLEAN);
- BEGIN
- HALT(99) (* abstract *)
- END Read;
- PROCEDURE Available*(VAR num: INTEGER; VAR break: BOOLEAN);
- BEGIN
- HALT(99) (* abstract *)
- END Available;
- PROCEDURE KeyState*(VAR k: SET);
- BEGIN
- HALT(99) (* abstract *)
- END KeyState;
- PROCEDURE &Init*;
- BEGIN
- NEW(timer)
- END Init;
- END OberonInput;
- TYPE
- MouseFixer = OBJECT (Sink)
- VAR ctrl: BOOLEAN;
- PROCEDURE Handle*(VAR m: Message);
- VAR new: BOOLEAN;
- BEGIN {EXCLUSIVE}
- WITH m: KeyboardMsg DO
- new := m.flags * Ctrl # {};
- IF new # ctrl THEN
- ctrl := new;
- IF ctrl THEN main.SetKeys({1}) ELSE main.SetKeys({}) END
- END
- END
- END Handle;
- PROCEDURE &Init*;
- BEGIN
- ctrl := FALSE; keyboard.Register(SELF)
- END Init;
- END MouseFixer;
- VAR
- keyboard*, mouse*, pointer*: Group;
- main*: Pointer;
- oberonInput*: Plugins.Registry;
- mouseFixer: MouseFixer;
- (** Return a default message broadcaster instance. *)
- PROCEDURE NewBroadcaster*(): Group;
- VAR b: Broadcaster;
- BEGIN
- NEW(b); NEW(b.sentinel); b.sentinel.next := NIL;
- RETURN b
- END NewBroadcaster;
- PROCEDURE Init;
- VAR s: ARRAY 16 OF CHAR; i, threshold, speedup: LONGINT;
- BEGIN
- Machine.GetConfig("Threshold", s);
- i := 0; threshold := Machine.StrToInt(i, s);
- IF threshold <= 0 THEN threshold := 5 END;
- Machine.GetConfig("Speedup", s);
- i := 0; speedup := Machine.StrToInt(i, s);
- IF speedup <= 0 THEN speedup := 15 END;
- NEW(main, threshold, speedup);
- Machine.GetConfig("MB", s);
- IF (s = "2") OR (s = "-2") THEN NEW(mouseFixer) END
- END Init;
- BEGIN
- keyboard := NewBroadcaster();
- mouse := NewBroadcaster();
- pointer := NewBroadcaster();
- NEW(oberonInput, "Inputs", "Oberon input drivers");
- Init
- END Inputs.
|