mouse.pp 9.4 KB

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