gallium/draw: initial code to properly support llvm in the draw module
[mesa.git] / src / glut / fbdev / input.c
index 2528a74a1058268ab1da72e115ff11595c15cb5d..1445682c760f98bd129c37c6e18131027355d546 100644 (file)
@@ -53,7 +53,7 @@
 int GpmMouse;
 #endif
 
-int CurrentVT;
+int CurrentVT = 0;
 int ConsoleFD = -1;
 
 int KeyboardModifiers;
@@ -65,8 +65,8 @@ double MouseSpeed = 0;
 
 int KeyRepeatMode = GLUT_KEY_REPEAT_DEFAULT;
 
-/* only display the mouse if there is a registered callback for it */
-int MouseEnabled = 0;
+int MouseVisible = 0;
+int LastMouseTime = 0;
 
 static int OldKDMode = -1;
 static int OldMode = KD_TEXT;
@@ -79,6 +79,8 @@ static int MouseFD;
 
 static int kbdpipe[2];
 
+static int LastStdinKeyTime, LastStdinSpecialKey = -1, LastStdinCode = -1;
+
 #define MODIFIER(mod) \
     KeyboardModifiers = release ? KeyboardModifiers & ~mod   \
                                 : KeyboardModifiers | mod;
@@ -93,7 +95,6 @@ static void KeyboardHandler(int sig)
    unsigned char code;
 
    while(read(ConsoleFD, &code, 1) == 1) {
-
       int release, labelval;
       struct kbentry entry;
       static int lalt; /* only left alt does vt switch */
@@ -163,10 +164,46 @@ static void LedModifier(int led, int release)
         KeyboardLedState ^= led;
         releaseflag &= ~led;
       }
+
    ioctl(ConsoleFD, KDSKBLED, KeyboardLedState);
    ioctl(ConsoleFD, KDSETLED, 0x80);
 }
 
