--- SheepShaver/src/Unix/video_x.cpp 2003/05/22 22:12:05 1.3 +++ SheepShaver/src/Unix/video_x.cpp 2003/12/27 10:37:30 1.8 @@ -18,15 +18,25 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "sysdeps.h" + #include #include #include #include #include #include +#include #include -#include "sysdeps.h" +#ifdef ENABLE_XF86_DGA +#include +#endif + +#ifdef ENABLE_XF86_VIDMODE +# include +#endif + #include "main.h" #include "adb.h" #include "prefs.h" @@ -38,20 +48,18 @@ #define DEBUG 0 #include "debug.h" -#ifdef ENABLE_XF86_DGA -#include -#endif - -#ifdef ENABLE_XF86_VIDMODE -#include -#endif +// Constants +const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; // Global variables static int32 frame_skip; +static int16 mouse_wheel_mode; +static int16 mouse_wheel_lines; static bool redraw_thread_active = false; // Flag: Redraw thread installed static pthread_t redraw_thread; // Redraw thread +static bool local_X11; // Flag: X server running on local machine? static volatile bool thread_stop_req = false; static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req @@ -73,6 +81,8 @@ static bool emerg_quit = false; // Fl static bool emul_suspended = false; // Flag: emulator suspended static Window suspend_win; // "Suspend" window 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 static int screen; // Screen number @@ -118,7 +128,8 @@ static int num_x_video_modes; static void *redraw_func(void *arg); -// From main_linux.cpp +// From main_unix.cpp +extern char *x_display_name; extern Display *x_display; // From sys_unix.cpp @@ -157,11 +168,6 @@ static bool open_window(int width, int h // Set absolute mouse mode ADBSetRelMouseMode(false); - // Read frame skip prefs - frame_skip = PrefsFindInt32("frameskip"); - if (frame_skip == 0) - frame_skip = 1; - // Create window XSetWindowAttributes wattr; wattr.event_mask = eventmask = win_eventmask; @@ -195,12 +201,16 @@ static bool open_window(int width, int h XFree((char *)hints); } + // 1-bit mode is big-endian; if the X server is little-endian, we can't + // use SHM because that doesn't allow changing the image byte order + bool need_msb_image = (depth == 1 && XImageByteOrder(x_display) == LSBFirst); + // Try to create and attach SHM image have_shm = false; - if (depth != 1 && XShmQueryExtension(x_display)) { + if (local_X11 && !need_msb_image && XShmQueryExtension(x_display)) { // Create SHM image ("height + 2" for safety) - img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height); + img = XShmCreateImage(x_display, vis, depth == 1 ? 1 : xdepth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height); shminfo.shmid = shmget(IPC_PRIVATE, (height + 2) * img->bytes_per_line, IPC_CREAT | 0777); the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0); shminfo.shmaddr = img->data = (char *)the_buffer_copy; @@ -528,6 +538,71 @@ static void close_display(void) * 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) { if (allow & test) { @@ -597,6 +672,22 @@ bool VideoInit(void) mainBuffer.pageInfo = NULL; #endif + // Check if X server runs on local machine + local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0) + || (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0); + + // Init keycode translation + keycode_init(); + + // Read frame skip prefs + frame_skip = PrefsFindInt32("frameskip"); + if (frame_skip == 0) + frame_skip = 1; + + // Read mouse wheel prefs + mouse_wheel_mode = PrefsFindInt32("mousewheelmode"); + mouse_wheel_lines = PrefsFindInt32("mousewheellines"); + // Init variables private_data = NULL; cur_mode = 0; // Window 640x480 @@ -612,7 +703,7 @@ bool VideoInit(void) #ifdef ENABLE_XF86_DGA // DGA available? int event_base, error_base; - if (XF86DGAQueryExtension(x_display, &event_base, &error_base)) { + if (local_X11 && XF86DGAQueryExtension(x_display, &event_base, &error_base)) { int dga_flags = 0; XF86DGAQueryDirectVideo(x_display, screen, &dga_flags); has_dga = dga_flags & XF86DGADirectPresent; @@ -1068,14 +1159,14 @@ static int kc_decode(KeySym ks) return -1; } -static int event2keycode(XKeyEvent *ev) +static int event2keycode(XKeyEvent &ev) { KeySym ks; int as; int i = 0; do { - ks = XLookupKeysym(ev, i++); + ks = XLookupKeysym(&ev, i++); as = kc_decode(ks); if (as != -1) return as; @@ -1099,6 +1190,19 @@ static void handle_events(void) unsigned int button = ((XButtonEvent *)&event)->button; if (button < 4) ADBMouseDown(button - 1); + else if (button < 6) { // Wheel mouse + if (mouse_wheel_mode == 0) { + int key = (button == 5) ? 0x79 : 0x74; // Page up/down + ADBKeyDown(key); + ADBKeyUp(key); + } else { + int key = (button == 5) ? 0x3d : 0x3e; // Cursor up/down + for(int i=0; i