mouse.inc 10.0 KB

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