mouse.pp 10 KB

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