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

📄 sdl_gsevents.c

📁 Simple DirectMedia Layer - Simple DirectMedia Layer 是一个跨平台的多媒体库设计用来提供快速图形framebuffer和音频驱动。应用MPEG为软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	SDL - Simple DirectMedia Layer	Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga	This library is free software; you can redistribute it and/or	modify it under the terms of the GNU Library General Public	License as published by the Free Software Foundation; either	version 2 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	Library General Public License for more details.	You should have received a copy of the GNU Library General Public	License along with this library; if not, write to the Free	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA	Sam Lantinga	slouken@libsdl.org*/#ifdef SAVE_RCSIDstatic char rcsid = "@(#) $Id: SDL_gsevents.c,v 1.4 2002/03/06 11:23:06 slouken Exp $";#endif/* Handle the event stream, converting console events into SDL events */#include <sys/types.h>#include <sys/time.h>#include <sys/ioctl.h>#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <string.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.h"#include "SDL_mutex.h"#include "SDL_sysevents.h"#include "SDL_sysvideo.h"#include "SDL_events_c.h"#include "SDL_gsvideo.h"#include "SDL_gsevents_c.h"#include "SDL_gskeys.h"#ifndef GPM_NODE_FIFO#define GPM_NODE_FIFO	"/dev/gpmdata"#endif/* 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 GS_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 ) {		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 GS_InGraphicsMode(_THIS){	return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));}int GS_EnterGraphicsMode(_THIS){	struct termios keyboard_termios;	/* Set medium-raw keyboard mode */	if ( (keyboard_fd >= 0) && !GS_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) {			GS_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 ) {			GS_CloseKeyboard(this);			SDL_SetError("Unable to set keyboard in raw mode");			return(-1);		}		if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {			GS_CloseKeyboard(this);			SDL_SetError("Unable to set keyboard in graphics mode");			return(-1);		}	}	return(keyboard_fd);}void GS_LeaveGraphicsMode(_THIS){	if ( GS_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 */		if ( saved_vt > 0 ) {			ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);		}	}}void GS_CloseKeyboard(_THIS){	if ( keyboard_fd >= 0 ) {		GS_LeaveGraphicsMode(this);		if ( keyboard_fd > 0 ) {			close(keyboard_fd);		}	}	keyboard_fd = -1;}int GS_OpenKeyboard(_THIS){	/* Open only if not already opened */ 	if ( keyboard_fd < 0 ) {		char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };		char *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];				sprintf(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 */			current_vt = 0;			keyboard_fd = open("/dev/tty", O_RDWR); 		}#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 */		GS_vgainitkeymaps(keyboard_fd); 	} 	return(keyboard_fd);}static enum {	MOUSE_NONE = -1,	MOUSE_GPM,	/* Note: GPM uses the MSC protocol */	MOUSE_PS2,	MOUSE_IMPS2,	MOUSE_MS,	MOUSE_BM,	NUM_MOUSE_DRVS} mouse_drv = MOUSE_NONE;void GS_CloseMouse(_THIS){	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];			sprintf(path, "/proc/%s/status", entry->d_name);			status=fopen(path, "r");			if ( status ) {				name[0] = '\0';				fscanf(status, "Name: %s", name);				if ( strcmp(name, wanted_name) == 0 ) {					pid = atoi(entry->d_name);				}				fclose(status);			}		}	}	return pid;}/* Returns true if /dev/gpmdata is being written to by gpm */static int gpm_available(void){	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 */	if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {		return(0);	}	available = 0;	proc = opendir("/proc");	if ( proc ) {		while ( (pid=find_pid(proc, "gpm")) > 0 ) {			sprintf(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 ) {					if ( strcmp(arg, "-R") == 0 ) {						available = 1;					}					arglen = strlen(arg)+1;					len -= arglen;					arg += arglen;				}				close(cmdline);			}		}		closedir(proc);	}	return available;}/* rcg06112001 Set up IMPS/2 mode, if possible. This gives *  us access to the mousewheel, etc. Returns zero if *  writes to device failed, but you still need to query the *  device to see which mode it's actually in. */static int set_imps2_mode(int fd){	/* If you wanted to control the mouse mode (and we do :)  ) ...		Set IMPS/2 protocol:			{0xf3,200,0xf3,100,0xf3,80}		Reset mouse device:			{0xFF}	*/	Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};	Uint8 reset = 0xff;	fd_set fdset;	struct timeval tv;	int retval = 0;	if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {		if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {			retval = 1;		}	}	/* Get rid of any chatter from the above */	FD_ZERO(&fdset);	FD_SET(fd, &fdset);	tv.tv_sec = 0;	tv.tv_usec = 0;	while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {		char temp[32];		read(fd, temp, sizeof(temp));	}	return retval;}/* Returns true if the mouse uses the IMPS/2 protocol */static int detect_imps2(int fd){	int imps2;	imps2 = 0;	if ( getenv("SDL_MOUSEDEV_IMPS2") ) {		imps2 = 1;	}	if ( ! imps2 ) {		Uint8 query_ps2 = 0xF2;		fd_set fdset;		struct timeval tv;		/* Get rid of any mouse motion noise */		FD_ZERO(&fdset);		FD_SET(fd, &fdset);		tv.tv_sec = 0;		tv.tv_usec = 0;		while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {			char temp[32];			read(fd, temp, sizeof(temp));		}   		/* Query for the type of mouse protocol */   		if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {   			Uint8 ch = 0;			/* Get the mouse protocol response */			do {				FD_ZERO(&fdset);				FD_SET(fd, &fdset);				tv.tv_sec = 1;				tv.tv_usec = 0;				if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) {					break;				}			} while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&			          ((ch == 0xFA) || (ch == 0xAA)) );			/* Experimental values (Logitech wheelmouse) */#ifdef DEBUG_MOUSEfprintf(stderr, "Last mouse mode: 0x%x\n", ch);#endif			if ( ch == 3 ) {				imps2 = 1;			}		}	}	return imps2;}int GS_OpenMouse(_THIS){	int i;	const char *mousedev;	const char *mousedrv;

⌨️ 快捷键说明

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