Colors customizable - 'w' + 'f' "fix" - Alex
[terminatorX.git] / src / tX_mouse.cc
index c6bc2fc01df3fdd3571a5fe720793a25e57dd3aa..196d48d190fd919e2cc523ebc09cb0c358799e1d 100644 (file)
@@ -1,6 +1,6 @@
 /*
     terminatorX - realtime audio scratching software
-    Copyright (C) 1999  Alexander König
+    Copyright (C) 1999-2003  Alexander König
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
  
     Description: This implements the mouse AND keyboard Input handling in
                 Grab-Mode.
-*/    
+*/
+
+#include <sys/wait.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/xf86dga.h>
 
 #include "tX_mouse.h"
 #include "tX_mastergui.h"
 #include "tX_engine.h"
 #include "tX_vtt.h"
 
-tx_mouse :: tx_mouse()
-{
+#define TX_MOUSE_SPEED_NORMAL 0.05
+#define TX_MOUSE_SPEED_WARP 250000
+
+tx_mouse :: tx_mouse() {
        mask=PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
        xmot=(XMotionEvent *) &xev;
        xkey=(XKeyEvent *) &xev;
        xbut=(XButtonEvent *) &xev;
+       
+#ifdef USE_DGA2
+       xdgamot=(XDGAMotionEvent *) &xev;
+       xdgakey=(XDGAKeyEvent *) &xev;
+       xdgabut=(XDGAButtonEvent *) &xev;
+#endif 
+       
        grabbed=0;
+       warp=TX_MOUSE_SPEED_NORMAL;
 }
 
-int tx_mouse :: grab()
-{      
+
+int tx_mouse :: grab() {       
+#ifdef USE_DGA2
+       XDGAMode *mode;
+#endif 
+
        if (grabbed) return(0);
 
-       dpy=XOpenDisplay(NULL); // FIXME: use correct display
+       warp_override=false;
+       
+       dpy=XOpenDisplay(NULL);
        if (!dpy)
        {
+               fputs("GrabMode Error: couldn't connect to XDisplay.", stderr);
                return(ENG_ERR_XOPEN);
        }
 
+
+#ifdef USE_DGA2
+       mode=XDGAQueryModes(dpy,DefaultScreen(dpy), &num);
+       
+       printf("Found %i DGA2-Modes:\n", num);
+       
+       for(i=0; i<num; i++)
+       {
+               printf("%2i: %s\n", i, mode[i].name);
+       }
+       XFree(mode);
+#endif 
+                               
+       XSelectInput(dpy, xwindow, mask);       
+
+       XSetInputFocus(dpy, xwindow, None, CurrentTime);
+
        if (globals.xinput_enable)
        {
                if (set_xinput())
                {
                        XCloseDisplay(dpy);
+                       fputs("GrabMode Error: failed to setup XInput.", stderr);
                        return(ENG_ERR_XINPUT);
                }
        }
-                               
-       XSelectInput(dpy, xwindow, mask);       
-
-       XSetInputFocus(dpy, xwindow, None, CurrentTime);
 
         if (GrabSuccess != XGrabPointer(dpy, xwindow, False, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync,GrabModeAsync,None,None,CurrentTime))
        {
                reset_xinput();
                XCloseDisplay(dpy);
+               fputs("GrabMode Error: XGrabPointer failed.", stderr);
                return(ENG_ERR_GRABMOUSE);
        }       
        
@@ -72,25 +108,50 @@ int tx_mouse :: grab()
                XUngrabPointer (dpy, CurrentTime);
                reset_xinput();         
                XCloseDisplay(dpy);
-
+               fputs("GrabMode Error: XGrabKeyboard failed.", stderr);
                return(ENG_ERR_GRABKEY);
        }
        
-       
+
+#ifdef USE_DGA2
+       if (!XDGASetMode(dpy, DefaultScreen(dpy), 1))
+#else  
        if (!XF86DGADirectVideo(dpy,DefaultScreen(dpy),XF86DGADirectMouse))
+#endif
        {
                XUngrabKeyboard(dpy, CurrentTime);                              
                XUngrabPointer (dpy, CurrentTime);
                reset_xinput();         
                XCloseDisplay(dpy);
+               fputs("GrabMode Error: Failed to enable XF86DGA.", stderr);             
                return(ENG_ERR_DGA);
        }
 
+#ifdef USE_DGA2
+       XDGASelectInput(dpy, DefaultScreen(dpy), mask);
+#endif 
+
        XAutoRepeatOff(dpy);    
        otime=CurrentTime;
        
        grabbed=1;
-       vtt_class::focus_no(0);
+       
+       std::list<vtt_class *> :: iterator v;
+       int c=0;
+       
+       for (v=vtt_class::main_list.begin(); v!=vtt_class::main_list.end(); v++) {
+               if (!(*v)->audio_hidden) {
+                       vtt_class::focus_no(c);
+                       break;
+               }
+               c++;
+               //vtt_class::focus_no(0);
+       }
+       
+       
+       warp=TX_MOUSE_SPEED_NORMAL;
+       
+       tX_debug("tX_mouse::grab(): this: %08x, dpy: %08x", (int) this, (int) dpy);
        
        return(0);
 }
@@ -99,28 +160,101 @@ void tx_mouse :: ungrab()
 {
        if (!grabbed) return;
 
+       tX_debug("tX_mouse::ungrab(): this: %08x, dpy: %08x", (int) this, (int) dpy);
+       
+#ifdef USE_DGA2        
+       XDGASetMode(dpy, DefaultScreen(dpy), 0);
+#else
        XF86DGADirectVideo(dpy,DefaultScreen(dpy),0);
+#endif 
 
        XUngrabKeyboard(dpy, CurrentTime);              
        XUngrabPointer (dpy, CurrentTime);
        XAutoRepeatOn(dpy);
-
-       reset_xinput(); 
        
        XCloseDisplay(dpy);
 
+       if (globals.xinput_enable)
+       {
+               reset_xinput(); 
+       }
+
        vtt_class::unfocus();
 
+       tX_debug("tX_mouse::ungrab(): done");
+       
        grabbed=0;
 }
 
+#ifdef USE_XSETPOINTER
+
+void tx_mouse :: set_x_pointer(char *devname)
+{
+       pid_t pid;
+       int status;
+               
+       pid = fork();
+       
+       if (pid==-1) 
+       { 
+               /* OOPS. fork failed */
+               perror("tX: Error: Couldn't fork process!");
+               return; 
+       }
+       
+       if (pid==0) 
+       {
+               /* The child execlps xsetpointer */
+               execlp("xsetpointer", "xsetpointer", devname, NULL);
+               perror("tX: Error: Failed to execute xpointer!");
+               exit(0);
+       }
+       
+       /* parent waits for xsetpointer to finish */
+       waitpid(pid,  &status, WUNTRACED);
+}
 
+#else
+
+void tx_mouse :: set_x_pointer(char *devname)
+{
+       XDeviceInfo *devlist;                   
+       XDevice *device;
+       int listmax, i;
+       
+       devlist=XListInputDevices(dpy, &listmax);
+       
+       for (i=0; i<listmax; i++)
+       {
+               if(strcmp(devlist[i].name, devname)==0)
+               {
+                       device=XOpenDevice(dpy, devlist[i].id);
+                       if (device)
+                       {
+                               if (XChangePointerDevice(dpy, device, 0, 1))
+                               {
+                                       printf("tX: Error: failed to set pointer device.");                     
+                               }
+                               XCloseDevice(dpy, device);
+                       }
+                       else
+                       {
+                               printf("tX: Error: failed to open XInput device.");
+                       }               
+               }
+       }
+               
+       XFreeDeviceList(devlist);               
+}
+
+#endif
 
 int tx_mouse :: set_xinput()
 {
        XDeviceInfo *devlist;                   
        int listmax, i;
-       int match=-1;
+       
+       OrgXPointer=0;
        
        if (globals.xinput_enable)
        {       
@@ -128,53 +262,51 @@ int tx_mouse :: set_xinput()
        
                for (i=0; i<listmax; i++)
                {
-                       if(!strcmp(globals.xinput_device,devlist[i].name))
-                       {
-                               match=i;
-                       }
-               
                        if(devlist[i].use == IsXPointer)
                        {
                                OrgXPointer=devlist[i].id;
+                               strcpy(OrgXPointerName, devlist[i].name);
                        }
                }
                
-               if (match>=0)
-               {
-                       input_device=NULL;
-                       input_device=XOpenDevice(dpy,devlist[match].id);
-/*                     if (XChangePointerDevice(dpy,input_device, 0, 1)!=Success)
-                       {
-                               match=-1;
-                       }*/
-                       XCloseDevice(dpy, input_device);
-               }
-               
                XFreeDeviceList(devlist);               
-       
-               if (match>=0) return(0); 
-               else return(1);
+               
+               set_x_pointer(globals.xinput_device);
        }
        
+       if (OrgXPointer==0) printf("tX: Error failed to detect core pointer.");
        return(0);
 }
 
+
+void tx_mouse :: reset_xinput()
+{
+       if (globals.xinput_enable)
+       {
+               if (OrgXPointer) set_x_pointer(OrgXPointerName);
+       }
+}
+
+
 #define vtt vtt_class::focused_vtt
 
 int tx_mouse :: check_event()
 {
        if (XCheckWindowEvent(dpy, xwindow, mask, &xev))
        {
+#ifdef USE_DGA2
+               puts("Got an event");
+#endif         
                if (vtt)
                switch(xev.type)
                {
                        case MotionNotify:
-                               ntime=xmot->time;
-                               dtime=(f_prec) ntime-otime;
-                               if (dtime<=0) dtime=1.0;
-                               otime=ntime;
                                
-                               vtt->xy_input(((f_prec) xmot->x_root)/dtime,((f_prec) xmot->y_root)/dtime);
+                               if (warp_override) {
+                                       vtt->sp_speed.handle_mouse_input(((f_prec) xmot->x_root)*globals.mouse_speed*warp);
+                               } else {
+                                       vtt->xy_input((f_prec) xmot->x_root, (f_prec) xmot->y_root);
+                               }
                                break;
                        
                        case ButtonPress:
@@ -183,9 +315,9 @@ int tx_mouse :: check_event()
                                        case 1: if (vtt->is_playing)
                                                        vtt->set_scratch(1); 
                                                else
-                                                       vtt->trigger();
+                                                       vtt->sp_trigger.receive_input_value(1);
                                                break;
-                                       case 2: vtt->set_mute(1); break;
+                                       case 2: vtt->sp_mute.receive_input_value(1); break;
                                        case 3: vtt_class::focus_next(); break;
                                }
                                break;
@@ -194,11 +326,15 @@ int tx_mouse :: check_event()
                                switch (xbut->button)
                                {       
                                        case 1: vtt->set_scratch(0); break;
-                                       case 2: vtt->set_mute(0); break;
+                                       case 2: vtt->sp_mute.receive_input_value(0); break;
                                }
                                break;
-                       
                        case KeyPress:
+#ifdef USE_DGA2
+                               puts("Yeah its a key");
+                               XDGAKeyEventToXKeyEvent(xdgakey, (XKeyEvent *) &xev_copy);
+                               memcpy(&xev, &xev_copy, sizeof(XEvent));
+#endif                 
                        {
                                key=XKeycodeToKeysym(dpy, xkey->keycode, 0);
                                
@@ -207,22 +343,30 @@ int tx_mouse :: check_event()
                                        case XK_space: vtt->set_scratch(1); break;
                                        case XK_Escape: return(1);
                                        
-                                       case XK_Return: vtt->trigger(); break;
-                                       case XK_BackSpace : vtt->stop(); break;
+                                       case XK_Return: vtt->sp_trigger.receive_input_value(1); break;
+                                       case XK_BackSpace : vtt->sp_trigger.receive_input_value(0); break;
                                        
                                        case XK_Tab: vtt_class::focus_next(); break;
                                        
-                                       case XK_s: vtt->set_sync_client(!vtt->is_sync_client, vtt->sync_cycles); break;
+                                       case XK_s: vtt->sp_sync_client.receive_input_value(!vtt->is_sync_client); break;
                                        
                                        case XK_m:
                                        case XK_Control_L:
                                        case XK_Control_R:                                              
-                                       vtt->set_mute(1);
+                                       vtt->sp_mute.receive_input_value(1);
                                        break;
                                                
                                        case XK_Alt_L:
                                        case XK_Alt_R:
-                                       vtt->set_mute(0);
+                                       vtt->sp_mute.receive_input_value(0);
+                                       break;
+                                       
+                                       case XK_w:
+                                       vtt->sp_mute.receive_input_value(1);
+                                       case XK_f: 
+                                       warp_override=true;
+                                       warp=((float) vtt->samples_in_buffer)/TX_MOUSE_SPEED_WARP;      
+                                       vtt->set_scratch(1);
                                        break;
                                                
                                        case XK_F1: vtt_class::focus_no(0); break;
@@ -237,10 +381,6 @@ int tx_mouse :: check_event()
                                        case XK_F10: vtt_class::focus_no(9); break;
                                        case XK_F11: vtt_class::focus_no(10); break;
                                        case XK_F12: vtt_class::focus_no(11); break;
-                                       /*
-                                       case XK_f:
-                                       warp=((float) globals.scratch_size)/50000.0;                                            
-                                       */
                                }
                        } break;
                        
@@ -255,12 +395,19 @@ int tx_mouse :: check_event()
                                        case XK_m:
                                        case XK_Control_L:
                                        case XK_Control_R:                                              
-                                       vtt->set_mute(0);
+                                       vtt->sp_mute.receive_input_value(0);
                                        break;
                                                
                                        case XK_Alt_L:
                                        case XK_Alt_R:
-                                       vtt->set_mute(1);
+                                       vtt->sp_mute.receive_input_value(1);
+                                       break;
+                                       
+                                       case XK_w:
+                                       vtt->sp_mute.receive_input_value(0);
+                                       case XK_f: warp=TX_MOUSE_SPEED_NORMAL;
+                                       warp_override=false;
+                                       vtt->set_scratch(0);
                                        break;                                  
                                }
                        }
@@ -269,14 +416,3 @@ int tx_mouse :: check_event()
        }
        return(0);
 }
-
-void tx_mouse :: reset_xinput()
-{
-       
-/*     if (globals.xinput_enable)
-       {
-               input_device=XOpenDevice(dpy, OrgXPointer);
-               XChangePointerDevice(dpy, input_device, 0, 1);
-               XCloseDevice(dpy,input_device); 
-       }*/
-}