mouse.pp 11 KB

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