123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by Florian Klaempfl
- member of the Free Pascal development team
- Mouse unit for linux
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit Mouse;
- interface
- {$i mouseh.inc}
- implementation
- uses
- Video,
- MouCalls, DosCalls;
- {$i mouse.inc}
- var
- PendingMouseEventOrder: array [0..MouseEventBufSize-1] of cardinal;
- MouseEventOrderHead, MouseEventOrderTail: cardinal;
- const
- NoMouse = $FFFF;
- DefaultMouse = 0;
- Handle: word = DefaultMouse;
- HideCounter: cardinal = 0;
- OldEventMask: longint = -1;
- procedure SysInitMouse;
- var
- Loc: TPtrLoc;
- SetPrev: boolean;
- SysEvent: TMouEventInfo;
- QI: TMouQueInfo;
- W: word;
- begin
- SetPrev := MouGetPtrPos (Loc, DefaultMouse) = 0;
- if MouGetEventMask (W, DefaultMouse) = 0 then OldEventMask := W;
- MouseEventOrderTail := 0;
- MouseEventOrderHead := 0;
- HideCounter := 0;
- if MouOpen (nil, Handle) = Error_Mouse_No_Device then Handle := NoMouse else
- begin
- W := Mou_NoWait;
- repeat
- MouGetNumQueEl (QI, Handle);
- if QI.cEvents <> 0 then MouReadEventQue (SysEvent, W, Handle);
- until QI.cEvents = 0;
- W := $FFFF;
- MouSetEventMask (W, Handle);
- if SetPrev then MouSetPtrPos (Loc, Handle);
- (*
- It would be possible to issue a MouRegister call here to hook our own mouse
- handler, but such handler would have to be in a DLL and it is questionable,
- whether there would be so many advantages in doing so.
- *)
- MouDrawPtr (Handle);
- end;
- end;
- procedure SysDoneMouse;
- var
- W: word;
- begin
- if (Handle <> NoMouse) and (Handle <> DefaultMouse) then
- begin
- (*
- If our own mouse handler would be installed in InitMouse, MouDeregister would
- have appeared here.
- *)
- HideCounter := 0;
- HideMouse;
- MouClose (Handle);
- end;
- if OldEventMask <> -1 then
- begin
- W := OldEventMask;
- MouSetEventMask (W, 0);
- end;
- end;
- function SysDetectMouse:byte;
- var
- Buttons: word;
- TempHandle: word;
- begin
- MouOpen (nil, TempHandle);
- if MouGetNumButtons (Buttons, TempHandle) = 0 then
- SysDetectMouse := Buttons
- else
- SysDetectMouse := 0;
- MouClose (TempHandle);
- end;
- procedure SysShowMouse;
- begin
- if Handle <> NoMouse then
- begin
- if HideCounter <> 0 then
- begin
- Dec (HideCounter);
- if HideCounter = 0 then MouDrawPtr (Handle);
- end;
- end;
- end;
- procedure SysHideMouse;
- var
- PtrRect: TNoPtrRect;
- begin
- if Handle <> NoMouse then
- begin
- Inc (HideCounter);
- case HideCounter of
- 0: Dec (HideCounter); (* HideCounter overflowed - stay at the maximum *)
- 1: begin
- PtrRect.Row := 0;
- PtrRect.Col := 0;
- PtrRect.cRow := Pred (ScreenHeight);
- PtrRect.cCol := Pred (ScreenWidth);
- MouRemovePtr (PtrRect, Handle);
- end;
- end;
- end;
- end;
- function SysGetMouseX: word;
- var
- Event: TMouseEvent;
- begin
- if Handle = NoMouse then
- SysGetMouseX := 0
- else
- begin
- PollMouseEvent (Event);
- SysGetMouseX := Event.X;
- end;
- end;
- function SysGetMouseY: word;
- var
- Event: TMouseEvent;
- begin
- if Handle = NoMouse then
- SysGetMouseY := 0
- else
- begin
- PollMouseEvent (Event);
- SysGetMouseY := Event.Y;
- end;
- end;
- procedure SysGetMouseXY (var X: word; var Y: word);
- var
- Loc: TPtrLoc;
- begin
- if Handle = NoMouse then
- begin
- X := 0;
- Y := 0;
- end else if MouGetPtrPos (Loc, Handle) <> 0 then
- begin
- X := $FFFF;
- Y := $FFFF;
- end else
- begin
- X := Loc.Col;
- Y := Loc.Row;
- end;
- end;
- procedure SysSetMouseXY (X, Y: word);
- var
- Loc: TPtrLoc;
- begin
- if Handle <> NoMouse then
- begin
- Loc.Row := Y;
- Loc.Col := X;
- MouSetPtrPos (Loc, Handle);
- end;
- end;
- procedure TranslateEvents (const SysEvent: TMouEventInfo;
- var Event: TMouseEvent);
- begin
- Event.Buttons := 0;
- Event.Action := 0;
- if SysEvent.fs and (Mouse_Motion_With_BN1_Down or Mouse_BN1_Down) <> 0 then
- Event.Buttons := Event.Buttons or MouseLeftButton;
- if SysEvent.fs and (Mouse_Motion_With_BN2_Down or Mouse_BN2_Down) <> 0 then
- Event.Buttons := Event.Buttons or MouseRightButton;
- if SysEvent.fs and (Mouse_Motion_With_BN3_Down or Mouse_BN3_Down) <> 0 then
- Event.Buttons := Event.Buttons or MouseMiddleButton;
- Event.X := SysEvent.Col;
- Event.Y := SysEvent.Row;
- if Event.Buttons <> LastMouseEvent.Buttons then
- if (Event.Buttons and MouseLeftButton = 0) and
- (LastMouseEvent.Buttons and MouseLeftButton = MouseLeftButton)
- then Event.Action := MouseActionUp else
- if (Event.Buttons and MouseRightButton = 0) and
- (LastMouseEvent.Buttons and MouseRightButton = MouseRightButton)
- then Event.Action := MouseActionUp else
- if (Event.Buttons and MouseMiddleButton = 0) and
- (LastMouseEvent.Buttons and MouseMiddleButton = MouseMiddleButton)
- then Event.Action := MouseActionUp
- else Event.Action := MouseActionDown
- else if (Event.X <> LastMouseEvent.X) or (Event.Y <> LastMouseEvent.Y)
- then Event.Action := MouseActionMove;
- LastMouseEvent := Event;
- end;
- procedure NullOrder;
- var
- I: cardinal;
- begin
- if PendingMouseEvents > 0 then
- begin
- I := MouseEventOrderHead;
- repeat
- PendingMouseEventOrder [I] := 0;
- if I = Pred (MouseEventBufSize) then I := 0 else Inc (I);
- until (I <> MouseEventOrderTail);
- end;
- end;
- procedure LowerOrder;
- var
- I: cardinal;
- begin
- if PendingMouseEvents > 0 then
- begin
- I := MouseEventOrderHead;
- repeat
- if PendingMouseEventOrder [I] <> 0 then
- begin
- Dec (PendingMouseEventOrder [I]);
- if I = Pred (MouseEventBufSize) then I := 0 else Inc (I);
- end;
- until (I <> MouseEventOrderTail) or (PendingMouseEventOrder [I] = 0);
- end;
- end;
- function SysPollMouseEvent (var MouseEvent: TMouseEvent) :boolean;
- var
- SysEvent: TMouEventInfo;
- P, Q: PMouseEvent;
- Event: TMouseEvent;
- WF: word;
- QI: TMouQueInfo;
- begin
- if (PendingMouseEvents = 0) or
- (PendingMouseEventOrder [MouseEventOrderHead] <> 0) and
- (PendingMouseEvents < MouseEventBufSize) then
- begin
- MouGetNumQueEl (QI, Handle);
- if QI.cEvents = 0 then NullOrder else
- begin
- LowerOrder;
- WF := Mou_NoWait;
- if (MouReadEventQue (SysEvent, WF, Handle) = 0) then
- begin
- if PendingMouseHead = @PendingMouseEvent then
- P := @PendingMouseEvent [MouseEventBufSize - 1] else
- begin
- P := PendingMouseHead;
- Dec (P);
- end;
- TranslateEvents (SysEvent, P^);
- if P^.Action <> 0 then
- begin
- if PendingMouseEvents < MouseEventBufSize then
- begin
- Q := P;
- WF := Mou_NoWait;
- while (P^.Action = MouseActionMove) and
- (PendingMouseEventOrder [MouseEventOrderHead] <> 0) and
- (MouReadEventQue (SysEvent, WF, Handle) = 0) and
- ((SysEvent.fs <> 0) or (LastMouseEvent.Buttons <> 0)) do
- begin
- LowerOrder;
- TranslateEvents (SysEvent, Event);
- if Event.Action <> MouseActionMove then
- begin
- if Q = @PendingMouseEvent then
- Q := @PendingMouseEvent [MouseEventBufSize - 1] else Dec (Q);
- if MouseEventOrderHead = 0 then
- MouseEventOrderHead := MouseEventBufSize - 1 else
- Dec (MouseEventOrderHead);
- PendingMouseEventOrder [MouseEventOrderHead] := 0;
- Q^ := P^;
- Inc (PendingMouseEvents);
- if MouseEventOrderHead = 0 then
- MouseEventOrderHead := MouseEventBufSize - 1 else
- Dec (MouseEventOrderHead);
- PendingMouseEventOrder [MouseEventOrderHead] := 0;
- end else WF := Mou_NoWait;
- P^ := Event;
- end;
- P := Q;
- end;
- Inc (PendingMouseEvents);
- if MouseEventOrderHead = 0 then
- MouseEventOrderHead := MouseEventBufSize - 1 else
- Dec (MouseEventOrderHead);
- PendingMouseEventOrder [MouseEventOrderHead] := 0;
- PendingMouseHead := P;
- end;
- end else NullOrder;
- end;
- end;
- if PendingMouseEvents <> 0 then
- begin
- MouseEvent := PendingMouseHead^;
- LastMouseEvent := MouseEvent;
- SysPollMouseEvent := true;
- end else
- begin
- SysPollMouseEvent := false;
- MouseEvent := LastMouseEvent;
- MouseEvent.Action := 0;
- end;
- end;
- function SysGetMouseButtons: word;
- var
- Event: TMouseEvent;
- begin
- PollMouseEvent (Event);
- SysGetMouseButtons := Event.Buttons;
- end;
- procedure SysGetMouseEvent (var MouseEvent: TMouseEvent);
- begin
- if (PendingMouseEvents = 0) or
- (PendingMouseEventOrder [MouseEventOrderHead] <> 0) then
- repeat
- DosSleep (1);
- PollMouseEvent (MouseEvent);
- until (PendingMouseEvents <> 0) and
- (PendingMouseEventOrder [MouseEventOrderHead] = 0) else
- begin
- MouseEvent := PendingMouseHead^;
- LastMouseEvent := MouseEvent;
- end;
- Inc (PendingMouseHead);
- if longint (PendingMouseHead) = longint (@PendingMouseEvent)
- + SizeOf (PendingMouseEvent) then PendingMouseHead := @PendingMouseEvent;
- Inc (MouseEventOrderHead);
- if MouseEventOrderHead = MouseEventBufSize then MouseEventOrderHead := 0;
- Dec (PendingMouseEvents);
- end;
- procedure SysPutMouseEvent (const MouseEvent: TMouseEvent);
- var
- QI: TMouQueInfo;
- begin
- if PendingMouseEvents < MouseEventBufSize then
- begin
- PendingMouseTail^ := MouseEvent;
- Inc (PendingMouseTail);
- if longint (PendingMouseTail) = longint (@PendingMouseEvent) +
- SizeOf (PendingMouseEvent) then PendingMouseTail := @PendingMouseEvent;
- MouGetNumQueEl (QI, Handle);
- PendingMouseEventOrder [MouseEventOrderTail] := QI.cEvents;
- Inc (MouseEventOrderTail);
- if MouseEventOrderTail = MouseEventBufSize then MouseEventOrderTail := 0;
- Inc (PendingMouseEvents);
- end;
- end;
- Const
- SysMouseDriver : TMouseDriver = (
- UseDefaultQueue : False;
- InitDriver : @SysInitMouse;
- DoneDriver : @SysDoneMouse;
- DetectMouse : @SysDetectMouse;
- ShowMouse : @SysShowMouse;
- HideMouse : @SysHideMouse;
- GetMouseX : @SysGetMouseX;
- GetMouseY : @SysGetMouseY;
- GetMouseButtons : @SysGetMouseButtons;
- SetMouseXY : @SysSetMouseXY;
- GetMouseEvent : @SysGetMouseEvent;
- PollMouseEvent : @SysPollMouseEvent;
- PutMouseEvent : @SysPutMouseEvent;
- );
- Begin
- SetMouseDriver(SysMouseDriver);
- end.
|