--- uae/src/xwin.c 2018/04/24 16:38:39 1.1 +++ uae/src/xwin.c 2018/04/24 17:16:24 1.1.1.20 @@ -1,10 +1,14 @@ - /* + /* * UAE - The Un*x Amiga Emulator - * + * * X interface - * + * * Copyright 1995, 1996 Bernd Schmidt * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste + * Copyright 1998 Marcus Sundberg + * DGA support by Kai Kollmorgen + * X11/DGA merge, hotkeys and grabmouse by Marcus Sundberg + * Copyright 2003-2004 Richard Drummond */ #include "sysconfig.h" @@ -15,40 +19,77 @@ #include #include -#ifndef DONT_WANT_SHM -#include -#include -#include -#endif - #include #include -#include "config.h" #include "options.h" +#include "threaddep/thread.h" +#include "uae.h" #include "memory.h" +#include "xwin.h" #include "custom.h" +#include "drawing.h" #include "newcpu.h" -#include "xwin.h" #include "keyboard.h" #include "keybuf.h" #include "gui.h" #include "debug.h" +#include "picasso96.h" +#include "inputdevice.h" +#include "hotkeys.h" + +#ifdef __cplusplus +#define VI_CLASS c_class +#else +#define VI_CLASS class +#endif + +#ifdef USE_DGA_EXTENSION + +#ifdef USE_VIDMODE_EXTENSION +#include +#define VidMode_MINMAJOR 0 +#define VidMode_MINMINOR 0 +#endif + +#include +#define DGA_MINMAJOR 0 +#define DGA_MINMINOR 0 + +#endif /* USE_DGA_EXTENSION */ + +#if SHM_SUPPORT_LINKS == 1 + +#include +#include +#include + +#define DO_PUTIMAGE(IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT) \ + do { \ + if (currprefs.x11_use_mitshm && shmavail) \ + XShmPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT), 0); \ + else \ + XPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT)); \ + } while (0) +#else +#define DO_PUTIMAGE(IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT) \ + XPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT)) +#endif #ifdef __cplusplus static RETSIGTYPE sigbrkhandler(...) #else -static RETSIGTYPE sigbrkhandler(int foo) +static RETSIGTYPE sigbrkhandler (int foo) #endif { activate_debugger(); #if !defined(__unix) || defined(__NeXT__) - signal(SIGINT, sigbrkhandler); + signal (SIGINT, sigbrkhandler); #endif } -void setup_brkhandler(void) +void setup_brkhandler (void) { #if defined(__unix) && !defined(__NeXT__) struct sigaction sa; @@ -57,897 +98,1694 @@ void setup_brkhandler(void) #ifdef SA_RESTART sa.sa_flags = SA_RESTART; #endif - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); + sigemptyset (&sa.sa_mask); + sigaction (SIGINT, &sa, NULL); #else - signal(SIGINT, sigbrkhandler); -#endif + signal (SIGINT, sigbrkhandler); +#endif } +struct disp_info { + XImage *ximg; + char *image_mem; +#if SHM_SUPPORT_LINKS == 1 + XShmSegmentInfo shminfo; +#endif +}; + static Display *display; static int screen; static Window rootwin, mywin; +static Atom delete_win; -static GC whitegc,blackgc; -static XColor black,white; -static Colormap cmap; +static GC mygc; +static XColor black, white; +static Colormap cmap, cmap2; +static int red_bits, green_bits, blue_bits; +static int red_shift, green_shift, blue_shift; + +/* Kludge-O-Matic. + * Unfortunately the X server loses colormap changes in DGA mode. Switching + * back and forth between two identical colormaps fixes this problem. */ +static int dga_colormap_installed; static int need_dither; +static int screen_is_picasso; +static char picasso_invalid_lines[1201]; +static int picasso_has_invalid_lines; +static int picasso_invalid_start, picasso_invalid_stop; +static int picasso_maxw = 0, picasso_maxh = 0; + static int autorepeatoff = 0; -static char *image_mem; -static XImage *img; +static struct disp_info ami_dinfo, pic_dinfo; static Visual *vis; static XVisualInfo visualInfo; static int bitdepth, bit_unit; -#ifndef DONT_WANT_SHM -static int use_shm = 1; -static XShmSegmentInfo shminfo; -#endif static Cursor blankCursor, xhairCursor; static int cursorOn; +static int inverse_byte_order = 0; -#ifdef LOW_BANDWIDTH -static int use_low_bandwidth = 1; -#else -static int use_low_bandwidth = 0; +static int current_width, current_height; + +static int x11_init_ok; +static int dgaavail = 0, vidmodeavail = 0, shmavail = 0; +static int dgamode; +static int grabbed; + +void toggle_mousegrab (void); +void framerate_up (void); +void framerate_down (void); +int xkeysym2amiga (int); +struct uae_hotkeyseq *get_x11_default_hotkeys (void); + +int pause_emulation; + +static int oldx, oldy; +static int inwindow; + +#define EVENTMASK (KeyPressMask|KeyReleaseMask|ButtonPressMask \ + |ButtonReleaseMask|PointerMotionMask \ + |FocusChangeMask|EnterWindowMask \ + |ExposureMask |LeaveWindowMask) +#define DGA_EVENTMASK (KeyPressMask|KeyReleaseMask|ButtonPressMask \ + |ButtonReleaseMask|PointerMotionMask) + +#if SHM_SUPPORT_LINKS == 1 +/* Hack to detect shm-failure, probably due to displaying on a + * remote server. */ +static int shmerror; +static int (*oldshmerrorhandler) (Display *, XErrorEvent *); + +static int shmerrorhandler (Display *dsp, XErrorEvent *ev) +{ + if (ev->error_code == BadAccess) + shmerror=1; + else + (*oldshmerrorhandler) (dsp, ev); + return 0; +} #endif -xcolnr xcolors[4096]; +static void get_image (int w, int h, struct disp_info *dispi) +{ + XImage *new_img; + char *p; + +#if SHM_SUPPORT_LINKS == 1 + if (currprefs.x11_use_mitshm && shmavail) { + XShmSegmentInfo *shminfo = &dispi->shminfo; + + new_img = XShmCreateImage (display, vis, bitdepth, ZPixmap, 0, shminfo, w, h); + + shminfo->shmid = shmget (IPC_PRIVATE, h * new_img->bytes_per_line, + IPC_CREAT | 0777); + shminfo->shmaddr = new_img->data = (char *)shmat (shminfo->shmid, 0, 0); + dispi->image_mem = new_img->data; + shminfo->readOnly = False; + /* Try to let the Xserver attach */ + shmerror = 0; + oldshmerrorhandler = XSetErrorHandler (shmerrorhandler); + XShmAttach (display, shminfo); + XSync (display, 0); + XSetErrorHandler (oldshmerrorhandler); + if (shmerror) { + shmdt (shminfo->shmaddr); + XDestroyImage (new_img); + shminfo->shmid = -1; + shmavail = 0; + write_log ("MIT-SHM extension failed, trying fallback.\n"); + } else { + /* now deleting means making it temporary */ + shmctl (shminfo->shmid, IPC_RMID, 0); + dispi->ximg = new_img; + write_log ("Using MIT-SHM extension.\n"); + return; + } + } +#endif - /* Keyboard and mouse */ + /* Question for people who know about X: Could we allocate the buffer + * after creating the image and then do new_img->data = buffer, as above in + * the SHM case? + */ + write_log ("Using normal image buffer.\n"); + p = (char *)xmalloc (h * w * ((bit_unit + 7) / 8)); /* ??? */ + new_img = XCreateImage (display, vis, bitdepth, ZPixmap, 0, p, + w, h, 32, 0); + if (new_img->bytes_per_line != w * ((bit_unit + 7) / 8)) + write_log ("Possible bug here... graphics may look strange.\n"); + + dispi->image_mem = p; + dispi->ximg = new_img; +} + +#ifdef USE_VIDMODE_EXTENSION +static XF86VidModeModeInfo **allmodes; +static int vidmodecount; -static int keystate[256]; +static int get_vidmodes (void) +{ + return XF86VidModeGetAllModeLines (display, screen, &vidmodecount, &allmodes); +} +#endif -int buttonstate[3]; -int lastmx, lastmy; -int newmousecounters; +#ifdef USE_DGA_EXTENSION -static int inwindow; -const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask - |ButtonReleaseMask|PointerMotionMask - |FocusChangeMask|EnterWindowMask - |ExposureMask - |LeaveWindowMask); +static int fb_bank, fb_banks, fb_mem; +static char *fb_addr; +static int fb_width; + +static void switch_to_best_mode (void) +{ + Screen *scr = ScreenOfDisplay (display, screen); + int w = WidthOfScreen (scr); + int h = HeightOfScreen (scr); + int d = DefaultDepthOfScreen (scr); +#ifdef USE_VIDMODE_EXTENSION + int i, best; + if (vidmodeavail) { + best = 0; + for (i = 1; i < vidmodecount; i++) { + if (allmodes[i]->hdisplay >= current_width + && allmodes[i]->vdisplay >= current_height + && allmodes[i]->hdisplay <= allmodes[best]->hdisplay + && allmodes[i]->vdisplay <= allmodes[best]->vdisplay) + best = i; + } + write_log ("entering DGA mode: %dx%d (%d, %d)\n", + allmodes[best]->hdisplay, allmodes[best]->vdisplay, + current_width, current_height); + XF86VidModeSwitchToMode (display, screen, allmodes[best]); + XF86VidModeSetViewPort (display, screen, 0, 0); + } +#endif + XMoveWindow (display, mywin, 0, 0); + XWarpPointer (display, None, rootwin, 0, 0, 0, 0, 0, 0); + XF86DGADirectVideo (display, screen, XF86DGADirectGraphics | XF86DGADirectMouse | XF86DGADirectKeyb); + XF86DGASetViewPort (display, screen, 0, 0); + memset (fb_addr, 0, (w * h) * (d / 8)); +} -static int vsize, hsize, hpixels; -static char *oldpixbuf; +static void enter_dga_mode (void) +{ + XRaiseWindow (display, mywin); + + /* We want all the key presses */ + XGrabKeyboard (display, rootwin, 1, GrabModeAsync, + GrabModeAsync, CurrentTime); + + /* and all the mouse moves */ + XGrabPointer (display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, None, CurrentTime); -struct vidbuf_description gfxvidinfo; + switch_to_best_mode (); + + gfxvidinfo.rowbytes = fb_width*gfxvidinfo.pixbytes; + gfxvidinfo.bufmem = fb_addr; + gfxvidinfo.linemem = 0; + gfxvidinfo.emergmem = malloc (gfxvidinfo.rowbytes); + gfxvidinfo.maxblocklines = 10000; +} -void flush_line(int y) +static void leave_dga_mode (void) { - int xs = 0, xe; - int len, factor; - char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem; - char *src, *dst; - if (gfxvidinfo.maxlinetoscr) - xe = gfxvidinfo.maxlinetoscr-1; - else - xe = hsize-1; + XF86DGADirectVideo (display, screen, 0); + XUngrabPointer (display, CurrentTime); + XUngrabKeyboard (display, CurrentTime); +#ifdef USE_VIDMODE_EXTENSION + if (vidmodeavail) + XF86VidModeSwitchToMode (display, screen, allmodes[0]); +#endif +} +#endif - if (!use_low_bandwidth) - fprintf(stderr, "Bug!\n"); - - switch(gfxvidinfo.pixbytes) { - case 4: - { - int *newp = (int *)linebuf; - int *oldp = (int *)(oldpixbuf + y*gfxvidinfo.rowbytes); - while (newp[xs] == oldp[xs]) { - if (xs == xe) - return; - xs++; +static char *oldpixbuf; + +void flush_line (int y) +{ + char *linebuf = gfxvidinfo.linemem; + int xs, xe; + int len; + + if (linebuf == NULL) + linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem; + +#ifdef USE_DGA_EXTENSION + if (dgamode && need_dither) { + DitherLine ((unsigned char *)(fb_addr + fb_width*y), + (uae_u16 *)linebuf, 0, y, gfxvidinfo.width, bit_unit); + return; + } +#endif + xs = 0; + xe = gfxvidinfo.width - 1; + + if (currprefs.x11_use_low_bandwidth) { + char *src, *dst; + switch (gfxvidinfo.pixbytes) { + case 4: + { + uae_u32 *newp = (uae_u32 *)linebuf; + uae_u32 *oldp = (uae_u32 *)((uae_u8 *)ami_dinfo.image_mem + y*ami_dinfo.ximg->bytes_per_line); + while (newp[xs] == oldp[xs]) { + if (xs == xe) + return; + xs++; + } + while (newp[xe] == oldp[xe]) xe--; + + dst = (char *)(oldp + xs); src = (char *)(newp + xs); } - while (newp[xe] == oldp[xe]) xe--; - - dst = (char *)(oldp + xs); src = (char *)(newp + xs); - } - break; - case 2: - { - short *newp = (short *)linebuf; - short *oldp = (short *)(oldpixbuf + y*gfxvidinfo.rowbytes); - while (newp[xs] == oldp[xs]) { - if (xs == xe) - return; - xs++; + break; + case 2: + { + uae_u16 *newp = (uae_u16 *)linebuf; + uae_u16 *oldp = (uae_u16 *)((uae_u8 *)ami_dinfo.image_mem + y*ami_dinfo.ximg->bytes_per_line); + while (newp[xs] == oldp[xs]) { + if (xs == xe) + return; + xs++; + } + while (newp[xe] == oldp[xe]) xe--; + + dst = (char *)(oldp + xs); src = (char *)(newp + xs); } - while (newp[xe] == oldp[xe]) xe--; + break; + case 1: + { + uae_u8 *newp = (uae_u8 *)linebuf; + uae_u8 *oldp = (uae_u8 *)((uae_u8 *)ami_dinfo.image_mem + y*ami_dinfo.ximg->bytes_per_line); + while (newp[xs] == oldp[xs]) { + if (xs == xe) + return; + xs++; + } + while (newp[xe] == oldp[xe]) xe--; - dst = (char *)(oldp + xs); src = (char *)(newp + xs); - } - break; - case 1: - { - char *newp = (char *)linebuf; - char *oldp = (char *)(oldpixbuf + y*gfxvidinfo.rowbytes); - while (newp[xs] == oldp[xs]) { - if (xs == xe) - return; - xs++; + dst = (char *)(oldp + xs); src = (char *)(newp + xs); } - while (newp[xe] == oldp[xe]) xe--; + break; - dst = (char *)(oldp + xs); src = (char *)(newp + xs); + default: + abort (); + break; } - break; - default: + len = xe - xs + 1; + memcpy (dst, src, len * gfxvidinfo.pixbytes); + } else if (need_dither) { + uae_u8 *target = (uae_u8 *)ami_dinfo.image_mem + ami_dinfo.ximg->bytes_per_line * y; + len = gfxvidinfo.width; + DitherLine (target, (uae_u16 *)linebuf, 0, y, gfxvidinfo.width, bit_unit); + } else { + write_log ("Bug!\n"); abort(); - break; } - len = xe - xs + 1; - memcpy (dst, src, len * gfxvidinfo.pixbytes); - - if (need_dither) { - UBYTE *target = (UBYTE *)image_mem + img->bytes_per_line * y; - xs &= ~(8/bit_unit - 1); - len = xe - xs + 1; - len += 3; len &= ~3; - len += (8/bit_unit - 1); len &= ~(8/bit_unit-1); - if (len & 3) - printf("%d\n",len); - DitherLine(target + xs*bit_unit/8, (UWORD *)linebuf + xs, xs, y, len, bit_unit); - } -#ifndef DONT_WANT_SHM - if (use_shm) - XShmPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1, 0); - else -#endif - XPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1); + DO_PUTIMAGE (ami_dinfo.ximg, xs, y, xs, y, len, 1); } void flush_block (int ystart, int ystop) { - int len, xs = 0; - - if (gfxvidinfo.maxlinetoscr) - len = gfxvidinfo.maxlinetoscr; - else - len = hsize; -#ifndef DONT_WANT_SHM - if (use_shm) - XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, - ystop - ystart + 1, 0); - else -#endif - XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, - ystop - ystart + 1); + if (dgamode) + return; + + DO_PUTIMAGE (ami_dinfo.ximg, 0, ystart, 0, ystart, gfxvidinfo.width, ystop - ystart + 1); } void flush_screen (int ystart, int ystop) { -#ifndef DONT_WANT_SHM - if (use_shm) XSync(display, 0); + if (dgamode) + return; + +#if SHM_SUPPORT_LINKS == 1 + if (currprefs.x11_use_mitshm && shmavail) + XSync (display, 0); #endif } -void calc_adjustment(void) +void flush_clear_screen (void) { - switch (screen_res) { - case 0: case 1: case 2: /* LoRes, 320x300 */ - gfxvidinfo.x_adjust = prev_max_diwstop - 320; - break; - - case 3: /* 640x480 */ - gfxvidinfo.x_adjust = prev_max_diwstop - 640; - break; - default: - gfxvidinfo.x_adjust = 0; - break; - } + flush_screen(0,0); } -static __inline__ int bitsInMask(unsigned long mask) +STATIC_INLINE int bitsInMask (unsigned long mask) { /* count bits in mask */ int n = 0; - while(mask) { - n += mask&1; + while (mask) { + n += mask & 1; mask >>= 1; } return n; } -static __inline__ int maskShift(unsigned long mask) +STATIC_INLINE int maskShift (unsigned long mask) { /* determine how far mask is shifted */ int n = 0; - while(!(mask&1)) { + while (!(mask & 1)) { n++; mask >>= 1; } return n; } -static int get_color(int r, int g, int b, xcolnr *cnp) +static unsigned long pixel_return[256]; +static XColor parsed_xcolors[256]; +static int ncolors = 0; + +static int blackval = 32767; +static int whiteval = 0; + +static int get_color (int r, int g, int b, xcolnr *cnp) { - XColor col; + XColor *col = parsed_xcolors + ncolors; char str[10]; - sprintf(str, "rgb:%x/%x/%x", r, g, b); - XParseColor(display, cmap, str, &col); - if (XAllocColor(display, cmap, &col)) { - *cnp = col.pixel; - return 1; - } - return 0; + + sprintf (str, "rgb:%x/%x/%x", r, g, b); + XParseColor (display, cmap, str, col); + *cnp = col->pixel = pixel_return[ncolors]; + XStoreColor (display, cmap, col); + XStoreColor (display, cmap2, col); + + if (r + g + b < blackval) + blackval = r + g + b, black = *col; + if (r + g + b > whiteval) + whiteval = r + g + b, white = *col; + + ncolors++; + return 1; } -static int init_colors(void) +static int init_colors (void) { + int i; + + if (visualInfo.VI_CLASS == TrueColor) { + red_bits = bitsInMask (visualInfo.red_mask); + green_bits = bitsInMask (visualInfo.green_mask); + blue_bits = bitsInMask (visualInfo.blue_mask); + red_shift = maskShift (visualInfo.red_mask); + green_shift = maskShift (visualInfo.green_mask); + blue_shift = maskShift (visualInfo.blue_mask); + } + if (need_dither) { if (bitdepth == 1) setup_greydither (1, get_color); else setup_dither (bitdepth, get_color); - return 1; + } else { + if (bitdepth != 8 && bitdepth != 12 && bitdepth != 15 + && bitdepth != 16 && bitdepth != 24) { + write_log ("Unsupported bit depth (%d)\n", bitdepth); + return 0; + } + + switch (visualInfo.VI_CLASS) { + case TrueColor: + alloc_colors64k (red_bits, green_bits, blue_bits, red_shift, + green_shift, blue_shift); + + XParseColor (display, cmap, "#000000", &black); + if (! XAllocColor (display, cmap, &black)) + write_log ("Whoops??\n"); + XParseColor (display, cmap, "#ffffff", &white); + if (! XAllocColor (display, cmap, &white)) + write_log ("Whoops??\n"); + break; + + case GrayScale: + case PseudoColor: + alloc_colors256 (get_color); + break; + + default: + write_log ("Unsupported visual class (%d)\n", visualInfo.VI_CLASS); + return 0; + } } - - if (bitdepth != 8 && bitdepth != 12 - && bitdepth != 16 && bitdepth != 24) { - fprintf(stderr, "Unsupported bit depth (%d)\n", bitdepth); + switch (gfxvidinfo.pixbytes) { + case 2: + for (i = 0; i < 4096; i++) + xcolors[i] = xcolors[i] * 0x00010001; + gfxvidinfo.can_double = 1; + break; + case 1: + for (i = 0; i < 4096; i++) + xcolors[i] = xcolors[i] * 0x01010101; + gfxvidinfo.can_double = 1; + break; + default: + gfxvidinfo.can_double = 0; + break; + } + if (inverse_byte_order) + switch (gfxvidinfo.pixbytes) { + case 4: + for(i = 0; i < 4096; i++) + xcolors[i] = ((((xcolors[i]>>0)&255) << 24) + | (((xcolors[i]>>8)&255) << 16) + | (((xcolors[i]>>16)&255) << 8) + | (((xcolors[i]>>24)&255) << 0)); + break; + case 2: + for (i = 0; i < 4096; i++) + xcolors[i] = (xcolors[i]>>8) | ((xcolors[i]&255)<<8); + break; + default: + break; + } + return 1; +} + +static int dga_available (void) +{ +#ifdef USE_DGA_EXTENSION + int MajorVersion, MinorVersion; + int EventBase, ErrorBase; + + if (! XF86DGAQueryVersion (display, &MajorVersion, &MinorVersion)) { + write_log ("Unable to query video extension version\n"); return 0; } - -#ifdef __cplusplus - switch(visualInfo.c_class) -#else - switch(visualInfo.class) -#endif + if (! XF86DGAQueryExtension (display, &EventBase, &ErrorBase)) { + write_log ("Unable to query video extension information\n"); + return 0; + } + /* Fail if the extension version in the server is too old */ + if (MajorVersion < DGA_MINMAJOR + || (MajorVersion == DGA_MINMAJOR && MinorVersion < DGA_MINMINOR)) { - case TrueColor: - { - int red_bits = bitsInMask(visualInfo.red_mask); - int green_bits = bitsInMask(visualInfo.green_mask); - int blue_bits = bitsInMask(visualInfo.blue_mask); - int red_shift = maskShift(visualInfo.red_mask); - int green_shift = maskShift(visualInfo.green_mask); - int blue_shift = maskShift(visualInfo.blue_mask); - alloc_colors64k(red_bits, green_bits, blue_bits, red_shift, - green_shift, blue_shift); - } - break; + write_log ( + "Xserver is running an old XFree86-DGA version" + " (%d.%d)\n", MajorVersion, MinorVersion); + write_log ("Minimum required version is %d.%d\n", + DGA_MINMAJOR, DGA_MINMINOR); + return 0; + } + if (geteuid () != 0) { + write_log ("UAE is not running as root, DGA extension disabled.\n"); + return 0; + } + if (! XF86DGAGetVideo (display, screen, &fb_addr, &fb_width, &fb_bank, &fb_mem) + || fb_bank < fb_mem) + { + write_log ("Problems with DGA - disabling DGA extension.\n"); + return 0; + } + write_log ("DGA extension: addr:%X, width %d, bank size %d mem size %d\n", + fb_addr, fb_width, fb_bank, fb_mem); - case GrayScale: - case PseudoColor: - alloc_colors256(get_color); - break; - - default: -#ifdef __cplusplus - fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.c_class); + return 1; #else - fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.class); + return 0; #endif +} + +static int vid_mode_available (void) +{ +#ifdef USE_VIDMODE_EXTENSION + int MajorVersion, MinorVersion; + int EventBase, ErrorBase; + + if (! dgaavail) + return 0; + if (! XF86VidModeQueryVersion (display, &MajorVersion, &MinorVersion)) { + write_log ("Unable to query video extension version\n"); + return 0; + } + if (! XF86VidModeQueryExtension (display, &EventBase, &ErrorBase)) { + write_log ("Unable to query video extension information\n"); + return 0; + } + if (MajorVersion < VidMode_MINMAJOR + || (MajorVersion == VidMode_MINMAJOR && MinorVersion < VidMode_MINMINOR)) { + /* Fail if the extension version in the server is too old */ + write_log ("Xserver is running an old XFree86-VidMode version (%d.%d)\n", + MajorVersion, MinorVersion); + write_log ("Minimum required version is %d.%d\n", + VidMode_MINMAJOR, VidMode_MINMINOR); + return 0; + } + if (! get_vidmodes ()) { + write_log ("Error getting video mode information\n"); return 0; } return 1; +#else + return 0; +#endif } -int graphics_init(void) +static int shm_available (void) +{ +#if SHM_SUPPORT_LINKS == 1 + if (XShmQueryExtension (display)) + return 1; +#endif + return 0; +} + +int graphics_setup (void) { - int i,j; char *display_name = 0; - XSetWindowAttributes wattr; - XPixmapFormatValues *xpfvs; - need_dither = 0; - - if (screen_res < 3) { - fprintf(stderr, "Low resolution mode selected. Forcing 320x300.\n"); - } - - display = XOpenDisplay(display_name); + + display = XOpenDisplay (display_name); if (display == 0) { - fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name)); - return 0; - } - screen = XDefaultScreen(display); - rootwin = XRootWindow(display,screen); - - /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */ - if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) { - /* for our HP boxes */ - } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) { - } else if (XMatchVisualInfo(display, screen, 4, PseudoColor, &visualInfo)) { - /* VGA16 server. Argh. */ - } else if (XMatchVisualInfo(display, screen, 1, StaticGray, &visualInfo)) { - /* Mono server. Yuk */ - } else { - fprintf(stderr, "Can't obtain appropriate X visual.\n"); + write_log ("Can't connect to X server %s\n", XDisplayName (display_name)); return 0; } - vis = visualInfo.visual; - bitdepth = visualInfo.depth; - - /* We now have the bitdepth of the display, but that doesn't tell us yet - * how many bits to use per pixel. The VGA16 server has a bitdepth of 4, - * but uses 1 byte per pixel. */ - xpfvs = XListPixmapFormats(display, &i); - for (j = 0; j < i && xpfvs->depth != bitdepth; j++, xpfvs++) - ; - if (j == i) { - fprintf(stderr, "Your X server is feeling ill.\n"); - return 0; + + shmavail = shm_available (); + dgaavail = dga_available (); + vidmodeavail = vid_mode_available (); + + { + int local_byte_order; + int x = 0x04030201; + char *y=(char*)&x; + + local_byte_order = y[0] == 0x04 ? MSBFirst : LSBFirst; + if (ImageByteOrder(display) != local_byte_order) + inverse_byte_order = 1; } - - bit_unit = xpfvs->bits_per_pixel; - fprintf(stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit); - switch (screen_res) { - case 0: case 1: case 2: - hsize = hpixels = 320; - correct_aspect = 0; - break; - case 3: - hsize = hpixels = 640; - break; - case 4: - hpixels = 796; hsize = 800; /* ??? */ - break; + return 1; +} + +static void lock_window_size (void) +{ + XSizeHints hint; + + hint.flags = PMinSize | PMaxSize; + hint.min_width = current_width; + hint.min_height = current_height; + hint.max_width = current_width; + hint.max_height = current_height; + XSetWMNormalHints (display, mywin, &hint); +} + +static void init_dispinfo (struct disp_info *disp) +{ +#if SHM_SUPPORT_LINKS == 1 + disp->shminfo.shmid = -1; +#endif + disp->ximg = 0; +} + +static void reset_cursor (void) +{ + if (! dgamode) { + if (! currprefs.x11_hide_cursor) + XDefineCursor (display, mywin, xhairCursor); + else + XDefineCursor (display, mywin, blankCursor); + cursorOn = 1; } - vsize = correct_aspect ? 2*numscrlines : numscrlines; +} + +static void graphics_subinit (void) +{ + int i, j; + XSetWindowAttributes wattr; + XClassHint classhint; + XWMHints *hints; + unsigned long valuemask; + - cmap = XCreateColormap(display, rootwin, vis, AllocNone); - XParseColor(display, cmap, "#000000", &black); - if (!XAllocColor(display, cmap, &black)) - fprintf(stderr, "Whoops??\n"); - XParseColor(display, cmap, "#ffffff", &white); - if (!XAllocColor(display, cmap, &white)) - fprintf(stderr, "Whoops??\n"); + if (screen_is_picasso) { + // Set height, width for Picasso gfx + current_width = picasso_vidinfo.width; + current_height = picasso_vidinfo.height; + dgamode = currprefs.gfx_pfullscreen && dgaavail; + curr_gfx = 0; + } else { + // Set height, width for Amiga gfx + dgamode = currprefs.gfx_afullscreen && dgaavail; + if (dgamode) + curr_gfx = &currprefs.gfx_f; + else + curr_gfx = &currprefs.gfx_w; + + current_width = curr_gfx->width; + current_height = curr_gfx->height; + } + if (!screen_is_picasso) { + gfxvidinfo.width = current_width; + gfxvidinfo.height = current_height; + } - wattr.event_mask = eventmask; - wattr.background_pixel = black.pixel; + wattr.background_pixel = /*black.pixel*/0; wattr.backing_store = Always; wattr.backing_planes = bitdepth; wattr.border_pixmap = None; - wattr.border_pixel = black.pixel; + wattr.border_pixel = /*black.pixel*/0; wattr.colormap = cmap; + valuemask = (CWEventMask | CWBackPixel | CWBorderPixel + | CWBackingStore | CWBackingPlanes | CWColormap); - mywin = XCreateWindow(display, rootwin, 0, 0, hpixels, vsize, 0, - bitdepth, InputOutput, vis, - CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore - |CWBackingPlanes|CWColormap, - &wattr); - XMapWindow(display,mywin); - XStoreName(display, mywin, "UAE"); - - blankCursor = XCreatePixmapCursor(display, - XCreatePixmap(display, mywin, 1, 1, 1), - XCreatePixmap(display, mywin, 1, 1, 1), - &black, &white, 0, 0); - xhairCursor = XCreateFontCursor(display, XC_crosshair); - - whitegc = XCreateGC(display,mywin,0,0); - blackgc = XCreateGC(display,mywin,0,0); - - XSetForeground(display,blackgc,black.pixel); - XSetForeground(display,whitegc,white.pixel); + if (dgamode) { + wattr.event_mask = DGA_EVENTMASK; + wattr.override_redirect = 1; + valuemask |= CWOverrideRedirect; + } else + wattr.event_mask = EVENTMASK; - if (bitdepth < 8 || (bitdepth == 8 && color_mode == 3)) { - gfxvidinfo.pixbytes = 2; - use_low_bandwidth = 1; - need_dither = 1; -#ifndef DONT_WANT_SHM - use_shm = 0; + XSync (display, 0); + delete_win = XInternAtom(display, "WM_DELETE_WINDOW", False); + mywin = XCreateWindow (display, rootwin, 0, 0, current_width, current_height, + 0, bitdepth, InputOutput, vis, valuemask, &wattr); + XSetWMProtocols (display, mywin, &delete_win, 1); + XSync (display, 0); + + XStoreName (display, mywin, "UAE"); + XSetIconName (display, mywin, "UAE Screen"); + + /* set class hint */ + classhint.res_name = "UAE"; + classhint.res_class = "UAEScreen"; + XSetClassHint(display, mywin, &classhint); + + hints = XAllocWMHints(); + /* Set window group leader to self to become an application + * that can be hidden by e.g. WindowMaker. + * Would be more useful if we could find out what the + * (optional) GTK+ window ID is :-/ */ + hints->window_group = mywin; + hints->flags = WindowGroupHint; + XSetWMHints(display, mywin, hints); + + XMapRaised (display, mywin); + XSync (display, 0); + mygc = XCreateGC (display, mywin, 0, 0); + + if (dgamode) { +#ifdef USE_DGA_EXTENSION + enter_dga_mode (); + /*setuid(getuid());*/ + picasso_vidinfo.rowbytes = fb_width * picasso_vidinfo.pixbytes; #endif } else { - gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4 - : bitdepth == 12 || bitdepth == 16 ? 2 - : 1); - } - -#ifndef DONT_WANT_SHM - if (use_shm) { - img = XShmCreateImage(display, vis, bitdepth, ZPixmap, 0, &shminfo, hsize, vsize); - - shminfo.shmid = shmget(IPC_PRIVATE, vsize * img->bytes_per_line, - IPC_CREAT | 0777); - shminfo.shmaddr = img->data = image_mem = (char *)shmat(shminfo.shmid, 0, 0); - shminfo.readOnly = False; - /* let the xserver attach */ - XShmAttach(display, &shminfo); - XSync(display,0); - /* now deleting means making it temporary */ - shmctl(shminfo.shmid, IPC_RMID, 0); - } else -#endif - { - /* Question for people who know about X: Could we allocate the buffer - * after creating the image and then do img->data = buffer, as above in - * the SHM case? - */ - image_mem = (char *)malloc(vsize * hsize * bit_unit / 8); /* ??? */ - img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, image_mem, - hsize, vsize, 32, 0); - if (img->bytes_per_line != hsize * bit_unit / 8) - fprintf (stderr, "Possible bug here... graphics may look strange.\n"); + get_image (current_width, current_height, &ami_dinfo); + if (screen_is_picasso) { + get_image (current_width, current_height, &pic_dinfo); + picasso_vidinfo.rowbytes = pic_dinfo.ximg->bytes_per_line; + } } - + + picasso_vidinfo.extra_mem = 1; + if (need_dither) { - gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * hsize; - gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * vsize); - } else { - gfxvidinfo.rowbytes = img->bytes_per_line; - gfxvidinfo.bufmem = image_mem; + gfxvidinfo.maxblocklines = 0; + gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * current_width; + gfxvidinfo.linemem = (char *)malloc (gfxvidinfo.rowbytes); + } else if (! dgamode) { + gfxvidinfo.emergmem = 0; + gfxvidinfo.linemem = 0; + gfxvidinfo.bufmem = ami_dinfo.image_mem; + gfxvidinfo.rowbytes = ami_dinfo.ximg->bytes_per_line; + if (currprefs.x11_use_low_bandwidth) { + gfxvidinfo.maxblocklines = 0; + gfxvidinfo.rowbytes = ami_dinfo.ximg->bytes_per_line; + gfxvidinfo.linemem = (char *)malloc (gfxvidinfo.rowbytes); + } else { + gfxvidinfo.maxblocklines = 100; /* whatever... */ + } } - - gfxvidinfo.maxline = 100000; /* no limit */ - if (use_low_bandwidth) { - gfxvidinfo.maxblocklines = 0; - oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * vsize); - } else { - gfxvidinfo.maxblocklines = 100; /* whatever... */ + if (visualInfo.VI_CLASS != TrueColor && ! screen_is_picasso) { + int i; + for (i = 0; i < 256; i++) + XStoreColor (display, cmap, parsed_xcolors + i); } - if (!init_colors()) - return 0; +#ifdef USE_DGA_EXTENSION + if (dgamode) { + dga_colormap_installed = 0; + XF86DGAInstallColormap (display, screen, cmap2); + XF86DGAInstallColormap (display, screen, cmap); + } +#endif + + reset_cursor (); + + if (screen_is_picasso) { + picasso_has_invalid_lines = 0; + picasso_invalid_start = picasso_vidinfo.height + 1; + picasso_invalid_stop = -1; + memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines); + } - buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; - for(i=0; i<256; i++) - keystate[i] = 0; - - lastmx = lastmy = 0; - newmousecounters = 0; inwindow = 0; - - if (!no_xhair) - XDefineCursor(display, mywin, xhairCursor); - else - XDefineCursor(display, mywin, blankCursor); - cursorOn = 1; - return 1; + inputdevice_release_all_keys (); + reset_hotkeys (); } -void graphics_leave(void) +static int get_best_visual (XVisualInfo *vi) { - if (autorepeatoff) - XAutoRepeatOn(display); -} + screen = XDefaultScreen (display); + rootwin = XRootWindow (display, screen); -/* Decode KeySyms. This function knows about all keys that are common - * between different keyboard languages. */ -static int kc_decode (KeySym ks) -{ - switch (ks) { - case XK_B: case XK_b: return AK_B; - case XK_C: case XK_c: return AK_C; - case XK_D: case XK_d: return AK_D; - case XK_E: case XK_e: return AK_E; - case XK_F: case XK_f: return AK_F; - case XK_G: case XK_g: return AK_G; - case XK_H: case XK_h: return AK_H; - case XK_I: case XK_i: return AK_I; - case XK_J: case XK_j: return AK_J; - case XK_K: case XK_k: return AK_K; - case XK_L: case XK_l: return AK_L; - case XK_N: case XK_n: return AK_N; - case XK_O: case XK_o: return AK_O; - case XK_P: case XK_p: return AK_P; - case XK_R: case XK_r: return AK_R; - case XK_S: case XK_s: return AK_S; - case XK_T: case XK_t: return AK_T; - case XK_U: case XK_u: return AK_U; - case XK_V: case XK_v: return AK_V; - case XK_W: case XK_w: return AK_W; - case XK_X: case XK_x: return AK_X; - - case XK_0: return AK_0; - case XK_1: return AK_1; - case XK_2: return AK_2; - case XK_3: return AK_3; - case XK_4: return AK_4; - case XK_5: return AK_5; - case XK_6: return AK_6; - case XK_7: return AK_7; - case XK_8: return AK_8; - case XK_9: return AK_9; - - /* You never know which Keysyms might be missing on some workstation - * This #ifdef should be enough. */ -#if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End) - case XK_KP_0: case XK_KP_Insert: return AK_NP0; - case XK_KP_1: case XK_KP_End: return AK_NP1; - case XK_KP_2: case XK_KP_Down: return AK_NP2; - case XK_KP_3: case XK_KP_Next: return AK_NP3; - case XK_KP_4: case XK_KP_Left: return AK_NP4; - case XK_KP_5: case XK_KP_Begin: return AK_NP5; - case XK_KP_6: case XK_KP_Right: return AK_NP6; - case XK_KP_7: case XK_KP_Home: return AK_NP7; - case XK_KP_8: case XK_KP_Up: return AK_NP8; - case XK_KP_9: case XK_KP_Prior: return AK_NP9; -#else - case XK_KP_0: return AK_NP0; - case XK_KP_1: return AK_NP1; - case XK_KP_2: return AK_NP2; - case XK_KP_3: return AK_NP3; - case XK_KP_4: return AK_NP4; - case XK_KP_5: return AK_NP5; - case XK_KP_6: return AK_NP6; - case XK_KP_7: return AK_NP7; - case XK_KP_8: return AK_NP8; - case XK_KP_9: return AK_NP9; -#endif - case XK_KP_Divide: return AK_NPDIV; - case XK_KP_Multiply: return AK_NPMUL; - case XK_KP_Subtract: return AK_NPSUB; - case XK_KP_Add: return AK_NPADD; - case XK_KP_Decimal: return AK_NPDEL; - case XK_KP_Enter: return AK_ENT; - - case XK_F1: return AK_F1; - case XK_F2: return AK_F2; - case XK_F3: return AK_F3; - case XK_F4: return AK_F4; - case XK_F5: return AK_F5; - case XK_F6: return AK_F6; - case XK_F7: return AK_F7; - case XK_F8: return AK_F8; - case XK_F9: return AK_F9; - case XK_F10: return AK_F10; - - case XK_BackSpace: return AK_BS; - case XK_Delete: return AK_DEL; - case XK_Control_L: case XK_Control_R: return AK_CTRL; - case XK_Tab: return AK_TAB; - case XK_Alt_L: return AK_LALT; - case XK_Alt_R: return AK_RALT; - case XK_Meta_R: case XK_Hyper_R: return AK_RAMI; - case XK_Meta_L: case XK_Hyper_L: return AK_LAMI; - case XK_Return: return AK_RET; - case XK_space: return AK_SPC; - case XK_Shift_L: return AK_LSH; - case XK_Shift_R: return AK_RSH; - case XK_Escape: return AK_ESC; - - case XK_Insert: return AK_BACKSLASH; - case XK_End: return AK_HELP; - case XK_Caps_Lock: return AK_CAPSLOCK; - - case XK_Up: return AK_UP; - case XK_Down: return AK_DN; - case XK_Left: return AK_LF; - case XK_Right: return AK_RT; - - case XK_F11: return AK_BACKSLASH; - case XK_F12: return AK_mousestuff; -#ifdef XK_F14 - case XK_F14: -#endif - case XK_Scroll_Lock: return AK_inhibit; - -#ifdef XK_Page_Up /* These are missing occasionally */ - case XK_Page_Up: return AK_RAMI; /* PgUp mapped to right amiga */ - case XK_Page_Down: return AK_LAMI; /* PgDn mapped to left amiga */ -#endif + /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */ + if (XMatchVisualInfo (display, screen, 12, TrueColor, vi)) { + } else if (XMatchVisualInfo (display, screen, 15, TrueColor, vi)) { + } else if (XMatchVisualInfo (display, screen, 16, TrueColor, vi)) { + } else if (XMatchVisualInfo (display, screen, 24, TrueColor, vi)) { + } else if (XMatchVisualInfo (display, screen, 8, PseudoColor, vi)) { + /* for our HP boxes */ + } else if (XMatchVisualInfo (display, screen, 8, GrayScale, vi)) { + } else if (XMatchVisualInfo (display, screen, 4, PseudoColor, vi)) { + /* VGA16 server. Argh. */ + } else if (XMatchVisualInfo (display, screen, 1, StaticGray, vi)) { + /* Mono server. Yuk */ + } else { + write_log ("Can't obtain appropriate X visual.\n"); + return 0; } - return -1; + return 1; } -static int decode_fr(KeySym ks) +static int get_visual_bit_unit (XVisualInfo *vi, int bitdepth) { - switch(ks) { /* FR specific */ - case XK_A: case XK_a: return AK_Q; - case XK_M: case XK_m: return AK_SEMICOLON; - case XK_Q: case XK_q: return AK_A; - case XK_Y: case XK_y: return AK_Y; - case XK_Z: case XK_z: return AK_Z; - case XK_bracketleft: return AK_LBRACKET; - case XK_bracketright: return AK_RBRACKET; - case XK_comma: return AK_M; - case XK_less: case XK_greater: return AK_LTGT; - case XK_period: return AK_COMMA; - case XK_parenright: return AK_MINUS; - case XK_equal: return AK_SLASH; - case XK_numbersign: return AK_NUMBERSIGN; - case XK_slash: return AK_PERIOD; - case XK_minus: return AK_EQUAL; - case XK_backslash: return AK_BACKSLASH; + int bit_unit = 0; + XPixmapFormatValues *xpfvs; + int i,j; + + /* We now have the bitdepth of the display, but that doesn't tell us yet + * how many bits to use per pixel. The VGA16 server has a bitdepth of 4, + * but uses 1 byte per pixel. */ + xpfvs = XListPixmapFormats (display, &i); + for (j = 0; j < i && xpfvs[j].depth != bitdepth; j++) + ; + if (j < i) + bit_unit = xpfvs[j].bits_per_pixel; + XFree (xpfvs); + if (j == i) { + write_log ("Your X server is feeling ill.\n"); } - return -1; + return bit_unit; } -static int decode_us(KeySym ks) +int graphics_init (void) { - switch(ks) { /* US specific */ - case XK_A: case XK_a: return AK_A; - case XK_M: case XK_m: return AK_M; - case XK_Q: case XK_q: return AK_Q; - case XK_Y: case XK_y: return AK_Y; - case XK_Z: case XK_z: return AK_Z; - case XK_bracketleft: return AK_LBRACKET; - case XK_bracketright: return AK_RBRACKET; - case XK_comma: return AK_COMMA; - case XK_period: return AK_PERIOD; - case XK_slash: return AK_SLASH; - case XK_semicolon: return AK_SEMICOLON; - case XK_minus: return AK_MINUS; - case XK_equal: return AK_EQUAL; - /* this doesn't work: */ - case XK_quoteright: return AK_QUOTE; - case XK_quoteleft: return AK_BACKQUOTE; - case XK_backslash: return AK_BACKSLASH; + int i,j; + XPixmapFormatValues *xpfvs; + + if (currprefs.x11_use_mitshm && ! shmavail) { + write_log ("MIT-SHM extension not supported by X server.\n"); } + if (currprefs.color_mode > 5) + write_log ("Bad color mode selected. Using default.\n"), currprefs.color_mode = 0; - return -1; -} + x11_init_ok = 0; + need_dither = 0; + screen_is_picasso = 0; + dgamode = 0; -static int decode_de(KeySym ks) -{ - switch(ks) { - /* DE specific */ - case XK_A: case XK_a: return AK_A; - case XK_M: case XK_m: return AK_M; - case XK_Q: case XK_q: return AK_Q; - case XK_Y: case XK_y: return AK_Z; - case XK_Z: case XK_z: return AK_Y; - case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON; - case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE; - case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET; - case XK_plus: case XK_asterisk: return AK_RBRACKET; - case XK_comma: return AK_COMMA; - case XK_period: return AK_PERIOD; - case XK_less: case XK_greater: return AK_LTGT; - case XK_numbersign: return AK_NUMBERSIGN; - case XK_ssharp: return AK_MINUS; - case XK_apostrophe: return AK_EQUAL; - case XK_asciicircum: return AK_BACKQUOTE; - case XK_minus: return AK_SLASH; + init_dispinfo (&ami_dinfo); + init_dispinfo (&pic_dinfo); + + screen = XDefaultScreen (display); + rootwin = XRootWindow (display, screen); + + if (!get_best_visual (&visualInfo)) return 0; + + vis = visualInfo.visual; + bitdepth = visualInfo.depth; + + if (!(bit_unit = get_visual_bit_unit (&visualInfo, bitdepth))) return 0; + + write_log ("Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit); + + fixup_prefs_dimensions (&currprefs.gfx_w); + fixup_prefs_dimensions (&currprefs.gfx_f); + + cmap = XCreateColormap (display, rootwin, vis, AllocNone); + cmap2 = XCreateColormap (display, rootwin, vis, AllocNone); + if (visualInfo.VI_CLASS == GrayScale || visualInfo.VI_CLASS == PseudoColor) { + XAllocColorCells (display, cmap, 0, 0, 0, pixel_return, 1 << bitdepth); + XAllocColorCells (display, cmap2, 0, 0, 0, pixel_return, 1 << bitdepth); } - return -1; + if (bitdepth < 8 || (bitdepth == 8 && currprefs.color_mode == 3)) { + gfxvidinfo.pixbytes = 2; + currprefs.x11_use_low_bandwidth = 0; + need_dither = 1; + } else { + gfxvidinfo.pixbytes = bit_unit >> 3; + } + + if (! init_colors ()) + return 0; + + blankCursor = XCreatePixmapCursor (display, + XCreatePixmap (display, rootwin, 1, 1, 1), + XCreatePixmap (display, rootwin, 1, 1, 1), + &black, &white, 0, 0); + xhairCursor = XCreateFontCursor (display, XC_crosshair); + + graphics_subinit (); + + grabbed = 0; + + return x11_init_ok = 1; } -static int decode_se(KeySym ks) +static void destroy_dinfo (struct disp_info *dinfo) { - switch(ks) { - /* SE specific */ - case XK_A: case XK_a: return AK_A; - case XK_M: case XK_m: return AK_M; - case XK_Q: case XK_q: return AK_Q; - case XK_Y: case XK_y: return AK_Y; - case XK_Z: case XK_z: return AK_Z; - case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON; - case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE; - case XK_Aring: case XK_aring: return AK_LBRACKET; - case XK_comma: return AK_COMMA; - case XK_period: return AK_PERIOD; - case XK_minus: return AK_SLASH; - case XK_less: case XK_greater: return AK_LTGT; - case XK_plus: case XK_question: return AK_EQUAL; - case XK_at: case XK_onehalf: return AK_BACKQUOTE; - case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET; - case XK_backslash: case XK_bar: return AK_MINUS; - - case XK_numbersign: return AK_NUMBERSIGN; - } - - return -1; - } + if (dinfo->ximg == NULL) + return; +#if SHM_SUPPORT_LINKS == 1 + if (dinfo->shminfo.shmid != -1) + shmdt (dinfo->shminfo.shmaddr); + dinfo->shminfo.shmid = -1; +#endif + XDestroyImage (dinfo->ximg); + dinfo->ximg = NULL; +} -static int decode_it(KeySym ks) +static void graphics_subshutdown (void) { - switch(ks) { - /* IT specific */ - case XK_A: case XK_a: return AK_A; - case XK_M: case XK_m: return AK_M; - case XK_Q: case XK_q: return AK_Q; - case XK_Y: case XK_y: return AK_Y; - case XK_Z: case XK_z: return AK_Z; - case XK_Ograve: case XK_ograve: return AK_SEMICOLON; - case XK_Agrave: case XK_agrave: return AK_QUOTE; - case XK_Egrave: case XK_egrave: return AK_LBRACKET; - case XK_plus: case XK_asterisk: return AK_RBRACKET; - case XK_comma: return AK_COMMA; - case XK_period: return AK_PERIOD; - case XK_less: case XK_greater: return AK_LTGT; - case XK_backslash: case XK_bar: return AK_BACKQUOTE; - case XK_apostrophe: return AK_MINUS; - case XK_Igrave: case XK_igrave: return AK_EQUAL; - case XK_minus: return AK_SLASH; - case XK_numbersign: return AK_NUMBERSIGN; + XSync (display, 0); +#ifdef USE_DGA_EXTENSION + if (dgamode) + leave_dga_mode (); +#endif + + destroy_dinfo (&ami_dinfo); + destroy_dinfo (&pic_dinfo); + + if (mywin) { + XDestroyWindow (display, mywin); + mywin = 0; } - return -1; + if (gfxvidinfo.linemem != NULL) + free (gfxvidinfo.linemem); + if (gfxvidinfo.emergmem != NULL) + free (gfxvidinfo.emergmem); } -static int keycode2amiga(XKeyEvent *event) +void graphics_leave (void) { - KeySym ks; - int as; - int index = 0; - - do { - ks = XLookupKeysym(event, index); - as = kc_decode (ks); - - if (as == -1) { - switch(keyboard_lang) { - - case KBD_LANG_FR: - as = decode_fr(ks); - break; - - case KBD_LANG_US: - as = decode_us(ks); - break; - - case KBD_LANG_DE: - as = decode_de(ks); - break; - - case KBD_LANG_SE: - as = decode_se(ks); - break; - - case KBD_LANG_IT: - as = decode_it(ks); - break; - - default: - as = -1; - break; - } - } - if(-1 != as) - return as; - index++; - } while (ks != NoSymbol); - return -1; + if (! x11_init_ok) + return; + + graphics_subshutdown (); + + if (autorepeatoff) + XAutoRepeatOn (display); + + XFlush (display); + XSync (display, 0); + + XFreeColormap (display, cmap); + XFreeColormap (display, cmap2); + +#if 0 + XCloseDisplay (display); +#endif + dumpcustom (); } static struct timeval lastMotionTime; -void handle_events(void) +static int refresh_necessary = 0; + +void handle_events (void) { - int refresh = 0; - newmousecounters = 0; - gui_handle_events(); - + gui_handle_events (); + for (;;) { XEvent event; #if 0 - if (!XCheckMaskEvent(display, eventmask, &event)) break; + if (! XCheckMaskEvent (display, eventmask, &event)) + break; #endif - if (!XPending(display)) break; - XNextEvent(display, &event); - - switch(event.type) { - case KeyPress: { - int kc = keycode2amiga((XKeyEvent *)&event); - if (kc == -1) break; - switch (kc) { - case AK_mousestuff: - togglemouse(); - break; - - case AK_inhibit: - inhibit_frame ^= 1; - break; - - default: - if (!keystate[kc]) { - keystate[kc] = 1; - record_key (kc << 1); - } - break; - } - break; - } - case KeyRelease: { - int kc = keycode2amiga((XKeyEvent *)&event); - if (kc == -1) break; - keystate[kc] = 0; - record_key ((kc << 1) | 1); - break; + if (! XPending (display)) + break; + + XNextEvent (display, &event); + + switch (event.type) { + case KeyPress: + case KeyRelease: { + int state = (event.type == KeyPress); + KeySym keysym; + int index = 0; + int ievent, amiga_keycode; + do { + keysym = XLookupKeysym ((XKeyEvent *)&event, index); + if ((ievent = match_hotkey_sequence (keysym, state))) { + handle_hotkey_event (ievent, state); + break; + } else + if ((amiga_keycode = xkeysym2amiga (keysym)) >= 0) { + inputdevice_do_keyboard (amiga_keycode, state); + break; + } + index++; + } while (keysym != NoSymbol); + break; } case ButtonPress: - buttonstate[((XButtonEvent *)&event)->button-1] = 1; + case ButtonRelease: { + int state = (event.type == ButtonPress); + int buttonno = -1; + switch ((int)((XButtonEvent *)&event)->button) { + case 1: buttonno = 0; break; + case 2: buttonno = 2; break; + case 3: buttonno = 1; break; + /* buttons 4 and 5 report mousewheel events */ + case 4: if (state) record_key (0x7a << 1); break; + case 5: if (state) record_key (0x7b << 1); break; + } + if (buttonno >=0) + setmousebuttonstate(0, buttonno, state); break; - case ButtonRelease: - buttonstate[((XButtonEvent *)&event)->button-1] = 0; + } + case MotionNotify: + if (dgamode) { + int tx = ((XMotionEvent *)&event)->x_root; + int ty = ((XMotionEvent *)&event)->y_root; + setmousestate (0, 0, tx, 0); + setmousestate (0, 1, ty, 0); + } else if (grabbed) { + int realmove = 0; + int tx, ty,ttx,tty; + + tx = ((XMotionEvent *)&event)->x; + ty = ((XMotionEvent *)&event)->y; + if (! event.xmotion.send_event) { + setmousestate (0, 0, tx - oldx, 0); + setmousestate (0, 1, ty - oldy, 0); + realmove = 1; +#undef ABS +#define ABS(a) (((a)<0) ? -(a) : (a) ) + if (ABS(current_width / 2 - tx) > 3 * current_width / 8 + || ABS(current_height / 2 - ty) > 3 * current_height / 8) + { +#undef ABS + XEvent event; + ttx = current_width / 2; + tty = current_height / 2; + event.type = MotionNotify; + event.xmotion.display = display; + event.xmotion.window = mywin; + event.xmotion.x = ttx; + event.xmotion.y = tty; + XSendEvent (display, mywin, False, + PointerMotionMask, &event); + XWarpPointer (display, None, mywin, 0, 0, 0, 0, ttx, tty); + } + } else { + tx = event.xmotion.x; + ty = event.xmotion.y; + } + oldx = tx; + oldy = ty; + } else if (inwindow) { + int tx = ((XMotionEvent *)&event)->x; + int ty = ((XMotionEvent *)&event)->y; + setmousestate(0, 0, tx, 1); + setmousestate(0, 1, ty, 1); + if (! cursorOn && !currprefs.x11_hide_cursor) { + XDefineCursor(display, mywin, xhairCursor); + cursorOn = 1; + } + gettimeofday(&lastMotionTime, NULL); + } break; case EnterNotify: - newmousecounters = 1; - lastmx = ((XCrossingEvent *)&event)->x; - lastmy = ((XCrossingEvent *)&event)->y; + { + int tx = ((XCrossingEvent *)&event)->x; + int ty = ((XCrossingEvent *)&event)->y; + setmousestate (0, 0, tx, 1); + setmousestate (0, 1, ty, 1); + } inwindow = 1; break; case LeaveNotify: inwindow = 0; break; case FocusIn: - if (!autorepeatoff) - XAutoRepeatOff(display); + if (! autorepeatoff) + XAutoRepeatOff (display); autorepeatoff = 1; break; case FocusOut: if (autorepeatoff) - XAutoRepeatOn(display); + XAutoRepeatOn (display); autorepeatoff = 0; break; - case MotionNotify: - if (inwindow) { - lastmx = ((XMotionEvent *)&event)->x; - lastmy = ((XMotionEvent *)&event)->y; - if(!cursorOn && !no_xhair) { - XDefineCursor(display, mywin, xhairCursor); - cursorOn = 1; - } - gettimeofday(&lastMotionTime, NULL); - } - break; case Expose: - refresh = 1; + refresh_necessary = 1; + break; + case ClientMessage: + if (((Atom)event.xclient.data.l[0]) == delete_win) { + uae_quit (); + } break; } } - if(refresh) { -#ifndef DONT_WANT_SHM - if (use_shm) - XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize, 0); - else +#if defined PICASSO96 + if (! dgamode) { + if (screen_is_picasso && refresh_necessary) { + DO_PUTIMAGE (pic_dinfo.ximg, 0, 0, 0, 0, + picasso_vidinfo.width, picasso_vidinfo.height); + refresh_necessary = 0; + memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines); + } else if (screen_is_picasso && picasso_has_invalid_lines) { + int i; + int strt = -1; + + picasso_invalid_lines[picasso_vidinfo.height] = 0; + for (i = picasso_invalid_start; i < picasso_invalid_stop + 2; i++) { + if (picasso_invalid_lines[i]) { + picasso_invalid_lines[i] = 0; + if (strt != -1) + continue; + strt = i; + } else { + if (strt == -1) + continue; + DO_PUTIMAGE (pic_dinfo.ximg, 0, strt, 0, strt, + picasso_vidinfo.width, i - strt); + strt = -1; + } + } + if (strt != -1) + abort (); + } + } + picasso_has_invalid_lines = 0; + picasso_invalid_start = picasso_vidinfo.height + 1; + picasso_invalid_stop = -1; #endif - XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize); + + if (! dgamode) { + if (! screen_is_picasso && refresh_necessary) { + DO_PUTIMAGE (ami_dinfo.ximg, 0, 0, 0, 0, current_width, current_height); + refresh_necessary = 0; + } + if (cursorOn && !currprefs.x11_hide_cursor) { + struct timeval now; + int diff; + gettimeofday(&now, NULL); + diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 + + (now.tv_usec - lastMotionTime.tv_usec); + if (diff > 1000000) { + XDefineCursor (display, mywin, blankCursor); + cursorOn = 0; + } + } } - if(cursorOn && !no_xhair) { - struct timeval now; - int diff; - gettimeofday(&now, NULL); - diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 + - (now.tv_usec - lastMotionTime.tv_usec); - if(diff > 1000000) { - XDefineCursor(display, mywin, blankCursor); - cursorOn = 0; +} + +int check_prefs_changed_gfx (void) +{ + int a_changed = 0, p_changed = 0; + + if (!screen_is_picasso) { + if (!dgamode + && memcmp (&changed_prefs.gfx_w, &currprefs.gfx_w, sizeof (struct gfx_params)) != 0) + { + a_changed = 1; + fixup_prefs_dimensions (&changed_prefs.gfx_w); + currprefs.gfx_w = changed_prefs.gfx_w; + } else if (dgamode + && memcmp (&changed_prefs.gfx_f, &currprefs.gfx_f, sizeof (struct gfx_params)) != 0) + { + a_changed = 1; + fixup_prefs_dimensions (&changed_prefs.gfx_f); + currprefs.gfx_f = changed_prefs.gfx_f; } + if (changed_prefs.gfx_afullscreen != currprefs.gfx_afullscreen) { + a_changed = 1; + } + } else if (changed_prefs.gfx_pfullscreen != currprefs.gfx_pfullscreen) { + p_changed = 1; } - - /* "Affengriff" */ - if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI]) - m68k_reset(); + + currprefs.gfx_afullscreen = changed_prefs.gfx_afullscreen; + currprefs.gfx_pfullscreen = changed_prefs.gfx_pfullscreen; + + if (!a_changed && !p_changed) + return 0; + + gui_update_gfx (); + + graphics_subinit (); + + if (! inwindow) + XWarpPointer (display, None, mywin, 0, 0, 0, 0, + current_width / 2, current_height / 2); + + notice_screen_contents_lost (); + init_row_map (); + if (screen_is_picasso) + picasso_enablescreen (1); + return 0; } -int debuggable(void) +int debuggable (void) { return 1; } -int needmousehack(void) +int needmousehack (void) +{ + if (dgamode || grabbed) + return 0; + else + return 1; +} + +int mousehack_allowed (void) { return 1; } -void LED(int on) +void LED (int on) { +#if 0 /* Maybe that is responsible for the joystick emulation problems on SunOS? */ static int last_on = -1; XKeyboardControl control; - if (last_on == on) return; + if (last_on == on) + return; last_on = on; control.led = 1; /* implementation defined */ control.led_mode = on ? LedModeOn : LedModeOff; XChangeKeyboardControl(display, KBLed | KBLedMode, &control); +#endif +} + +#ifdef PICASSO96 + +void DX_Invalidate (int first, int last) +{ + if (first > last) + return; + + picasso_has_invalid_lines = 1; + if (first < picasso_invalid_start) + picasso_invalid_start = first; + if (last > picasso_invalid_stop) + picasso_invalid_stop = last; + + while (first <= last) { + picasso_invalid_lines[first] = 1; + first++; + } +} + +int DX_BitsPerCannon (void) +{ + return 8; +} + +static int palette_update_start=256; +static int palette_update_end=0; + +static void DX_SetPalette_real (int start, int count) +{ + if (! screen_is_picasso || picasso96_state.RGBFormat != RGBFB_CHUNKY) + return; + + if (picasso_vidinfo.pixbytes != 1) { + /* This is the case when we're emulating a 256 color display. */ + while (count-- > 0) { + int r = picasso96_state.CLUT[start].Red; + int g = picasso96_state.CLUT[start].Green; + int b = picasso96_state.CLUT[start].Blue; + picasso_vidinfo.clut[start++] = (doMask256 (r, red_bits, red_shift) + | doMask256 (g, green_bits, green_shift) + | doMask256 (b, blue_bits, blue_shift)); + } + return; + } + + while (count-- > 0) { + XColor col = parsed_xcolors[start]; + col.red = picasso96_state.CLUT[start].Red * 0x0101; + col.green = picasso96_state.CLUT[start].Green * 0x0101; + col.blue = picasso96_state.CLUT[start].Blue * 0x0101; + XStoreColor (display, cmap, &col); + XStoreColor (display, cmap2, &col); + start++; + } +#ifdef USE_DGA_EXTENSION + if (dgamode) { + dga_colormap_installed ^= 1; + if (dga_colormap_installed == 1) + XF86DGAInstallColormap (display, screen, cmap2); + else + XF86DGAInstallColormap (display, screen, cmap); + } +#endif +} +void DX_SetPalette (int start, int count) +{ + DX_SetPalette_real (start, count); +} + +static void DX_SetPalette_delayed (int start, int count) +{ + if (bit_unit!=8) { + DX_SetPalette_real(start,count); + return; + } + if (startpalette_update_end) + palette_update_end=start+count; +} + +void DX_SetPalette_vsync(void) +{ + if (palette_update_end>palette_update_start) { + DX_SetPalette_real(palette_update_start, + palette_update_end-palette_update_start); + palette_update_end=0; + palette_update_start=256; + } +} + +int DX_Fill (int dstx, int dsty, int width, int height, uae_u32 color, RGBFTYPE rgbtype) +{ + /* not implemented yet */ + return 0; +} + +int DX_Blit (int srcx, int srcy, int dstx, int dsty, int width, int height, BLIT_OPCODE opcode) +{ + /* not implemented yet */ + return 0; +} + +#define MAX_SCREEN_MODES 12 + +static int x_size_table[MAX_SCREEN_MODES] = { 320, 320, 320, 320, 640, 640, 640, 800, 1024, 1152, 1280, 1280 }; +static int y_size_table[MAX_SCREEN_MODES] = { 200, 240, 256, 400, 350, 480, 512, 600, 768, 864, 960, 1024 }; + +int DX_FillResolutions (uae_u16 *ppixel_format) +{ + Screen *scr = ScreenOfDisplay (display, screen); + int i, count = 0; + int w = WidthOfScreen (scr); + int h = HeightOfScreen (scr); + int emulate_chunky = 0; + + /* we now need to find display depth first */ + XVisualInfo vi; + if (!get_best_visual (&vi)) return 0; + bitdepth = vi.depth; + bit_unit = get_visual_bit_unit (&vi, bitdepth); + + if (ImageByteOrder (display) == LSBFirst) { + picasso_vidinfo.rgbformat = (bit_unit == 8 ? RGBFB_CHUNKY + : bitdepth == 15 && bit_unit == 16 ? RGBFB_R5G5B5PC + : bitdepth == 16 && bit_unit == 16 ? RGBFB_R5G6B5PC + : bit_unit == 24 ? RGBFB_B8G8R8 + : bit_unit == 32 ? RGBFB_B8G8R8A8 + : RGBFB_NONE); + } else { + picasso_vidinfo.rgbformat = (bit_unit == 8 ? RGBFB_CHUNKY + : bitdepth == 15 && bit_unit == 16 ? RGBFB_R5G5B5 + : bitdepth == 16 && bit_unit == 16 ? RGBFB_R5G6B5 + : bit_unit == 24 ? RGBFB_R8G8B8 + : bit_unit == 32 ? RGBFB_A8R8G8B8 + : RGBFB_NONE); + } + + *ppixel_format = 1 << picasso_vidinfo.rgbformat; + if (vi.VI_CLASS == TrueColor && (bit_unit == 16 || bit_unit == 32)) + *ppixel_format |= RGBFF_CHUNKY, emulate_chunky = 1; + +#if defined USE_DGA_EXTENSION && defined USE_VIDMODE_EXTENSION + if (dgaavail && vidmodeavail) { + for (i = 0; i < vidmodecount && count < MAX_PICASSO_MODES; i++) { + int j; + for (j = 0; j <= emulate_chunky && count < MAX_PICASSO_MODES; j++) { + DisplayModes[count].res.width = allmodes[i]->hdisplay; + DisplayModes[count].res.height = allmodes[i]->vdisplay; + DisplayModes[count].depth = j == 1 ? 1 : bit_unit >> 3; + DisplayModes[count].refresh = 75; + count++; + } + } + } else +#endif + { + for (i = 0; i < MAX_SCREEN_MODES && count < MAX_PICASSO_MODES; i++) { + int j; + for (j = 0; j <= emulate_chunky && count < MAX_PICASSO_MODES; j++) { + if (x_size_table[i] <= w && y_size_table[i] <= h) { + if (x_size_table[i] > picasso_maxw) + picasso_maxw = x_size_table[i]; + if (y_size_table[i] > picasso_maxh) + picasso_maxh = y_size_table[i]; + DisplayModes[count].res.width = x_size_table[i]; + DisplayModes[count].res.height = y_size_table[i]; + DisplayModes[count].depth = j == 1 ? 1 : bit_unit >> 3; + DisplayModes[count].refresh = 75; + count++; + } + } + } + } + + return count; +} + +static void set_window_for_picasso (void) +{ + if (current_width == picasso_vidinfo.width && current_height == picasso_vidinfo.height) + return; + + graphics_subshutdown (); + current_width = picasso_vidinfo.width; + current_height = picasso_vidinfo.height; +#if 0 && defined USE_DGA_EXTENSION && defined USE_VIDMODE_EXTENSION + if (dgamode && vidmodeavail) + switch_to_best_mode (); +#endif + graphics_subinit (); +} + +void gfx_set_picasso_modeinfo (int w, int h, int depth, int rgbfmt) +{ + if (screen_is_picasso + && picasso_vidinfo.width == w + && picasso_vidinfo.height == h) + return; + + picasso_vidinfo.width = w; + picasso_vidinfo.height = h; + picasso_vidinfo.depth = depth; + picasso_vidinfo.pixbytes = bit_unit >> 3; + + if (screen_is_picasso) + set_window_for_picasso (); +} + +void gfx_set_picasso_baseaddr (uaecptr a) +{ +} + +void gfx_set_picasso_state (int on) +{ + if (on == screen_is_picasso) + return; + graphics_subshutdown (); + screen_is_picasso = on; + if (on) { + current_width = picasso_vidinfo.width; + current_height = picasso_vidinfo.height; + graphics_subinit (); + } else { + current_width = gfxvidinfo.width; + current_height = gfxvidinfo.height; + graphics_subinit (); + reset_drawing (); + } + if (on) + DX_SetPalette_real (0, 256); +} + +uae_u8 *gfx_lock_picasso (void) +{ +#ifdef USE_DGA_EXTENSION + if (dgamode) + return fb_addr; + else +#endif + return pic_dinfo.ximg->data; +} + +void gfx_unlock_picasso (void) +{ +} +#endif + +int lockscr (void) +{ + return 1; +} + +void unlockscr (void) +{ +} + +void toggle_mousegrab (void) +{ + if (grabbed) { + XUngrabPointer (display, CurrentTime); + XUndefineCursor (display, mywin); + reset_cursor (); + grabbed = 0; + } else if (! dgamode) { + XGrabPointer (display, mywin, 1, 0, GrabModeAsync, GrabModeAsync, + mywin, blankCursor, CurrentTime); + oldx = current_width / 2; + oldy = current_height / 2; + XWarpPointer (display, None, mywin, 0, 0, 0, 0, oldx, oldy); + grabbed = 1; + } +} + +void framerate_up (void) +{ + if (currprefs.gfx_framerate < 20) + changed_prefs.gfx_framerate = currprefs.gfx_framerate + 1; +} + +void framerate_down (void) +{ + if (currprefs.gfx_framerate > 1) + changed_prefs.gfx_framerate = currprefs.gfx_framerate - 1; +} + +int is_fullscreen (void) +{ +#ifdef USE_DGA_EXTENSION + return dgamode; +#else + return 0; +#endif +} + +void toggle_fullscreen (void) +{ +#ifdef USE_DGA_EXTENSION + changed_prefs.gfx_afullscreen = changed_prefs.gfx_pfullscreen = !dgamode; +#endif +} + +void screenshot (int type) +{ + write_log ("Screenshot not implemented yet\n"); +} + +/* + * Mouse inputdevice functions + */ + +/* Hardwire for 3 axes and 3 buttons + * There is no 3rd axis as such - mousewheel events are + * supplied by X on buttons 4 and 5. + */ +#define MAX_BUTTONS 3 +#define MAX_AXES 3 +#define FIRST_AXIS 0 +#define FIRST_BUTTON MAX_AXES + +static int init_mouse (void) +{ + return 1; +} + +static void close_mouse (void) +{ + return; +} + +static int acquire_mouse (unsigned int num, int flags) +{ + return 1; +} + +static void unacquire_mouse (unsigned int num) +{ + return; +} + +static unsigned int get_mouse_num (void) +{ + return 1; +} + +static const char *get_mouse_name (unsigned int mouse) +{ + return 0; +} + +static unsigned int get_mouse_widget_num (unsigned int mouse) +{ + return MAX_AXES + MAX_BUTTONS; +} + +static int get_mouse_widget_first (unsigned int mouse, int type) +{ + switch (type) { + case IDEV_WIDGET_BUTTON: + return FIRST_BUTTON; + case IDEV_WIDGET_AXIS: + return FIRST_AXIS; + } + return -1; +} + +static int get_mouse_widget_type (unsigned int mouse, unsigned int num, char *name, uae_u32 *code) +{ + if (num >= MAX_AXES && num < MAX_AXES + MAX_BUTTONS) { + if (name) + sprintf (name, "Button %d", num + 1 + MAX_AXES); + return IDEV_WIDGET_BUTTON; + } else if (num < MAX_AXES) { + if (name) + sprintf (name, "Axis %d", num + 1); + return IDEV_WIDGET_AXIS; + } + return IDEV_WIDGET_NONE; +} + +static void read_mouse (void) +{ + /* We handle mouse input in handle_events() */ +} + +struct inputdevice_functions inputdevicefunc_mouse = { + init_mouse, close_mouse, acquire_mouse, unacquire_mouse, read_mouse, + get_mouse_num, get_mouse_name, + get_mouse_widget_num, get_mouse_widget_type, + get_mouse_widget_first +}; + +/* + * Keyboard inputdevice functions + */ +static unsigned int get_kb_num (void) +{ + return 1; +} + +static const char *get_kb_name (unsigned int kb) +{ + return "Default keyboard"; +} + +static unsigned int get_kb_widget_num (unsigned int kb) +{ + return 255; // fix me +} + +static int get_kb_widget_first (unsigned int kb, int type) +{ + return 0; +} + +static int get_kb_widget_type (unsigned int kb, unsigned int num, char *name, uae_u32 *code) +{ + // fix me + *code = num; + return IDEV_WIDGET_KEY; +} + +static int keyhack (int scancode, int pressed, int num) +{ + return scancode; +} + +static void read_kb (void) +{ +} +static int init_kb (void) +{ + set_default_hotkeys (get_x11_default_hotkeys()); + return 1; +} + +static void close_kb (void) +{ +} + +static int acquire_kb (unsigned int num, int flags) +{ + return 1; +} + +static void unacquire_kb (unsigned int num) +{ +} + +/* + * Default inputdevice config for X11 mouse + */ +void input_get_default_mouse (struct uae_input_device *uid) +{ + /* Supports only one mouse */ + uid[0].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_MOUSE1_HORIZ; + uid[0].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_MOUSE1_VERT; + uid[0].eventid[ID_AXIS_OFFSET + 2][0] = INPUTEVENT_MOUSE1_WHEEL; + uid[0].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY1_FIRE_BUTTON; + uid[0].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY1_2ND_BUTTON; + uid[0].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY1_3RD_BUTTON; + uid[0].enabled = 1; +} + +struct inputdevice_functions inputdevicefunc_keyboard = +{ + init_kb, close_kb, acquire_kb, unacquire_kb, + read_kb, get_kb_num, get_kb_name, get_kb_widget_num, + get_kb_widget_type, get_kb_widget_first +}; + +int getcapslockstate (void) +{ + return 0; +} + +void setcapslockstate (int state) +{ +} + +/* + * Handle gfx cfgfile options + */ +void target_save_options (FILE *f, struct uae_prefs *p) +{ + fprintf (f, "x11.low_bandwidth=%s\n", p->x11_use_low_bandwidth ? "true" : "false"); + fprintf (f, "x11.use_mitshm=%s\n", p->x11_use_mitshm ? "true" : "false"); + fprintf (f, "x11.hide_cursor=%s\n", p->x11_hide_cursor ? "true" : "false"); +} + +int target_parse_option (struct uae_prefs *p, char *option, char *value) +{ + return (cfgfile_yesno (option, value, "low_bandwidth", &p->x11_use_low_bandwidth) + || cfgfile_yesno (option, value, "use_mitshm", &p->x11_use_mitshm) + || cfgfile_yesno (option, value, "hide_cursor", &p->x11_hide_cursor)); } -void target_specific_usage(void) +void target_default_options (struct uae_prefs *p) { - printf(" -S n : Sound emulation accuracy (n = 0, 1, 2 or 3)\n" - " For sound emulation, n = 2 is recommended\n"); - printf(" -b n : Use n bits for sound output (8 or 16)\n"); - printf(" -R n : Use n Hz to output sound. Common values are\n" - " 22050 Hz or 44100 Hz\n"); - printf(" -B n : Use a sound buffer of n bytes (use small\n" - " values on fast machines)\n"); - printf(" -x : Use visible cross-hair cursor\n"); - printf(" -l lang : Set keyboard language to lang, where lang is\n" - " DE, SE, US, FR or IT\n"); - printf(" -p command : Use command to pipe printer output to.\n"); - printf(" -I device : Name of the used serial device (i.e. /dev/ttyS1\n"); + p->x11_use_low_bandwidth = 0; + p->x11_use_mitshm = 1; + p->x11_hide_cursor = 1; }