mouse.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  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. TempHandle: word;
  84. begin
  85. MouOpen (nil, TempHandle);
  86. if MouGetNumButtons (Buttons, TempHandle) = 0 then
  87. SysDetectMouse := Buttons
  88. else
  89. SysDetectMouse := 0;
  90. MouClose (TempHandle);
  91. end;
  92. procedure SysShowMouse;
  93. begin
  94. if Handle <> NoMouse then
  95. begin
  96. if HideCounter <> 0 then
  97. begin
  98. Dec (HideCounter);
  99. if HideCounter = 0 then MouDrawPtr (Handle);
  100. end;
  101. end;
  102. end;
  103. procedure SysHideMouse;
  104. var
  105. PtrRect: TNoPtrRect;
  106. begin
  107. if Handle <> NoMouse then
  108. begin
  109. Inc (HideCounter);
  110. case HideCounter of
  111. 0: Dec (HideCounter); (* HideCounter overflowed - stay at the maximum *)
  112. 1: begin
  113. PtrRect.Row := 0;
  114. PtrRect.Col := 0;
  115. PtrRect.cRow := Pred (ScreenHeight);
  116. PtrRect.cCol := Pred (ScreenWidth);
  117. MouRemovePtr (PtrRect, Handle);
  118. end;
  119. end;
  120. end;
  121. end;
  122. function SysGetMouseX: word;
  123. var
  124. Event: TMouseEvent;
  125. begin
  126. if Handle = NoMouse then
  127. SysGetMouseX := 0
  128. else
  129. begin
  130. PollMouseEvent (Event);
  131. SysGetMouseX := Event.X;
  132. end;
  133. end;
  134. function SysGetMouseY: word;
  135. var
  136. Event: TMouseEvent;
  137. begin
  138. if Handle = NoMouse then
  139. SysGetMouseY := 0
  140. else
  141. begin
  142. PollMouseEvent (Event);
  143. SysGetMouseY := Event.Y;
  144. end;
  145. end;
  146. procedure SysGetMouseXY (var X: word; var Y: word);
  147. var
  148. Loc: TPtrLoc;
  149. begin
  150. if Handle = NoMouse then
  151. begin
  152. X := 0;
  153. Y := 0;
  154. end else if MouGetPtrPos (Loc, Handle) <> 0 then
  155. begin
  156. X := $FFFF;
  157. Y := $FFFF;
  158. end else
  159. begin
  160. X := Loc.Col;
  161. Y := Loc.Row;
  162. end;
  163. end;
  164. procedure SysSetMouseXY (X, Y: word);
  165. var
  166. Loc: TPtrLoc;
  167. begin
  168. if Handle <> NoMouse then
  169. begin
  170. Loc.Row := Y;
  171. Loc.Col := X;
  172. MouSetPtrPos (Loc, Handle);
  173. end;
  174. end;
  175. procedure TranslateEvents (const SysEvent: TMouEventInfo;
  176. var Event: TMouseEvent);
  177. begin
  178. Event.Buttons := 0;
  179. Event.Action := 0;
  180. if SysEvent.fs and (Mouse_Motion_With_BN1_Down or Mouse_BN1_Down) <> 0 then
  181. Event.Buttons := Event.Buttons or MouseLeftButton;
  182. if SysEvent.fs and (Mouse_Motion_With_BN2_Down or Mouse_BN2_Down) <> 0 then
  183. Event.Buttons := Event.Buttons or MouseRightButton;
  184. if SysEvent.fs and (Mouse_Motion_With_BN3_Down or Mouse_BN3_Down) <> 0 then
  185. Event.Buttons := Event.Buttons or MouseMiddleButton;
  186. Event.X := SysEvent.Col;
  187. Event.Y := SysEvent.Row;
  188. if Event.Buttons <> LastMouseEvent.Buttons then
  189. if (Event.Buttons and MouseLeftButton = 0) and
  190. (LastMouseEvent.Buttons and MouseLeftButton = MouseLeftButton)
  191. then Event.Action := MouseActionUp else
  192. if (Event.Buttons and MouseRightButton = 0) and
  193. (LastMouseEvent.Buttons and MouseRightButton = MouseRightButton)
  194. then Event.Action := MouseActionUp else
  195. if (Event.Buttons and MouseMiddleButton = 0) and
  196. (LastMouseEvent.Buttons and MouseMiddleButton = MouseMiddleButton)
  197. then Event.Action := MouseActionUp
  198. else Event.Action := MouseActionDown
  199. else if (Event.X <> LastMouseEvent.X) or (Event.Y <> LastMouseEvent.Y)
  200. then Event.Action := MouseActionMove;
  201. LastMouseEvent := Event;
  202. end;
  203. procedure NullOrder;
  204. var
  205. I: cardinal;
  206. begin
  207. if PendingMouseEvents > 0 then
  208. begin
  209. I := MouseEventOrderHead;
  210. repeat
  211. PendingMouseEventOrder [I] := 0;
  212. if I = Pred (MouseEventBufSize) then I := 0 else Inc (I);
  213. until (I <> MouseEventOrderTail);
  214. end;
  215. end;
  216. procedure LowerOrder;
  217. var
  218. I: cardinal;
  219. begin
  220. if PendingMouseEvents > 0 then
  221. begin
  222. I := MouseEventOrderHead;
  223. repeat
  224. if PendingMouseEventOrder [I] <> 0 then
  225. begin
  226. Dec (PendingMouseEventOrder [I]);
  227. if I = Pred (MouseEventBufSize) then I := 0 else Inc (I);
  228. end;
  229. until (I <> MouseEventOrderTail) or (PendingMouseEventOrder [I] = 0);
  230. end;
  231. end;
  232. function SysPollMouseEvent (var MouseEvent: TMouseEvent) :boolean;
  233. var
  234. SysEvent: TMouEventInfo;
  235. P, Q: PMouseEvent;
  236. Event: TMouseEvent;
  237. WF: word;
  238. QI: TMouQueInfo;
  239. begin
  240. if (PendingMouseEvents = 0) or
  241. (PendingMouseEventOrder [MouseEventOrderHead] <> 0) and
  242. (PendingMouseEvents < MouseEventBufSize) then
  243. begin
  244. MouGetNumQueEl (QI, Handle);
  245. if QI.cEvents = 0 then NullOrder else
  246. begin
  247. LowerOrder;
  248. WF := Mou_NoWait;
  249. if (MouReadEventQue (SysEvent, WF, Handle) = 0) then
  250. begin
  251. if PendingMouseHead = @PendingMouseEvent then
  252. P := @PendingMouseEvent [MouseEventBufSize - 1] else
  253. begin
  254. P := PendingMouseHead;
  255. Dec (P);
  256. end;
  257. TranslateEvents (SysEvent, P^);
  258. if P^.Action <> 0 then
  259. begin
  260. if PendingMouseEvents < MouseEventBufSize then
  261. begin
  262. Q := P;
  263. WF := Mou_NoWait;
  264. while (P^.Action = MouseActionMove) and
  265. (PendingMouseEventOrder [MouseEventOrderHead] <> 0) and
  266. (MouReadEventQue (SysEvent, WF, Handle) = 0) and
  267. ((SysEvent.fs <> 0) or (LastMouseEvent.Buttons <> 0)) do
  268. begin
  269. LowerOrder;
  270. TranslateEvents (SysEvent, Event);
  271. if Event.Action <> MouseActionMove then
  272. begin
  273. if Q = @PendingMouseEvent then
  274. Q := @PendingMouseEvent [MouseEventBufSize - 1] else Dec (Q);
  275. if MouseEventOrderHead = 0 then
  276. MouseEventOrderHead := MouseEventBufSize - 1 else
  277. Dec (MouseEventOrderHead);
  278. PendingMouseEventOrder [MouseEventOrderHead] := 0;
  279. Q^ := P^;
  280. Inc (PendingMouseEvents);
  281. if MouseEventOrderHead = 0 then
  282. MouseEventOrderHead := MouseEventBufSize - 1 else
  283. Dec (MouseEventOrderHead);
  284. PendingMouseEventOrder [MouseEventOrderHead] := 0;
  285. end else WF := Mou_NoWait;
  286. P^ := Event;
  287. end;
  288. P := Q;
  289. end;
  290. Inc (PendingMouseEvents);
  291. if MouseEventOrderHead = 0 then
  292. MouseEventOrderHead := MouseEventBufSize - 1 else
  293. Dec (MouseEventOrderHead);
  294. PendingMouseEventOrder [MouseEventOrderHead] := 0;
  295. PendingMouseHead := P;
  296. end;
  297. end else NullOrder;
  298. end;
  299. end;
  300. if PendingMouseEvents <> 0 then
  301. begin
  302. MouseEvent := PendingMouseHead^;
  303. LastMouseEvent := MouseEvent;
  304. SysPollMouseEvent := true;
  305. end else
  306. begin
  307. SysPollMouseEvent := false;
  308. MouseEvent := LastMouseEvent;
  309. MouseEvent.Action := 0;
  310. end;
  311. end;
  312. function SysGetMouseButtons: word;
  313. var
  314. Event: TMouseEvent;
  315. begin
  316. PollMouseEvent (Event);
  317. SysGetMouseButtons := Event.Buttons;
  318. end;
  319. procedure SysGetMouseEvent (var MouseEvent: TMouseEvent);
  320. begin
  321. if (PendingMouseEvents = 0) or
  322. (PendingMouseEventOrder [MouseEventOrderHead] <> 0) then
  323. repeat
  324. DosSleep (1);
  325. PollMouseEvent (MouseEvent);
  326. until (PendingMouseEvents <> 0) and
  327. (PendingMouseEventOrder [MouseEventOrderHead] = 0) else
  328. begin
  329. MouseEvent := PendingMouseHead^;
  330. LastMouseEvent := MouseEvent;
  331. end;
  332. Inc (PendingMouseHead);
  333. if longint (PendingMouseHead) = longint (@PendingMouseEvent)
  334. + SizeOf (PendingMouseEvent) then PendingMouseHead := @PendingMouseEvent;
  335. Inc (MouseEventOrderHead);
  336. if MouseEventOrderHead = MouseEventBufSize then MouseEventOrderHead := 0;
  337. Dec (PendingMouseEvents);
  338. end;
  339. procedure SysPutMouseEvent (const MouseEvent: TMouseEvent);
  340. var
  341. QI: TMouQueInfo;
  342. begin
  343. if PendingMouseEvents < MouseEventBufSize then
  344. begin
  345. PendingMouseTail^ := MouseEvent;
  346. Inc (PendingMouseTail);
  347. if longint (PendingMouseTail) = longint (@PendingMouseEvent) +
  348. SizeOf (PendingMouseEvent) then PendingMouseTail := @PendingMouseEvent;
  349. MouGetNumQueEl (QI, Handle);
  350. PendingMouseEventOrder [MouseEventOrderTail] := QI.cEvents;
  351. Inc (MouseEventOrderTail);
  352. if MouseEventOrderTail = MouseEventBufSize then MouseEventOrderTail := 0;
  353. Inc (PendingMouseEvents);
  354. end;
  355. end;
  356. Const
  357. SysMouseDriver : TMouseDriver = (
  358. UseDefaultQueue : False;
  359. InitDriver : @SysInitMouse;
  360. DoneDriver : @SysDoneMouse;
  361. DetectMouse : @SysDetectMouse;
  362. ShowMouse : @SysShowMouse;
  363. HideMouse : @SysHideMouse;
  364. GetMouseX : @SysGetMouseX;
  365. GetMouseY : @SysGetMouseY;
  366. GetMouseButtons : @SysGetMouseButtons;
  367. SetMouseXY : @SysSetMouseXY;
  368. GetMouseEvent : @SysGetMouseEvent;
  369. PollMouseEvent : @SysPollMouseEvent;
  370. PutMouseEvent : @SysPutMouseEvent;
  371. );
  372. Begin
  373. SetMouseDriver(SysMouseDriver);
  374. end.