mouse.pp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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,linuxvcs
  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. function detect_xterm_mouse:boolean;
  113. const mouse_terminals:array[0..6] of string[7]=('cons','eterm','gnome',
  114. 'konsole','rxvt','screen',
  115. 'xterm');
  116. var term:string;
  117. i:byte;
  118. begin
  119. detect_xterm_mouse:=true;
  120. term:=fpgetenv('TERM');
  121. for i:=low(mouse_terminals) to high(mouse_terminals) do
  122. if copy(term,1,length(mouse_terminals[i]))=mouse_terminals[i] then
  123. exit;
  124. detect_xterm_mouse:=false;
  125. end;
  126. procedure SysInitMouse;
  127. {$ifndef NOGPM}
  128. var connect:TGPMConnect;
  129. e:Tgpm_event;
  130. {$endif ndef NOGPM}
  131. begin
  132. { if gpm_fs<>-1 then
  133. runerror(240);}
  134. {Test wether to use X-terminals.}
  135. if detect_xterm_mouse then
  136. begin
  137. {Use the xterm mouse.}
  138. gpm_fs:=-2;
  139. write(#27'[?1001s'); { save old hilit tracking }
  140. write(#27'[?1000h'); { enable mouse tracking }
  141. end;
  142. {$ifndef NOGPM}
  143. if (gpm_fs=-1) and (vcs_device<>-1) then
  144. begin
  145. {Use the gpm mouse.}
  146. { open gpm }
  147. connect.EventMask:=GPM_MOVE or GPM_DRAG or GPM_DOWN or GPM_UP;
  148. connect.DefaultMask:=0;
  149. connect.MinMod:=0;
  150. connect.MaxMod:=0;
  151. gpm_fs:=gpm_open(connect,0);
  152. { initialize SysLastMouseEvent }
  153. if gpm_fs<>-1 then
  154. begin
  155. Gpm_GetSnapshot(e);
  156. GPMEvent2MouseEvent(e,SysLastMouseEvent);
  157. end;
  158. end;
  159. {$endif NOGPM}
  160. end;
  161. procedure SysDoneMouse;
  162. begin
  163. if gpm_fs<>-1 then
  164. HideMouse;
  165. if gpm_fs=-2 then
  166. begin
  167. {xterm mouse}
  168. write(#27'[?1000l'); { disable mouse tracking }
  169. write(#27'[?1001r'); { Restore old hilit tracking }
  170. end
  171. {$ifndef NOGPM}
  172. else
  173. gpm_close
  174. {$endif};
  175. gpm_fs:=-1;
  176. end;
  177. function SysDetectMouse:byte;
  178. {$ifndef NOGPM}
  179. var
  180. connect : TGPMConnect;
  181. fds : tFDSet;
  182. e : Tgpm_event;
  183. {$endif ndef NOGPM}
  184. begin
  185. if detect_xterm_mouse then
  186. SysDetectMouse:=2
  187. {$ifndef NOGPM}
  188. else
  189. begin
  190. if gpm_fs=-1 then
  191. begin
  192. connect.EventMask:=GPM_MOVE or GPM_DRAG or GPM_DOWN or GPM_UP;
  193. connect.DefaultMask:=0;
  194. connect.MinMod:=0;
  195. connect.MaxMod:=0;
  196. gpm_fs:=gpm_open(connect,0);
  197. end;
  198. if gpm_fs>=0 then
  199. begin
  200. fpFD_ZERO(fds);
  201. fpFD_SET(gpm_fs,fds);
  202. while fpSelect(gpm_fs+1,@fds,nil,nil,1)>0 do
  203. begin
  204. fillchar(e,sizeof(e),#0);
  205. Gpm_GetEvent(e);
  206. end;
  207. end;
  208. if gpm_fs<>-1 then
  209. SysDetectMouse:=Gpm_GetSnapshot(nil)
  210. else
  211. SysDetectMouse:=0;
  212. end
  213. {$endif NOGPM};
  214. end;
  215. procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
  216. {$ifndef NOGPM}
  217. var
  218. e : Tgpm_event;
  219. {$endif ndef NOGPM}
  220. begin
  221. fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  222. if gpm_fs<0 then
  223. exit;
  224. {$ifndef NOGPM}
  225. Gpm_GetEvent(e);
  226. GPMEvent2MouseEvent(e,MouseEvent);
  227. SysLastMouseEvent:=MouseEvent;
  228. { update mouse cursor }
  229. if PrintMouseCur then
  230. PlaceMouseCur(MouseEvent.y*ScreenWidth+MouseEvent.x);
  231. {$endif ndef NOGPM}
  232. end;
  233. function SysPollMouseEvent(var MouseEvent: TMouseEvent):boolean;
  234. {$ifndef NOGPM}
  235. var
  236. e : Tgpm_event;
  237. fds : tFDSet;
  238. {$endif ndef NOGPM}
  239. begin
  240. fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  241. {$ifndef NOGPM}
  242. if gpm_fs<0 then
  243. exit(false);
  244. if gpm_fs>0 then
  245. begin
  246. fpFD_ZERO(fds);
  247. fpFD_SET(gpm_fs,fds);
  248. end;
  249. if (fpSelect(gpm_fs+1,@fds,nil,nil,1)>0) then
  250. begin
  251. FillChar(e,SizeOf(e),#0);
  252. { Gpm_snapshot does not work here PM }
  253. Gpm_GetEvent(e);
  254. GPMEvent2MouseEvent(e,MouseEvent);
  255. SysLastMouseEvent:=MouseEvent;
  256. if (MouseEvent.Action<>0) then
  257. begin
  258. { As we now use Gpm_GetEvent, we need to put in
  259. in the MouseEvent queue PM }
  260. PutMouseEvent(MouseEvent);
  261. SysPollMouseEvent:=true;
  262. { update mouse cursor is also required here
  263. as next call will read MouseEvent from queue }
  264. if PrintMouseCur then
  265. PlaceMouseCur(MouseEvent.y*ScreenWidth+MouseEvent.x);
  266. end
  267. else
  268. SysPollMouseEvent:=false;
  269. end
  270. else
  271. {$endif NOGPM}
  272. SysPollMouseEvent:=false;
  273. end;
  274. function SysGetMouseX: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. { Remove mouse event, we are only interrested in
  286. the X,Y so all other events can be thrown away }
  287. GetMouseEvent(ME);
  288. SysGetMouseX:=ME.X
  289. end
  290. else
  291. begin
  292. SysGetMouseX:=SysLastMouseEvent.x;
  293. end;
  294. {$endif ndef NOGPM}
  295. end;
  296. function SysGetMouseY:word;
  297. {$ifndef NOGPM}
  298. var
  299. me : TMouseEvent;
  300. {$endif ndef NOGPM}
  301. begin
  302. if gpm_fs<0 then
  303. exit(0);
  304. {$ifndef NOGPM}
  305. if PollMouseEvent(ME) then
  306. begin
  307. { Remove mouse event, we are only interrested in
  308. the X,Y so all other events can be thrown away }
  309. GetMouseEvent(ME);
  310. SysGetMouseY:=ME.Y
  311. end
  312. else
  313. begin
  314. SysGetMouseY:=SysLastMouseEvent.y;
  315. end;
  316. {$endif ndef NOGPM}
  317. end;
  318. procedure SysShowMouse;
  319. var
  320. x,y : word;
  321. begin
  322. PrintMouseCur:=true;
  323. { Wait with showing the cursor until the mouse has moved. Else the
  324. cursor updates will be to quickly }
  325. if WaitMouseMove then
  326. exit;
  327. if (MouseCurOfs>=0) or (gpm_fs=-1) then
  328. PlaceMouseCur(MouseCurOfs)
  329. else
  330. begin
  331. x:=SysGetMouseX;
  332. y:=SysGetMouseY;
  333. if (x<=ScreenWidth) and (y<=ScreenHeight) then
  334. PlaceMouseCur(Y*ScreenWidth+X)
  335. else
  336. PlaceMouseCur(MouseCurOfs);
  337. end;
  338. end;
  339. procedure SysHideMouse;
  340. begin
  341. if (MouseCurOfs>=0) then
  342. PlaceMouseCur(-1);
  343. WaitMouseMove:=true;
  344. PrintMouseCur:=false;
  345. end;
  346. function SysGetMouseButtons:word;
  347. {$ifndef NOGPM}
  348. var
  349. me : TMouseEvent;
  350. {$endif ndef NOGPM}
  351. begin
  352. if gpm_fs<0 then
  353. exit(0);
  354. {$ifndef NOGPM}
  355. if PollMouseEvent(ME) then
  356. begin
  357. { Remove mouse event, we are only interrested in
  358. the buttons so all other events can be thrown away }
  359. GetMouseEvent(ME);
  360. SysGetMouseButtons:=ME.Buttons;
  361. end
  362. else
  363. begin
  364. SysGetMouseButtons:=SysLastMouseEvent.buttons;
  365. end;
  366. {$endif ndef NOGPM}
  367. end;
  368. Const
  369. SysMouseDriver : TMouseDriver = (
  370. UseDefaultQueue : true;
  371. InitDriver : @SysInitMouse;
  372. DoneDriver : @SysDoneMouse;
  373. DetectMouse : @SysDetectMouse;
  374. ShowMouse : @SysShowMouse;
  375. HideMouse : @SysHideMouse;
  376. GetMouseX : @SysGetMouseX;
  377. GetMouseY : @SysGetMouseY;
  378. GetMouseButtons : @SysGetMouseButtons;
  379. SetMouseXY : Nil;
  380. GetMouseEvent : @SysGetMouseEvent;
  381. PollMouseEvent : @SysPollMouseEvent;
  382. PutMouseEvent : Nil;
  383. );
  384. {$else ifndef NOMOUSE}
  385. Const
  386. SysMouseDriver : TMouseDriver = (
  387. UseDefaultQueue : true;
  388. InitDriver : Nil;
  389. DoneDriver : Nil;
  390. DetectMouse : Nil;
  391. ShowMouse : Nil;
  392. HideMouse : Nil;
  393. GetMouseX : Nil;
  394. GetMouseY : Nil;
  395. GetMouseButtons : Nil;
  396. SetMouseXY : Nil;
  397. GetMouseEvent : Nil;
  398. PollMouseEvent : Nil;
  399. PutMouseEvent : Nil;
  400. );
  401. {$endif}
  402. Begin
  403. SetMouseDriver(SysMouseDriver);
  404. end.