+static void HandleKeyPress(unsigned char key, int up)
+{
+   if(up) {
+      if(KeyboardUpFunc)
+         KeyboardUpFunc(key, MouseX, MouseY);
+   } else
+      if(KeyboardFunc)
+         KeyboardFunc(key, MouseX, MouseY);
+      else
+         if(key == 27)
+            exit(0);  /* no handler, to provide a way to exit */
+}
+
+static void HandleSpecialPress(int key, int up)
+{
+   if(up) {
+      if(SpecialUpFunc)
+         SpecialUpFunc(key, MouseX, MouseY);
+   } else
+      if(SpecialFunc)
+         SpecialFunc(key, MouseX, MouseY);
+}
+
+static void ReleaseStdinKey(void)
+{
+   if(LastStdinSpecialKey != -1) {
+      HandleSpecialPress(LastStdinSpecialKey, 1);
+      LastStdinSpecialKey = -1;
+   }
+   if(LastStdinCode != -1) {
+      HandleKeyPress(LastStdinCode, 1);
+      LastStdinCode = -1;
+   }
+}
+
 #define READKEY read(kbdpipe[0], &code, 1)
 static int ReadKey(void)
 {
@@ -175,8 +212,14 @@ static int ReadKey(void)
    int specialkey = 0;
    struct kbentry entry; 
 
-   if(READKEY != 1)
+   if(READKEY != 1) {
+      /* if we are reading from stdin, we detect key releases when the key
+         does not repeat after a given timeout */
+      if(ConsoleFD == 0 && LastStdinKeyTime + 100 < glutGet(GLUT_ELAPSED_TIME))
+         ReleaseStdinKey();
       return 0;
+   }
+
    if(code == 0)
       return 0;
 
@@ -185,65 +228,82 @@ static int ReadKey(void)
       KeyboardModifiers = 0;
    altset:
       if(code == 27 && READKEY == 1) {
-        switch(code) {
-        case 79: /* function key */
-           READKEY;
-           if(code == 50) {
-              READKEY;
-           shiftfunc:
-              KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
-              specialkey = GLUT_KEY_F1 + code - 53;
-              READKEY;
-           } else {
-              READKEY;
-              specialkey = GLUT_KEY_F1 + code - 80;                
-           }
-           break;
-        case 91:
-           READKEY;
-           switch(code) {
-           case 68:
-              specialkey = GLUT_KEY_LEFT; break;
-           case 65:
-              specialkey = GLUT_KEY_UP; break;
-           case 67:
-              specialkey = GLUT_KEY_RIGHT; break;
-           case 66:
-              specialkey = GLUT_KEY_DOWN; break;
-           case 53:
-              specialkey = GLUT_KEY_PAGE_UP; READKEY; break;
-           case 54:
-              specialkey = GLUT_KEY_PAGE_DOWN; READKEY; break;
-           case 49:
-              specialkey = GLUT_KEY_HOME; READKEY; break;
-           case 52:
-              specialkey = GLUT_KEY_END; READKEY; break;
-           case 50:
-              READKEY;
-              if(code != 126)
-                 goto shiftfunc;
-              specialkey = GLUT_KEY_INSERT;
-              break; 
-           case 51:
-              code = '\b';
-              goto stdkey;
-           case 91:
-              READKEY;
-              specialkey = GLUT_KEY_F1 + code - 65;
-              break;
-           default:
-              return 0;
-           }
-           break;
-        default:
+         if(code != 91) {
            KeyboardModifiers |= GLUT_ACTIVE_ALT;
            goto altset;
         }
+         READKEY;
+         switch(code) {
+         case 68:
+            specialkey = GLUT_KEY_LEFT; break;
+         case 65:
+            specialkey = GLUT_KEY_UP; break;
+         case 67:
+            specialkey = GLUT_KEY_RIGHT; break;
+         case 66:
+            specialkey = GLUT_KEY_DOWN; break;
+         case 52:
+            specialkey = GLUT_KEY_END; READKEY; break;
+         case 53:
+            specialkey = GLUT_KEY_PAGE_UP; READKEY; break;
+         case 54:
+            specialkey = GLUT_KEY_PAGE_DOWN; READKEY; break;
+         case 49:
+            READKEY;
+            if(code == 126)
+               specialkey = GLUT_KEY_HOME;
+            else {
+               specialkey = GLUT_KEY_F1 + code - 50;
+               READKEY;
+            }
+            break;
+         case 50:
+            READKEY;
+            if(code == 126)
+               specialkey = GLUT_KEY_INSERT;
+            else {
+               if(code > '1')
+                  code--;
+               if(code > '6')
+                  code--;
+               if(code > '3') {
+                  KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
+                  code -= 12;
+               }
+               specialkey = GLUT_KEY_F1 + code - 40;
+               READKEY;
+            }
+            break; 
+         case 51:
+            READKEY;
+            if(code == 126) {
+               code = '\b';
+               goto stdkey;
+            }
+            KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
+            specialkey = GLUT_KEY_F1 + code - 45;
+            READKEY;
+            break;
+         case 91:
+            READKEY;
+            specialkey = GLUT_KEY_F1 + code - 65;
+            break;
+         default:
+            return 0;
+        }
       }
 
       if(specialkey) {
-        if(SpecialFunc)
-           SpecialFunc(specialkey, MouseX, MouseY);
+         LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME);
+
+         if(LastStdinSpecialKey != specialkey) {
+            ReleaseStdinKey();
+            HandleSpecialPress(specialkey, 0);
+            LastStdinSpecialKey = specialkey;
+            LastStdinKeyTime += 200; /* initial repeat */
+         } else
+         if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF)
+            HandleSpecialPress(specialkey, 0);
       } else {
         if(code >= 1 && code <= 26 && code != '\r') {
            KeyboardModifiers |= GLUT_ACTIVE_CTRL;
@@ -255,8 +315,15 @@ static int ReadKey(void)
            KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
 
       stdkey:
-        if(KeyboardFunc)
-           KeyboardFunc(code, MouseX, MouseY);
+         LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME);
+         if(LastStdinCode != code) {
+            ReleaseStdinKey();
+            HandleKeyPress(code, 0);
+            LastStdinCode = code;
+            LastStdinKeyTime += 200; /* initial repeat */
+         } else
+         if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF)
+            HandleSpecialPress(code, 0);
       }
       return 1;
    }
@@ -342,19 +409,17 @@ static int ReadKey(void)
         labelval = '\b';
         break;
       case K_ENTER:
-      case K_ENTER - 1: /* keypad enter */
         labelval = '\r'; break;
       }
 
+   /* likely a keypad input, but depends on keyboard mapping, ignore */
+   if(labelval == 512)
+      return 1;
+
    /* dispatch callback */
-   if(specialkey) {
-      if(release) {
-        if(SpecialUpFunc)
-           SpecialUpFunc(specialkey, MouseX, MouseY);
-      } else
-        if(SpecialFunc)
-           SpecialFunc(specialkey, MouseX, MouseY);
-   } else {
+   if(specialkey)
+      HandleSpecialPress(specialkey, release);
+   else {
       char c = labelval;
 
       if(KeyboardLedState & LED_CAP) {
@@ -364,12 +429,7 @@ static int ReadKey(void)
            if(c >= 'a' && c <= 'z')
               c += 'A' - 'a';
       }
-      if(release) {
-        if(KeyboardUpFunc)
-           KeyboardUpFunc(c, MouseX, MouseY);
-      } else
-        if(KeyboardFunc)
-           KeyboardFunc(c, MouseX, MouseY);
+      HandleKeyPress(c, release);
    }
    return 1;
 }
