mouse.pp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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. {$ifdef NOMOUSE}
  16. {$DEFINE NOGPM}
  17. {$ENDIF}
  18. {$i mouseh.inc}
  19. implementation
  20. uses
  21. BaseUnix,Video
  22. {$ifndef NOGPM}
  23. ,gpm
  24. {$endif ndef NOGPM}
  25. ;
  26. {$i mouse.inc}
  27. {$ifndef NOMOUSE}
  28. const
  29. WaitMouseMove : boolean = false;
  30. PrintMouseCur : boolean = false;
  31. mousecurofs : longint = -1;
  32. var
  33. mousecurcell : TVideoCell;
  34. SysLastMouseEvent : TMouseEvent;
  35. const
  36. gpm_fs : longint = -1;
  37. {$ifndef NOGPM}
  38. procedure GPMEvent2MouseEvent(const e:TGPMEvent;var mouseevent:tmouseevent);
  39. var
  40. PrevButtons : byte;
  41. begin
  42. PrevButtons:=SysLastMouseEvent.Buttons;
  43. if e.x>0 then
  44. mouseevent.x:=e.x-1
  45. else
  46. MouseEvent.x:=0;
  47. if e.y>0 then
  48. MouseEvent.y:=e.y-1
  49. else
  50. MouseEvent.y:=0;
  51. MouseEvent.buttons:=0;
  52. if e.buttons and Gpm_b_left<>0 then
  53. inc(MouseEvent.buttons,1);
  54. if e.buttons and Gpm_b_right<>0 then
  55. inc(MouseEvent.buttons,2);
  56. if e.buttons and Gpm_b_middle<>0 then
  57. inc(MouseEvent.buttons,4);
  58. case (e.EventType and $f) of
  59. GPM_MOVE,
  60. GPM_DRAG :
  61. begin
  62. MouseEvent.Action:=MouseActionMove;
  63. WaitMouseMove:=false;
  64. end;
  65. GPM_DOWN :
  66. begin
  67. MouseEvent.Action:=MouseActionDown;
  68. WaitMouseMove:=false;
  69. end;
  70. GPM_UP :
  71. begin
  72. { gpm apparently sends the button that is left up
  73. while mouse unit expects the button state after
  74. the button was released PM }
  75. if MouseEvent.Buttons<>0 then
  76. begin
  77. MouseEvent.Buttons:=MouseEvent.Buttons xor PrevButtons;
  78. MouseEvent.Action:=MouseActionUp;
  79. end
  80. { this does probably never happen...
  81. but its just a security PM }
  82. else
  83. MouseEvent.Action:=MouseActionMove;
  84. WaitMouseMove:=false;
  85. end;
  86. else
  87. MouseEvent.Action:=0;
  88. end;
  89. end;
  90. {$ENDIF}
  91. procedure PlaceMouseCur(ofs:longint);
  92. var
  93. upd : boolean;
  94. begin
  95. if (VideoBuf=nil) or (MouseCurOfs=Ofs) then
  96. exit;
  97. upd:=false;
  98. if (MouseCurOfs<>-1) and (VideoBuf^[MouseCurOfs]=MouseCurCell) then
  99. begin
  100. VideoBuf^[MouseCurOfs]:=MouseCurCell xor $7f00;
  101. upd:=true;
  102. end;
  103. MouseCurOfs:=ofs;
  104. if (MouseCurOfs<>-1) then
  105. begin
  106. MouseCurCell:=VideoBuf^[MouseCurOfs] xor $7f00;
  107. VideoBuf^[MouseCurOfs]:=MouseCurCell;
  108. upd:=true;
  109. end;
  110. if upd then
  111. Updatescreen(false);
  112. end;
  113. procedure SysInitMouse;
  114. {$ifndef NOGPM}
  115. var
  116. connect : TGPMConnect;
  117. E : TGPMEvent;
  118. {$endif ndef NOGPM}
  119. begin
  120. {$ifndef NOGPM}
  121. if gpm_fs=-1 then
  122. begin
  123. { open gpm }
  124. connect.EventMask:=GPM_MOVE or GPM_DRAG or GPM_DOWN or GPM_UP;
  125. connect.DefaultMask:=0;
  126. connect.MinMod:=0;
  127. connect.MaxMod:=0;
  128. gpm_fs:=Gpm_Open(connect,0);
  129. if (gpm_fs=-2) and (fpgetenv('TERM')<>'xterm') then
  130. begin
  131. gpm_fs:=-1;
  132. Gpm_Close;
  133. end;
  134. { initialize SysLastMouseEvent }
  135. if gpm_fs<>-1 then
  136. begin
  137. Gpm_GetSnapshot(e);
  138. GPMEvent2MouseEvent(e,SysLastMouseEvent);
  139. end;
  140. end;
  141. { show mousepointer }
  142. if gpm_fs<>-1 then
  143. ShowMouse;
  144. {$else ifdef NOGPM}
  145. if (fpgetenv('TERM')='xterm') then
  146. begin
  147. gpm_fs:=-2;
  148. Write(#27'[?1001s'); { save old hilit tracking }
  149. Write(#27'[?1000h'); { enable mouse tracking }
  150. end;
  151. {$endif NOGPM}
  152. end;
  153. procedure SysDoneMouse;
  154. begin
  155. If gpm_fs<>-1 then
  156. begin
  157. HideMouse;
  158. {$ifndef NOGPM}
  159. Gpm_Close;
  160. {$else ifdef NOGPM}
  161. Write(#27'[?1000l'); { disable mouse tracking }
  162. Write(#27'[?1001r'); { Restore old hilit tracking }
  163. {$endif ifdef NOGPM}
  164. gpm_fs:=-1;
  165. end;
  166. end;
  167. function SysDetectMouse:byte;
  168. {$ifndef NOGPM}
  169. var
  170. x : longint;
  171. connect : TGPMConnect;
  172. {$endif ndef NOGPM}
  173. begin
  174. {$ifndef NOGPM}
  175. if gpm_fs=-1 then
  176. begin
  177. connect.EventMask:=GPM_MOVE or GPM_DRAG or GPM_DOWN or GPM_UP;
  178. connect.DefaultMask:=0;
  179. connect.MinMod:=0;
  180. connect.MaxMod:=0;
  181. gpm_fs:=Gpm_Open(connect,0);
  182. if (gpm_fs=-2) and (fpgetenv('TERM')<>'xterm') then
  183. begin
  184. Gpm_Close;
  185. gpm_fs:=-1;
  186. end;
  187. end;
  188. { always a mouse deamon present }
  189. if gpm_fs<>-1 then
  190. SysDetectMouse:=Gpm_GetSnapshot(nil)
  191. else
  192. SysDetectMouse:=0;
  193. {$else ifdef NOGPM}
  194. if (fpgetenv('TERM')='xterm') then
  195. SysDetectMouse:=2;
  196. {$endif NOGPM}
  197. end;
  198. function SysGetMouseX:word;
  199. {$ifndef NOGPM}
  200. var
  201. me : TMouseEvent;
  202. {$endif ndef NOGPM}
  203. begin
  204. if gpm_fs<0 then
  205. exit(0);
  206. {$ifndef NOGPM}
  207. if PollMouseEvent(ME) then
  208. begin
  209. GetMouseEvent(ME);
  210. SysGetMouseX:=ME.X
  211. end
  212. else
  213. begin
  214. SysGetMouseX:=SysLastMouseEvent.x;
  215. end;
  216. {$endif ndef NOGPM}
  217. end;
  218. function SysGetMouseY:word;
  219. {$ifndef NOGPM}
  220. var
  221. me : TMouseEvent;
  222. {$endif ndef NOGPM}
  223. begin
  224. if gpm_fs<0 then
  225. exit(0);
  226. {$ifndef NOGPM}
  227. if PollMouseEvent(ME) then
  228. begin
  229. GetMouseEvent(ME);
  230. SysGetMouseY:=ME.Y
  231. end
  232. else
  233. begin
  234. SysGetMouseY:=SysLastMouseEvent.y;
  235. end;
  236. {$endif ndef NOGPM}
  237. end;
  238. procedure SysShowMouse;
  239. var
  240. x,y : word;
  241. begin
  242. PrintMouseCur:=true;
  243. { Wait with showing the cursor until the mouse has moved. Else the
  244. cursor updates will be to quickly }
  245. if WaitMouseMove then
  246. exit;
  247. if (MouseCurOfs>=0) or (gpm_fs=-1) then
  248. PlaceMouseCur(MouseCurOfs)
  249. else
  250. begin
  251. x:=SysGetMouseX;
  252. y:=SysGetMouseY;
  253. if (x<=ScreenWidth) and (y<=ScreenHeight) then
  254. PlaceMouseCur(Y*ScreenWidth+X)
  255. else
  256. PlaceMouseCur(MouseCurOfs);
  257. end;
  258. end;
  259. procedure SysHideMouse;
  260. begin
  261. if (MouseCurOfs>=0) then
  262. PlaceMouseCur(-1);
  263. WaitMouseMove:=true;
  264. PrintMouseCur:=false;
  265. end;
  266. function SysGetMouseButtons:word;
  267. {$ifndef NOGPM}
  268. var
  269. me : TMouseEvent;
  270. {$endif ndef NOGPM}
  271. begin
  272. if gpm_fs<0 then
  273. exit(0);
  274. {$ifndef NOGPM}
  275. if PollMouseEvent(ME) then
  276. begin
  277. // why should we remove that event ?? PM
  278. // GetMouseEvent(ME);
  279. SysGetMouseButtons:=ME.buttons
  280. end
  281. else
  282. begin
  283. SysGetMouseButtons:=SysLastMouseEvent.Buttons;
  284. end;
  285. {$endif ndef NOGPM}
  286. end;
  287. procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
  288. {$ifndef NOGPM}
  289. var
  290. e : TGPMEvent;
  291. {$endif ndef NOGPM}
  292. begin
  293. fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  294. if gpm_fs<0 then
  295. exit;
  296. {$ifndef NOGPM}
  297. Gpm_GetEvent(e);
  298. GPMEvent2MouseEvent(e,MouseEvent);
  299. SysLastMouseEvent:=MouseEvent;
  300. { update mouse cursor }
  301. if PrintMouseCur then
  302. PlaceMouseCur(MouseEvent.y*ScreenWidth+MouseEvent.x);
  303. {$endif ndef NOGPM}
  304. end;
  305. function SysPollMouseEvent(var MouseEvent: TMouseEvent):boolean;
  306. {$ifndef NOGPM}
  307. var
  308. e : TGPMEvent;
  309. fds : tFDSet;
  310. {$endif ndef NOGPM}
  311. begin
  312. fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  313. {$ifndef NOGPM}
  314. if gpm_fs<0 then
  315. exit(false);
  316. if gpm_fs>0 then
  317. begin
  318. fpFD_ZERO(fds);
  319. fpFD_SET(gpm_fs,fds);
  320. end;
  321. if (fpSelect(gpm_fs+1,@fds,nil,nil,1)>0) then
  322. begin
  323. FillChar(e,SizeOf(e),#0);
  324. { Gpm_snapshot does not work here PM }
  325. Gpm_GetEvent(e);
  326. GPMEvent2MouseEvent(e,MouseEvent);
  327. SysLastMouseEvent:=MouseEvent;
  328. if (MouseEvent.Action<>0) then
  329. begin
  330. { As we now use Gpm_GetEvent, we need to put in
  331. in the MouseEvent queue PM }
  332. PutMouseEvent(MouseEvent);
  333. SysPollMouseEvent:=true;
  334. { update mouse cursor is also required here
  335. as next call will read MouseEvent from queue }
  336. if PrintMouseCur then
  337. PlaceMouseCur(MouseEvent.y*ScreenWidth+MouseEvent.x);
  338. end
  339. else
  340. SysPollMouseEvent:=false;
  341. end
  342. else
  343. {$endif NOGPM}
  344. SysPollMouseEvent:=false;
  345. end;
  346. Const
  347. SysMouseDriver : TMouseDriver = (
  348. UseDefaultQueue : true;
  349. InitDriver : @SysInitMouse;
  350. DoneDriver : @SysDoneMouse;
  351. DetectMouse : @SysDetectMouse;
  352. ShowMouse : @SysShowMouse;
  353. HideMouse : @SysHideMouse;
  354. GetMouseX : @SysGetMouseX;
  355. GetMouseY : @SysGetMouseY;
  356. GetMouseButtons : @SysGetMouseButtons;
  357. SetMouseXY : Nil;
  358. GetMouseEvent : @SysGetMouseEvent;
  359. PollMouseEvent : @SysPollMouseEvent;
  360. PutMouseEvent : Nil;
  361. );
  362. {$else ifndef NOMOUSE}
  363. Const
  364. SysMouseDriver : TMouseDriver = (
  365. UseDefaultQueue : true;
  366. InitDriver : Nil;
  367. DoneDriver : Nil;
  368. DetectMouse : Nil;
  369. ShowMouse : Nil;
  370. HideMouse : Nil;
  371. GetMouseX : Nil;
  372. GetMouseY : Nil;
  373. GetMouseButtons : Nil;
  374. SetMouseXY : Nil;
  375. GetMouseEvent : Nil;
  376. PollMouseEvent : Nil;
  377. PutMouseEvent : Nil;
  378. );
  379. {$endif}
  380. Begin
  381. SetMouseDriver(SysMouseDriver);
  382. end.
  383. {
  384. $Log$
  385. Revision 1.13 2004-11-03 16:51:05 peter
  386. * fixed valgrind issues
  387. Revision 1.12 2003/10/24 18:09:56 marco
  388. * 1.0.x fixes merged
  389. Revision 1.11 2003/09/16 16:13:56 marco
  390. * fdset functions renamed to fp<posix name>
  391. Revision 1.10 2003/09/14 20:15:01 marco
  392. * Unix reform stage two. Remove all calls from Unix that exist in Baseunix.
  393. Revision 1.9 2002/10/14 18:37:15 peter
  394. * use Unix unit
  395. Revision 1.8 2002/09/15 17:52:30 peter
  396. * Updates from the fixes branch
  397. Revision 1.2.2.9 2002/09/11 06:49:59 pierre
  398. * use gpm_fs in FD_SET
  399. Revision 1.2.2.8 2002/09/02 13:48:48 pierre
  400. * mouse event for consoles hopefully fixed
  401. }