Updated keyboard input so that glut programs can read from stdin without
[mesa.git] / src / glut / fbdev / input.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 * Copyright (C) 1995-2006 Brian Paul
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22 * Library for glut using mesa fbdev driver
23 *
24 * Written by Sean D'Epagnier (c) 2006
25 */
26
27 #include <errno.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <termios.h>
35 #include <inttypes.h>
36
37 #include <sys/ioctl.h>
38 #include <sys/poll.h>
39 #include <sys/kd.h>
40
41 #include <linux/keyboard.h>
42 #include <linux/fb.h>
43 #include <linux/vt.h>
44
45 #include <GL/glut.h>
46
47 #include "internal.h"
48
49 #define MOUSEDEV "/dev/gpmdata"
50
51 #ifdef HAVE_GPM
52 #include <gpm.h>
53 int GpmMouse;
54 #endif
55
56 int CurrentVT = 0;
57 int ConsoleFD = -1;
58
59 int KeyboardModifiers;
60
61 int MouseX, MouseY;
62 int NumMouseButtons;
63
64 double MouseSpeed = 0;
65
66 int KeyRepeatMode = GLUT_KEY_REPEAT_DEFAULT;
67
68 int MouseVisible = 0;
69 int LastMouseTime = 0;
70
71 static int OldKDMode = -1;
72 static int OldMode = KD_TEXT;
73 static struct vt_mode OldVTMode;
74 static struct termios OldTermios;
75
76 static int KeyboardLedState;
77
78 static int MouseFD;
79
80 static int kbdpipe[2];
81
82 static int LastStdinKeyTime, LastStdinSpecialKey = -1, LastStdinCode = -1;
83
84 #define MODIFIER(mod) \
85 KeyboardModifiers = release ? KeyboardModifiers & ~mod \
86 : KeyboardModifiers | mod;
87
88 /* signal handler attached to SIGIO on keyboard input, vt
89 switching and modifiers is handled in the signal handler
90 other keypresses read from a pipe that leaves the handler
91 if a program locks up the glut loop, you can still switch
92 vts and kill it without Alt-SysRq hack */
93 static void KeyboardHandler(int sig)
94 {
95 unsigned char code;
96
97 while(read(ConsoleFD, &code, 1) == 1) {
98 int release, labelval;
99 struct kbentry entry;
100 static int lalt; /* only left alt does vt switch */
101
102 release = code & 0x80;
103
104 entry.kb_index = code & 0x7F;
105 entry.kb_table = 0;
106
107 if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
108 sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
109 exit(0);
110 }
111
112 labelval = entry.kb_value;
113
114 switch(labelval) {
115 case K_SHIFT:
116 case K_SHIFTL:
117 MODIFIER(GLUT_ACTIVE_SHIFT);
118 continue;
119 case K_CTRL:
120 MODIFIER(GLUT_ACTIVE_CTRL);
121 continue;
122 case K_ALT:
123 lalt = !release;
124 case K_ALTGR:
125 MODIFIER(GLUT_ACTIVE_ALT);
126 continue;
127 }
128
129 if(lalt && !release) {
130 /* VT switch, we must do it */
131 int vt = -1;
132 struct vt_stat st;
133 if(labelval >= K_F1 && labelval <= K_F12)
134 vt = labelval - K_F1 + 1;
135
136 if(labelval == K_LEFT)
137 if(ioctl(ConsoleFD, VT_GETSTATE, &st) >= 0)
138 vt = st.v_active - 1;
139
140 if(labelval == K_RIGHT)
141 if(ioctl(ConsoleFD, VT_GETSTATE, &st) >= 0)
142 vt = st.v_active + 1;
143
144 if(vt != -1) {
145 if(Swapping)
146 VTSwitch = vt;
147 else
148 if(ioctl(ConsoleFD, VT_ACTIVATE, vt) < 0)
149 sprintf(exiterror, "Error switching console\n");
150 continue;
151 }
152 }
153 write(kbdpipe[1], &code, 1);
154 }
155 }
156
157 static void LedModifier(int led, int release)
158 {
159 static int releaseflag = K_CAPS | K_NUM | K_HOLD;
160 if(release)
161 releaseflag |= led;
162 else
163 if(releaseflag & led) {
164 KeyboardLedState ^= led;
165 releaseflag &= ~led;
166 }
167
168 ioctl(ConsoleFD, KDSKBLED, KeyboardLedState);
169 ioctl(ConsoleFD, KDSETLED, 0x80);
170 }
171
172 static void HandleKeyPress(unsigned char key, int up)
173 {
174 if(up) {
175 if(KeyboardUpFunc)
176 KeyboardUpFunc(key, MouseX, MouseY);
177 } else
178 if(KeyboardFunc)
179 KeyboardFunc(key, MouseX, MouseY);
180 else
181 if(key == 27)
182 exit(0); /* no handler, to provide a way to exit */
183 }
184
185 static void HandleSpecialPress(int key, int up)
186 {
187 if(up) {
188 if(SpecialUpFunc)
189 SpecialUpFunc(key, MouseX, MouseY);
190 } else
191 if(SpecialFunc)
192 SpecialFunc(key, MouseX, MouseY);
193 }
194
195 static void ReleaseStdinKey(void)
196 {
197 if(LastStdinSpecialKey != -1) {
198 HandleSpecialPress(LastStdinSpecialKey, 1);
199 LastStdinSpecialKey = -1;
200 }
201 if(LastStdinCode != -1) {
202 HandleKeyPress(LastStdinCode, 1);
203 LastStdinCode = -1;
204 }
205 }
206
207 #define READKEY read(kbdpipe[0], &code, 1)
208 static int ReadKey(void)
209 {
210 int release, labelval, labelvalnoshift;
211 unsigned char code;
212 int specialkey = 0;
213 struct kbentry entry;
214
215 if(READKEY != 1) {
216 /* if we are reading from stdin, we detect key releases when the key
217 does not repeat after a given timeout */
218 if(ConsoleFD == 0 && LastStdinKeyTime + 100 < glutGet(GLUT_ELAPSED_TIME))
219 ReleaseStdinKey();
220 return 0;
221 }
222
223 if(code == 0)
224 return 0;
225
226 /* stdin input escape code based */
227 if(ConsoleFD == 0) {
228 KeyboardModifiers = 0;
229 altset:
230 if(code == 27 && READKEY == 1) {
231 if(code != 91) {
232 KeyboardModifiers |= GLUT_ACTIVE_ALT;
233 goto altset;
234 }
235 READKEY;
236 switch(code) {
237 case 68:
238 specialkey = GLUT_KEY_LEFT; break;
239 case 65:
240 specialkey = GLUT_KEY_UP; break;
241 case 67:
242 specialkey = GLUT_KEY_RIGHT; break;
243 case 66:
244 specialkey = GLUT_KEY_DOWN; break;
245 case 52:
246 specialkey = GLUT_KEY_END; READKEY; break;
247 case 53:
248 specialkey = GLUT_KEY_PAGE_UP; READKEY; break;
249 case 54:
250 specialkey = GLUT_KEY_PAGE_DOWN; READKEY; break;
251 case 49:
252 READKEY;
253 if(code == 126)
254 specialkey = GLUT_KEY_HOME;
255 else {
256 specialkey = GLUT_KEY_F1 + code - 50;
257 READKEY;
258 }
259 break;
260 case 50:
261 READKEY;
262 if(code == 126)
263 specialkey = GLUT_KEY_INSERT;
264 else {
265 if(code > '1')
266 code--;
267 if(code > '6')
268 code--;
269 if(code > '3') {
270 KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
271 code -= 12;
272 }
273 specialkey = GLUT_KEY_F1 + code - 40;
274 READKEY;
275 }
276 break;
277 case 51:
278 READKEY;
279 if(code == 126) {
280 code = '\b';
281 goto stdkey;
282 }
283 KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
284 specialkey = GLUT_KEY_F1 + code - 45;
285 READKEY;
286 break;
287 case 91:
288 READKEY;
289 specialkey = GLUT_KEY_F1 + code - 65;
290 break;
291 default:
292 return 0;
293 }
294 }
295
296 if(specialkey) {
297 LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME);
298
299 if(LastStdinSpecialKey != specialkey) {
300 ReleaseStdinKey();
301 HandleSpecialPress(specialkey, 0);
302 LastStdinSpecialKey = specialkey;
303 LastStdinKeyTime += 200; /* initial repeat */
304 } else
305 if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF)
306 HandleSpecialPress(specialkey, 0);
307 } else {
308 if(code >= 1 && code <= 26 && code != '\r') {
309 KeyboardModifiers |= GLUT_ACTIVE_CTRL;
310 code += 'a' - 1;
311 }
312 if((code >= 43 && code <= 34) || (code == 60)
313 || (code >= 62 && code <= 90) || (code == 94)
314 || (code == 95) || (code >= 123 && code <= 126))
315 KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
316
317 stdkey:
318 LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME);
319 if(LastStdinCode != code) {
320 ReleaseStdinKey();
321 HandleKeyPress(code, 0);
322 LastStdinCode = code;
323 LastStdinKeyTime += 200; /* initial repeat */
324 } else
325 if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF)
326 HandleSpecialPress(code, 0);
327 }
328 return 1;
329 }
330
331 /* linux kbd reading */
332 release = code & 0x80;
333 code &= 0x7F;
334
335 if(KeyRepeatMode == GLUT_KEY_REPEAT_OFF) {
336 static char keystates[128];
337 if(release)
338 keystates[code] = 0;
339 else {
340 if(keystates[code])
341 return 1;
342 keystates[code] = 1;
343 }
344 }
345
346 entry.kb_index = code;
347 entry.kb_table = 0;
348
349 if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
350 sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
351 exit(0);
352 }
353
354 labelvalnoshift = entry.kb_value;
355
356 if(KeyboardModifiers & GLUT_ACTIVE_SHIFT)
357 entry.kb_table |= K_SHIFTTAB;
358
359 if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
360 sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
361 exit(0);
362 }
363
364 labelval = entry.kb_value;
365
366 switch(labelvalnoshift) {
367 case K_CAPS:
368 LedModifier(LED_CAP, release);
369 return 0;
370 case K_NUM:
371 LedModifier(LED_NUM, release);
372 return 0;
373 case K_HOLD: /* scroll lock suspends glut */
374 LedModifier(LED_SCR, release);
375 while(KeyboardLedState & LED_SCR) {
376 usleep(10000);
377 ReadKey();
378 }
379 return 0;
380 }
381
382 /* we could queue keypresses here */
383 if(KeyboardLedState & LED_SCR)
384 return 0;
385
386 if(labelvalnoshift >= K_F1 && labelvalnoshift <= K_F12)
387 specialkey = GLUT_KEY_F1 + labelvalnoshift - K_F1;
388 else
389 switch(labelvalnoshift) {
390 case K_LEFT:
391 specialkey = GLUT_KEY_LEFT; break;
392 case K_UP:
393 specialkey = GLUT_KEY_UP; break;
394 case K_RIGHT:
395 specialkey = GLUT_KEY_RIGHT; break;
396 case K_DOWN:
397 specialkey = GLUT_KEY_DOWN; break;
398 case K_PGUP:
399 specialkey = GLUT_KEY_PAGE_UP; break;
400 case K_PGDN:
401 specialkey = GLUT_KEY_PAGE_DOWN; break;
402 case K_FIND:
403 specialkey = GLUT_KEY_HOME; break;
404 case K_SELECT:
405 specialkey = GLUT_KEY_END; break;
406 case K_INSERT:
407 specialkey = GLUT_KEY_INSERT; break;
408 case K_REMOVE:
409 labelval = '\b';
410 break;
411 case K_ENTER:
412 labelval = '\r'; break;
413 }
414
415 /* likely a keypad input, but depends on keyboard mapping, ignore */
416 if(labelval == 512)
417 return 1;
418
419 /* dispatch callback */
420 if(specialkey)
421 HandleSpecialPress(specialkey, release);
422 else {
423 char c = labelval;
424
425 if(KeyboardLedState & LED_CAP) {
426 if(c >= 'A' && c <= 'Z')
427 c += 'a' - 'A';
428 else
429 if(c >= 'a' && c <= 'z')
430 c += 'A' - 'a';
431 }
432 HandleKeyPress(c, release);
433 }
434 return 1;
435 }
436
437 void glutIgnoreKeyRepeat(int ignore)
438 {
439 KeyRepeatMode = ignore ? GLUT_KEY_REPEAT_OFF : GLUT_KEY_REPEAT_ON;
440 }
441
442 void glutSetKeyRepeat(int repeatMode)
443 {
444 KeyRepeatMode = repeatMode;
445 }
446
447 void glutForceJoystickFunc(void)
448 {
449 }
450
451 static void HandleMousePress(int button, int pressed)
452 {
453 if(TryMenu(button, pressed))
454 return;
455
456 if(MouseFunc)
457 MouseFunc(button, pressed ? GLUT_DOWN : GLUT_UP, MouseX, MouseY);
458 }
459
460 static int ReadMouse(void)
461 {
462 int l, r, m;
463 static int ll, lm, lr;
464 signed char dx, dy;
465
466 #ifdef HAVE_GPM
467 if(GpmMouse) {
468 Gpm_Event event;
469 struct pollfd pfd;
470 pfd.fd = gpm_fd;
471 pfd.events = POLLIN;
472 if(poll(&pfd, 1, 1) != 1)
473 return 0;
474
475 if(Gpm_GetEvent(&event) != 1)
476 return 0;
477
478 l = event.buttons & GPM_B_LEFT;
479 m = event.buttons & GPM_B_MIDDLE;
480 r = event.buttons & GPM_B_RIGHT;
481
482 /* gpm is weird in that it gives a button number when the button
483 is released, with type set to GPM_UP, this is only a problem
484 if it is the last button released */
485
486 if(event.type & GPM_UP)
487 if(event.buttons == GPM_B_LEFT || event.buttons == GPM_B_MIDDLE ||
488 event.buttons == GPM_B_RIGHT || event.buttons == GPM_B_FOURTH)
489 l = m = r = 0;
490
491 dx = event.dx;
492 dy = event.dy;
493 } else
494 #endif
495 {
496 char data[4];
497
498 if(MouseFD == -1)
499 return 0;
500
501 if(read(MouseFD, data, 4) != 4)
502 return 0;
503
504 l = ((data[0] & 0x20) >> 3);
505 m = ((data[3] & 0x10) >> 3);
506 r = ((data[0] & 0x10) >> 4);
507
508 dx = (((data[0] & 0x03) << 6) | (data[1] & 0x3F));
509 dy = (((data[0] & 0x0C) << 4) | (data[2] & 0x3F));
510 }
511
512 MouseX += dx * MouseSpeed;
513 if(MouseX < 0)
514 MouseX = 0;
515 else
516 if(MouseX >= VarInfo.xres)
517 MouseX = VarInfo.xres - 1;
518
519 MouseY += dy * MouseSpeed;
520 if(MouseY < 0)
521 MouseY = 0;
522 else
523 if(MouseY >= VarInfo.yres)
524 MouseY = VarInfo.yres - 1;
525
526 if(l != ll)
527 HandleMousePress(GLUT_LEFT_BUTTON, l);
528 if(m != lm)
529 HandleMousePress(GLUT_MIDDLE_BUTTON, m);
530 if(r != lr)
531 HandleMousePress(GLUT_RIGHT_BUTTON, r);
532
533 ll = l, lm = m, lr = r;
534
535 if(dx || dy || !MouseVisible) {
536 if(l || m || r) {
537 if(MotionFunc)
538 MotionFunc(MouseX, MouseY);
539 } else
540 if(PassiveMotionFunc)
541 PassiveMotionFunc(MouseX, MouseY);
542
543 EraseCursor();
544
545 MouseVisible = 1;
546
547 if(ActiveMenu)
548 Redisplay = 1;
549 else
550 SwapCursor();
551 }
552
553 LastMouseTime = glutGet(GLUT_ELAPSED_TIME);
554
555 return 1;
556 }
557
558 void ReceiveInput(void)
559 {
560 if(ConsoleFD != -1)
561 while(ReadKey());
562
563 while(ReadMouse());
564
565 /* implement a 2 second timeout on the mouse */
566 if(MouseVisible && glutGet(GLUT_ELAPSED_TIME) - LastMouseTime > 2000) {
567 EraseCursor();
568 MouseVisible = 0;
569 SwapCursor();
570 }
571 }
572
573 static void VTSwitchHandler(int sig)
574 {
575 struct vt_stat st;
576 switch(sig) {
577 case SIGUSR1:
578 ioctl(ConsoleFD, VT_RELDISP, 1);
579 Active = 0;
580 #ifdef MULTIHEAD
581 VisiblePoll = 1;
582 TestVisible();
583 #else
584 VisibleSwitch = 1;
585 Visible = 0;
586 #endif
587 break;
588 case SIGUSR2:
589 ioctl(ConsoleFD, VT_GETSTATE, &st);
590 if(st.v_active)
591 ioctl(ConsoleFD, VT_RELDISP, VT_ACKACQ);
592
593 RestoreColorMap();
594
595 Active = 1;
596 Visible = 1;
597 VisibleSwitch = 1;
598
599 Redisplay = 1;
600 break;
601 }
602 }
603
604 void InitializeVT(int usestdin)
605 {
606 struct termios tio;
607 struct vt_mode vt;
608 char console[128];
609
610 signal(SIGIO, SIG_IGN);
611
612 Active = 1;
613
614 if(usestdin) {
615 ConsoleFD = 0;
616 goto setattribs;
617 }
618
619 /* detect the current vt if it was not specified */
620 if(CurrentVT == 0) {
621 int fd = open("/dev/tty", O_RDWR | O_NDELAY, 0);
622 struct vt_stat st;
623 if(fd == -1) {
624 sprintf(exiterror, "Failed to open /dev/tty\n");
625 exit(0);
626 }
627
628 if(ioctl(fd, VT_GETSTATE, &st) == -1) {
629 fprintf(stderr, "Could not detect current vt, specify with -vt\n");
630 fprintf(stderr, "Defaulting to stdin input\n");
631 ConsoleFD = 0;
632 close(fd);
633 goto setattribs;
634 }
635
636 CurrentVT = st.v_active;
637 close(fd);
638 }
639
640 /* if we close with the modifier set in glutIconifyWindow, we won't
641 get the signal when they are released, so set to zero here */
642 KeyboardModifiers = 0;
643
644 /* open the console tty */
645 sprintf(console, "/dev/tty%d", CurrentVT);
646 ConsoleFD = open(console, O_RDWR | O_NDELAY, 0);
647 if (ConsoleFD < 0) {
648 sprintf(exiterror, "error couldn't open %s,"
649 " defaulting to stdin \n", console);
650 ConsoleFD = 0;
651 goto setattribs;
652 }
653
654 signal(SIGUSR1, VTSwitchHandler);
655 signal(SIGUSR2, VTSwitchHandler);
656
657 if (ioctl(ConsoleFD, VT_GETMODE, &OldVTMode) < 0) {
658 sprintf(exiterror,"Failed to grab %s, defaulting to stdin\n", console);
659 close(ConsoleFD);
660 ConsoleFD = 0;
661 goto setattribs;
662 }
663
664 vt = OldVTMode;
665
666 vt.mode = VT_PROCESS;
667 vt.waitv = 0;
668 vt.relsig = SIGUSR1;
669 vt.acqsig = SIGUSR2;
670 if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
671 sprintf(exiterror, "error: ioctl(VT_SETMODE) failed: %s\n",
672 strerror(errno));
673 close(ConsoleFD);
674 ConsoleFD = 0;
675 exit(1);
676 }
677
678 if (ioctl(ConsoleFD, KDGKBMODE, &OldKDMode) < 0) {
679 sprintf(exiterror, "Warning: ioctl KDGKBMODE failed!\n");
680 OldKDMode = K_XLATE;
681 }
682
683 /* use SIGIO so VT switching can work if the program is locked */
684 signal(SIGIO, KeyboardHandler);
685
686 pipe(kbdpipe);
687
688 if(fcntl(kbdpipe[0], F_SETFL, O_NONBLOCK | O_ASYNC) < 0) {
689 sprintf(exiterror, "Failed to set keyboard to non-blocking\n");
690 exit(0);
691 }
692
693 fcntl(ConsoleFD, F_SETOWN, getpid());
694
695 if(ioctl(ConsoleFD, KDGETMODE, &OldMode) < 0)
696 sprintf(exiterror, "Warning: Failed to get terminal mode\n");
697
698 #ifdef HAVE_GPM
699 if(!GpmMouse)
700 #endif
701 if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0)
702 sprintf(exiterror,"Warning: Failed to set terminal to graphics\n");
703
704 if(ioctl(ConsoleFD, KDSKBMODE, K_MEDIUMRAW) < 0) {
705 sprintf(exiterror, "ioctl KDSKBMODE failed!\n");
706 exit(0);
707 }
708
709 if(ioctl(ConsoleFD, KDGKBLED, &KeyboardLedState) < 0) {
710 sprintf(exiterror, "ioctl KDGKBLED failed!\n");
711 exit(0);
712 }
713
714 setattribs:
715 /* enable async input input */
716 if(fcntl(ConsoleFD, F_SETFL, O_ASYNC) < 0) {
717 sprintf(exiterror, "Failed to set O_ASYNC mode on fd %d\n", ConsoleFD);
718 exit(0);
719 }
720
721 /* save old terminos settings */
722 if (tcgetattr(ConsoleFD, &OldTermios) < 0) {
723 sprintf(exiterror, "tcgetattr failed\n");
724 exit(0);
725 }
726
727 tio = OldTermios;
728
729 /* terminos settings for straight-through mode */
730 tio.c_lflag &= ~(ICANON | ECHO | ISIG);
731 tio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
732 tio.c_iflag |= IGNBRK;
733
734 tio.c_cc[VMIN] = 0;
735 tio.c_cc[VTIME] = 0;
736
737 if (tcsetattr(ConsoleFD, TCSANOW, &tio) < 0) {
738 sprintf(exiterror, "tcsetattr failed\n");
739 exit(0);
740 }
741 }
742
743 void RestoreVT(void)
744 {
745 if(ConsoleFD < 0)
746 return;
747
748 if (tcsetattr(ConsoleFD, TCSANOW, &OldTermios) < 0)
749 sprintf(exiterror, "tcsetattr failed\n");
750
751 /* setting the mode to text from graphics restores the colormap */
752 if(
753 #ifdef HAVE_GPM
754 !GpmMouse ||
755 #endif
756 ConsoleFD == 0)
757 if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0)
758 goto skipioctl; /* no need to fail twice */
759
760 if(ioctl(ConsoleFD, KDSETMODE, OldMode) < 0)
761 fprintf(stderr, "ioctl KDSETMODE failed!\n");
762
763 skipioctl:
764
765 if(ConsoleFD == 0)
766 return;
767
768 /* restore keyboard state */
769 if (ioctl(ConsoleFD, VT_SETMODE, &OldVTMode) < 0)
770 fprintf(stderr, "Failed to set vtmode\n");
771
772 if (ioctl(ConsoleFD, KDSKBMODE, OldKDMode) < 0)
773 fprintf(stderr, "ioctl KDSKBMODE failed!\n");
774
775 close(ConsoleFD);
776
777 close(kbdpipe[0]);
778 close(kbdpipe[1]);
779 }
780
781 void InitializeMouse(void)
782 {
783 #ifdef HAVE_GPM
784 if(!GpmMouse)
785 #endif
786 {
787 const char *mousedev = getenv("MOUSE");
788 if(!mousedev)
789 mousedev = MOUSEDEV;
790 if((MouseFD = open(mousedev, O_RDONLY | O_NONBLOCK)) >= 0) {
791 if(!MouseSpeed)
792 MouseSpeed = 1;
793 NumMouseButtons = 3;
794 return;
795 }
796 }
797 #ifdef HAVE_GPM
798 {
799 Gpm_Connect conn;
800 int c;
801 conn.eventMask = ~0; /* Want to know about all the events */
802 conn.defaultMask = 0; /* don't handle anything by default */
803 conn.minMod = 0; /* want everything */
804 conn.maxMod = ~0; /* all modifiers included */
805 if(Gpm_Open(&conn, 0) != -1) {
806 if(!MouseSpeed)
807 MouseSpeed = 8;
808 NumMouseButtons = 3;
809 return;
810 }
811 fprintf(stderr, "Cannot open gpmctl.\n");
812 }
813 #endif
814 fprintf(stderr,"Cannot open %s.\n"
815 "Continuing without Mouse\n", MOUSEDEV);
816 }
817
818 void CloseMouse(void)
819 {
820 #ifdef HAVE_GPM
821 if(GpmMouse) {
822 if(NumMouseButtons)
823 Gpm_Close();
824 } else
825 #endif
826 if(MouseFD >= 0)
827 close(MouseFD);
828 }