mouse.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Mouse unit for linux
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit Mouse;
  13. interface
  14. {$i mouseh.inc}
  15. implementation
  16. uses
  17. Video,
  18. MouCalls, DosCalls;
  19. {$i mouse.inc}
  20. var
  21. PendingMouseEventOrder: array [0..MouseEventBufSize-1] of cardinal;
  22. MouseEventOrderHead, MouseEventOrderTail: cardinal;
  23. const
  24. NoMouse = $FFFF;
  25. DefaultMouse = 0;
  26. Handle: word = DefaultMouse;
  27. HideCounter: cardinal = 0;
  28. OldEventMask: longint = -1;
  29. procedure SysInitMouse;
  30. var
  31. Loc: TPtrLoc;
  32. SetPrev: boolean;
  33. SysEvent: TMouEventInfo;
  34. QI: TMouQueInfo;
  35. W: word;
  36. begin
  37. SetPrev := MouGetPtrPos (Loc, DefaultMouse) = 0;
  38. if MouGetEventMask (W, DefaultMouse) = 0 then OldEventMask := W;
  39. MouseEventOrderTail := 0;
  40. MouseEventOrderHead := 0;
  41. HideCounter := 0;
  42. if MouOpen (nil, Handle) = Error_Mouse_No_Device then Handle := NoMouse else
  43. begin
  44. W := Mou_NoWait;
  45. repeat
  46. MouGetNumQueEl (QI, Handle);
  47. if QI.cEvents <> 0 then MouReadEventQue (SysEvent, W, Handle);
  48. until QI.cEvents = 0;
  49. W := $FFFF;
  50. MouSetEventMask (W, Handle);
  51. if SetPrev then MouSetPtrPos (Loc, Handle);
  52. (*
  53. It would be possible to issue a MouRegister call here to hook our own mouse
  54. handler, but such handler would have to be in a DLL and it is questionable,
  55. whether there would be so many advantages in doing so.
  56. *)
  57. MouDrawPtr (Handle);
  58. end;
  59. end;
  60. procedure SysDoneMouse;
  61. var
  62. W: word;
  63. begin
  64. if (Handle <> NoMouse) and (Handle <> DefaultMouse) then
  65. begin
  66. (*
  67. If our own mouse handler would be installed in InitMouse, MouDeregister would
  68. have appeared here.
  69. *)
  70. HideCounter := 0;
  71. HideMouse;
  72. MouClose (Handle);
  73. end;
  74. if OldEventMask <> -1 then
  75. begin
  76. W := OldEventMask;
  77. MouSetEventMask (W, 0);
  78. end;
  79. end;
  80. function SysDetectMouse:byte;
  81. var
  82. Buttons: word;
  83. RC: longint;
  84. TempHandle: word;
  85. begin
  86. MouOpen (nil, TempHandle);
  87. if MouGetNumButtons (Buttons, TempHandle) = 0 then
  88. SysDetectMouse := Buttons
  89. else
  90. SysDetectMouse := 0;
  91. MouClose (TempHandle);
  92. end;
  93. procedure SysShowMouse;
  94. begin
  95. if Handle <> NoMouse then
  96. begin
  97. if HideCounter <> 0 then
  98. begin
  99. Dec (HideCounter);
  100. if HideCounter = 0 then MouDrawPtr (Handle);
  101. end;
  102. end;
  103. end;
  104. procedure SysHideMouse;
  105. var
  106. PtrRect: TNoPtrRect;
  107. begin
  108. if Handle <> NoMouse then
  109. begin
  110. Inc (HideCounter);
  111. case HideCounter of
  112. 0: Dec (HideCounter); (* HideCounter overflowed - stay at the maximum *)
  113. 1: begin
  114. PtrRect.Row := 0;
  115. PtrRect.Col := 0;
  116. PtrRect.cRow := Pred (ScreenHeight);
  117. PtrRect.cCol := Pred (ScreenWidth);
  118. MouRemovePtr (PtrRect, Handle);
  119. end;
  120. end;
  121. end;
  122. end;
  123. function SysGetMouseX: word;
  124. var
  125. Event: TMouseEvent;
  126. begin
  127. if Handle = NoMouse then
  128. SysGetMouseX := 0
  129. else
  130. begin
  131. PollMouseEvent (Event);
  132. SysGetMouseX := Event.X;
  133. end;
  134. end;
  135. function SysGetMouseY: word;
  136. var
  137. Event: TMouseEvent;
  138. begin
  139. if Handle = NoMouse then
  140. SysGetMouseY := 0
  141. else
  142. begin
  143. PollMouseEvent (Event);
  144. SysGetMouseY := Event.Y;
  145. end;
  146. end;
  147. procedure SysGetMouseXY (var X: word; var Y: word);
  148. var
  149. Loc: TPtrLoc;
  150. begin
  151. if Handle = NoMouse then
  152. begin
  153. X := 0;
  154. Y := 0;
  155. end else if MouGetPtrPos (Loc, Handle) <> 0 then
  156. begin
  157. X := $FFFF;
  158. Y := $FFFF;
  159. end else
  160. begin
  161. X := Loc.Col;
  162. Y := Loc.Row;
  163. end;
  164. end;
  165. procedure SysSetMouseXY (X, Y: word);
  166. var
  167. Loc: TPtrLoc;
  168. begin
  169. if Handle <> NoMouse then
  170. begin
  171. Loc.Row := Y;
  172. Loc.Col := X;
  173. MouSetPtrPos (Loc, Handle);
  174. end;
  175. end;
  176. procedure TranslateEvents (const SysEvent: TMouEventInfo;
  177. var Event: TMouseEvent);
  178. begin
  179. Event.Buttons := 0;
  180. Event.Action := 0;
  181. if SysEvent.fs and (Mouse_Motion_With_BN1_Down or Mouse_BN1_Down) <> 0 then
  182. Event.Buttons := Event.Buttons or MouseLeftButton;
  183. if SysEvent.fs and (Mouse_Motion_With_BN2_Down or Mouse_BN2_Down) <> 0 then
  184. Event.Buttons := Event.Buttons or MouseRightButton;
  185. if SysEvent.fs and (Mouse_Motion_With_BN3_Down or Mouse_BN3_Down) <> 0 then
  186. Event.Buttons := Event.Buttons or MouseMiddleButton;
  187. Event.X := SysEvent.Col;
  188. Event.Y := SysEvent.Row;
  189. if Event.Buttons <> LastMouseEvent.Buttons then
  190. if (Event.Buttons and MouseLeftButton = 0) and
  191. (LastMouseEvent.Buttons and MouseLeftButton = MouseLeftButton)
  192. then Event.Action := MouseActionUp else
  193. if (Event.Buttons and MouseRightButton = 0) and
  194. (LastMouseEvent.Buttons and MouseRightButton = MouseRightButton)
  195. then Event.Action := MouseActionUp else
  196. if (Event.Buttons and MouseMiddleButton = 0) and
  197. (LastMouseEvent.Buttons and MouseMiddleButton = MouseMiddleButton)
  198. then Event.Action := MouseActionUp
  199. else Event.Action := MouseActionDown
  200. else if (Event.X <> LastMouseEvent.X) or (Event.Y <> LastMouseEvent.Y)
  201. then Event.Action := MouseActionMove;
  202. LastMouseEvent := Event;
  203. end;
  204. procedure NullOrder;
  205. var
  206. I: cardinal;
  207. begin
  208. if PendingMouseEvents > 0 then
  209. begin
  210. I := MouseEventOrderHead;
  211. repeat
  212. PendingMouseEventOrder [I] := 0;
  213. if I = Pred (MouseEventBufSize) then I := 0 else Inc (I);
  214. until (I <> MouseEventOrderTail);
  215. end;
  216. end;
  217. procedure LowerOrder;
  218. var
  219. I: cardinal;
  220. begin
  221. if PendingMouseEvents > 0 then
  222. begin
  223. I := MouseEventOrderHead;
  224. repeat
  225. if PendingMouseEventOrder [I] <> 0 then
  226. begin
  227. Dec (PendingMouseEventOrder [I]);
  228. if I = Pred (MouseEventBufSize) then I := 0 else Inc (I);
  229. end;
  230. until (I <> MouseEventOrderTail) or (PendingMouseEventOrder [I] = 0);
  231. end;
  232. end;
  233. function SysPollMouseEvent (var MouseEvent: TMouseEvent) :boolean;
  234. var
  235. SysEvent: TMouEventInfo;
  236. P, Q: PMouseEvent;
  237. Event: TMouseEvent;
  238. WF: word;
  239. QI: TMouQueInfo;
  240. begin
  241. if (PendingMouseEvents = 0) or
  242. (PendingMouseEventOrder [MouseEventOrderHead] <> 0) and
  243. (PendingMouseEvents < MouseEventBufSize) then
  244. begin
  245. MouGetNumQueEl (QI, Handle);
  246. if QI.cEvents = 0 then NullOrder else
  247. begin
  248. LowerOrder;
  249. WF := Mou_NoWait;
  250. if (MouReadEventQue (SysEvent, WF, Handle) = 0) then
  251. begin
  252. if PendingMouseHead = @PendingMouseEvent then
  253. P := @PendingMouseEvent [MouseEventBufSize - 1] else
  254. begin
  255. P := PendingMouseHead;
  256. Dec (P);
  257. end;
  258. TranslateEvents (SysEvent, P^);
  259. if P^.Action <> 0 then
  260. begin
  261. if PendingMouseEvents < MouseEventBufSize then
  262. begin
  263. Q := P;
  264. WF := Mou_NoWait;
  265. while (P^.Action = MouseActionMove) and
  266. (PendingMouseEventOrder [MouseEventOrderHead] <> 0) and
  267. (MouReadEventQue (SysEvent, WF, Handle) = 0) and
  268. ((SysEvent.fs <> 0) or (LastMouseEvent.Buttons <> 0)) do
  269. begin
  270. LowerOrder;
  271. TranslateEvents (SysEvent, Event);
  272. if Event.Action <> MouseActionMove then
  273. begin
  274. if Q = @PendingMouseEvent then
  275. Q := @PendingMouseEvent [MouseEventBufSize - 1] else Dec (Q);
  276. if MouseEventOrderHead = 0 then
  277. MouseEventOrderHead := MouseEventBufSize - 1 else
  278. Dec (MouseEventOrderHead);
  279. PendingMouseEventOrder [MouseEventOrderHead] := 0;
  280. Q^ := P^;
  281. Inc (PendingMouseEvents);
  282. if MouseEventOrderHead = 0 then
  283. MouseEventOrderHead := MouseEventBufSize - 1 else
  284. Dec (MouseEventOrderHead);
  285. PendingMouseEventOrder [MouseEventOrderHead] := 0;
  286. end else WF := Mou_NoWait;
  287. P^ := Event;
  288. end;
  289. P := Q;
  290. end;
  291. Inc (PendingMouseEvents);
  292. if MouseEventOrderHead = 0 then
  293. MouseEventOrderHead := MouseEventBufSize - 1 else
  294. Dec (MouseEventOrderHead);
  295. PendingMouseEventOrder [MouseEventOrderHead] := 0;
  296. PendingMouseHead := P;
  297. end;
  298. end else NullOrder;
  299. end;
  300. end;
  301. if PendingMouseEvents <> 0 then
  302. begin
  303. MouseEvent := PendingMouseHead^;
  304. LastMouseEvent := MouseEvent;
  305. SysPollMouseEvent := true;
  306. end else
  307. begin
  308. SysPollMouseEvent := false;
  309. MouseEvent := LastMouseEvent;
  310. MouseEvent.Action := 0;
  311. end;
  312. end;
  313. function SysGetMouseButtons: word;
  314. var
  315. Event: TMouseEvent;
  316. begin
  317. PollMouseEvent (Event);
  318. SysGetMouseButtons := Event.Buttons;
  319. end;
  320. procedure SysGetMouseEvent (var MouseEvent: TMouseEvent);
  321. var
  322. Event: TMouEventInfo;
  323. begin
  324. if (PendingMouseEvents = 0) or
  325. (PendingMouseEventOrder [MouseEventOrderHead] <> 0) then
  326. repeat
  327. DosSleep (1);
  328. PollMouseEvent (MouseEvent);
  329. until (PendingMouseEvents <> 0) and
  330. (PendingMouseEventOrder [MouseEventOrderHead] = 0) else
  331. begin
  332. MouseEvent := PendingMouseHead^;
  333. LastMouseEvent := MouseEvent;
  334. end;
  335. Inc (PendingMouseHead);
  336. if longint (PendingMouseHead) = longint (@PendingMouseEvent)
  337. + SizeOf (PendingMouseEvent) then PendingMouseHead := @PendingMouseEvent;
  338. Inc (MouseEventOrderHead);
  339. if MouseEventOrderHead = MouseEventBufSize then MouseEventOrderHead := 0;
  340. Dec (PendingMouseEvents);
  341. end;
  342. procedure SysPutMouseEvent (const MouseEvent: TMouseEvent);
  343. var
  344. QI: TMouQueInfo;
  345. begin
  346. if PendingMouseEvents < MouseEventBufSize then
  347. begin
  348. PendingMouseTail^ := MouseEvent;
  349. Inc (PendingMouseTail);
  350. if longint (PendingMouseTail) = longint (@PendingMouseEvent) +
  351. SizeOf (PendingMouseEvent) then PendingMouseTail := @PendingMouseEvent;
  352. MouGetNumQueEl (QI, Handle);
  353. PendingMouseEventOrder [MouseEventOrderTail] := QI.cEvents;
  354. Inc (MouseEventOrderTail);
  355. if MouseEventOrderTail = MouseEventBufSize then MouseEventOrderTail := 0;
  356. Inc (PendingMouseEvents);
  357. end;
  358. end;
  359. Const
  360. SysMouseDriver : TMouseDriver = (
  361. UseDefaultQueue : False;
  362. InitDriver : @SysInitMouse;
  363. DoneDriver : @SysDoneMouse;
  364. DetectMouse : @SysDetectMouse;
  365. ShowMouse : @SysShowMouse;
  366. HideMouse : @SysHideMouse;
  367. GetMouseX : @SysGetMouseX;
  368. GetMouseY : @SysGetMouseY;
  369. GetMouseButtons : @SysGetMouseButtons;
  370. SetMouseXY : @SysSetMouseXY;
  371. GetMouseEvent : @SysGetMouseEvent;
  372. PollMouseEvent : @SysPollMouseEvent;
  373. PutMouseEvent : @SysPutMouseEvent;
  374. );
  375. Begin
  376. SetMouseDriver(SysMouseDriver);
  377. end.