2
0

mouse.pp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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. e : TGPMEvent;
  172. connect : TGPMConnect;
  173. {$endif ndef NOGPM}
  174. begin
  175. {$ifndef NOGPM}
  176. if gpm_fs=-1 then
  177. begin
  178. connect.EventMask:=GPM_MOVE or GPM_DRAG or GPM_DOWN or GPM_UP;
  179. connect.DefaultMask:=0;
  180. connect.MinMod:=0;
  181. connect.MaxMod:=0;
  182. gpm_fs:=Gpm_Open(connect,0);
  183. if (gpm_fs=-2) and (fpgetenv('TERM')<>'xterm') then
  184. begin
  185. Gpm_Close;
  186. gpm_fs:=-1;
  187. end;
  188. end;
  189. { always a mouse deamon present }
  190. if gpm_fs<>-1 then
  191. begin
  192. x:=Gpm_GetSnapshot(e);
  193. GPMEvent2MouseEvent(e,SysLastMouseEvent);
  194. if x<>-1 then
  195. SysDetectMouse:=x
  196. else
  197. SysDetectMouse:=2;
  198. end
  199. else
  200. SysDetectMouse:=0;
  201. {$else ifdef NOGPM}
  202. if (fpgetenv('TERM')='xterm') then
  203. SysDetectMouse:=2;
  204. {$endif NOGPM}
  205. end;
  206. function SysGetMouseX:word;
  207. {$ifndef NOGPM}
  208. var
  209. me : TMouseEvent;
  210. {$endif ndef NOGPM}
  211. begin
  212. if gpm_fs<0 then
  213. exit(0);
  214. {$ifndef NOGPM}
  215. if PollMouseEvent(ME) then
  216. begin
  217. GetMouseEvent(ME);
  218. SysGetMouseX:=ME.X
  219. end
  220. else
  221. begin
  222. SysGetMouseX:=SysLastMouseEvent.x;
  223. end;
  224. {$endif ndef NOGPM}
  225. end;
  226. function SysGetMouseY:word;
  227. {$ifndef NOGPM}
  228. var
  229. me : TMouseEvent;
  230. {$endif ndef NOGPM}
  231. begin
  232. if gpm_fs<0 then
  233. exit(0);
  234. {$ifndef NOGPM}
  235. if PollMouseEvent(ME) then
  236. begin
  237. GetMouseEvent(ME);
  238. SysGetMouseY:=ME.Y
  239. end
  240. else
  241. begin
  242. SysGetMouseY:=SysLastMouseEvent.y;
  243. end;
  244. {$endif ndef NOGPM}
  245. end;
  246. procedure SysShowMouse;
  247. var
  248. x,y : word;
  249. begin
  250. PrintMouseCur:=true;
  251. { Wait with showing the cursor until the mouse has moved. Else the
  252. cursor updates will be to quickly }
  253. if WaitMouseMove then
  254. exit;
  255. if (MouseCurOfs>=0) or (gpm_fs=-1) then
  256. PlaceMouseCur(MouseCurOfs)
  257. else
  258. begin
  259. x:=SysGetMouseX;
  260. y:=SysGetMouseY;
  261. if (x<=ScreenWidth) and (y<=ScreenHeight) then
  262. PlaceMouseCur(Y*ScreenWidth+X)
  263. else
  264. PlaceMouseCur(MouseCurOfs);
  265. end;
  266. end;
  267. procedure SysHideMouse;
  268. begin
  269. if (MouseCurOfs>=0) then
  270. PlaceMouseCur(-1);
  271. WaitMouseMove:=true;
  272. PrintMouseCur:=false;
  273. end;
  274. function SysGetMouseButtons:word;
  275. {$ifndef NOGPM}
  276. var
  277. me : TMouseEvent;
  278. {$endif ndef NOGPM}
  279. begin
  280. if gpm_fs<0 then
  281. exit(0);
  282. {$ifndef NOGPM}
  283. if PollMouseEvent(ME) then
  284. begin
  285. // why should we remove that event ?? PM
  286. // GetMouseEvent(ME);
  287. SysGetMouseButtons:=ME.buttons
  288. end
  289. else
  290. begin
  291. SysGetMouseButtons:=SysLastMouseEvent.Buttons;
  292. end;
  293. {$endif ndef NOGPM}
  294. end;
  295. procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
  296. {$ifndef NOGPM}
  297. var
  298. e : TGPMEvent;
  299. {$endif ndef NOGPM}
  300. begin
  301. fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  302. if gpm_fs<0 then
  303. exit;
  304. {$ifndef NOGPM}
  305. Gpm_GetEvent(e);
  306. GPMEvent2MouseEvent(e,MouseEvent);
  307. SysLastMouseEvent:=MouseEvent;
  308. { update mouse cursor }
  309. if PrintMouseCur then
  310. PlaceMouseCur(MouseEvent.y*ScreenWidth+MouseEvent.x);
  311. {$endif ndef NOGPM}
  312. end;
  313. function SysPollMouseEvent(var MouseEvent: TMouseEvent):boolean;
  314. {$ifndef NOGPM}
  315. var
  316. e : TGPMEvent;
  317. fds : tFDSet;
  318. {$endif ndef NOGPM}
  319. begin
  320. fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  321. {$ifndef NOGPM}
  322. if gpm_fs<0 then
  323. exit(false);
  324. if gpm_fs>0 then
  325. begin
  326. fpFD_ZERO(fds);
  327. fpFD_SET(gpm_fs,fds);
  328. end;
  329. if (fpSelect(gpm_fs+1,@fds,nil,nil,1)>0) then
  330. begin
  331. FillChar(e,SizeOf(e),#0);
  332. { Gpm_snapshot does not work here PM }
  333. Gpm_GetEvent(e);
  334. GPMEvent2MouseEvent(e,MouseEvent);
  335. SysLastMouseEvent:=MouseEvent;
  336. if (MouseEvent.Action<>0) then
  337. begin
  338. { As we now use Gpm_GetEvent, we need to put in
  339. in the MouseEvent queue PM }
  340. PutMouseEvent(MouseEvent);
  341. SysPollMouseEvent:=true;
  342. { update mouse cursor is also required here
  343. as next call will read MouseEvent from queue }
  344. if PrintMouseCur then
  345. PlaceMouseCur(MouseEvent.y*ScreenWidth+MouseEvent.x);
  346. end
  347. else
  348. SysPollMouseEvent:=false;
  349. end
  350. else
  351. {$endif NOGPM}
  352. SysPollMouseEvent:=false;
  353. end;
  354. Const
  355. SysMouseDriver : TMouseDriver = (
  356. UseDefaultQueue : true;
  357. InitDriver : @SysInitMouse;
  358. DoneDriver : @SysDoneMouse;
  359. DetectMouse : @SysDetectMouse;
  360. ShowMouse : @SysShowMouse;
  361. HideMouse : @SysHideMouse;
  362. GetMouseX : @SysGetMouseX;
  363. GetMouseY : @SysGetMouseY;
  364. GetMouseButtons : @SysGetMouseButtons;
  365. SetMouseXY : Nil;
  366. GetMouseEvent : @SysGetMouseEvent;
  367. PollMouseEvent : @SysPollMouseEvent;
  368. PutMouseEvent : Nil;
  369. );
  370. {$else ifndef NOMOUSE}
  371. Const
  372. SysMouseDriver : TMouseDriver = (
  373. UseDefaultQueue : true;
  374. InitDriver : Nil;
  375. DoneDriver : Nil;
  376. DetectMouse : Nil;
  377. ShowMouse : Nil;
  378. HideMouse : Nil;
  379. GetMouseX : Nil;
  380. GetMouseY : Nil;
  381. GetMouseButtons : Nil;
  382. SetMouseXY : Nil;
  383. GetMouseEvent : Nil;
  384. PollMouseEvent : Nil;
  385. PutMouseEvent : Nil;
  386. );
  387. {$endif}
  388. Begin
  389. SetMouseDriver(SysMouseDriver);
  390. end.
  391. {
  392. $Log$
  393. Revision 1.12 2003-10-24 18:09:56 marco
  394. * 1.0.x fixes merged
  395. Revision 1.11 2003/09/16 16:13:56 marco
  396. * fdset functions renamed to fp<posix name>
  397. Revision 1.10 2003/09/14 20:15:01 marco
  398. * Unix reform stage two. Remove all calls from Unix that exist in Baseunix.
  399. Revision 1.9 2002/10/14 18:37:15 peter
  400. * use Unix unit
  401. Revision 1.8 2002/09/15 17:52:30 peter
  402. * Updates from the fixes branch
  403. Revision 1.2.2.9 2002/09/11 06:49:59 pierre
  404. * use gpm_fs in FD_SET
  405. Revision 1.2.2.8 2002/09/02 13:48:48 pierre
  406. * mouse event for consoles hopefully fixed
  407. }