sysmousetest.pas 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. Program Sysmousetest;
  2. {
  3. $Id$
  4. This program is part of the FPC demoes.
  5. Copyright (C) 2000 by Marco van de Voort
  6. Originally for a FPC on FreeBSD article in a 2000 edition of
  7. the German magazine FreeX
  8. A test for sysmouse. Moused must be loaded. Maybe works in xterm too if
  9. X Windows is configured to use sysmouse.
  10. See the file COPYING.FPC, included in this distribution,
  11. for details about the copyright.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. **********************************************************************}
  16. Uses BaseUnix,Unix,Console;
  17. CONST STDIN=0;
  18. TYPE ActionType=(click,paste);
  19. procedure Window1Handler(X,Y:LONGINT;Action:ActionType);
  20. begin
  21. IF Action=Click THEN
  22. Writeln('Click in Window 1, relative coordinates: ',X,':',Y)
  23. ELSE
  24. Writeln('Paste in Window 1, relative coordinates: ',X,':',Y);
  25. end;
  26. procedure Window2Handler(X,Y:LONGINT;Action:ActionType);
  27. begin
  28. IF Action=Click THEN
  29. Writeln('Click in Window 2, relative coordinates: ',X,':',Y)
  30. ELSE
  31. Writeln('Paste in Window 2, relative coordinates: ',X,':',Y);
  32. end;
  33. procedure Window3Handler(X,Y:LONGINT;Action:ActionType);
  34. begin
  35. IF Action=Click THEN
  36. Writeln('Click in Window 3, relative coordinates: ',X,':',Y)
  37. ELSE
  38. Writeln('Paste in Window 3, relative coordinates: ',X,':',Y);
  39. end;
  40. procedure Window4Handler(X,Y:LONGINT;Action:ActionType);
  41. begin
  42. IF Action=Click THEN
  43. Writeln('Click in Window 4, relative coordinates: ',X,':',Y)
  44. ELSE
  45. Writeln('Paste in Window 4, relative coordinates: ',X,':',Y);
  46. end;
  47. {Of course in a real window manager, all this would be more dynamic (so you
  48. can change windows, and have them stacked. }
  49. TYPE WindowHandlerProc = procedure (X,Y:longint;Action:ActionType);
  50. WindowListType = ARRAY[1..4] OF WindowHandlerProc;
  51. CONST WindowList : WindowListType=(@Window1Handler,@Window2Handler,
  52. @Window3Handler,@Window4Handler);
  53. var cwidth,cheight : longint; {Dimensions of a char cell.
  54. For pixels to chars}
  55. xpos,ypos,buttons : longint; {Location and type of last mouseclick}
  56. Focus : Longint; {Quarter of screen that has focus now}
  57. TermApp : Boolean;
  58. {
  59. * Signal handler for SIGUSR2: Retrieves mouse coordinates; converts pixels
  60. * to rows and columns.
  61. }
  62. procedure Sysmousehandler(Sig:Longint);cdecl; {IMPORTANT! call back has C calling convention}
  63. var mi : MOUSE_INFO;
  64. fd : longint;
  65. begin
  66. fd:=STDIN;
  67. mi.operation := MOUSE_GETINFO;
  68. IF NOT CONS_MOUSECTL(fd, mi) THEN
  69. {Mouse call failed, don't update vars}
  70. exit;
  71. xpos := mi.u.data.x;
  72. ypos := mi.u.data.y;
  73. buttons := mi.u.data.buttons and 7;
  74. end;
  75. procedure StartMouse;
  76. {initialise the mouse and determine the sizes of a standard character cell}
  77. var
  78. mi : mouse_info_t;
  79. vi : video_info_t;
  80. fd : longint;
  81. begin
  82. fd:=longint(stdin);
  83. if FBIO_GETMODE(fd,vi.vi_mode) AND FBIO_MODEINFO(fd,vi) then
  84. begin
  85. cwidth:=vi.vi_cwidth;
  86. cheight:=vi.vi_cheight;
  87. Writeln('Dimensions of a character cell (width :height) :',Cwidth,':',cheight);
  88. end;
  89. {ignore SIGUSR2 for a while, otherwise moving the mouse before handler
  90. installation will terminate the application}
  91. fpSignal(SIGUSR2,SignalHandler(SIG_IGN));
  92. { Have sysmouse send us SIGUSR2 for mouse state changes. }
  93. mi.operation := _MOUSE_MODE; { Note: underscore added!}
  94. mi.u.mode.mode := 0;
  95. mi.u.mode.signal := SIGUSR2;
  96. {If successful, register signal handler}
  97. if CONS_MOUSECTL(fd,mi) then
  98. begin
  99. { Connect SIGUSR2 to our (C calling convention!) mousehandler}
  100. fpsignal(SIGUSR2, @SysmouseHandler);
  101. {show mouse}
  102. mi.operation := MOUSE_SHOW;
  103. CONS_MOUSECTL(fd, mi);
  104. exit;
  105. end;
  106. end;
  107. procedure myhandler(x,y,but :longint);
  108. VAR WindowNr : Longint;
  109. begin
  110. {Upper left 2x2 character cell block terminates program}
  111. if (X<3) AND (Y<3) then
  112. begin
  113. TermApp:=TRUE;
  114. EXIT;
  115. end;
  116. {The screen is divided in four windows and are numbered as follows:
  117. 1|2
  118. ---
  119. 3|4}
  120. if (x<=40) then
  121. WindowNr:=1
  122. else
  123. WindowNr:=2;
  124. IF Y>12 THEN
  125. INC(WindowNr,2);
  126. IF WindowNr=Focus THEN
  127. BEGIN
  128. {This window already has focus. Normalise coordinates and
  129. pass the event to the window}
  130. IF X>40 THEN Dec(X,40);
  131. IF Y>12 THEN Dec(Y,12);
  132. IF (But and 1)=1 THEN
  133. WindowList[WindowNr](x,y,click)
  134. else
  135. IF (But and 4)=4 THEN
  136. WindowList[WindowNr](x,y,paste)
  137. else
  138. Writeln('I only have a two button mouse, so this one does nothing');
  139. END
  140. else
  141. BEGIN
  142. Writeln('Main handler is changing focus from to window',WindowNr);
  143. Focus:=WindowNr;
  144. end;
  145. end;
  146. procedure WaitForEvent;
  147. {
  148. * Wait in select() loop. If interrupted, check for mouse button press and
  149. * construct a minimal gpm pseudo-event and call MouseHandler(). Otherwise
  150. * hand over to wgetch().
  151. }
  152. var rfds : tsigset;
  153. begin
  154. fpsigemptyset(rfds);
  155. fpsigaddset(rfds,STDIN);
  156. while fpselect(1, @rfds,nil,nil,nil)<=0 DO
  157. begin
  158. IF TermApp THEN Exit;
  159. if (fpgeterrno= ESYSEINTR) AND (buttons<>0) THEN
  160. MyHandler ((xpos DIV cwidth)+1,(ypos DIV cheight)+1,buttons);
  161. end;
  162. end;
  163. begin
  164. // if physicalconsole(0) then
  165. // begin
  166. {Don't want to use ncurses, to easier link static}
  167. Write(#27'[?1001s'); { save old hilight tracking }
  168. Write(#27'[?1000h'); { enable mouse tracking }
  169. for cwidth:=1 to 25 DO Writeln;
  170. Writeln('Sysmouse demo, click upper-left corner to exit this program');
  171. Writeln;
  172. Writeln('Sysmouse implements a very simple mouse event driven windowing program');
  173. Writeln('The 4 quadrants of the screen act as windows, and focus is implemented');
  174. Writeln('Try to click (left or right) the different quadrants, and see what happens');
  175. Writeln;
  176. cwidth := 8; cheight := 16;
  177. Focus:=0;
  178. StartMouse;
  179. TermApp:=FALSE;
  180. while not TermApp do WaitForEvent;
  181. // end
  182. //else
  183. // Writeln('This program must be run from the physical console, not over telnet or under X');
  184. end.
  185. {
  186. $Log$
  187. Revision 1.1 2005-04-19 13:01:59 marco
  188. * sysmousetest for FreeBSD
  189. }