@@ -432,28 +492,22 @@ static int ReadMouse(void)
       dy = event.dy;
    } else
 #endif
-      {
-        char data[4];
-
-        if(MouseFD == -1)
-           return 0;
+   {
+      char data[4];
 
-        if(fcntl(MouseFD, F_SETFL, O_NONBLOCK) == -1) {
-           close(MouseFD);
-           MouseFD = -1;
-           return 0;
-        }
+      if(MouseFD == -1)
+         return 0;
 
-        if(read(MouseFD, data, 4) != 4)
-           return 0;
+      if(read(MouseFD, data, 4) != 4)
+         return 0;
        
-        l = ((data[0] & 0x20) >> 3);
-        m = ((data[3] & 0x10) >> 3);
-        r = ((data[0] & 0x10) >> 4);
+      l = ((data[0] & 0x20) >> 3);
+      m = ((data[3] & 0x10) >> 3);
+      r = ((data[0] & 0x10) >> 4);
 
-        dx = (((data[0] & 0x03) << 6) | (data[1] & 0x3F));
-        dy = (((data[0] & 0x0C) << 4) | (data[2] & 0x3F));
-      }
+      dx = (((data[0] & 0x03) << 6) | (data[1] & 0x3F));
+      dy = (((data[0] & 0x0C) << 4) | (data[2] & 0x3F));
+   }
 
    MouseX += dx * MouseSpeed;
    if(MouseX < 0)
@@ -478,7 +532,7 @@ static int ReadMouse(void)
 
    ll = l, lm = m, lr = r;
 
-   if(dx || dy) {
+   if(dx || dy || !MouseVisible) {
       if(l || m || r) {
         if(MotionFunc)
            MotionFunc(MouseX, MouseY);
@@ -488,12 +542,16 @@ static int ReadMouse(void)
 
       EraseCursor();
 
+      MouseVisible = 1;
+
       if(ActiveMenu)
         Redisplay = 1;
       else
         SwapCursor();
    }
 
+   LastMouseTime = glutGet(GLUT_ELAPSED_TIME);
+
    return 1;
 }
 
@@ -502,8 +560,14 @@ void ReceiveInput(void)
    if(ConsoleFD != -1)
       while(ReadKey());
     
-   if(MouseEnabled)
-      while(ReadMouse());
+   while(ReadMouse());
+
+   /* implement a 2 second timeout on the mouse */
+   if(MouseVisible && glutGet(GLUT_ELAPSED_TIME) - LastMouseTime > 2000) {
+      EraseCursor();
+      MouseVisible = 0;
+      SwapCursor();
+   }
 }
 
 static void VTSwitchHandler(int sig)
@@ -526,9 +590,6 @@ static void VTSwitchHandler(int sig)
       if(st.v_active)
         ioctl(ConsoleFD, VT_RELDISP, VT_ACKACQ);
 
-      /* this is a hack to turn the cursor off */
-      ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo);
-
       RestoreColorMap();
 
       Active = 1;
@@ -536,7 +597,6 @@ static void VTSwitchHandler(int sig)
       VisibleSwitch = 1;
 
       Redisplay = 1;
-
       break;
    }
 }
@@ -549,37 +609,11 @@ void InitializeVT(int usestdin)
 
    signal(SIGIO, SIG_IGN);
 
-   /* save old terminos settings */
-   if (tcgetattr(0, &OldTermios) < 0) {
-      sprintf(exiterror, "tcgetattr failed\n");
-      exit(0);
-   }
-
-   tio = OldTermios;
-
-   /* terminos settings for straight-through mode */  
-   tio.c_lflag &= ~(ICANON | ECHO  | ISIG);
-   tio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
-   tio.c_iflag |= IGNBRK;
-
-   tio.c_cc[VMIN]  = 0;
-   tio.c_cc[VTIME] = 0;
-
-   if (tcsetattr(0, TCSANOW, &tio) < 0) {
-      sprintf(exiterror, "tcsetattr failed\n");
-      exit(0);
-   }
-
-   if(fcntl(0, F_SETFL, O_NONBLOCK | O_ASYNC) < 0) {
-      sprintf(exiterror, "Failed to set keyboard to non-blocking\n");
-      exit(0);
-   }
-
    Active = 1;
 
    if(usestdin) {
       ConsoleFD = 0;
-      return;
+      goto setattribs;
    }
 
    /* detect the current vt if it was not specified */
