comparison src/video/fbcon/SDL_fbevents.c @ 1780:7a36f01acf71

Fixed bug #49 Added support for non-blocking VT switching on the framebuffer console.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 08 May 2006 05:33:02 +0000
parents e28233f37f8c
children d8030f368b84
comparison
equal deleted inserted replaced
1779:67fc81efcfc3 1780:7a36f01acf71
207 if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { 207 if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {
208 FB_CloseKeyboard(this); 208 FB_CloseKeyboard(this);
209 SDL_SetError("Unable to set keyboard in graphics mode"); 209 SDL_SetError("Unable to set keyboard in graphics mode");
210 return(-1); 210 return(-1);
211 } 211 }
212 /* Prevent switching the virtual terminal */
213 ioctl(keyboard_fd, VT_LOCKSWITCH, 1);
212 } 214 }
213 return(keyboard_fd); 215 return(keyboard_fd);
214 } 216 }
215 217
216 void FB_LeaveGraphicsMode(_THIS) 218 void FB_LeaveGraphicsMode(_THIS)
220 ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); 222 ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
221 tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); 223 tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
222 saved_kbd_mode = -1; 224 saved_kbd_mode = -1;
223 225
224 /* Head back over to the original virtual terminal */ 226 /* Head back over to the original virtual terminal */
227 ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);
225 if ( saved_vt > 0 ) { 228 if ( saved_vt > 0 ) {
226 ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); 229 ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
227 } 230 }
228 } 231 }
229 } 232 }
454 {0xf3,200,0xf3,100,0xf3,80} 457 {0xf3,200,0xf3,100,0xf3,80}
455 Reset mouse device: 458 Reset mouse device:
456 {0xFF} 459 {0xFF}
457 */ 460 */
458 Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; 461 Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
459 Uint8 reset = 0xff; 462 /*Uint8 reset = 0xff;*/
460 fd_set fdset; 463 fd_set fdset;
461 struct timeval tv; 464 struct timeval tv;
462 int retval = 0; 465 int retval = 0;
463 466
464 if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { 467 if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
914 start = 0; 917 start = 0;
915 } 918 }
916 return; 919 return;
917 } 920 }
918 921
919 /* Handle switching to another VC, returns when our VC is back. 922 /* Handle switching to another VC, returns when our VC is back */
920 This isn't necessarily the best solution. For SDL 1.3 we need 923 static void switch_vt_prep(_THIS)
921 a way of notifying the application when we lose access to the 924 {
922 video hardware and when we regain it. 925 SDL_Surface *screen = SDL_VideoSurface;
923 */ 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 SDL_PrivateAppActive(1, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS));
957 }
924 static void switch_vt(_THIS, unsigned short which) 958 static void switch_vt(_THIS, unsigned short which)
925 { 959 {
926 struct fb_var_screeninfo vinfo;
927 struct vt_stat vtstate; 960 struct vt_stat vtstate;
928 unsigned short v_active;
929 __u16 saved_pal[3*256];
930 SDL_Surface *screen;
931 Uint32 screen_arealen;
932 Uint8 *screen_contents = NULL;
933 961
934 /* Figure out whether or not we're switching to a new console */ 962 /* Figure out whether or not we're switching to a new console */
935 if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) || 963 if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
936 (which == vtstate.v_active) ) { 964 (which == vtstate.v_active) ) {
937 return; 965 return;
938 } 966 }
939 v_active = vtstate.v_active; 967
940 968 /* New console, switch to it */
941 /* Save the contents of the screen, and go to text mode */
942 SDL_mutexP(hw_lock); 969 SDL_mutexP(hw_lock);
943 wait_idle(this); 970 switch_vt_prep(this);
944 screen = SDL_VideoSurface;
945 if ( !SDL_ShadowSurface ) {
946 screen_arealen = (screen->h*screen->pitch);
947 screen_contents = (Uint8 *)SDL_malloc(screen_arealen);
948 if ( screen_contents ) {
949 SDL_memcpy(screen_contents, (Uint8 *)screen->pixels + screen->offset, screen_arealen);
950 }
951 }
952 FB_SavePaletteTo(this, 256, saved_pal);
953 ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo);
954 ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
955
956 /* New console, switch to it */
957 if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) { 971 if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) {
958 /* Wait for our console to be activated again */
959 ioctl(keyboard_fd, VT_WAITACTIVE, which); 972 ioctl(keyboard_fd, VT_WAITACTIVE, which);
960 while ( ioctl(keyboard_fd, VT_WAITACTIVE, v_active) < 0 ) { 973 switched_away = 1;
961 if ( (errno != EINTR) && (errno != EAGAIN) ) {
962 /* Unknown VT error - cancel this */
963 break;
964 }
965 SDL_Delay(500);
966 }
967 }
968
969 /* Restore graphics mode and the contents of the screen */
970 ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
971 ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo);
972 FB_RestorePaletteFrom(this, 256, saved_pal);
973 if ( screen_contents ) {
974 SDL_memcpy((Uint8 *)screen->pixels + screen->offset, screen_contents, screen_arealen);
975 SDL_free(screen_contents);
976 } else { 974 } else {
977 SDL_UpdateRect(screen, 0, 0, 0, 0); 975 switch_vt_done(this);
978 } 976 }
979 SDL_mutexV(hw_lock); 977 SDL_mutexV(hw_lock);
980 } 978 }
981 979
982 static void handle_keyboard(_THIS) 980 static void handle_keyboard(_THIS)
1030 fd_set fdset; 1028 fd_set fdset;
1031 int max_fd; 1029 int max_fd;
1032 static struct timeval zero; 1030 static struct timeval zero;
1033 1031
1034 do { 1032 do {
1033 if ( switched_away ) {
1034 struct vt_stat vtstate;
1035
1036 SDL_mutexP(hw_lock);
1037 if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) &&
1038 vtstate.v_active == current_vt ) {
1039 switched_away = 0;
1040 switch_vt_done(this);
1041 }
1042 SDL_mutexV(hw_lock);
1043 }
1044
1035 posted = 0; 1045 posted = 0;
1036 1046
1037 FD_ZERO(&fdset); 1047 FD_ZERO(&fdset);
1038 max_fd = 0; 1048 max_fd = 0;
1039 if ( keyboard_fd >= 0 ) { 1049 if ( keyboard_fd >= 0 ) {