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

📄 xkeymap.c

📁 rdesktop is a client for Microsoft Windows NT Terminal Server, Windows 2000 Terminal Services, Wind
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- c-basic-offset: 8 -*-   rdesktop: A Remote Desktop Protocol client.   User interface services - X keyboard mapping   Copyright (C) Matthew Chapman 1999-2005   Copyright (C) Peter Astrand <peter@cendio.se> 2003      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program 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 General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#ifdef RDP2VNC#include "vnc/x11stubs.h"#else#include <X11/Xlib.h>#include <X11/keysym.h>#endif#include <ctype.h>#include <limits.h>#include <time.h>#include <string.h>#include "rdesktop.h"#include "scancodes.h"#define KEYMAP_SIZE 0xffff+1#define KEYMAP_MASK 0xffff#define KEYMAP_MAX_LINE_LENGTH 80extern Display *g_display;extern Window g_wnd;extern char g_keymapname[16];extern unsigned int g_keylayout;extern int g_keyboard_type;extern int g_keyboard_subtype;extern int g_keyboard_functionkeys;extern int g_win_button_size;extern BOOL g_enable_compose;extern BOOL g_use_rdp5;extern BOOL g_numlock_sync;static BOOL keymap_loaded;static key_translation *keymap[KEYMAP_SIZE];static int min_keycode;static uint16 remote_modifier_state = 0;static uint16 saved_remote_modifier_state = 0;static void update_modifier_state(uint8 scancode, BOOL pressed);/* Free key_translation structure, including linked list */static voidfree_key_translation(key_translation * ptr){	key_translation *next;	while (ptr)	{		next = ptr->next;		xfree(ptr);		ptr = next;	}}static voidadd_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname){	KeySym keysym;	key_translation *tr;	keysym = XStringToKeysym(keyname);	if (keysym == NoSymbol)	{		DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring)\n", keyname, mapname));		return;	}	DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "		   "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));	tr = (key_translation *) xmalloc(sizeof(key_translation));	memset(tr, 0, sizeof(key_translation));	tr->scancode = scancode;	tr->modifiers = modifiers;	free_key_translation(keymap[keysym & KEYMAP_MASK]);	keymap[keysym & KEYMAP_MASK] = tr;	return;}static voidadd_sequence(char *rest, char *mapname){	KeySym keysym;	key_translation *tr, **prev_next;	size_t chars;	char keyname[KEYMAP_MAX_LINE_LENGTH];	/* Skip over whitespace after the sequence keyword */	chars = strspn(rest, " \t");	rest += chars;	/* Fetch the keysym name */	chars = strcspn(rest, " \t\0");	STRNCPY(keyname, rest, chars + 1);	rest += chars;	keysym = XStringToKeysym(keyname);	if (keysym == NoSymbol)	{		DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname, mapname));		return;	}	DEBUG_KBD(("Adding sequence for keysym (0x%lx, %s) -> ", keysym, keyname));	free_key_translation(keymap[keysym & KEYMAP_MASK]);	prev_next = &keymap[keysym & KEYMAP_MASK];	while (*rest)	{		/* Skip whitespace */		chars = strspn(rest, " \t");		rest += chars;		/* Fetch the keysym name */		chars = strcspn(rest, " \t\0");		STRNCPY(keyname, rest, chars + 1);		rest += chars;		keysym = XStringToKeysym(keyname);		if (keysym == NoSymbol)		{			DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname,				   mapname));			return;		}		/* Allocate space for key_translation structure */		tr = (key_translation *) xmalloc(sizeof(key_translation));		memset(tr, 0, sizeof(key_translation));		*prev_next = tr;		prev_next = &tr->next;		tr->seq_keysym = keysym;		DEBUG_KBD(("0x%x, ", (unsigned int) keysym));	}	DEBUG_KBD(("\n"));}BOOLxkeymap_from_locale(const char *locale){	char *str, *ptr;	FILE *fp;	/* Create a working copy */	str = xstrdup(locale);	/* Truncate at dot and at */	ptr = strrchr(str, '.');	if (ptr)		*ptr = '\0';	ptr = strrchr(str, '@');	if (ptr)		*ptr = '\0';	/* Replace _ with - */	ptr = strrchr(str, '_');	if (ptr)		*ptr = '-';	/* Convert to lowercase */	ptr = str;	while (*ptr)	{		*ptr = tolower((int) *ptr);		ptr++;	}	/* Try to open this keymap (da-dk) */	fp = xkeymap_open(str);	if (fp == NULL)	{		/* Truncate at dash */		ptr = strrchr(str, '-');		if (ptr)			*ptr = '\0';		/* Try the short name (da) */		fp = xkeymap_open(str);	}	if (fp)	{		fclose(fp);		STRNCPY(g_keymapname, str, sizeof(g_keymapname));		xfree(str);		return True;	}	xfree(str);	return False;}/* Joins two path components. The result should be freed with   xfree(). */static char *pathjoin(const char *a, const char *b){	char *result;	result = xmalloc(PATH_MAX * 2 + 1);	if (b[0] == '/')	{		strncpy(result, b, PATH_MAX);	}	else	{		strncpy(result, a, PATH_MAX);		strcat(result, "/");		strncat(result, b, PATH_MAX);	}	return result;}/* Try to open a keymap with fopen() */FILE *xkeymap_open(const char *filename){	char *path1, *path2;	char *home;	FILE *fp;	/* Try ~/.rdesktop/keymaps */	home = getenv("HOME");	if (home)	{		path1 = pathjoin(home, ".rdesktop/keymaps");		path2 = pathjoin(path1, filename);		xfree(path1);		fp = fopen(path2, "r");		xfree(path2);		if (fp)			return fp;	}	/* Try KEYMAP_PATH */	path1 = pathjoin(KEYMAP_PATH, filename);	fp = fopen(path1, "r");	xfree(path1);	if (fp)		return fp;	/* Try current directory, in case we are running from the source	   tree */	path1 = pathjoin("keymaps", filename);	fp = fopen(path1, "r");	xfree(path1);	if (fp)		return fp;	return NULL;}static BOOLxkeymap_read(char *mapname){	FILE *fp;	char line[KEYMAP_MAX_LINE_LENGTH];	unsigned int line_num = 0;	unsigned int line_length = 0;	char *keyname, *p;	char *line_rest;	uint8 scancode;	uint16 modifiers;	fp = xkeymap_open(mapname);	if (fp == NULL)	{		error("Failed to open keymap %s\n", mapname);		return False;	}	/* FIXME: More tolerant on white space */	while (fgets(line, sizeof(line), fp) != NULL)	{		line_num++;		/* Replace the \n with \0 */		p = strchr(line, '\n');		if (p != NULL)			*p = 0;		line_length = strlen(line);		/* Completely empty line */		if (strspn(line, " \t\n\r\f\v") == line_length)		{			continue;		}		/* Include */		if (str_startswith(line, "include "))		{			if (!xkeymap_read(line + sizeof("include ") - 1))				return False;			continue;		}		/* map */		if (str_startswith(line, "map "))		{			g_keylayout = strtoul(line + sizeof("map ") - 1, NULL, 16);			DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));			continue;		}		/* compose */		if (str_startswith(line, "enable_compose"))		{			DEBUG_KBD(("Enabling compose handling\n"));			g_enable_compose = True;			continue;		}		/* sequence */		if (str_startswith(line, "sequence"))		{			add_sequence(line + sizeof("sequence") - 1, mapname);			continue;		}		/* keyboard_type */		if (str_startswith(line, "keyboard_type "))		{			g_keyboard_type = strtol(line + sizeof("keyboard_type ") - 1, NULL, 16);			DEBUG_KBD(("keyboard_type 0x%x\n", g_keyboard_type));			continue;		}		/* keyboard_subtype */		if (str_startswith(line, "keyboard_subtype "))		{			g_keyboard_subtype =				strtol(line + sizeof("keyboard_subtype ") - 1, NULL, 16);			DEBUG_KBD(("keyboard_subtype 0x%x\n", g_keyboard_subtype));			continue;		}		/* keyboard_functionkeys */		if (str_startswith(line, "keyboard_functionkeys "))		{			g_keyboard_functionkeys =				strtol(line + sizeof("keyboard_functionkeys ") - 1, NULL, 16);			DEBUG_KBD(("keyboard_functionkeys 0x%x\n", g_keyboard_functionkeys));			continue;		}		/* Comment */		if (line[0] == '#')		{			continue;		}		/* Normal line */		keyname = line;		p = strchr(line, ' ');		if (p == NULL)		{			error("Bad line %d in keymap %s\n", line_num, mapname);			continue;		}		else		{			*p = 0;		}		/* scancode */		p++;		scancode = strtol(p, &line_rest, 16);		/* flags */		/* FIXME: Should allow case-insensitive flag names. 		   Fix by using lex+yacc... */		modifiers = 0;		if (strstr(line_rest, "altgr"))		{			MASK_ADD_BITS(modifiers, MapAltGrMask);		}		if (strstr(line_rest, "shift"))		{			MASK_ADD_BITS(modifiers, MapLeftShiftMask);		}		if (strstr(line_rest, "numlock"))		{			MASK_ADD_BITS(modifiers, MapNumLockMask);		}		if (strstr(line_rest, "localstate"))		{			MASK_ADD_BITS(modifiers, MapLocalStateMask);		}		if (strstr(line_rest, "inhibit"))		{			MASK_ADD_BITS(modifiers, MapInhibitMask);		}		add_to_keymap(keyname, scancode, modifiers, mapname);		if (strstr(line_rest, "addupper"))		{			/* Automatically add uppercase key, with same modifiers 			   plus shift */			for (p = keyname; *p; p++)				*p = toupper((int) *p);			MASK_ADD_BITS(modifiers, MapLeftShiftMask);			add_to_keymap(keyname, scancode, modifiers, mapname);		}	}	fclose(fp);	return True;}/* Before connecting and creating UI */voidxkeymap_init(void){	unsigned int max_keycode;	if (strcmp(g_keymapname, "none"))	{		if (xkeymap_read(g_keymapname))			keymap_loaded = True;	}	XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);}static voidsend_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey){	uint8 winkey;	if (leftkey)		winkey = SCANCODE_CHAR_LWIN;	else		winkey = SCANCODE_CHAR_RWIN;	if (pressed)	{		if (g_use_rdp5)		{			rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);		}		else		{			/* RDP4 doesn't support winkey. Fake with Ctrl-Esc */			rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);			rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);		}	}	else	{		/* key released */		if (g_use_rdp5)		{			rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);		}		else		{			rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);			rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);		}	}}static voidreset_winkey(uint32 ev_time){	if (g_use_rdp5)	{		/* For some reason, it seems to suffice to release		 *either* the left or right winkey. */		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN);	}}/* Handle special key combinations */BOOLhandle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed){	switch (keysym)	{		case XK_Return:			if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))			    && (get_key_state(state, XK_Control_L)				|| get_key_state(state, XK_Control_R)))			{				/* Ctrl-Alt-Enter: toggle full screen */				if (pressed)					xwin_toggle_fullscreen();

⌨️ 快捷键说明

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