@@ -590,15 +624,16 @@ void InitializeVT(int usestdin)
         sprintf(exiterror, "Failed to open /dev/tty\n");
         exit(0);
       }
+
       if(ioctl(fd, VT_GETSTATE, &st) == -1) {
         fprintf(stderr, "Could not detect current vt, specify with -vt\n");
         fprintf(stderr, "Defaulting to stdin input\n");
         ConsoleFD = 0;
         close(fd);
-        return;
-      } else
-        CurrentVT =  st.v_active;
+         goto setattribs;
+      }
 
+      CurrentVT =  st.v_active;
       close(fd);
    }
     
@@ -613,7 +648,7 @@ void InitializeVT(int usestdin)
       sprintf(exiterror, "error couldn't open %s,"
              " defaulting to stdin \n", console);
       ConsoleFD = 0;
-      return;
+      goto setattribs;
    }
 
    signal(SIGUSR1, VTSwitchHandler);
@@ -623,7 +658,7 @@ void InitializeVT(int usestdin)
       sprintf(exiterror,"Failed to grab %s, defaulting to stdin\n", console);
       close(ConsoleFD);
       ConsoleFD = 0;
-      return;
+      goto setattribs;
    }
 
    vt = OldVTMode;
@@ -655,7 +690,7 @@ void InitializeVT(int usestdin)
       exit(0);
    }
 
-   fcntl(0, F_SETOWN, getpid());
+   fcntl(ConsoleFD, F_SETOWN, getpid());
 
    if(ioctl(ConsoleFD, KDGETMODE, &OldMode) < 0)
       sprintf(exiterror, "Warning: Failed to get terminal mode\n");
@@ -668,7 +703,6 @@ void InitializeVT(int usestdin)
 
    if(ioctl(ConsoleFD, KDSKBMODE, K_MEDIUMRAW) < 0) {
       sprintf(exiterror, "ioctl KDSKBMODE failed!\n");
-      tcsetattr(0, TCSANOW, &OldTermios);
       exit(0);
    }
 
@@ -676,6 +710,34 @@ void InitializeVT(int usestdin)
       sprintf(exiterror, "ioctl KDGKBLED failed!\n");
       exit(0);
    }
+
+ setattribs:
+   /* enable async input input */
+   if(fcntl(ConsoleFD, F_SETFL, O_ASYNC) < 0) {
+      sprintf(exiterror, "Failed to set O_ASYNC mode on fd %d\n", ConsoleFD);
+      exit(0);
+   }
+
+   /* save old terminos settings */
+   if (tcgetattr(ConsoleFD, &OldTermios) < 0) {
+      sprintf(exiterror, "tcgetattr failed\n");
+      exit(0);
+   }
+
+   tio = OldTermios;
+
+   /* terminos settings for straight-through mode */  
+   tio.c_lflag &= ~(ICANON | ECHO  | ISIG);
+   tio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
+   tio.c_iflag |= IGNBRK;
+
+   tio.c_cc[VMIN]  = 0;
+   tio.c_cc[VTIME] = 0;
+
+   if (tcsetattr(ConsoleFD, TCSANOW, &tio) < 0) {
+      sprintf(exiterror, "tcsetattr failed\n");
+      exit(0);
+   }
 }
 
 void RestoreVT(void)
@@ -683,13 +745,13 @@ void RestoreVT(void)
    if(ConsoleFD < 0)
       return;
 
-   if (tcsetattr(0, TCSANOW, &OldTermios) < 0)
-      fprintf(stderr, "tcsetattr failed\n");
+   if (tcsetattr(ConsoleFD, TCSANOW, &OldTermios) < 0)
+      sprintf(exiterror, "tcsetattr failed\n");
 
-   /* setting the mode to text from graphics restores the colormap*/
+   /* setting the mode to text from graphics restores the colormap */
    if(
 #ifdef HAVE_GPM
-   GpmMouse ||
+   !GpmMouse ||
 #endif
    ConsoleFD == 0)
       if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0)
@@ -725,11 +787,11 @@ void InitializeMouse(void)
       const char *mousedev = getenv("MOUSE");
       if(!mousedev)
         mousedev = MOUSEDEV;
-      if((MouseFD = open(mousedev, O_RDONLY)) >= 0) {
-        if(!MouseSpeed)
-           MouseSpeed = 1;
-        NumMouseButtons = 3;
-        return;
+      if((MouseFD = open(mousedev, O_RDONLY | O_NONBLOCK)) >= 0) {
+         if(!MouseSpeed)
+            MouseSpeed = 1;
+         NumMouseButtons = 3;
+         return;
       }
    }
 #ifdef HAVE_GPM