mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-12 01:30:03 +00:00
Merge in "keycodes" support from Basilisk II. e.g. make French keyboard
layout work correctly for me.
This commit is contained in:
parent
45df157a5e
commit
1dbe1179c6
@ -44,6 +44,7 @@ static bool start_clicked = true; // Return value of PrefsEditor() function
|
|||||||
// Prototypes
|
// Prototypes
|
||||||
static void create_volumes_pane(GtkWidget *top);
|
static void create_volumes_pane(GtkWidget *top);
|
||||||
static void create_graphics_pane(GtkWidget *top);
|
static void create_graphics_pane(GtkWidget *top);
|
||||||
|
static void create_input_pane(GtkWidget *top);
|
||||||
static void create_serial_pane(GtkWidget *top);
|
static void create_serial_pane(GtkWidget *top);
|
||||||
static void create_memory_pane(GtkWidget *top);
|
static void create_memory_pane(GtkWidget *top);
|
||||||
static void read_settings(void);
|
static void read_settings(void);
|
||||||
@ -170,6 +171,11 @@ static GtkWidget *make_entry(GtkWidget *top, int label_id, const char *prefs_ite
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *get_file_entry_path(GtkWidget *entry)
|
||||||
|
{
|
||||||
|
return gtk_entry_get_text(GTK_ENTRY(entry));
|
||||||
|
}
|
||||||
|
|
||||||
static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
|
static GtkWidget *make_checkbox(GtkWidget *top, int label_id, const char *prefs_item, GtkSignalFunc func)
|
||||||
{
|
{
|
||||||
GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
|
GtkWidget *button = gtk_check_button_new_with_label(GetString(label_id));
|
||||||
@ -313,6 +319,7 @@ bool PrefsEditor(void)
|
|||||||
|
|
||||||
create_volumes_pane(notebook);
|
create_volumes_pane(notebook);
|
||||||
create_graphics_pane(notebook);
|
create_graphics_pane(notebook);
|
||||||
|
create_input_pane(notebook);
|
||||||
create_serial_pane(notebook);
|
create_serial_pane(notebook);
|
||||||
create_memory_pane(notebook);
|
create_memory_pane(notebook);
|
||||||
|
|
||||||
@ -630,6 +637,50 @@ static void create_graphics_pane(GtkWidget *top)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "Input" pane
|
||||||
|
*/
|
||||||
|
|
||||||
|
static GtkWidget *w_keycode_file;
|
||||||
|
|
||||||
|
// Set sensitivity of widgets
|
||||||
|
static void set_input_sensitive(void)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Use Raw Keycodes" button toggled
|
||||||
|
static void tb_keycodes(GtkWidget *widget)
|
||||||
|
{
|
||||||
|
PrefsReplaceBool("keycodes", GTK_TOGGLE_BUTTON(widget)->active);
|
||||||
|
set_input_sensitive();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read settings from widgets and set preferences
|
||||||
|
static void read_input_settings(void)
|
||||||
|
{
|
||||||
|
const char *str = get_file_entry_path(w_keycode_file);
|
||||||
|
if (str && strlen(str))
|
||||||
|
PrefsReplaceString("keycodefile", str);
|
||||||
|
else
|
||||||
|
PrefsRemoveItem("keycodefile");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create "Input" pane
|
||||||
|
static void create_input_pane(GtkWidget *top)
|
||||||
|
{
|
||||||
|
GtkWidget *box, *hbox, *menu, *label;
|
||||||
|
GtkObject *adj;
|
||||||
|
|
||||||
|
box = make_pane(top, STR_INPUT_PANE_TITLE);
|
||||||
|
|
||||||
|
make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes));
|
||||||
|
w_keycode_file = make_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile");
|
||||||
|
|
||||||
|
set_input_sensitive();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Serial/Network" pane
|
* "Serial/Network" pane
|
||||||
*/
|
*/
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
// Platform-specific preferences items
|
// Platform-specific preferences items
|
||||||
prefs_desc platform_prefs_items[] = {
|
prefs_desc platform_prefs_items[] = {
|
||||||
{"ether", TYPE_STRING, false, "device name of Mac ethernet adapter"},
|
{"ether", TYPE_STRING, false, "device name of Mac ethernet adapter"},
|
||||||
|
{"keycodes", TYPE_BOOLEAN, false, "use keycodes rather than keysyms to decode keyboard"},
|
||||||
|
{"keycodefile", TYPE_STRING, false, "path of keycode translation file"},
|
||||||
{NULL, TYPE_END, false, NULL} // End of list
|
{NULL, TYPE_END, false, NULL} // End of list
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -91,6 +93,7 @@ void SavePrefs(void)
|
|||||||
|
|
||||||
void AddPlatformPrefsDefaults(void)
|
void AddPlatformPrefsDefaults(void)
|
||||||
{
|
{
|
||||||
|
PrefsAddBool("keycodes", false);
|
||||||
PrefsReplaceString("extfs", "/");
|
PrefsReplaceString("extfs", "/");
|
||||||
PrefsAddInt32("windowmodes", 3);
|
PrefsAddInt32("windowmodes", 3);
|
||||||
PrefsAddInt32("screenmodes", 0x3f);
|
PrefsAddInt32("screenmodes", 0x3f);
|
||||||
|
@ -55,6 +55,8 @@ user_string_def platform_strings[] = {
|
|||||||
{STR_AUDIO_FORMAT_WARN, "/dev/dsp doesn't support signed 16 bit format. Audio output will be disabled."},
|
{STR_AUDIO_FORMAT_WARN, "/dev/dsp doesn't support signed 16 bit format. Audio output will be disabled."},
|
||||||
{STR_SCSI_DEVICE_OPEN_WARN, "Cannot open %s (%s). SCSI Manager access to this device will be disabled."},
|
{STR_SCSI_DEVICE_OPEN_WARN, "Cannot open %s (%s). SCSI Manager access to this device will be disabled."},
|
||||||
{STR_SCSI_DEVICE_NOT_SCSI_WARN, "%s doesn't seem to comply to the Generic SCSI API. SCSI Manager access to this device will be disabled."},
|
{STR_SCSI_DEVICE_NOT_SCSI_WARN, "%s doesn't seem to comply to the Generic SCSI API. SCSI Manager access to this device will be disabled."},
|
||||||
|
{STR_KEYCODE_FILE_WARN, "Cannot open keycode translation file %s (%s)."},
|
||||||
|
{STR_KEYCODE_VENDOR_WARN, "Cannot find vendor '%s' in keycode translation file %s."},
|
||||||
{STR_PREFS_MENU_FILE_GTK, "/_File"},
|
{STR_PREFS_MENU_FILE_GTK, "/_File"},
|
||||||
{STR_PREFS_ITEM_START_GTK, "/File/_Start SheepShaver"},
|
{STR_PREFS_ITEM_START_GTK, "/File/_Start SheepShaver"},
|
||||||
{STR_PREFS_ITEM_ZAP_PRAM_GTK, "/File/_Zap PRAM File"},
|
{STR_PREFS_ITEM_ZAP_PRAM_GTK, "/File/_Zap PRAM File"},
|
||||||
@ -62,6 +64,9 @@ user_string_def platform_strings[] = {
|
|||||||
{STR_PREFS_ITEM_QUIT_GTK, "/File/_Quit SheepShaver"},
|
{STR_PREFS_ITEM_QUIT_GTK, "/File/_Quit SheepShaver"},
|
||||||
{STR_HELP_MENU_GTK, "/_Help"},
|
{STR_HELP_MENU_GTK, "/_Help"},
|
||||||
{STR_HELP_ITEM_ABOUT_GTK, "/Help/_About SheepShaver"},
|
{STR_HELP_ITEM_ABOUT_GTK, "/Help/_About SheepShaver"},
|
||||||
|
{STR_INPUT_PANE_TITLE, "Keyboard"},
|
||||||
|
{STR_KEYCODES_CTRL, "Use Raw Keycodes"},
|
||||||
|
{STR_KEYCODE_FILE_CTRL, "Keycode Translation File"},
|
||||||
{STR_SUSPEND_WINDOW_TITLE, "SheepShaver suspended. Press Space to reactivate."},
|
{STR_SUSPEND_WINDOW_TITLE, "SheepShaver suspended. Press Space to reactivate."},
|
||||||
{STR_VOSF_INIT_ERR, "Cannot initialize Video on SEGV signals."},
|
{STR_VOSF_INIT_ERR, "Cannot initialize Video on SEGV signals."},
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ enum {
|
|||||||
STR_NO_XSERVER_ERR,
|
STR_NO_XSERVER_ERR,
|
||||||
STR_NO_XVISUAL_ERR,
|
STR_NO_XVISUAL_ERR,
|
||||||
STR_UNSUPP_DEPTH_ERR,
|
STR_UNSUPP_DEPTH_ERR,
|
||||||
|
STR_VOSF_INIT_ERR,
|
||||||
|
|
||||||
STR_PROC_CPUINFO_WARN,
|
STR_PROC_CPUINFO_WARN,
|
||||||
STR_NO_SHEEP_NET_DRIVER_WARN,
|
STR_NO_SHEEP_NET_DRIVER_WARN,
|
||||||
STR_SHEEP_NET_ATTACH_WARN,
|
STR_SHEEP_NET_ATTACH_WARN,
|
||||||
@ -46,6 +48,9 @@ enum {
|
|||||||
STR_AUDIO_FORMAT_WARN,
|
STR_AUDIO_FORMAT_WARN,
|
||||||
STR_SCSI_DEVICE_OPEN_WARN,
|
STR_SCSI_DEVICE_OPEN_WARN,
|
||||||
STR_SCSI_DEVICE_NOT_SCSI_WARN,
|
STR_SCSI_DEVICE_NOT_SCSI_WARN,
|
||||||
|
STR_KEYCODE_FILE_WARN,
|
||||||
|
STR_KEYCODE_VENDOR_WARN,
|
||||||
|
|
||||||
STR_PREFS_MENU_FILE_GTK,
|
STR_PREFS_MENU_FILE_GTK,
|
||||||
STR_PREFS_ITEM_START_GTK,
|
STR_PREFS_ITEM_START_GTK,
|
||||||
STR_PREFS_ITEM_ZAP_PRAM_GTK,
|
STR_PREFS_ITEM_ZAP_PRAM_GTK,
|
||||||
@ -54,7 +59,9 @@ enum {
|
|||||||
STR_HELP_MENU_GTK,
|
STR_HELP_MENU_GTK,
|
||||||
STR_HELP_ITEM_ABOUT_GTK,
|
STR_HELP_ITEM_ABOUT_GTK,
|
||||||
STR_SUSPEND_WINDOW_TITLE,
|
STR_SUSPEND_WINDOW_TITLE,
|
||||||
STR_VOSF_INIT_ERR
|
STR_INPUT_PANE_TITLE,
|
||||||
|
STR_KEYCODES_CTRL,
|
||||||
|
STR_KEYCODE_FILE_CTRL
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,15 +18,28 @@
|
|||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "sysdeps.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
#include <X11/extensions/XShm.h>
|
#include <X11/extensions/XShm.h>
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <pthread.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREADS
|
||||||
|
# include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_XF86_DGA
|
||||||
|
#include <X11/extensions/xf86dga.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_XF86_VIDMODE
|
||||||
|
# include <X11/extensions/xf86vmode.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "sysdeps.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "adb.h"
|
#include "adb.h"
|
||||||
#include "prefs.h"
|
#include "prefs.h"
|
||||||
@ -38,14 +51,9 @@
|
|||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#ifdef ENABLE_XF86_DGA
|
|
||||||
#include <X11/extensions/xf86dga.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_XF86_VIDMODE
|
|
||||||
#include <X11/extensions/xf86vmode.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
static int32 frame_skip;
|
static int32 frame_skip;
|
||||||
@ -74,6 +82,8 @@ static bool emerg_quit = false; // Flag: Ctrl-Esc pressed, emergency quit req
|
|||||||
static bool emul_suspended = false; // Flag: emulator suspended
|
static bool emul_suspended = false; // Flag: emulator suspended
|
||||||
static Window suspend_win; // "Suspend" window
|
static Window suspend_win; // "Suspend" window
|
||||||
static void *fb_save = NULL; // Saved frame buffer for suspend
|
static void *fb_save = NULL; // Saved frame buffer for suspend
|
||||||
|
static bool use_keycodes = false; // Flag: Use keycodes rather than keysyms
|
||||||
|
static int keycode_table[256]; // X keycode -> Mac keycode translation table
|
||||||
|
|
||||||
// X11 variables
|
// X11 variables
|
||||||
static int screen; // Screen number
|
static int screen; // Screen number
|
||||||
@ -534,6 +544,71 @@ static void close_display(void)
|
|||||||
* Initialization
|
* Initialization
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Init keycode translation table
|
||||||
|
static void keycode_init(void)
|
||||||
|
{
|
||||||
|
bool use_kc = PrefsFindBool("keycodes");
|
||||||
|
if (use_kc) {
|
||||||
|
|
||||||
|
// Get keycode file path from preferences
|
||||||
|
const char *kc_path = PrefsFindString("keycodefile");
|
||||||
|
|
||||||
|
// Open keycode table
|
||||||
|
FILE *f = fopen(kc_path ? kc_path : KEYCODE_FILE_NAME, "r");
|
||||||
|
if (f == NULL) {
|
||||||
|
char str[256];
|
||||||
|
sprintf(str, GetString(STR_KEYCODE_FILE_WARN), kc_path ? kc_path : KEYCODE_FILE_NAME, strerror(errno));
|
||||||
|
WarningAlert(str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default translation table
|
||||||
|
for (int i=0; i<256; i++)
|
||||||
|
keycode_table[i] = -1;
|
||||||
|
|
||||||
|
// Search for server vendor string, then read keycodes
|
||||||
|
const char *vendor = ServerVendor(x_display);
|
||||||
|
bool vendor_found = false;
|
||||||
|
char line[256];
|
||||||
|
while (fgets(line, 255, f)) {
|
||||||
|
// Read line
|
||||||
|
int len = strlen(line);
|
||||||
|
if (len == 0)
|
||||||
|
continue;
|
||||||
|
line[len-1] = 0;
|
||||||
|
|
||||||
|
// Comments begin with "#" or ";"
|
||||||
|
if (line[0] == '#' || line[0] == ';' || line[0] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (vendor_found) {
|
||||||
|
// Read keycode
|
||||||
|
int x_code, mac_code;
|
||||||
|
if (sscanf(line, "%d %d", &x_code, &mac_code) == 2)
|
||||||
|
keycode_table[x_code & 0xff] = mac_code;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Search for vendor string
|
||||||
|
if (strstr(vendor, line) == vendor)
|
||||||
|
vendor_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keycode file completely read
|
||||||
|
fclose(f);
|
||||||
|
use_keycodes = vendor_found;
|
||||||
|
|
||||||
|
// Vendor not found? Then display warning
|
||||||
|
if (!vendor_found) {
|
||||||
|
char str[256];
|
||||||
|
sprintf(str, GetString(STR_KEYCODE_VENDOR_WARN), vendor, kc_path ? kc_path : KEYCODE_FILE_NAME);
|
||||||
|
WarningAlert(str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type)
|
static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type)
|
||||||
{
|
{
|
||||||
if (allow & test) {
|
if (allow & test) {
|
||||||
@ -607,6 +682,9 @@ bool VideoInit(void)
|
|||||||
local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0)
|
local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0)
|
||||||
|| (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0);
|
|| (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0);
|
||||||
|
|
||||||
|
// Init keycode translation
|
||||||
|
keycode_init();
|
||||||
|
|
||||||
// Init variables
|
// Init variables
|
||||||
private_data = NULL;
|
private_data = NULL;
|
||||||
cur_mode = 0; // Window 640x480
|
cur_mode = 0; // Window 640x480
|
||||||
@ -1078,14 +1156,14 @@ static int kc_decode(KeySym ks)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int event2keycode(XKeyEvent *ev)
|
static int event2keycode(XKeyEvent &ev)
|
||||||
{
|
{
|
||||||
KeySym ks;
|
KeySym ks;
|
||||||
int as;
|
int as;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ks = XLookupKeysym(ev, i++);
|
ks = XLookupKeysym(&ev, i++);
|
||||||
as = kc_decode(ks);
|
as = kc_decode(ks);
|
||||||
if (as != -1)
|
if (as != -1)
|
||||||
return as;
|
return as;
|
||||||
@ -1128,8 +1206,10 @@ static void handle_events(void)
|
|||||||
|
|
||||||
// Keyboard
|
// Keyboard
|
||||||
case KeyPress: {
|
case KeyPress: {
|
||||||
int code;
|
int code = event2keycode(event.xkey);
|
||||||
if ((code = event2keycode((XKeyEvent *)&event)) != -1) {
|
if (use_keycodes && code != -1)
|
||||||
|
code = keycode_table[event.xkey.keycode & 0xff];
|
||||||
|
if (code != -1) {
|
||||||
if (!emul_suspended) {
|
if (!emul_suspended) {
|
||||||
ADBKeyDown(code);
|
ADBKeyDown(code);
|
||||||
if (code == 0x36)
|
if (code == 0x36)
|
||||||
@ -1142,8 +1222,10 @@ static void handle_events(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KeyRelease: {
|
case KeyRelease: {
|
||||||
int code;
|
int code = event2keycode(event.xkey);
|
||||||
if ((code = event2keycode((XKeyEvent *)&event)) != -1) {
|
if (use_keycodes && code != 1)
|
||||||
|
code = keycode_table[event.xkey.keycode & 0xff];
|
||||||
|
if (code != -1) {
|
||||||
ADBKeyUp(code);
|
ADBKeyUp(code);
|
||||||
if (code == 0x36)
|
if (code == 0x36)
|
||||||
ctrl_down = false;
|
ctrl_down = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user