mouse.pp 11 KB

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