⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_fbevents.c

📁 linux下面的一个开源的多媒体中间件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    SDL - Simple DirectMedia Layer    Copyright (C) 1997-2006 Sam Lantinga    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Lesser General Public    License as published by the Free Software Foundation; either    version 2.1 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Lesser General Public License for more details.    You should have received a copy of the GNU Lesser General Public    License along with this library; if not, write to the Free Software    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA    Sam Lantinga    slouken@libsdl.org*/#include "SDL_config.h"/* Handle the event stream, converting console events into SDL events */#include <stdio.h>#include <sys/types.h>#include <sys/time.h>#include <sys/ioctl.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <limits.h>/* For parsing /proc */#include <dirent.h>#include <ctype.h>#include <linux/vt.h>#include <linux/kd.h>#include <linux/keyboard.h>#include "SDL_timer.h"#include "SDL_mutex.h"#include "../SDL_sysvideo.h"#include "../../events/SDL_sysevents.h"#include "../../events/SDL_events_c.h"#include "SDL_fbvideo.h"#include "SDL_fbevents_c.h"#include "SDL_fbkeys.h"#include "SDL_fbelo.h"#ifndef GPM_NODE_FIFO#define GPM_NODE_FIFO	"/dev/gpmdata"#endif/*#define DEBUG_KEYBOARD*//*#define DEBUG_MOUSE*//* The translation tables from a console scancode to a SDL keysym */#define NUM_VGAKEYMAPS	(1<<KG_CAPSSHIFT)static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];static SDLKey keymap[128];static Uint16 keymap_temp[128]; /* only used at startup */static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);/* Ugh, we have to duplicate the kernel's keysym mapping code...   Oh, it's not so bad. :-)   FIXME: Add keyboard LED handling code */static void FB_vgainitkeymaps(int fd){	struct kbentry entry;	int map, i;	/* Don't do anything if we are passed a closed keyboard */	if ( fd < 0 ) {		return;	}	/* Load all the keysym mappings */	for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {		SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));		for ( i=0; i<NR_KEYS; ++i ) {			entry.kb_table = map;			entry.kb_index = i;			if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {				/* fill keytemp. This replaces SDL_fbkeys.h */				if ( (map == 0) && (i<128) ) {					keymap_temp[i] = entry.kb_value;				}				/* The "Enter" key is a special case */				if ( entry.kb_value == K_ENTER ) {					entry.kb_value = K(KT_ASCII,13);				}				/* Handle numpad specially as well */				if ( KTYP(entry.kb_value) == KT_PAD ) {					switch ( entry.kb_value ) {					case K_P0:					case K_P1:					case K_P2:					case K_P3:					case K_P4:					case K_P5:					case K_P6:					case K_P7:					case K_P8:					case K_P9:						vga_keymap[map][i]=entry.kb_value;						vga_keymap[map][i]+= '0';						break;										case K_PPLUS:						vga_keymap[map][i]=K(KT_ASCII,'+');						break;										case K_PMINUS:						vga_keymap[map][i]=K(KT_ASCII,'-');						break;										case K_PSTAR:						vga_keymap[map][i]=K(KT_ASCII,'*');						break;										case K_PSLASH:						vga_keymap[map][i]=K(KT_ASCII,'/');						break;										case K_PENTER:						vga_keymap[map][i]=K(KT_ASCII,'\r');						break;										case K_PCOMMA:						vga_keymap[map][i]=K(KT_ASCII,',');						break;										case K_PDOT:						vga_keymap[map][i]=K(KT_ASCII,'.');						break;					default:						break;					}				}				/* Do the normal key translation */				if ( (KTYP(entry.kb_value) == KT_LATIN) ||					 (KTYP(entry.kb_value) == KT_ASCII) ||					 (KTYP(entry.kb_value) == KT_LETTER) ) {					vga_keymap[map][i] = entry.kb_value;				}			}		}	}}int FB_InGraphicsMode(_THIS){	return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));}int FB_EnterGraphicsMode(_THIS){	struct termios keyboard_termios;	/* Set medium-raw keyboard mode */	if ( (keyboard_fd >= 0) && !FB_InGraphicsMode(this) ) {		/* Switch to the correct virtual terminal */		if ( current_vt > 0 ) {			struct vt_stat vtstate;			if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {				saved_vt = vtstate.v_active;			}			if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) {				ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);			}		}		/* Set the terminal input mode */		if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {			SDL_SetError("Unable to get terminal attributes");			if ( keyboard_fd > 0 ) {				close(keyboard_fd);			}			keyboard_fd = -1;			return(-1);		}		if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {			SDL_SetError("Unable to get current keyboard mode");			if ( keyboard_fd > 0 ) {				close(keyboard_fd);			}			keyboard_fd = -1;			return(-1);		}		keyboard_termios = saved_kbd_termios;		keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);		keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);		keyboard_termios.c_cc[VMIN] = 0;		keyboard_termios.c_cc[VTIME] = 0;		if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {			FB_CloseKeyboard(this);			SDL_SetError("Unable to set terminal attributes");			return(-1);		}		/* This will fail if we aren't root or this isn't our tty */		if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {			FB_CloseKeyboard(this);			SDL_SetError("Unable to set keyboard in raw mode");			return(-1);		}		if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {			FB_CloseKeyboard(this);			SDL_SetError("Unable to set keyboard in graphics mode");			return(-1);		}		/* Prevent switching the virtual terminal */		ioctl(keyboard_fd, VT_LOCKSWITCH, 1);	}	return(keyboard_fd);}void FB_LeaveGraphicsMode(_THIS){	if ( FB_InGraphicsMode(this) ) {		ioctl(keyboard_fd, KDSETMODE, KD_TEXT);		ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);		tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);		saved_kbd_mode = -1;		/* Head back over to the original virtual terminal */		ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1);		if ( saved_vt > 0 ) {			ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);		}	}}void FB_CloseKeyboard(_THIS){	if ( keyboard_fd >= 0 ) {		FB_LeaveGraphicsMode(this);		if ( keyboard_fd > 0 ) {			close(keyboard_fd);		}	}	keyboard_fd = -1;}int FB_OpenKeyboard(_THIS){	/* Open only if not already opened */ 	if ( keyboard_fd < 0 ) {		static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };		static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };		int i, tty0_fd;		/* Try to query for a free virtual terminal */		tty0_fd = -1;		for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {			tty0_fd = open(tty0[i], O_WRONLY, 0);		}		if ( tty0_fd < 0 ) {			tty0_fd = dup(0); /* Maybe stdin is a VT? */		}		ioctl(tty0_fd, VT_OPENQRY, &current_vt);		close(tty0_fd);		if ( (geteuid() == 0) && (current_vt > 0) ) {			for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) {				char vtpath[12];				SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], current_vt);				keyboard_fd = open(vtpath, O_RDWR, 0);#ifdef DEBUG_KEYBOARD				fprintf(stderr, "vtpath = %s, fd = %d\n",					vtpath, keyboard_fd);#endif /* DEBUG_KEYBOARD */				/* This needs to be our controlling tty				   so that the kernel ioctl() calls work				*/				if ( keyboard_fd >= 0 ) {					tty0_fd = open("/dev/tty", O_RDWR, 0);					if ( tty0_fd >= 0 ) {						ioctl(tty0_fd, TIOCNOTTY, 0);						close(tty0_fd);					}				}			}		} 		if ( keyboard_fd < 0 ) {			/* Last resort, maybe our tty is a usable VT */			struct vt_stat vtstate;			keyboard_fd = open("/dev/tty", O_RDWR);			if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {				current_vt = vtstate.v_active;			} else {				current_vt = 0;			} 		}#ifdef DEBUG_KEYBOARD		fprintf(stderr, "Current VT: %d\n", current_vt);#endif 		saved_kbd_mode = -1;		/* Make sure that our input is a console terminal */		{ int dummy;		  if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {			close(keyboard_fd);			keyboard_fd = -1;			SDL_SetError("Unable to open a console terminal");		  }		}		/* Set up keymap */		FB_vgainitkeymaps(keyboard_fd); 	} 	return(keyboard_fd);}static enum {	MOUSE_NONE = -1,	MOUSE_MSC,	/* Note: GPM uses the MSC protocol */	MOUSE_PS2,	MOUSE_IMPS2,	MOUSE_MS,	MOUSE_BM,	MOUSE_ELO,	MOUSE_TSLIB,	NUM_MOUSE_DRVS} mouse_drv = MOUSE_NONE;void FB_CloseMouse(_THIS){#if SDL_INPUT_TSLIB	if (ts_dev != NULL) {		ts_close(ts_dev);		ts_dev = NULL;		mouse_fd = -1;	}#endif /* SDL_INPUT_TSLIB */	if ( mouse_fd > 0 ) {		close(mouse_fd);	}	mouse_fd = -1;}/* Returns processes listed in /proc with the desired name */static int find_pid(DIR *proc, const char *wanted_name){	struct dirent *entry;	int pid;	/* First scan proc for the gpm process */	pid = 0;	while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {		if ( isdigit(entry->d_name[0]) ) {			FILE *status;			char path[PATH_MAX];			char name[PATH_MAX];			SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status", entry->d_name);			status=fopen(path, "r");			if ( status ) {				name[0] = '\0';				fscanf(status, "Name: %s", name);				if ( SDL_strcmp(name, wanted_name) == 0 ) {					pid = SDL_atoi(entry->d_name);				}				fclose(status);			}		}	}	return pid;}/* Returns true if /dev/gpmdata is being written to by gpm */static int gpm_available(char *proto, size_t protolen){	int available;	DIR *proc;	int pid;	int cmdline, len, arglen;	char path[PATH_MAX];	char args[PATH_MAX], *arg;	/* Don't bother looking if the fifo isn't there */#ifdef DEBUG_MOUSE 	fprintf(stderr,"testing gpm\n");#endif	if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {		return(0);	}	available = 0;	proc = opendir("/proc");	if ( proc ) {		char raw_proto[10] = { '\0' };		char repeat_proto[10] = { '\0' };		while ( !available && (pid=find_pid(proc, "gpm")) > 0 ) {			SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid);			cmdline = open(path, O_RDONLY, 0);			if ( cmdline >= 0 ) {				len = read(cmdline, args, sizeof(args));				arg = args;				while ( len > 0 ) {					arglen = SDL_strlen(arg)+1;#ifdef DEBUG_MOUSE 				        fprintf(stderr,"gpm arg %s len %d\n",arg,arglen);#endif					if ( SDL_strcmp(arg, "-t") == 0) {						/* protocol string, keep it for later */						char *t, *s;						t = arg + arglen;						s = SDL_strchr(t, ' ');						if (s) *s = 0;						SDL_strlcpy(raw_proto, t, SDL_arraysize(raw_proto));						if (s) *s = ' ';					}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -