353f68f67807d74506bd8289cb922d6baed92fbd
[terminatorX.git] / src / tX_mouse.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2002  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_mouse.cc
20  
21     Description: This implements the mouse AND keyboard Input handling in
22                  Grab-Mode.
23 */
24
25 #include <sys/wait.h>
26 #include <X11/Xlib.h>
27 #include <X11/extensions/xf86dga.h>
28
29 #include "tX_mouse.h"
30 #include "tX_mastergui.h"
31 #include "tX_global.h"
32 #include "tX_engine.h"
33 #include "tX_vtt.h"
34
35 #define TX_MOUSE_SPEED_NORMAL 0.05
36 #define TX_MOUSE_SPEED_WARP 250000
37
38 tx_mouse :: tx_mouse()
39 {
40         mask=PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
41         xmot=(XMotionEvent *) &xev;
42         xkey=(XKeyEvent *) &xev;
43         xbut=(XButtonEvent *) &xev;
44         
45 #ifdef USE_DGA2
46         xdgamot=(XDGAMotionEvent *) &xev;
47         xdgakey=(XDGAKeyEvent *) &xev;
48         xdgabut=(XDGAButtonEvent *) &xev;
49 #endif  
50         
51         grabbed=0;
52         warp=TX_MOUSE_SPEED_NORMAL;
53 }
54
55
56 int tx_mouse :: grab()
57 {       
58 #ifdef USE_DGA2
59         XDGAMode *mode;
60 #endif  
61         int i, num=0;
62
63         if (grabbed) return(0);
64
65         dpy=XOpenDisplay(NULL);
66         if (!dpy)
67         {
68                 fputs("GrabMode Error: couldn't connect to XDisplay.", stderr);
69                 return(ENG_ERR_XOPEN);
70         }
71
72
73 #ifdef USE_DGA2
74         mode=XDGAQueryModes(dpy,DefaultScreen(dpy), &num);
75         
76         printf("Found %i DGA2-Modes:\n", num);
77         
78         for(i=0; i<num; i++)
79         {
80                 printf("%2i: %s\n", i, mode[i].name);
81         }
82         XFree(mode);
83 #endif  
84                                 
85         XSelectInput(dpy, xwindow, mask);       
86
87         XSetInputFocus(dpy, xwindow, None, CurrentTime);
88
89         if (globals.xinput_enable)
90         {
91                 if (set_xinput())
92                 {
93                         XCloseDisplay(dpy);
94                         fputs("GrabMode Error: failed to setup XInput.", stderr);
95                         return(ENG_ERR_XINPUT);
96                 }
97         }
98
99         if (GrabSuccess != XGrabPointer(dpy, xwindow, False, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync,GrabModeAsync,None,None,CurrentTime))
100         {
101                 reset_xinput();
102                 XCloseDisplay(dpy);
103                 fputs("GrabMode Error: XGrabPointer failed.", stderr);
104                 return(ENG_ERR_GRABMOUSE);
105         }       
106         
107         if (GrabSuccess != XGrabKeyboard(dpy, xwindow, False, GrabModeAsync,GrabModeAsync,CurrentTime))
108         {
109                 XUngrabPointer (dpy, CurrentTime);
110                 reset_xinput();         
111                 XCloseDisplay(dpy);
112                 fputs("GrabMode Error: XGrabKeyboard failed.", stderr);
113                 return(ENG_ERR_GRABKEY);
114         }
115         
116
117 #ifdef USE_DGA2
118         if (!XDGASetMode(dpy, DefaultScreen(dpy), 1))
119 #else   
120         if (!XF86DGADirectVideo(dpy,DefaultScreen(dpy),XF86DGADirectMouse))
121 #endif
122         {
123                 XUngrabKeyboard(dpy, CurrentTime);                              
124                 XUngrabPointer (dpy, CurrentTime);
125                 reset_xinput();         
126                 XCloseDisplay(dpy);
127                 fputs("GrabMode Error: Failed to enable XF86DGA.", stderr);             
128                 return(ENG_ERR_DGA);
129         }
130
131 #ifdef USE_DGA2
132         XDGASelectInput(dpy, DefaultScreen(dpy), mask);
133 #endif  
134
135         XAutoRepeatOff(dpy);    
136         otime=CurrentTime;
137         
138         grabbed=1;
139         vtt_class::focus_no(0);
140         warp=TX_MOUSE_SPEED_NORMAL;
141         
142         return(0);
143 }
144
145 void tx_mouse :: ungrab()
146 {
147         if (!grabbed) return;
148         
149 #ifdef USE_DGA2 
150         XDGASetMode(dpy, DefaultScreen(dpy), 0);
151 #else
152         XF86DGADirectVideo(dpy,DefaultScreen(dpy),0);
153 #endif  
154
155         XUngrabKeyboard(dpy, CurrentTime);              
156         XUngrabPointer (dpy, CurrentTime);
157         XAutoRepeatOn(dpy);
158         
159         XCloseDisplay(dpy);
160
161         if (globals.xinput_enable)
162         {
163                 reset_xinput(); 
164         }
165
166         vtt_class::unfocus();
167
168         grabbed=0;
169 }
170
171 #ifdef USE_XSETPOINTER
172
173 void tx_mouse :: set_x_pointer(char *devname)
174 {
175         pid_t pid;
176         int status;
177                 
178         pid = fork();
179         
180         if (pid==-1) 
181         { 
182                 /* OOPS. fork failed */
183                 perror("tX: Error: Couldn't fork process!");
184                 return; 
185         }
186         
187         if (pid==0) 
188         {
189                 /* The child execlps xsetpointer */
190                 execlp("xsetpointer", "xsetpointer", devname, NULL);
191                 perror("tX: Error: Failed to execute xpointer!");
192                 exit(0);
193         }
194         
195         /* parent waits for xsetpointer to finish */
196         waitpid(pid,  &status, WUNTRACED);
197 }
198
199 #else
200
201 void tx_mouse :: set_x_pointer(char *devname)
202 {
203         XDeviceInfo *devlist;                   
204         XDevice *device;
205         int listmax, i;
206         
207         devlist=XListInputDevices(dpy, &listmax);
208         
209         for (i=0; i<listmax; i++)
210         {
211                 if(strcmp(devlist[i].name, devname)==0)
212                 {
213                         device=XOpenDevice(dpy, devlist[i].id);
214                         if (device)
215                         {
216                                 if (XChangePointerDevice(dpy, device, 0, 1))
217                                 {
218                                         printf("tX: Error: failed to set pointer device.");                     
219                                 }
220                                 XCloseDevice(dpy, device);
221                         }
222                         else
223                         {
224                                 printf("tX: Error: failed to open XInput device.");
225                         }               
226                 }
227         }
228                 
229         XFreeDeviceList(devlist);               
230 }
231
232 #endif
233
234 int tx_mouse :: set_xinput()
235 {
236         XDeviceInfo *devlist;                   
237         int listmax, i;
238         
239         OrgXPointer=0;
240         
241         if (globals.xinput_enable)
242         {       
243                 devlist=XListInputDevices(dpy, &listmax);
244         
245                 for (i=0; i<listmax; i++)
246                 {
247                         if(devlist[i].use == IsXPointer)
248                         {
249                                 OrgXPointer=devlist[i].id;
250                                 strcpy(OrgXPointerName, devlist[i].name);
251                         }
252                 }
253                 
254                 XFreeDeviceList(devlist);               
255                 
256                 set_x_pointer(globals.xinput_device);
257         }
258         
259         if (OrgXPointer==0) printf("tX: Error failed to detect core pointer.");
260         return(0);
261 }
262
263
264 void tx_mouse :: reset_xinput()
265 {
266         if (globals.xinput_enable)
267         {
268                 if (OrgXPointer) set_x_pointer(OrgXPointerName);
269         }
270 }
271
272
273 #define vtt vtt_class::focused_vtt
274
275 int tx_mouse :: check_event()
276 {
277         if (XCheckWindowEvent(dpy, xwindow, mask, &xev))
278         {
279 #ifdef USE_DGA2
280                 puts("Got an event");
281 #endif          
282                 if (vtt)
283                 switch(xev.type)
284                 {
285                         case MotionNotify:
286                                 vtt->xy_input(((f_prec) xmot->x_root)*warp,((f_prec) xmot->y_root)*warp);
287                                 break;
288                         
289                         case ButtonPress:
290                                 switch(xbut->button)
291                                 {
292                                         case 1: if (vtt->is_playing)
293                                                         vtt->set_scratch(1); 
294                                                 else
295                                                         vtt->sp_trigger.receive_input_value(1);
296                                                 break;
297                                         case 2: vtt->sp_mute.receive_input_value(1); break;
298                                         case 3: vtt_class::focus_next(); break;
299                                 }
300                                 break;
301                         
302                         case ButtonRelease:
303                                 switch (xbut->button)
304                                 {       
305                                         case 1: vtt->set_scratch(0); break;
306                                         case 2: vtt->sp_mute.receive_input_value(0); break;
307                                 }
308                                 break;
309                         case KeyPress:
310 #ifdef USE_DGA2
311                                 puts("Yeah its a key");
312                                 XDGAKeyEventToXKeyEvent(xdgakey, (XKeyEvent *) &xev_copy);
313                                 memcpy(&xev, &xev_copy, sizeof(XEvent));
314 #endif                  
315                         {
316                                 key=XKeycodeToKeysym(dpy, xkey->keycode, 0);
317                                 
318                                 switch(key)
319                                 {
320                                         case XK_space: vtt->set_scratch(1); break;
321                                         case XK_Escape: return(1);
322                                         
323                                         case XK_Return: vtt->sp_trigger.receive_input_value(1); break;
324                                         case XK_BackSpace : vtt->sp_trigger.receive_input_value(0); break;
325                                         
326                                         case XK_Tab: vtt_class::focus_next(); break;
327                                         
328                                         case XK_s: vtt->sp_sync_client.receive_input_value(!vtt->is_sync_client); break;
329                                         
330                                         case XK_m:
331                                         case XK_Control_L:
332                                         case XK_Control_R:                                              
333                                         vtt->sp_mute.receive_input_value(1);
334                                         break;
335                                                 
336                                         case XK_Alt_L:
337                                         case XK_Alt_R:
338                                         vtt->sp_mute.receive_input_value(0);
339                                         break;
340                                         
341                                         case XK_w:
342                                         vtt->sp_mute.receive_input_value(1);
343                                         case XK_f: 
344                                         warp=((float) vtt->samples_in_buffer)/TX_MOUSE_SPEED_WARP;      
345                                         vtt->set_scratch(1);
346                                         break;
347                                                 
348                                         case XK_F1: vtt_class::focus_no(0); break;
349                                         case XK_F2: vtt_class::focus_no(1); break;
350                                         case XK_F3: vtt_class::focus_no(2); break;
351                                         case XK_F4: vtt_class::focus_no(3); break;
352                                         case XK_F5: vtt_class::focus_no(4); break;
353                                         case XK_F6: vtt_class::focus_no(5); break;
354                                         case XK_F7: vtt_class::focus_no(6); break;
355                                         case XK_F8: vtt_class::focus_no(7); break;
356                                         case XK_F9: vtt_class::focus_no(8); break;
357                                         case XK_F10: vtt_class::focus_no(9); break;
358                                         case XK_F11: vtt_class::focus_no(10); break;
359                                         case XK_F12: vtt_class::focus_no(11); break;
360                                 }
361                         } break;
362                         
363                         case KeyRelease:
364                         {
365                                 key=XKeycodeToKeysym (dpy, xkey->keycode, 0);
366                                 
367                                 switch(key)
368                                 {
369                                         case XK_space: vtt->set_scratch(0); break;
370                                         
371                                         case XK_m:
372                                         case XK_Control_L:
373                                         case XK_Control_R:                                              
374                                         vtt->sp_mute.receive_input_value(0);
375                                         break;
376                                                 
377                                         case XK_Alt_L:
378                                         case XK_Alt_R:
379                                         vtt->sp_mute.receive_input_value(1);
380                                         break;
381                                         
382                                         case XK_w:
383                                         vtt->sp_mute.receive_input_value(0);
384                                         case XK_f: warp=TX_MOUSE_SPEED_NORMAL;
385                                         vtt->set_scratch(0);
386                                         break;                                  
387                                 }
388                         }
389                 }
390                 else {  puts("no vtt"); return(1); }
391         }
392         return(0);
393 }