Mercurial > sdl-ios-xcode
comparison src/video/fbcon/SDL_fbevents.c @ 1659:14717b52abc0 SDL-1.3
Merge trunk-1.3-3
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 17 May 2006 08:18:28 +0000 |
parents | 980d2a0dc2a3 |
children | 782fd950bd46 |
comparison
equal
deleted
inserted
replaced
1658:e49147870aac | 1659:14717b52abc0 |
---|---|
53 | 53 |
54 #ifndef GPM_NODE_FIFO | 54 #ifndef GPM_NODE_FIFO |
55 #define GPM_NODE_FIFO "/dev/gpmdata" | 55 #define GPM_NODE_FIFO "/dev/gpmdata" |
56 #endif | 56 #endif |
57 | 57 |
58 /*#define DEBUG_KEYBOARD*/ | |
59 /*#define DEBUG_MOUSE*/ | |
58 | 60 |
59 /* The translation tables from a console scancode to a SDL keysym */ | 61 /* The translation tables from a console scancode to a SDL keysym */ |
60 #define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) | 62 #define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) |
61 static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; | 63 static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; |
62 static SDLKey keymap[128]; | 64 static SDLKey keymap[128]; |
205 if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { | 207 if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { |
206 FB_CloseKeyboard(this); | 208 FB_CloseKeyboard(this); |
207 SDL_SetError("Unable to set keyboard in graphics mode"); | 209 SDL_SetError("Unable to set keyboard in graphics mode"); |
208 return(-1); | 210 return(-1); |
209 } | 211 } |
212 /* Prevent switching the virtual terminal */ | |
213 ioctl(keyboard_fd, VT_LOCKSWITCH, 1); | |
210 } | 214 } |
211 return(keyboard_fd); | 215 return(keyboard_fd); |
212 } | 216 } |
213 | 217 |
214 void FB_LeaveGraphicsMode(_THIS) | 218 void FB_LeaveGraphicsMode(_THIS) |
218 ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); | 222 ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); |
219 tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); | 223 tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); |
220 saved_kbd_mode = -1; | 224 saved_kbd_mode = -1; |
221 | 225 |
222 /* Head back over to the original virtual terminal */ | 226 /* Head back over to the original virtual terminal */ |
227 ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); | |
223 if ( saved_vt > 0 ) { | 228 if ( saved_vt > 0 ) { |
224 ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); | 229 ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); |
225 } | 230 } |
226 } | 231 } |
227 } | 232 } |
278 } | 283 } |
279 } | 284 } |
280 } | 285 } |
281 if ( keyboard_fd < 0 ) { | 286 if ( keyboard_fd < 0 ) { |
282 /* Last resort, maybe our tty is a usable VT */ | 287 /* Last resort, maybe our tty is a usable VT */ |
283 current_vt = 0; | 288 struct vt_stat vtstate; |
289 | |
284 keyboard_fd = open("/dev/tty", O_RDWR); | 290 keyboard_fd = open("/dev/tty", O_RDWR); |
291 | |
292 if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { | |
293 current_vt = vtstate.v_active; | |
294 } else { | |
295 current_vt = 0; | |
296 } | |
285 } | 297 } |
286 #ifdef DEBUG_KEYBOARD | 298 #ifdef DEBUG_KEYBOARD |
287 fprintf(stderr, "Current VT: %d\n", current_vt); | 299 fprintf(stderr, "Current VT: %d\n", current_vt); |
288 #endif | 300 #endif |
289 saved_kbd_mode = -1; | 301 saved_kbd_mode = -1; |
358 } | 370 } |
359 return pid; | 371 return pid; |
360 } | 372 } |
361 | 373 |
362 /* Returns true if /dev/gpmdata is being written to by gpm */ | 374 /* Returns true if /dev/gpmdata is being written to by gpm */ |
363 static int gpm_available(void) | 375 static int gpm_available(char *proto, size_t protolen) |
364 { | 376 { |
365 int available; | 377 int available; |
366 DIR *proc; | 378 DIR *proc; |
367 int pid; | 379 int pid; |
368 int cmdline, len, arglen; | 380 int cmdline, len, arglen; |
369 char path[PATH_MAX]; | 381 char path[PATH_MAX]; |
370 char args[PATH_MAX], *arg; | 382 char args[PATH_MAX], *arg; |
371 | 383 |
372 /* Don't bother looking if the fifo isn't there */ | 384 /* Don't bother looking if the fifo isn't there */ |
385 #ifdef DEBUG_MOUSE | |
386 fprintf(stderr,"testing gpm\n"); | |
387 #endif | |
373 if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { | 388 if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { |
374 return(0); | 389 return(0); |
375 } | 390 } |
376 | 391 |
377 available = 0; | 392 available = 0; |
378 proc = opendir("/proc"); | 393 proc = opendir("/proc"); |
379 if ( proc ) { | 394 if ( proc ) { |
380 while ( (pid=find_pid(proc, "gpm")) > 0 ) { | 395 char raw_proto[10] = { '\0' }; |
396 char repeat_proto[10] = { '\0' }; | |
397 while ( !available && (pid=find_pid(proc, "gpm")) > 0 ) { | |
381 SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid); | 398 SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid); |
382 cmdline = open(path, O_RDONLY, 0); | 399 cmdline = open(path, O_RDONLY, 0); |
383 if ( cmdline >= 0 ) { | 400 if ( cmdline >= 0 ) { |
384 len = read(cmdline, args, sizeof(args)); | 401 len = read(cmdline, args, sizeof(args)); |
385 arg = args; | 402 arg = args; |
386 while ( len > 0 ) { | 403 while ( len > 0 ) { |
387 if ( SDL_strcmp(arg, "-R") == 0 ) { | 404 arglen = SDL_strlen(arg)+1; |
405 #ifdef DEBUG_MOUSE | |
406 fprintf(stderr,"gpm arg %s len %d\n",arg,arglen); | |
407 #endif | |
408 if ( SDL_strcmp(arg, "-t") == 0) { | |
409 /* protocol string, keep it for later */ | |
410 char *t, *s; | |
411 t = arg + arglen; | |
412 s = SDL_strchr(t, ' '); | |
413 if (s) *s = 0; | |
414 SDL_strlcpy(raw_proto, t, SDL_arraysize(raw_proto)); | |
415 if (s) *s = ' '; | |
416 } | |
417 if ( SDL_strncmp(arg, "-R", 2) == 0 ) { | |
418 char *t, *s; | |
388 available = 1; | 419 available = 1; |
420 t = arg + 2; | |
421 s = SDL_strchr(t, ' '); | |
422 if (s) *s = 0; | |
423 SDL_strlcpy(repeat_proto, t, SDL_arraysize(repeat_proto)); | |
424 if (s) *s = ' '; | |
389 } | 425 } |
390 arglen = SDL_strlen(arg)+1; | |
391 len -= arglen; | 426 len -= arglen; |
392 arg += arglen; | 427 arg += arglen; |
393 } | 428 } |
394 close(cmdline); | 429 close(cmdline); |
395 } | 430 } |
396 } | 431 } |
397 closedir(proc); | 432 closedir(proc); |
433 | |
434 if ( available ) { | |
435 if ( SDL_strcmp(repeat_proto, "raw") == 0 ) { | |
436 SDL_strlcpy(proto, raw_proto, protolen); | |
437 } else if ( *repeat_proto ) { | |
438 SDL_strlcpy(proto, repeat_proto, protolen); | |
439 } else { | |
440 SDL_strlcpy(proto, "msc", protolen); | |
441 } | |
442 } | |
398 } | 443 } |
399 return available; | 444 return available; |
400 } | 445 } |
401 | 446 |
402 | 447 |
412 {0xf3,200,0xf3,100,0xf3,80} | 457 {0xf3,200,0xf3,100,0xf3,80} |
413 Reset mouse device: | 458 Reset mouse device: |
414 {0xFF} | 459 {0xFF} |
415 */ | 460 */ |
416 Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; | 461 Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; |
417 Uint8 reset = 0xff; | 462 /*Uint8 reset = 0xff;*/ |
418 fd_set fdset; | 463 fd_set fdset; |
419 struct timeval tv; | 464 struct timeval tv; |
420 int retval = 0; | 465 int retval = 0; |
421 | 466 |
422 if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { | 467 if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { |
550 static const char *ps2mice[] = { | 595 static const char *ps2mice[] = { |
551 "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL | 596 "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL |
552 }; | 597 }; |
553 /* First try to use GPM in repeater mode */ | 598 /* First try to use GPM in repeater mode */ |
554 if ( mouse_fd < 0 ) { | 599 if ( mouse_fd < 0 ) { |
555 if ( gpm_available() ) { | 600 char proto[10]; |
601 if ( gpm_available(proto, SDL_arraysize(proto)) ) { | |
556 mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); | 602 mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); |
557 if ( mouse_fd >= 0 ) { | 603 if ( mouse_fd >= 0 ) { |
604 if ( SDL_strcmp(proto, "msc") == 0 ) { | |
605 mouse_drv = MOUSE_MSC; | |
606 } else if ( SDL_strcmp(proto, "ps2") == 0 ) { | |
607 mouse_drv = MOUSE_PS2; | |
608 } else if ( SDL_strcmp(proto, "imps2") == 0 ) { | |
609 mouse_drv = MOUSE_IMPS2; | |
610 } else if ( SDL_strcmp(proto, "ms") == 0 || | |
611 SDL_strcmp(proto, "bare") == 0 ) { | |
612 mouse_drv = MOUSE_MS; | |
613 } else if ( SDL_strcmp(proto, "bm") == 0 ) { | |
614 mouse_drv = MOUSE_BM; | |
615 } else { | |
616 /* Unknown protocol... */ | |
558 #ifdef DEBUG_MOUSE | 617 #ifdef DEBUG_MOUSE |
559 fprintf(stderr, "Using GPM mouse\n"); | 618 fprintf(stderr, "GPM mouse using unknown protocol = %s\n", proto); |
560 #endif | 619 #endif |
561 mouse_drv = MOUSE_MSC; | 620 close(mouse_fd); |
562 } | 621 mouse_fd = -1; |
622 } | |
623 } | |
624 #ifdef DEBUG_MOUSE | |
625 if ( mouse_fd >= 0 ) { | |
626 fprintf(stderr, "Using GPM mouse, protocol = %s\n", proto); | |
627 } | |
628 #endif /* DEBUG_MOUSE */ | |
563 } | 629 } |
564 } | 630 } |
565 /* Now try to use a modern PS/2 mouse */ | 631 /* Now try to use a modern PS/2 mouse */ |
566 for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) { | 632 for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) { |
567 mouse_fd = open(ps2mice[i], O_RDWR, 0); | 633 mouse_fd = open(ps2mice[i], O_RDWR, 0); |
851 start = 0; | 917 start = 0; |
852 } | 918 } |
853 return; | 919 return; |
854 } | 920 } |
855 | 921 |
856 /* Handle switching to another VC, returns when our VC is back. | 922 /* Handle switching to another VC, returns when our VC is back */ |
857 This isn't necessarily the best solution. For SDL 1.3 we need | 923 static void switch_vt_prep(_THIS) |
858 a way of notifying the application when we lose access to the | 924 { |
859 video hardware and when we regain it. | 925 SDL_Surface *screen = SDL_VideoSurface; |
860 */ | 926 |
927 SDL_PrivateAppActive(0, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); | |
928 | |
929 /* Save the contents of the screen, and go to text mode */ | |
930 wait_idle(this); | |
931 screen_arealen = ((screen->h + (2*this->offset_y)) * screen->pitch); | |
932 screen_contents = (Uint8 *)SDL_malloc(screen_arealen); | |
933 if ( screen_contents ) { | |
934 SDL_memcpy(screen_contents, screen->pixels, screen_arealen); | |
935 } | |
936 FB_SavePaletteTo(this, 256, screen_palette); | |
937 ioctl(console_fd, FBIOGET_VSCREENINFO, &screen_vinfo); | |
938 ioctl(keyboard_fd, KDSETMODE, KD_TEXT); | |
939 ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); | |
940 } | |
941 static void switch_vt_done(_THIS) | |
942 { | |
943 SDL_Surface *screen = SDL_VideoSurface; | |
944 | |
945 /* Restore graphics mode and the contents of the screen */ | |
946 ioctl(keyboard_fd, VT_LOCKSWITCH, 1); | |
947 ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS); | |
948 ioctl(console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo); | |
949 FB_RestorePaletteFrom(this, 256, screen_palette); | |
950 if ( screen_contents ) { | |
951 SDL_memcpy(screen->pixels, screen_contents, screen_arealen); | |
952 SDL_free(screen_contents); | |
953 screen_contents = NULL; | |
954 } | |
955 | |
956 /* Get updates to the shadow surface while switched away */ | |
957 if ( SDL_ShadowSurface ) { | |
958 SDL_UpdateRect(SDL_ShadowSurface, 0, 0, 0, 0); | |
959 } | |
960 | |
961 SDL_PrivateAppActive(1, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); | |
962 } | |
861 static void switch_vt(_THIS, unsigned short which) | 963 static void switch_vt(_THIS, unsigned short which) |
862 { | 964 { |
863 struct fb_var_screeninfo vinfo; | |
864 struct vt_stat vtstate; | 965 struct vt_stat vtstate; |
865 unsigned short v_active; | |
866 __u16 saved_pal[3*256]; | |
867 SDL_Surface *screen; | |
868 Uint32 screen_arealen; | |
869 Uint8 *screen_contents = NULL; | |
870 | 966 |
871 /* Figure out whether or not we're switching to a new console */ | 967 /* Figure out whether or not we're switching to a new console */ |
872 if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) || | 968 if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) || |
873 (which == vtstate.v_active) ) { | 969 (which == vtstate.v_active) ) { |
874 return; | 970 return; |
875 } | 971 } |
876 v_active = vtstate.v_active; | 972 |
877 | 973 /* New console, switch to it */ |
878 /* Save the contents of the screen, and go to text mode */ | |
879 SDL_mutexP(hw_lock); | 974 SDL_mutexP(hw_lock); |
880 wait_idle(this); | 975 switch_vt_prep(this); |
881 screen = SDL_VideoSurface; | |
882 if ( !SDL_ShadowSurface ) { | |
883 screen_arealen = (screen->h*screen->pitch); | |
884 screen_contents = (Uint8 *)SDL_malloc(screen_arealen); | |
885 if ( screen_contents ) { | |
886 SDL_memcpy(screen_contents, (Uint8 *)screen->pixels + screen->offset, screen_arealen); | |
887 } | |
888 } | |
889 FB_SavePaletteTo(this, 256, saved_pal); | |
890 ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo); | |
891 ioctl(keyboard_fd, KDSETMODE, KD_TEXT); | |
892 | |
893 /* New console, switch to it */ | |
894 if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) { | 976 if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) { |
895 /* Wait for our console to be activated again */ | |
896 ioctl(keyboard_fd, VT_WAITACTIVE, which); | 977 ioctl(keyboard_fd, VT_WAITACTIVE, which); |
897 while ( ioctl(keyboard_fd, VT_WAITACTIVE, v_active) < 0 ) { | 978 switched_away = 1; |
898 if ( (errno != EINTR) && (errno != EAGAIN) ) { | |
899 /* Unknown VT error - cancel this */ | |
900 break; | |
901 } | |
902 SDL_Delay(500); | |
903 } | |
904 } | |
905 | |
906 /* Restore graphics mode and the contents of the screen */ | |
907 ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS); | |
908 ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo); | |
909 FB_RestorePaletteFrom(this, 256, saved_pal); | |
910 if ( screen_contents ) { | |
911 SDL_memcpy((Uint8 *)screen->pixels + screen->offset, screen_contents, screen_arealen); | |
912 SDL_free(screen_contents); | |
913 } else { | 979 } else { |
914 SDL_UpdateRect(screen, 0, 0, 0, 0); | 980 switch_vt_done(this); |
915 } | 981 } |
916 SDL_mutexV(hw_lock); | 982 SDL_mutexV(hw_lock); |
917 } | 983 } |
918 | 984 |
919 static void handle_keyboard(_THIS) | 985 static void handle_keyboard(_THIS) |
967 fd_set fdset; | 1033 fd_set fdset; |
968 int max_fd; | 1034 int max_fd; |
969 static struct timeval zero; | 1035 static struct timeval zero; |
970 | 1036 |
971 do { | 1037 do { |
1038 if ( switched_away ) { | |
1039 struct vt_stat vtstate; | |
1040 | |
1041 SDL_mutexP(hw_lock); | |
1042 if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) && | |
1043 vtstate.v_active == current_vt ) { | |
1044 switched_away = 0; | |
1045 switch_vt_done(this); | |
1046 } | |
1047 SDL_mutexV(hw_lock); | |
1048 } | |
1049 | |
972 posted = 0; | 1050 posted = 0; |
973 | 1051 |
974 FD_ZERO(&fdset); | 1052 FD_ZERO(&fdset); |
975 max_fd = 0; | 1053 max_fd = 0; |
976 if ( keyboard_fd >= 0 ) { | 1054 if ( keyboard_fd >= 0 ) { |
1035 keymap[i] = SDLK_RSUPER; | 1113 keymap[i] = SDLK_RSUPER; |
1036 break; | 1114 break; |
1037 case SCANCODE_LEFTWIN: | 1115 case SCANCODE_LEFTWIN: |
1038 keymap[i] = SDLK_LSUPER; | 1116 keymap[i] = SDLK_LSUPER; |
1039 break; | 1117 break; |
1118 case SCANCODE_LEFTALT: | |
1119 keymap[i] = SDLK_LALT; | |
1120 break; | |
1121 case SCANCODE_RIGHTALT: | |
1122 keymap[i] = SDLK_RALT; | |
1123 break; | |
1040 case 127: | 1124 case 127: |
1041 keymap[i] = SDLK_MENU; | 1125 keymap[i] = SDLK_MENU; |
1042 break; | 1126 break; |
1043 /* this should take care of all standard ascii keys */ | 1127 /* this should take care of all standard ascii keys */ |
1044 default: | 1128 default: |
1136 map |= (1<<KG_SHIFT); | 1220 map |= (1<<KG_SHIFT); |
1137 } | 1221 } |
1138 if ( modstate & KMOD_CTRL ) { | 1222 if ( modstate & KMOD_CTRL ) { |
1139 map |= (1<<KG_CTRL); | 1223 map |= (1<<KG_CTRL); |
1140 } | 1224 } |
1141 if ( modstate & KMOD_ALT ) { | 1225 if ( modstate & KMOD_LALT ) { |
1142 map |= (1<<KG_ALT); | 1226 map |= (1<<KG_ALT); |
1143 } | 1227 } |
1144 if ( modstate & KMOD_MODE ) { | 1228 if ( modstate & KMOD_RALT ) { |
1145 map |= (1<<KG_ALTGR); | 1229 map |= (1<<KG_ALTGR); |
1146 } | 1230 } |
1147 if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { | 1231 if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { |
1148 if ( modstate & KMOD_CAPS ) { | 1232 if ( modstate & KMOD_CAPS ) { |
1149 map ^= (1<<KG_SHIFT); | 1233 map ^= (1<<KG_SHIFT); |