Xxfdga only when available, beginnings of the new tX_mouse.
[terminatorX.git] / src / tX_mouse.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2011  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
28 #include <config.h>
29
30 #ifdef HAVE_X11_EXTENSIONS_XXF86DGA_H
31 #include <X11/extensions/Xxf86dga.h>
32 #endif
33
34 #ifdef HAVE_X11_EXTENSIONS_XF86DGA_H
35 #include <X11/extensions/xf86dga.h>
36 #endif
37
38 #include <gdk/gdkx.h>
39 #include <gtk/gtk.h>
40
41 #include "tX_mouse.h"
42 #include "tX_mastergui.h"
43 #include "tX_global.h"
44 #include "tX_engine.h"
45 #include "tX_vtt.h"
46 #include <stdlib.h>
47
48 #define TX_MOUSE_SPEED_NORMAL 0.05
49 #define TX_MOUSE_SPEED_WARP 250000
50
51 tx_mouse :: tx_mouse()
52 {
53         mask=PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
54         xmot=(XMotionEvent *) &xev;
55         xkey=(XKeyEvent *) &xev;
56         xbut=(XButtonEvent *) &xev;
57         
58 #ifdef USE_DGA2
59         xdgamot=(XDGAMotionEvent *) &xev;
60         xdgakey=(XDGAKeyEvent *) &xev;
61         xdgabut=(XDGAButtonEvent *) &xev;
62 #endif  
63         
64         grabbed=0;
65         warp=TX_MOUSE_SPEED_NORMAL;
66 }
67
68
69 int tx_mouse :: grab()
70 {       
71 #ifdef USE_DGA2
72         XDGAMode *mode;
73 #endif  
74
75         if (grabbed) return 0;
76
77         warp_override=false;
78         dpy = gdk_x11_get_default_xdisplay();
79 //      GdkDisplay* gdk_dpy = gdk_display_get_default();
80
81         if (!dpy/* && !gdk_dpy*/) {
82                 fputs("GrabMode Error: couldn't connect to XDisplay.", stderr);
83                 return(ENG_ERR_XOPEN);
84         }
85
86 #ifdef USE_DGA2
87         mode=XDGAQueryModes(dpy,DefaultScreen(dpy), &num);
88         
89         printf("Found %i DGA2-Modes:\n", num);
90         
91         for(i=0; i<num; i++) {
92                 printf("%2i: %s\n", i, mode[i].name);
93         }
94         XFree(mode);
95 #endif  
96
97         savedEventMask = gdk_window_get_events(top_window);
98         GdkEventMask newEventMask = GdkEventMask (GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK);
99         gdk_window_set_events(top_window, newEventMask);
100         gtk_window_present(GTK_WINDOW(main_window));
101
102 //      if (globals.xinput_enable) {
103 //              if (set_xinput()) {
104 //                      XCloseDisplay(dpy);
105 //                      fputs("GrabMode Error: failed to setup XInput.", stderr);
106 //                      return(ENG_ERR_XINPUT);
107 //              }
108 //      }
109
110
111         GdkGrabStatus grab_status =gdk_pointer_grab(top_window, FALSE, GdkEventMask (GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK), NULL, NULL, GDK_CURRENT_TIME);
112
113         if (grab_status != GDK_GRAB_SUCCESS) {
114                 //reset_xinput();
115                 //XCloseDisplay(dpy);
116                 //fputs("GrabMode Error: XGrabPointer failed.", stderr);
117                 return(-1);
118         }       
119         
120         grab_status = gdk_keyboard_grab(top_window, FALSE, GDK_CURRENT_TIME);
121
122         if (grab_status != GDK_GRAB_SUCCESS) {
123                 GdkDisplay* display = gdk_display_get_default();
124                 gdk_display_pointer_ungrab(display, GDK_CURRENT_TIME);
125                 //XUngrabPointer (dpy, CurrentTime);
126                 //reset_xinput();
127                 //XCloseDisplay(dpy);
128                 //fputs("GrabMode Error: XGrabKeyboard failed.", stderr);
129                 return(-2);
130         }
131         
132
133 #ifdef USE_DGA2
134         if (!XDGASetMode(dpy, DefaultScreen(dpy), 1)) {
135 #else   
136 //      if (!XF86DGADirectVideo(dpy,DefaultScreen(dpy),XF86DGADirectMouse)) {
137 #endif
138 //              XUngrabKeyboard(dpy, CurrentTime);
139 //              XUngrabPointer (dpy, CurrentTime);
140 //              reset_xinput();
141 //              XCloseDisplay(dpy);
142 //              fputs("GrabMode Error: Failed to enable XF86DGA.", stderr);
143 //              return(ENG_ERR_DGA);
144 //      }
145
146 #ifdef USE_DGA2
147         XDGASelectInput(dpy, DefaultScreen(dpy), mask);
148 #endif  
149
150         XAutoRepeatOff(dpy);    
151         otime=CurrentTime;
152         
153         grabbed=1;
154         
155         std::list<vtt_class *> :: iterator v;
156         int c=0;
157         
158         for (v=vtt_class::main_list.begin(); v!=vtt_class::main_list.end(); v++) {
159                 if (!(*v)->audio_hidden) {
160                         vtt_class::focus_no(c);
161                         break;
162                 }
163                 c++;
164                 //vtt_class::focus_no(0);
165         }
166
167         warp=TX_MOUSE_SPEED_NORMAL;
168         
169         return(0);
170 }
171
172 void tx_mouse :: ungrab()
173 {
174         if (!grabbed) return;
175
176         tX_debug("tX_mouse::ungrab(): this: %08x, dpy: %08x", (int) this, (int) dpy);
177         
178 #ifdef USE_DGA2 
179         XDGASetMode(dpy, DefaultScreen(dpy), 0);
180 #else
181 //      XF86DGADirectVideo(dpy,DefaultScreen(dpy),0);
182 #endif  
183
184         GdkDisplay *gdk_dpy = gdk_display_get_default();
185         gdk_display_keyboard_ungrab(gdk_dpy, GDK_CURRENT_TIME);
186         gdk_display_pointer_ungrab(gdk_dpy, GDK_CURRENT_TIME);
187
188         XAutoRepeatOn(dpy);
189         
190         if (globals.xinput_enable) {
191                 reset_xinput(); 
192         }
193
194         vtt_class::unfocus();
195
196         tX_debug("tX_mouse::ungrab(): done");
197         
198         grabbed=0;
199 }
200
201 #ifdef USE_XSETPOINTER
202
203 void tx_mouse :: set_x_pointer(char *devname)
204 {
205         pid_t pid;
206         int status;
207                 
208         pid = fork();
209         
210         if (pid==-1) { 
211                 /* OOPS. fork failed */
212                 perror("tX: Error: Failed to fork a new process!");
213                 return; 
214         }
215         
216         if (pid==0) {
217                 /* The child execlps xsetpointer */
218                 execlp("xsetpointer", "xsetpointer", devname, NULL);
219                 perror("tX: Error: Failed to execute xpointer!");
220                 exit(0);
221         }
222         
223         /* parent waits for xsetpointer to finish */
224         waitpid(pid,  &status, WUNTRACED);
225 }
226
227 #else
228
229 void tx_mouse :: set_x_pointer(char *devname)
230 {
231         XDeviceInfo *devlist;                   
232         XDevice *device;
233         int listmax, i;
234         
235         devlist=XListInputDevices(dpy, &listmax);
236         
237         for (i=0; i<listmax; i++) {
238                 if(strcmp(devlist[i].name, devname)==0) {
239                         device=XOpenDevice(dpy, devlist[i].id);
240                         if (device) {
241                                 if (XChangePointerDevice(dpy, device, 0, 1)) {
242                                         printf("tX: Error: failed to set pointer device.");                     
243                                 }
244                                 
245                                 XCloseDevice(dpy, device);
246                         } else {
247                                 printf("tX: Error: failed to open XInput device.");
248                         }               
249                 }
250         }
251                 
252         XFreeDeviceList(devlist);               
253 }
254
255 #endif
256
257 int tx_mouse :: set_xinput()
258 {
259         XDeviceInfo *devlist;                   
260         int listmax, i;
261         
262         OrgXPointer=0;
263         
264         if (globals.xinput_enable) {    
265                 devlist=XListInputDevices(dpy, &listmax);
266         
267                 for (i=0; i<listmax; i++) {
268                         if(devlist[i].use == IsXPointer) {
269                                 OrgXPointer=devlist[i].id;
270                                 strcpy(OrgXPointerName, devlist[i].name);
271                         }
272                 }
273                 
274                 XFreeDeviceList(devlist);                               
275                 set_x_pointer(globals.xinput_device);
276         }
277         
278         if (OrgXPointer==0) printf("tX: Error failed to detect core pointer.");
279         return(0);
280 }
281
282
283 void tx_mouse :: reset_xinput()
284 {
285         if (globals.xinput_enable) {
286                 if (OrgXPointer) set_x_pointer(OrgXPointerName);
287         }
288 }
289
290
291 #define vtt vtt_class::focused_vtt
292
293
294 void tx_mouse::motion_notify(GtkWidget *widget, GdkEventMotion *eventMotion) {
295         //eventMotion->x_root, eventMotion->y_root
296         if (vtt) {
297                 if (warp_override) {
298                         f_prec value=(abs(eventMotion->x_root)>abs(eventMotion->y_root)) ? eventMotion->x_root : eventMotion->y_root;
299                         vtt->sp_speed.handle_mouse_input(value*globals.mouse_speed*warp);
300                 } else {
301                         vtt->xy_input((f_prec) eventMotion->x_root*warp, (f_prec) eventMotion->y_root*warp);
302                 }
303         }
304 }
305
306 void tx_mouse::button_press(GtkWidget *widget, GdkEventButton *eventButton) {
307         if (vtt) {
308                 switch(eventButton->button) {
309                         case 1: if (vtt->is_playing)
310                                         vtt->set_scratch(1);
311                                 else
312                                         vtt->sp_trigger.receive_input_value(1);
313                                 break;
314                         case 2: vtt->sp_mute.receive_input_value(1); break;
315                         case 3: vtt_class::focus_next(); break;
316                 }
317         }
318 }
319
320 void tx_mouse::button_release(GtkWidget *widget, GdkEventButton *eventButton) {
321         if (vtt) {
322                 switch (eventButton->button) {
323                         case 1: vtt->set_scratch(0); break;
324                         case 2: vtt->sp_mute.receive_input_value(0); break;
325                 }
326         }
327 }
328
329 void tx_mouse::key_press(GtkWidget *widget, GdkEventKey *eventKey) {
330         if (vtt) {
331         }
332
333 }
334
335 void tx_mouse::key_release(GtkWidget *widget, GdkEventKey *eventKey) {
336         if (vtt) {
337
338         }
339
340 }
341
342 void tx_mouse::motion_notify_wrap(GtkWidget *widget, GdkEventMotion *eventMotion, void *data) {
343         tx_mouse* mouse = (tx_mouse *) data;
344         mouse->motion_notify(widget, eventMotion);
345 }
346
347 void tx_mouse::button_press_wrap(GtkWidget *widget, GdkEventButton *eventButton, void *data) {
348         tx_mouse* mouse = (tx_mouse *) data;
349         mouse->button_press(widget, eventButton);
350 }
351
352 void tx_mouse::button_release_wrap(GtkWidget *widget, GdkEventButton *eventButton, void *data) {
353         tx_mouse* mouse = (tx_mouse *) data;
354         mouse->button_release(widget, eventButton);
355 }
356
357 void tx_mouse::key_press_wrap(GtkWidget *widget, GdkEventKey *eventKey, void *data) {
358         tx_mouse* mouse = (tx_mouse *) data;
359         mouse->key_press(widget, eventKey);
360 }
361
362 void tx_mouse::key_release_wrap(GtkWidget *widget, GdkEventKey *eventKey, void *data) {
363         tx_mouse* mouse = (tx_mouse *) data;
364         mouse->key_release(widget, eventKey);
365 }
366
367 int tx_mouse :: check_event()
368 {
369         if (XCheckWindowEvent(dpy, x_window, mask, &xev) && vtt) {
370 #ifdef USE_DGA2
371                 puts("Got an event");
372 #endif          
373                 switch(xev.type) {
374                         case MotionNotify:
375                                 
376                                 if (warp_override) {
377                                         f_prec value=(abs(xmot->x_root)>abs(xmot->y_root)) ? xmot->x_root : xmot->y_root;
378                                         vtt->sp_speed.handle_mouse_input(value*globals.mouse_speed*warp);
379                                 } else {
380                                         vtt->xy_input((f_prec) xmot->x_root*warp, (f_prec) xmot->y_root*warp);
381                                 }
382                                 break;
383                         
384                         case ButtonPress:
385                                 switch(xbut->button) {
386                                         case 1: if (vtt->is_playing)
387                                                         vtt->set_scratch(1); 
388                                                 else
389                                                         vtt->sp_trigger.receive_input_value(1);
390                                                 break;
391                                         case 2: vtt->sp_mute.receive_input_value(1); break;
392                                         case 3: vtt_class::focus_next(); break;
393                                 }
394                                 break;
395                         
396                         case ButtonRelease:
397                                 switch (xbut->button) { 
398                                         case 1: vtt->set_scratch(0); break;
399                                         case 2: vtt->sp_mute.receive_input_value(0); break;
400                                 }
401                                 break;
402
403                         case KeyPress:
404 #ifdef USE_DGA2
405                                 puts("Yeah its a key");
406                                 XDGAKeyEventToXKeyEvent(xdgakey, (XKeyEvent *) &xev_copy);
407                                 memcpy(&xev, &xev_copy, sizeof(XEvent));
408 #endif                  
409                                 key=XKeycodeToKeysym(dpy, xkey->keycode, 0);
410                                 
411                                 switch(key) {
412                                         case XK_space: vtt->set_scratch(1); break;
413                                         case XK_Escape: return(1);
414                                         
415                                         case XK_Return: vtt->sp_trigger.receive_input_value(1); break;
416                                         case XK_BackSpace : vtt->sp_trigger.receive_input_value(0); break;
417                                         
418                                         case XK_Tab: vtt_class::focus_next(); break;
419                                         
420                                         case XK_s: vtt->sp_sync_client.receive_input_value(!vtt->is_sync_client); break;
421                                         
422                                         case XK_m:
423                                         case XK_Control_L:
424                                         case XK_Control_R:                                              
425                                         vtt->sp_mute.receive_input_value(1);
426                                         break;
427                                                 
428                                         case XK_Alt_L:
429                                         case XK_Alt_R:
430                                         vtt->sp_mute.receive_input_value(0);
431                                         break;
432                                         
433                                         case XK_w:
434                                         vtt->sp_mute.receive_input_value(1);
435                                         case XK_f: 
436                                         warp_override=true;
437                                         warp=((float) vtt->samples_in_buffer)/TX_MOUSE_SPEED_WARP;      
438                                         vtt->set_scratch(1);
439                                         break;
440                                                 
441                                         case XK_F1: vtt_class::focus_no(0); break;
442                                         case XK_F2: vtt_class::focus_no(1); break;
443                                         case XK_F3: vtt_class::focus_no(2); break;
444                                         case XK_F4: vtt_class::focus_no(3); break;
445                                         case XK_F5: vtt_class::focus_no(4); break;
446                                         case XK_F6: vtt_class::focus_no(5); break;
447                                         case XK_F7: vtt_class::focus_no(6); break;
448                                         case XK_F8: vtt_class::focus_no(7); break;
449                                         case XK_F9: vtt_class::focus_no(8); break;
450                                         case XK_F10: vtt_class::focus_no(9); break;
451                                         case XK_F11: vtt_class::focus_no(10); break;
452                                         case XK_F12: vtt_class::focus_no(11); break;
453                                 }
454                                 break;
455                         
456                         case KeyRelease:
457                                 key=XKeycodeToKeysym (dpy, xkey->keycode, 0);
458                                 
459                                 switch(key) {
460                                         case XK_space: vtt->set_scratch(0); break;
461                                         
462                                         case XK_m:
463                                         case XK_Control_L:
464                                         case XK_Control_R:                                              
465                                         vtt->sp_mute.receive_input_value(0);
466                                         break;
467                                                 
468                                         case XK_Alt_L:
469                                         case XK_Alt_R:
470                                         vtt->sp_mute.receive_input_value(1);
471                                         break;
472                                         
473                                         case XK_w:
474                                         vtt->sp_mute.receive_input_value(0);
475                                         case XK_f: warp=TX_MOUSE_SPEED_NORMAL;
476                                         warp_override=false;
477                                         vtt->set_scratch(0);
478                                         break;                                  
479                                 }
480                 }
481         }
482         return 0;
483 }