summaryrefslogtreecommitdiff
path: root/demo/freebsd/sysmousetest.pas
blob: 7b2d34504143ab25f78f150dbacc3ce82f7470a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
Program Sysmousetest;
{

    This program is part of the FPC demoes.
    Copyright (C) 2000 by Marco van de Voort
    Originally for a FPC on FreeBSD article in a 2000 edition of
    the German magazine FreeX
  
    A test for sysmouse. Moused must be loaded. Maybe works in xterm too if
    X Windows is configured to use sysmouse.

    See the file COPYING.FPC, included in this distribution,
    for details about the copyright.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

 **********************************************************************}

Uses BaseUnix,Unix,Console;

CONST STDIN=0;

TYPE ActionType=(click,paste);

procedure Window1Handler(X,Y:LONGINT;Action:ActionType);

begin
  IF Action=Click THEN
   Writeln('Click in Window 1, relative coordinates: ',X,':',Y)
  ELSE
   Writeln('Paste in Window 1, relative coordinates: ',X,':',Y);
end;

procedure Window2Handler(X,Y:LONGINT;Action:ActionType);

begin
  IF Action=Click THEN
   Writeln('Click in Window 2, relative coordinates: ',X,':',Y)
  ELSE
   Writeln('Paste in Window 2, relative coordinates: ',X,':',Y);
end;

procedure Window3Handler(X,Y:LONGINT;Action:ActionType);

begin
  IF Action=Click THEN
   Writeln('Click in Window 3, relative coordinates: ',X,':',Y)
  ELSE
   Writeln('Paste in Window 3, relative coordinates: ',X,':',Y);
end;

procedure Window4Handler(X,Y:LONGINT;Action:ActionType);

begin
  IF Action=Click THEN
   Writeln('Click in Window 4, relative coordinates: ',X,':',Y)
  ELSE
   Writeln('Paste in Window 4, relative coordinates: ',X,':',Y);
end;

{Of course in a real window manager, all this would be more dynamic (so you
can change windows, and have them stacked. }

TYPE WindowHandlerProc = procedure (X,Y:longint;Action:ActionType);
     WindowListType    = ARRAY[1..4] OF WindowHandlerProc;

CONST WindowList : WindowListType=(@Window1Handler,@Window2Handler,
  	  	   @Window3Handler,@Window4Handler);

var cwidth,cheight    : longint; {Dimensions of a char cell. 
				   For pixels to chars}
    xpos,ypos,buttons : longint; {Location and type of last mouseclick}
    Focus	      : Longint; {Quarter of screen that has focus now}
    TermApp	      : Boolean;

{
 * Signal handler for SIGUSR2: Retrieves mouse coordinates; converts pixels
 * to rows and columns.
 }
procedure Sysmousehandler(Sig:Longint);cdecl;	{IMPORTANT!  call back has C calling convention}

var mi : MOUSE_INFO;
    fd : longint;
begin
        fd:=STDIN;
	mi.operation := MOUSE_GETINFO;
	IF NOT CONS_MOUSECTL(fd, mi) THEN 
        {Mouse call failed, don't update vars}
	 exit;			
		
	xpos := mi.u.data.x;
	ypos := mi.u.data.y;
	buttons := mi.u.data.buttons and 7;
end;	

procedure StartMouse;
{initialise the mouse and determine the sizes of a standard character cell}

var
	mi : mouse_info_t;
	vi : video_info_t;
	fd : longint;
	
begin 
  fd:=longint(stdin);	
  if FBIO_GETMODE(fd,vi.vi_mode) AND FBIO_MODEINFO(fd,vi) then
   begin   
    cwidth:=vi.vi_cwidth;   
    cheight:=vi.vi_cheight;
    Writeln('Dimensions of a character cell (width :height) :',Cwidth,':',cheight);
   end;

  {ignore SIGUSR2 for a while, otherwise moving the mouse before handler
    installation will terminate the application}
  
  fpSignal(SIGUSR2,SignalHandler(SIG_IGN));
  
 { Have sysmouse send us SIGUSR2 for mouse state changes. }

  mi.operation := _MOUSE_MODE; { Note: underscore added!}
  mi.u.mode.mode := 0;
  mi.u.mode.signal := SIGUSR2;

  {If successful, register signal handler}

  if CONS_MOUSECTL(fd,mi) then
   begin 
    { Connect SIGUSR2 to our (C calling convention!) mousehandler}

    fpsignal(SIGUSR2, @SysmouseHandler);

    {show mouse}
    mi.operation := MOUSE_SHOW;
    CONS_MOUSECTL(fd, mi);
    exit;
   end;
end;
	

procedure myhandler(x,y,but :longint);

VAR WindowNr : Longint;

begin
 {Upper left 2x2 character cell block terminates program}
 if (X<3) AND (Y<3) then
  begin
   TermApp:=TRUE;
   EXIT;
  end;
    {The screen is divided in four windows and are numbered as follows:

		   1|2
		   ---
		   3|4}

   if (x<=40) then
    WindowNr:=1
   else
    WindowNr:=2;
  IF Y>12 THEN
   INC(WindowNr,2);

  IF WindowNr=Focus THEN
   BEGIN
      {This window already has focus. Normalise coordinates and
	pass the event to the window}
     IF X>40 THEN Dec(X,40);
     IF Y>12 THEN Dec(Y,12);
    IF (But and 1)=1 THEN
     WindowList[WindowNr](x,y,click)
    else
     IF (But and 4)=4 THEN
      WindowList[WindowNr](x,y,paste)
    else
     Writeln('I only have a two button mouse, so this one does nothing');
  END
 else
  BEGIN
   Writeln('Main handler is changing focus from to window',WindowNr);
   Focus:=WindowNr;
  end;
end;

procedure WaitForEvent; 
{
 * Wait in select() loop.  If interrupted, check for mouse button press and
 * construct a minimal gpm pseudo-event and call MouseHandler(). Otherwise
 * hand over to wgetch().
}

var rfds : tsigset;
    
begin
  fpsigemptyset(rfds);
  fpsigaddset(rfds,STDIN);
  while fpselect(1, @rfds,nil,nil,nil)<=0 DO
    begin
      IF TermApp THEN Exit;
      if (fpgeterrno= ESYSEINTR) AND (buttons<>0) THEN
       MyHandler ((xpos DIV cwidth)+1,(ypos DIV cheight)+1,buttons);
    end;
end;

begin 
// if physicalconsole(0) then
// begin
 {Don't want to use ncurses, to easier link static}

  Write(#27'[?1001s'); { save old hilight tracking }
  Write(#27'[?1000h'); { enable mouse tracking }
  for cwidth:=1 to 25 DO Writeln; 
  Writeln('Sysmouse demo, click upper-left corner to exit this program');
  Writeln;
  Writeln('Sysmouse implements a very simple mouse event driven windowing program');
  Writeln('The 4 quadrants of the screen act as windows, and focus is implemented');
  Writeln('Try to click (left or right) the different quadrants, and see what happens');
  Writeln;
  cwidth := 8; cheight := 16;
  Focus:=0;
  StartMouse;
  TermApp:=FALSE;
  while not TermApp do WaitForEvent;
// end
//else 
//  Writeln('This program must be run from the physical console, not over telnet or under X');
end.