--- uae/src/xwin.c 2018/04/24 16:39:54 1.1.1.3 +++ uae/src/xwin.c 2018/04/24 16:51:21 1.1.1.9 @@ -5,7 +5,9 @@ * * 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 */ #include "sysconfig.h" @@ -24,10 +26,11 @@ #include "threaddep/penguin.h" #include "uae.h" #include "memory.h" +#include "xwin.h" #include "custom.h" +#include "drawing.h" #include "readcpu.h" #include "newcpu.h" -#include "xwin.h" #include "keyboard.h" #include "keybuf.h" #include "gui.h" @@ -52,7 +55,9 @@ #define DGA_MINMAJOR 0 #define DGA_MINMINOR 0 -#elif SHM_SUPPORT_LINKS == 1 +#endif /* USE_DGA_EXTENSION */ + +#if SHM_SUPPORT_LINKS == 1 #include #include @@ -60,30 +65,30 @@ #define DO_PUTIMAGE(IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT) \ do { \ - if (currprefs.use_mitshm) \ - XShmPutImage (display, mywin, blackgc, IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT, 0); \ + if (currprefs.x11_use_mitshm) \ + XShmPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT), 0); \ else \ - XPutImage (display, mywin, blackgc, IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT); \ + 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, blackgc, 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; @@ -92,32 +97,47 @@ 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); + 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,picassogc; -static XColor black,white; +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 */ +/* 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, *picasso_img; +static struct disp_info ami_dinfo, pic_dinfo; static Visual *vis; static XVisualInfo visualInfo; static int bitdepth, bit_unit; @@ -128,45 +148,104 @@ static int inverse_byte_order = 0; static int current_width, current_height; static int x11_init_ok; +static int dgaavail = 0, vidmodeavail = 0, shmavail = 0; +static int dgamode; - /* Keyboard and mouse */ +/* Keyboard and mouse */ static int keystate[256]; +static int oldx, oldy; +static int grabbed; + +struct uae_hotkeys { + KeySym syms[4]; + void (*handler)(void); + int retval; + int mask; +}; + +static void handle_modeswitch (void); +static void handle_mousegrab (void); +static void handle_inhibit (void); +static void framerate_up (void); +static void framerate_down (void); + +static void handle_interpol (void); +static struct uae_hotkeys hotkeys[] = { +#ifdef USE_DGA_EXTENSION + {{ XK_F12, XK_s, 0 }, handle_modeswitch, -1, 0 }, +#endif + {{ XK_F12, XK_q, 0 }, uae_quit, -1, 0 }, + {{ XK_F12, XK_m, 0 }, togglemouse, -1, 0 }, + {{ XK_F12, XK_g, 0 }, handle_mousegrab, -1, 0 }, + {{ XK_F12, XK_i, 0 }, handle_inhibit, -1, 0 }, + {{ XK_F12, XK_p, 0 }, handle_interpol, -1, 0 }, + {{ XK_F12, XK_KP_Add, 0 }, framerate_up, -1, 0 }, + {{ XK_F12, XK_KP_Subtract, 0 }, framerate_down, -1, 0 }, + {{ XK_Scroll_Lock, 0 }, handle_inhibit, -1, 0 }, + {{ 0 }, NULL, -1, 0 } /* List must be terminated */ +}; + static int inwindow; -const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask - |ButtonReleaseMask|PointerMotionMask -#ifndef USE_DGA_EXTENSION - |FocusChangeMask|EnterWindowMask - |ExposureMask - |LeaveWindowMask +#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 - ); -static XImage *get_image (int w, int h, char **mem_p) +static void get_image (int w, int h, struct disp_info *dispi) { XImage *new_img; char *p; #if SHM_SUPPORT_LINKS == 1 - if (currprefs.use_mitshm) { - XShmSegmentInfo *shminfo = xmalloc (sizeof (XShmSegmentInfo)); + if (currprefs.x11_use_mitshm && shmavail) { + XShmSegmentInfo *shminfo = &dispi->shminfo; - printf ("Using MIT-SHM extension.\n"); 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); - if (mem_p != 0) - *mem_p = new_img->data; + dispi->image_mem = new_img->data; shminfo->readOnly = False; - /* let the xserver attach */ + /* Try to let the Xserver attach */ + shmerror = 0; + oldshmerrorhandler = XSetErrorHandler (shmerrorhandler); XShmAttach (display, shminfo); - XSync (display,0); - /* now deleting means making it temporary */ - shmctl (shminfo->shmid, IPC_RMID, 0); - return new_img; + XSync (display, 0); + XSetErrorHandler (oldshmerrorhandler); + if (shmerror) { + shmdt (shminfo->shmaddr); + XDestroyImage (new_img); + shminfo->shmid = -1; + shmavail = 0; + fprintf (stderr, "MIT-SHM extension failed, trying fallback.\n"); + } else { + /* now deleting means making it temporary */ + shmctl (shminfo->shmid, IPC_RMID, 0); + dispi->ximg = new_img; + printf ("Using MIT-SHM extension.\n"); + return; + } } #endif @@ -176,30 +255,15 @@ static XImage *get_image (int w, int h, */ printf ("Using normal image buffer.\n"); p = (char *)xmalloc (h * w * ((bit_unit + 7) / 8)); /* ??? */ - if (mem_p != 0) - *mem_p = p; new_img = XCreateImage (display, vis, bitdepth, ZPixmap, 0, p, w, h, 32, 0); if (new_img->bytes_per_line != w * ((bit_unit + 7) / 8)) fprintf (stderr, "Possible bug here... graphics may look strange.\n"); - return new_img; -} - -#ifdef USE_DGA_EXTENSION - -static int fb_bank, fb_banks, fb_mem; -static char *fb_addr; -static int fb_width; - -static void switch_to_dga_mode (void) -{ - XF86DGADirectVideo(display, screen, XF86DGADirectGraphics | XF86DGADirectMouse | XF86DGADirectKeyb); - XF86DGASetViewPort (display, screen, 0, 0); - memset (fb_addr, 0, fb_mem * 1024); + dispi->image_mem = p; + dispi->ximg = new_img; } - #ifdef USE_VIDMODE_EXTENSION static XF86VidModeModeInfo **allmodes; static int vidmodecount; @@ -208,30 +272,40 @@ static int get_vidmodes (void) { return XF86VidModeGetAllModeLines (display, screen, &vidmodecount, &allmodes); } +#endif + +#ifdef USE_DGA_EXTENSION + +static int fb_bank, fb_banks, fb_mem; +static char *fb_addr; +static int fb_width; static void switch_to_best_mode (void) { int i, best; - 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; - } - printf ("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); +#ifdef USE_VIDMODE_EXTENSION + 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; + } + printf ("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); - switch_to_dga_mode (); + XF86DGADirectVideo (display, screen, XF86DGADirectGraphics | XF86DGADirectMouse | XF86DGADirectKeyb); + XF86DGASetViewPort (display, screen, 0, 0); + memset (fb_addr, 0, fb_mem * 1024); } -#else - -#endif static void enter_dga_mode (void) { @@ -249,61 +323,55 @@ static void enter_dga_mode (void) XGrabPointer (display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - XF86DGAGetVideo (display, screen, &fb_addr, &fb_width, &fb_bank, &fb_mem); - fprintf (stderr, "addr:%X, width %d, bank size %d mem size %d\n", - fb_addr, fb_width, fb_bank,fb_mem); - - if (fb_bank < fb_mem) - fprintf (stderr, "banksize < memsize, must use XF86DGASetVidPage !\n"); - 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; } static void leave_dga_mode (void) { #ifdef USE_VIDMODE_EXTENSION - XF86VidModeSwitchToMode (display, screen, allmodes[0]); + if (vidmodeavail) + XF86VidModeSwitchToMode (display, screen, allmodes[0]); #endif XF86DGADirectVideo (display, screen, 0); XUngrabPointer (display, CurrentTime); XUngrabKeyboard (display, CurrentTime); } - #endif + static char *oldpixbuf; -void flush_line(int y) +void flush_line (int y) { -#ifdef USE_DGA_EXTENSION - if (need_dither) { - char *addr = gfxvidinfo.linemem; - if (addr == NULL) - addr = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem; - - DitherLine((unsigned char *)(fb_addr + fb_width*y), (uae_u16 *)addr, 0, y, - gfxvidinfo.width, bit_unit); - } -#else - char *linebuf; - int xs = 0, xe; + char *linebuf = gfxvidinfo.linemem; + int xs, xe; int len; - linebuf = gfxvidinfo.linemem; if (linebuf == NULL) linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem; - xe = gfxvidinfo.width-1; +#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.use_low_bandwidth) { + if (currprefs.x11_use_low_bandwidth) { char *src, *dst; - switch(gfxvidinfo.pixbytes) { + switch (gfxvidinfo.pixbytes) { case 4: { uae_u32 *newp = (uae_u32 *)linebuf; - uae_u32 *oldp = (uae_u32 *)((uae_u8 *)image_mem + y*img->bytes_per_line); + 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; @@ -317,7 +385,7 @@ void flush_line(int y) case 2: { uae_u16 *newp = (uae_u16 *)linebuf; - uae_u16 *oldp = (uae_u16 *)((uae_u8 *)image_mem + y*img->bytes_per_line); + 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; @@ -331,7 +399,7 @@ void flush_line(int y) case 1: { uae_u8 *newp = (uae_u8 *)linebuf; - uae_u8 *oldp = (uae_u8 *)((uae_u8 *)image_mem + y*img->bytes_per_line); + 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; @@ -344,62 +412,59 @@ void flush_line(int y) break; default: - abort(); + abort (); break; } len = xe - xs + 1; memcpy (dst, src, len * gfxvidinfo.pixbytes); } else if (need_dither) { - uae_u8 *target = (uae_u8 *)image_mem + img->bytes_per_line * y; + uae_u8 *target = (uae_u8 *)ami_dinfo.image_mem + ami_dinfo.ximg->bytes_per_line * y; len = currprefs.gfx_width; - DitherLine(target, (uae_u16 *)linebuf, 0, y, gfxvidinfo.width, bit_unit); + DitherLine (target, (uae_u16 *)linebuf, 0, y, gfxvidinfo.width, bit_unit); } else { - fprintf(stderr, "Bug!\n"); + fprintf (stderr, "Bug!\n"); abort(); } - DO_PUTIMAGE (img, xs, y, xs, y, len, 1); -#endif + DO_PUTIMAGE (ami_dinfo.ximg, xs, y, xs, y, len, 1); } void flush_block (int ystart, int ystop) { -#ifdef USE_DGA_EXTENSION -#else - int len, xs = 0; + if (dgamode) + return; - len = gfxvidinfo.width; - DO_PUTIMAGE (img, xs, ystart, 0, ystart, len, ystop - ystart + 1); -#endif + DO_PUTIMAGE (ami_dinfo.ximg, 0, ystart, 0, ystart, gfxvidinfo.width, ystop - ystart + 1); } void flush_screen (int ystart, int ystop) { -#ifdef USE_DGA_EXTENSION -#else + if (dgamode) + return; + #if SHM_SUPPORT_LINKS == 1 - if (currprefs.use_mitshm) XSync(display, 0); -#endif + if (currprefs.x11_use_mitshm) + XSync (display, 0); #endif } -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; } @@ -413,13 +478,13 @@ static int ncolors = 0; static int blackval = 32767; static int whiteval = 0; -static int get_color(int r, int g, int b, xcolnr *cnp) +static int get_color (int r, int g, int b, xcolnr *cnp) { XColor *col = parsed_xcolors + ncolors; char str[10]; - sprintf(str, "rgb:%x/%x/%x", r, g, b); - XParseColor(display, cmap, str, col); + 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); @@ -433,13 +498,20 @@ static int get_color(int r, int g, int b 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) { - XAllocColorCells (display, cmap, 0, 0, 0, pixel_return, 256); - XAllocColorCells (display, cmap2, 0, 0, 0, pixel_return, 256); if (bitdepth == 1) setup_greydither (1, get_color); else @@ -447,35 +519,26 @@ static int init_colors(void) } else { if (bitdepth != 8 && bitdepth != 12 && bitdepth != 15 && bitdepth != 16 && bitdepth != 24) { - fprintf(stderr, "Unsupported bit depth (%d)\n", bitdepth); + fprintf (stderr, "Unsupported bit depth (%d)\n", bitdepth); return 0; } switch (visualInfo.VI_CLASS) { 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); - } - 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"); + alloc_colors64k (red_bits, green_bits, blue_bits, red_shift, + green_shift, blue_shift); + + 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"); break; case GrayScale: case PseudoColor: - XAllocColorCells (display, cmap, 0, 0, 0, pixel_return, 256); - XAllocColorCells (display, cmap2, 0, 0, 0, pixel_return, 256); - alloc_colors256(get_color); + alloc_colors256 (get_color); break; default: @@ -498,8 +561,8 @@ static int init_colors(void) gfxvidinfo.can_double = 0; break; } - if(inverse_byte_order) - switch(gfxvidinfo.pixbytes) { + if (inverse_byte_order) + switch (gfxvidinfo.pixbytes) { case 4: for(i = 0; i < 4096; i++) xcolors[i] = ((((xcolors[i]>>0)&255) << 24) @@ -517,73 +580,107 @@ static int init_colors(void) return 1; } -int graphics_setup(void) +static int dga_available (void) { - char *display_name = 0; #ifdef USE_DGA_EXTENSION int MajorVersion, MinorVersion; int EventBase, ErrorBase; - if (geteuid()) { - fprintf(stderr, "You must be root to use UAE with the DGA extensions.\n"); - return 0; - } -#endif - display = XOpenDisplay(display_name); - if (display == 0) { - fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name)); - return 0; - } - -#ifdef USE_DGA_EXTENSION - if (!XF86DGAQueryVersion (display, &MajorVersion, &MinorVersion)) { - fprintf(stderr, "Unable to query video extension version\n"); + if (! XF86DGAQueryVersion (display, &MajorVersion, &MinorVersion)) { + fprintf (stderr, "Unable to query video extension version\n"); return 0; } - - if (!XF86DGAQueryExtension (display, &EventBase, &ErrorBase)) { - fprintf(stderr, "Unable to query video extension information\n"); + if (! XF86DGAQueryExtension (display, &EventBase, &ErrorBase)) { + fprintf (stderr, "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)) { + if (MajorVersion < DGA_MINMAJOR + || (MajorVersion == DGA_MINMAJOR && MinorVersion < DGA_MINMINOR)) + { fprintf (stderr, "Xserver is running an old XFree86-DGA version" " (%d.%d)\n", MajorVersion, MinorVersion); fprintf (stderr, "Minimum required version is %d.%d\n", - DGA_MINMAJOR, DGA_MINMINOR); + DGA_MINMAJOR, DGA_MINMINOR); return 0; } + if (geteuid () != 0) { + fprintf (stderr, "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) + { + fprintf (stderr, "Problems with DGA - disabling DGA extension.\n"); + return 0; + } + fprintf (stderr, "DGA extension: addr:%X, width %d, bank size %d mem size %d\n", + fb_addr, fb_width, fb_bank, fb_mem); + + return 1; +#else + return 0; +#endif +} + +static int vid_mode_available (void) +{ #ifdef USE_VIDMODE_EXTENSION - if (!XF86VidModeQueryVersion (display, &MajorVersion, &MinorVersion)) { + int MajorVersion, MinorVersion; + int EventBase, ErrorBase; + + if (! dgaavail) + return 0; + if (! XF86VidModeQueryVersion (display, &MajorVersion, &MinorVersion)) { fprintf (stderr, "Unable to query video extension version\n"); return 0; } - - if (!XF86VidModeQueryExtension (display, &EventBase, &ErrorBase)) { + if (! XF86VidModeQueryExtension (display, &EventBase, &ErrorBase)) { fprintf (stderr, "Unable to query video extension information\n"); return 0; } - - /* Fail if the extension version in the server is too old */ - if (MajorVersion < VidMode_MINMAJOR || - (MajorVersion == VidMode_MINMAJOR && MinorVersion < VidMode_MINMINOR)) { - fprintf (stderr, - "Xserver is running an old XFree86-VidMode version" - " (%d.%d)\n", MajorVersion, MinorVersion); + if (MajorVersion < VidMode_MINMAJOR + || (MajorVersion == VidMode_MINMAJOR && MinorVersion < VidMode_MINMINOR)) { + /* Fail if the extension version in the server is too old */ + fprintf (stderr, "Xserver is running an old XFree86-VidMode version (%d.%d)\n", + MajorVersion, MinorVersion); fprintf (stderr, "Minimum required version is %d.%d\n", VidMode_MINMAJOR, VidMode_MINMINOR); return 0; } - if (!get_vidmodes ()) { + if (! get_vidmodes ()) { fprintf (stderr, "Error getting video mode information\n"); return 0; } + return 1; +#else + return 0; #endif - +} + +static int shm_available (void) +{ +#if SHM_SUPPORT_LINKS == 1 + if (XShmQueryExtension (display)) + return 1; #endif + return 0; +} + +int graphics_setup (void) +{ + char *display_name = 0; + + display = XOpenDisplay (display_name); + if (display == 0) { + fprintf (stderr, "Can't connect to X server %s\n", XDisplayName (display_name)); + return 0; + } + + shmavail = shm_available (); + dgaavail = dga_available (); + vidmodeavail = vid_mode_available (); { int local_byte_order; @@ -598,51 +695,190 @@ int graphics_setup(void) return 1; } -static void fixup_prefs_dimensions (void) +static void lock_window_size (void) { - if (currprefs.gfx_width < 320) - currprefs.gfx_width = 320; - if (currprefs.gfx_height < 200) - currprefs.gfx_height = 200; - if (currprefs.gfx_height > 300 && ! currprefs.gfx_linedbl) - currprefs.gfx_height = 300; - if (currprefs.gfx_height > 600) - currprefs.gfx_height = 600; + XSizeHints hint; - currprefs.gfx_width += 7; /* X86.S wants multiples of 4 bytes, might be 8 in the future. */ - currprefs.gfx_width &= ~7; + 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); } -int graphics_init(void) +static void init_dispinfo (struct disp_info *disp) { - int i,j; +#if SHM_SUPPORT_LINKS == 1 + disp->shminfo.shmid = -1; +#endif + disp->ximg = 0; +} + +static void graphics_subinit (void) +{ + int i, j; XSetWindowAttributes wattr; + XClassHint classhint; + XWMHints *hints; + unsigned long valuemask; + + dgamode = screen_is_picasso ? currprefs.gfx_pfullscreen : currprefs.gfx_afullscreen; + dgamode = dgamode && dgaavail; + + wattr.background_pixel = /*black.pixel*/0; + wattr.backing_store = Always; + wattr.backing_planes = bitdepth; + wattr.border_pixmap = None; + wattr.border_pixel = /*black.pixel*/0; + wattr.colormap = cmap; + valuemask = (CWEventMask | CWBackPixel | CWBorderPixel + | CWBackingStore | CWBackingPlanes | CWColormap); + + if (dgamode) { + wattr.event_mask = DGA_EVENTMASK; + wattr.override_redirect = 1; + valuemask |= CWOverrideRedirect; + } else + wattr.event_mask = EVENTMASK; + + 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 { + 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.maxblocklines = 0; + gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * currprefs.gfx_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... */ + } + } + + if (visualInfo.VI_CLASS != TrueColor && ! screen_is_picasso) { + int i; + for (i = 0; i < 256; i++) + XStoreColor (display, cmap, parsed_xcolors + i); + } + +#ifdef USE_DGA_EXTENSION + if (dgamode) { + dga_colormap_installed = 0; + XF86DGAInstallColormap (display, screen, cmap2); + XF86DGAInstallColormap (display, screen, cmap); + } +#endif + + if (! dgamode) { + if (! currprefs.x11_hide_cursor) + XDefineCursor (display, mywin, xhairCursor); + else + XDefineCursor (display, mywin, blankCursor); + cursorOn = 1; + } + + 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); + } + + lastmx = lastmy = 0; + newmousecounters = 0; + inwindow = 0; + for (i = 0; hotkeys[i].syms[0] != 0; i++) { + hotkeys[i].mask = 0; + for (j = 0; hotkeys[i].syms[j] != 0; j++) + hotkeys[i].mask |= (1 << j); + } +} + +int graphics_init (void) +{ + int i,j; XPixmapFormatValues *xpfvs; + if (currprefs.x11_use_mitshm && ! shmavail) { + fprintf (stderr, "MIT-SHM extension not supported by X server.\n"); + } if (currprefs.color_mode > 5) - fprintf(stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0; + fprintf (stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0; x11_init_ok = 0; need_dither = 0; screen_is_picasso = 0; + dgamode = 0; + + init_dispinfo (&ami_dinfo); + init_dispinfo (&pic_dinfo); - screen = XDefaultScreen(display); - rootwin = XRootWindow(display,screen); + 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, 15, 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)) { + if (XMatchVisualInfo (display, screen, 12, TrueColor, &visualInfo)) { + } else if (XMatchVisualInfo (display, screen, 15, 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)) { + } 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)) { + } else if (XMatchVisualInfo (display, screen, 1, StaticGray, &visualInfo)) { /* Mono server. Yuk */ } else { - fprintf(stderr, "Can't obtain appropriate X visual.\n"); + fprintf (stderr, "Can't obtain appropriate X visual.\n"); return 0; } vis = visualInfo.visual; @@ -651,140 +887,110 @@ int graphics_init(void) /* 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++) + 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) { - fprintf(stderr, "Your X server is feeling ill.\n"); + fprintf (stderr, "Your X server is feeling ill.\n"); return 0; } - bit_unit = xpfvs->bits_per_pixel; - fprintf(stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit); + fprintf (stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit); - fixup_prefs_dimensions (); + fixup_prefs_dimensions (&currprefs); gfxvidinfo.width = currprefs.gfx_width; gfxvidinfo.height = currprefs.gfx_height; - - cmap = XCreateColormap(display, rootwin, vis, AllocNone); - cmap2 = XCreateColormap(display, rootwin, vis, AllocNone); -#ifdef USE_DGA_EXTENSION - wattr.override_redirect = 1; -#endif - wattr.event_mask = eventmask; - wattr.background_pixel = /*black.pixel*/0; - wattr.backing_store = Always; - wattr.backing_planes = bitdepth; - wattr.border_pixmap = None; - wattr.border_pixel = /*black.pixel*/0; - wattr.colormap = cmap; - - mywin = XCreateWindow(display, rootwin, 0, 0, currprefs.gfx_width, currprefs.gfx_height, 0, - bitdepth, InputOutput, vis, - CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore - |CWBackingPlanes|CWColormap -#ifdef USE_DGA_EXTENSION - |CWOverrideRedirect -#endif - ,&wattr); - current_width = currprefs.gfx_width; current_height = currprefs.gfx_height; - - XMapWindow(display, mywin); -#ifdef USE_DGA_EXTENSION - XRaiseWindow(display, mywin); -#else - XStoreName(display, mywin, "UAE"); -#endif + + 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); + } if (bitdepth < 8 || (bitdepth == 8 && currprefs.color_mode == 3)) { gfxvidinfo.pixbytes = 2; - currprefs.use_low_bandwidth = 0; + currprefs.x11_use_low_bandwidth = 0; need_dither = 1; } else { gfxvidinfo.pixbytes = bit_unit >> 3; } -#ifdef USE_DGA_EXTENSION - enter_dga_mode (); - /*setuid(getuid());*/ -#else - - img = get_image (currprefs.gfx_width, currprefs.gfx_height, &image_mem); -#endif - - if (need_dither) { - gfxvidinfo.maxblocklines = 0; - gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * currprefs.gfx_width; - gfxvidinfo.linemem = (char *)malloc(gfxvidinfo.rowbytes); - } else if (currprefs.use_low_bandwidth) { - gfxvidinfo.maxblocklines = 0; - gfxvidinfo.rowbytes = img->bytes_per_line; - gfxvidinfo.linemem = gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes); - } else { - gfxvidinfo.maxblocklines = 100; /* whatever... */ -#ifndef USE_DGA_EXTENSION - gfxvidinfo.rowbytes = img->bytes_per_line; - gfxvidinfo.bufmem = image_mem; -#endif - gfxvidinfo.linemem = NULL; - } - - if (!init_colors()) + if (! init_colors ()) return 0; -#ifndef USE_DGA_EXTENSION - 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); - picassogc = XCreateGC (display,mywin,0,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); - XSetForeground(display, blackgc, black.pixel); - XSetForeground(display, whitegc, white.pixel); -#endif + graphics_subinit (); buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; - for(i=0; i<256; i++) + for (i = 0; i < 256; i++) keystate[i] = 0; + grabbed = 0; - lastmx = lastmy = 0; - newmousecounters = 0; - inwindow = 0; + return x11_init_ok = 1; +} -#ifndef USE_DGA_EXTENSION - if (!currprefs.no_xhair) - XDefineCursor(display, mywin, xhairCursor); - else - XDefineCursor(display, mywin, blankCursor); - cursorOn = 1; -#else - dga_colormap_installed = 0; - XF86DGAInstallColormap (display, screen, cmap); +static void destroy_dinfo (struct disp_info *dinfo) +{ + 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; +} - return x11_init_ok = 1; +static void graphics_subshutdown (void) +{ + XSync (display, 0); +#ifdef USE_DGA_EXTENSION + if (dgamode) + leave_dga_mode (); +#endif + + destroy_dinfo (&ami_dinfo); + destroy_dinfo (&pic_dinfo); + + XDestroyWindow (display, mywin); + + if (gfxvidinfo.linemem != NULL) + free (gfxvidinfo.linemem); + if (gfxvidinfo.emergmem != NULL) + free (gfxvidinfo.emergmem); } -void graphics_leave(void) +void graphics_leave (void) { - if (!x11_init_ok) + if (! x11_init_ok) return; + graphics_subshutdown (); + if (autorepeatoff) - XAutoRepeatOn(display); - XFlush(display); - XSync(display, 0); -#ifdef USE_DGA_EXTENSION - leave_dga_mode (); - dumpcustom(); -#endif + XAutoRepeatOn (display); + + XFlush (display); + XSync (display, 0); + + XFreeColormap (display, cmap); + XFreeColormap (display, cmap2); + + XCloseDisplay (display); + dumpcustom (); } /* Decode KeySyms. This function knows about all keys that are common @@ -892,19 +1098,11 @@ static int kc_decode (KeySym ks) case XK_Left: return AK_LF; case XK_Right: return AK_RT; +#if 0 case XK_F11: return AK_BACKSLASH; -#ifdef USE_DGA_EXTENSION - case XK_F12: - uae_quit(); - return -1; #else - case XK_F12: return AK_mousestuff; + case XK_F11: frametime = 0; timeframes = 0; bogusframe = 1; break; #endif -#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 */ @@ -913,7 +1111,7 @@ static int kc_decode (KeySym ks) return -1; } -static int decode_fr(KeySym ks) +static int decode_fr (KeySym ks) { switch(ks) { /* FR specific */ case XK_A: case XK_a: return AK_Q; @@ -922,6 +1120,7 @@ static int decode_fr(KeySym ks) case XK_Y: case XK_y: return AK_Y; case XK_W: case XK_w: return AK_Z; case XK_Z: case XK_z: return AK_W; +#if 0 case XK_bracketleft: return AK_LBRACKET; case XK_bracketright: return AK_RBRACKET; case XK_comma: return AK_M; @@ -933,12 +1132,37 @@ static int decode_fr(KeySym ks) case XK_slash: return AK_PERIOD; case XK_minus: return AK_EQUAL; case XK_backslash: return AK_BACKSLASH; +#else + /* not sure for this one: my X 3.3 server doesn't handle this key always + * correctly... But anyway, on new french keyboards, no more bracket key + * at this place. + */ + case XK_dead_circumflex: + case XK_dead_diaeresis: return AK_LBRACKET; + case XK_dollar: + case XK_sterling: return AK_RBRACKET; + case XK_comma: case XK_question: return AK_M; + case XK_less: case XK_greater: return AK_LTGT; + case XK_semicolon: case XK_period: return AK_COMMA; + case XK_parenright: case XK_degree: return AK_MINUS; + case XK_equal: case XK_plus: return AK_SLASH; + case XK_numbersign: return AK_NUMBERSIGN; + case XK_colon: case XK_slash: return AK_PERIOD; + case XK_minus: case XK_6: return AK_6; + case XK_ugrave: case XK_percent: return AK_QUOTE; + /* found a spare key - I hope it deserves this place. */ + case XK_asterisk: case XK_mu: return AK_BACKSLASH; + case XK_exclam: case XK_section: return AK_EQUAL; + case XK_twosuperior: case XK_asciitilde: return AK_BACKQUOTE; + case XK_Multi_key: return AK_RAMI; + case XK_Mode_switch: return AK_RALT; +#endif } return -1; } -static int decode_us(KeySym ks) +static int decode_us (KeySym ks) { switch(ks) { /* US specific */ case XK_A: case XK_a: return AK_A; @@ -964,7 +1188,7 @@ static int decode_us(KeySym ks) return -1; } -static int decode_de(KeySym ks) +static int decode_de (KeySym ks) { switch(ks) { /* DE specific */ @@ -991,7 +1215,7 @@ static int decode_de(KeySym ks) return -1; } -static int decode_se(KeySym ks) +static int decode_se (KeySym ks) { switch(ks) { /* SE specific */ @@ -1019,7 +1243,7 @@ static int decode_se(KeySym ks) return -1; } -static int decode_it(KeySym ks) +static int decode_it (KeySym ks) { switch(ks) { /* IT specific */ @@ -1046,7 +1270,7 @@ static int decode_it(KeySym ks) return -1; } -static int decode_es(KeySym ks) +static int decode_es (KeySym ks) { switch(ks) { /* ES specific */ @@ -1075,41 +1299,66 @@ static int decode_es(KeySym ks) return -1; } -static int keycode2amiga(XKeyEvent *event) +static int keycode2amiga (XKeyEvent *event) { KeySym ks; int as; int index = 0; do { - ks = XLookupKeysym(event, index); + int hkreturn = -1, returnnow = 0; + ks = XLookupKeysym (event, index); + if (event->type == KeyPress) { + int i, j; + for (i = 0; hotkeys[i].syms[0] != 0; i++) { + for (j = 0; hotkeys[i].syms[j] != 0; j++) { + if (ks == hotkeys[i].syms[j]) { + hotkeys[i].mask &= ~(1 << j); + if (hotkeys[i].mask == 0) { + returnnow = 1; + hkreturn = hotkeys[i].retval; + } + } + } + } + } else { + int i, j; + for (i = 0; hotkeys[i].syms[0] != 0; i++) { + for (j = 0; hotkeys[i].syms[j] != 0; j++) { + if (ks == hotkeys[i].syms[j]) { + hotkeys[i].mask |= (1 << j); + } + } + } + } + if (returnnow) + return -2; as = kc_decode (ks); if (as == -1) { - switch(currprefs.keyboard_lang) { - + switch (currprefs.keyboard_lang) { case KBD_LANG_FR: - as = decode_fr(ks); + as = decode_fr (ks); break; case KBD_LANG_US: - as = decode_us(ks); + as = decode_us (ks); break; case KBD_LANG_DE: - as = decode_de(ks); + as = decode_de (ks); break; case KBD_LANG_SE: - as = decode_se(ks); + as = decode_se (ks); break; case KBD_LANG_IT: - as = decode_it(ks); + as = decode_it (ks); break; case KBD_LANG_ES: - as = decode_es(ks); + as = decode_es (ks); break; default: @@ -1117,7 +1366,7 @@ static int keycode2amiga(XKeyEvent *even break; } } - if(-1 != as) + if (-1 != as) return as; index++; } while (ks != NoSymbol); @@ -1128,44 +1377,49 @@ static struct timeval lastMotionTime; static int refresh_necessary = 0; -void handle_events(void) +void handle_events (void) { 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); + if (! XPending (display)) + break; + + XNextEvent (display, &event); - switch(event.type) { + switch (event.type) { case KeyPress: { - int kc = keycode2amiga((XKeyEvent *)&event); - if (kc == -1) break; - switch (kc) { - case AK_mousestuff: - togglemouse(); - break; + int i; + int kc = keycode2amiga ((XKeyEvent *)&event); - case AK_inhibit: - toggle_inhibit_frame (0); + if (kc == -2) { + for (i = 0; hotkeys[i].syms[0] != 0; i++) { + if (hotkeys[i].mask == 0) { + if (hotkeys[i].handler != NULL) + hotkeys[i].handler(); + } + } break; + } - default: - if (!keystate[kc]) { - keystate[kc] = 1; - record_key (kc << 1); - } + if (kc == -1) break; + if (! keystate[kc]) { + keystate[kc] = 1; + record_key (kc << 1); } break; } case KeyRelease: { - int kc = keycode2amiga((XKeyEvent *)&event); - if (kc == -1) break; + int kc = keycode2amiga ((XKeyEvent *)&event); + if (kc < 0) + break; keystate[kc] = 0; record_key ((kc << 1) | 1); break; @@ -1176,7 +1430,65 @@ void handle_events(void) case ButtonRelease: buttonstate[((XButtonEvent *)&event)->button-1] = 0; break; -#ifndef USE_DGA_EXTENSION + case MotionNotify: + if (dgamode) { + newmousecounters = 0; + lastmx += ((XMotionEvent *)&event)->x_root; + lastmy += ((XMotionEvent *)&event)->y_root; + } else if (grabbed) { + int realmove = 0; + int tx, ty; + + tx = ((XMotionEvent *)&event)->x; + ty = ((XMotionEvent *)&event)->y; + + if (! event.xmotion.send_event) { + newmousecounters = 0; + lastmx += tx - oldx; + lastmy += ty - oldy; + 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; + tx = current_width / 2; + ty = current_height / 2; + event.type = MotionNotify; + event.xmotion.display = display; + event.xmotion.window = mywin; + event.xmotion.x = tx; + event.xmotion.y = ty; + XSendEvent (display, mywin, False, + PointerMotionMask, &event); + XWarpPointer (display, None, mywin, 0, 0, 0, 0, tx, ty); + } + } + oldx = tx; + oldy = ty; + } else if (inwindow) { + lastmx = ((XMotionEvent *)&event)->x; + lastmy = ((XMotionEvent *)&event)->y; + if (! cursorOn && !currprefs.x11_hide_cursor) { + XDefineCursor(display, mywin, xhairCursor); + cursorOn = 1; + } + gettimeofday(&lastMotionTime, NULL); + } + + if (ievent_alive) { + if (lastmx < 0) + lastmx = 0; + if (lastmx > current_width) + lastmx = current_width; + if (lastmy < 0) + lastmy = 0; + if (lastmy > current_height) + lastmy = current_height; + } + break; case EnterNotify: newmousecounters = 1; lastmx = ((XCrossingEvent *)&event)->x; @@ -1187,106 +1499,144 @@ void handle_events(void) 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 && !currprefs.no_xhair) { - XDefineCursor(display, mywin, xhairCursor); - cursorOn = 1; - } - gettimeofday(&lastMotionTime, NULL); - } - break; case Expose: refresh_necessary = 1; break; -#else - case MotionNotify: - newmousecounters = 0; - lastmx += ((XMotionEvent *)&event)->x_root; - lastmy += ((XMotionEvent *)&event)->y_root; -#endif + case ClientMessage: + if (event.xclient.data.l[0]==delete_win) { + uae_quit (); + } + break; } } -#if defined PICASSO96 && !defined USE_DGA_EXTENSION - if (screen_is_picasso && refresh_necessary) { - DO_PUTIMAGE (picasso_img, 0, 0, 0, 0, - picasso_vidinfo.width, picasso_vidinfo.height); - refresh_necessary = 0; - } else if (screen_is_picasso) { - int i; - int strt = -1, stop = -1; - picasso_invalid_lines[picasso_vidinfo.height] = 0; - for (i = 0; i < picasso_vidinfo.height + 1; i++) { - if (picasso_invalid_lines[i]) { - picasso_invalid_lines[i] = 0; - if (strt != -1) - continue; - strt = i; - } else { - if (strt == -1) - continue; - DO_PUTIMAGE (picasso_img, 0, strt, 0, strt, - picasso_vidinfo.width, i-strt); - strt = -1; + +#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 - -#ifndef USE_DGA_EXTENSION - if (!screen_is_picasso && refresh_necessary) { - DO_PUTIMAGE (img, 0, 0, 0, 0, currprefs.gfx_width, currprefs.gfx_height); - refresh_necessary = 0; - } - if(cursorOn && !currprefs.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; + + if (! dgamode) { + if (! screen_is_picasso && refresh_necessary) { + DO_PUTIMAGE (ami_dinfo.ximg, 0, 0, 0, 0, currprefs.gfx_width, currprefs.gfx_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; + } } } -#endif /* "Affengriff" */ - if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI]) - uae_reset(); + if ((keystate[AK_CTRL] || keystate[AK_RCTRL]) && keystate[AK_LAMI] && keystate[AK_RAMI]) + uae_reset (); } -int debuggable(void) +int check_prefs_changed_gfx (void) { - return 1; + if (changed_prefs.gfx_width != currprefs.gfx_width + || changed_prefs.gfx_height != currprefs.gfx_height) + fixup_prefs_dimensions (&changed_prefs); + + if (changed_prefs.gfx_width == currprefs.gfx_width + && changed_prefs.gfx_height == currprefs.gfx_height + && changed_prefs.gfx_lores == currprefs.gfx_lores + && changed_prefs.gfx_linedbl == currprefs.gfx_linedbl + && changed_prefs.gfx_correct_aspect == currprefs.gfx_correct_aspect + && changed_prefs.gfx_xcenter == currprefs.gfx_xcenter + && changed_prefs.gfx_ycenter == currprefs.gfx_ycenter + && changed_prefs.gfx_afullscreen == currprefs.gfx_afullscreen + && changed_prefs.gfx_pfullscreen == currprefs.gfx_pfullscreen) + return 0; + + graphics_subshutdown (); + currprefs.gfx_width = changed_prefs.gfx_width; + currprefs.gfx_height = changed_prefs.gfx_height; + currprefs.gfx_lores = changed_prefs.gfx_lores; + currprefs.gfx_linedbl = changed_prefs.gfx_linedbl; + currprefs.gfx_correct_aspect = changed_prefs.gfx_correct_aspect; + currprefs.gfx_xcenter = changed_prefs.gfx_xcenter; + currprefs.gfx_ycenter = changed_prefs.gfx_ycenter; + currprefs.gfx_afullscreen = changed_prefs.gfx_afullscreen; + currprefs.gfx_pfullscreen = changed_prefs.gfx_pfullscreen; + 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 needmousehack(void) +int debuggable (void) { -#ifdef USE_DGA_EXTENSION - return 0; -#else return 1; -#endif } -void LED(int on) +int needmousehack (void) +{ + if (dgamode) + return 0; + else + return 1; +} + +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; @@ -1294,19 +1644,23 @@ void LED(int on) #endif } -void write_log (const char *buf) -{ - fprintf (stderr, buf); -} - #ifdef PICASSO96 void DX_Invalidate (int first, int last) { - do { + 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++; - } while (first <= last); + } } int DX_BitsPerCannon (void) @@ -1314,11 +1668,24 @@ int DX_BitsPerCannon (void) return 8; } -void DX_SetPalette(int start, int count) +void DX_SetPalette (int start, int count) { - if (!screen_is_picasso || picasso_vidinfo.pixbytes != 1) + 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; @@ -1329,11 +1696,13 @@ void DX_SetPalette(int start, int count) start++; } #ifdef USE_DGA_EXTENSION - dga_colormap_installed ^= 1; - if (dga_colormap_installed == 1) - XF86DGAInstallColormap(display, screen, cmap2); - else - XF86DGAInstallColormap(display, screen, cmap); + if (dgamode) { + dga_colormap_installed ^= 1; + if (dga_colormap_installed == 1) + XF86DGAInstallColormap (display, screen, cmap2); + else + XF86DGAInstallColormap (display, screen, cmap); + } #endif } @@ -1348,100 +1717,75 @@ int DX_FillResolutions (uae_u16 *ppixel_ int i, count = 0; int w = WidthOfScreen (scr); int h = HeightOfScreen (scr); - int maxw = 0, maxh = 0; + int emulate_chunky = 0; - *ppixel_format = (bit_unit == 8 ? RGBFF_CHUNKY - : bitdepth == 15 && bit_unit == 16 ? RGBFF_R5G5B5PC - : bitdepth == 16 && bit_unit == 16 ? RGBFF_R5G6B5PC - : bit_unit == 24 ? RGBFF_B8G8R8 - : bit_unit == 32 ? RGBFF_B8G8R8A8 - : 0); + 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); + + *ppixel_format = 1 << picasso_vidinfo.rgbformat; + if (visualInfo.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 - for (i = 0; i < vidmodecount && i < MAX_PICASSO_MODES ; i++) { - DisplayModes[i].res.width = allmodes[i]->hdisplay; - DisplayModes[i].res.height = allmodes[i]->vdisplay; - DisplayModes[i].depth = bit_unit >> 3; - DisplayModes[i].refresh = 75; - } - count = i; -#else - for (i = 0; i < MAX_SCREEN_MODES && count < MAX_PICASSO_MODES ; i++) { - if (x_size_table[i] <= w && y_size_table[i] <= h) { - if (x_size_table[i] > maxw) - maxw = x_size_table[i]; - if (y_size_table[i] > maxh) - maxh = y_size_table[i]; - DisplayModes[count].res.width = x_size_table[i]; - DisplayModes[count].res.height = y_size_table[i]; - DisplayModes[count].depth = bit_unit >> 3; - DisplayModes[count].refresh = 75; - count++; + 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++; + } } - } -#endif - -#ifndef USE_DGA_EXTENSION - picasso_img = get_image (maxw, maxh, 0); + } 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) { - current_width = picasso_vidinfo.width; - current_height = picasso_vidinfo.height; - XResizeWindow (display, mywin, picasso_vidinfo.width, - picasso_vidinfo.height); -#if defined USE_DGA_EXTENSION && defined USE_VIDMODE_EXTENSION - switch_to_best_mode (); -#endif - } - DX_SetPalette (0, 256); -} - -static void set_window_for_amiga (void) -{ - int i; + if (current_width == picasso_vidinfo.width && current_height == picasso_vidinfo.height) + return; - if (current_width != currprefs.gfx_width || current_height != currprefs.gfx_height) { - current_width = currprefs.gfx_width; - current_height = currprefs.gfx_height; - XResizeWindow (display, mywin, currprefs.gfx_width, - currprefs.gfx_height); + current_width = picasso_vidinfo.width; + current_height = picasso_vidinfo.height; + XResizeWindow (display, mywin, current_width, current_height); #if defined USE_DGA_EXTENSION && defined USE_VIDMODE_EXTENSION + if (dgamode && vidmodeavail) switch_to_best_mode (); #endif - } - - if (gfxvidinfo.pixbytes == 1) - for (i = 0; i < 256; i++) { - XStoreColor (display, cmap, parsed_xcolors + i); - XStoreColor (display, cmap2, parsed_xcolors + i); - } -#ifdef USE_DGA_EXTENSION - dga_colormap_installed ^= 1; - if (dga_colormap_installed == 1) - XF86DGAInstallColormap(display, screen, cmap2); - else - XF86DGAInstallColormap(display, screen, cmap); -#endif } -void gfx_set_picasso_modeinfo (int w, int h, int depth) +void gfx_set_picasso_modeinfo (int w, int h, int depth, int rgbfmt) { picasso_vidinfo.width = w; picasso_vidinfo.height = h; picasso_vidinfo.depth = depth; - picasso_vidinfo.pixbytes = gfxvidinfo.pixbytes; -#ifdef USE_DGA_EXTENSION - picasso_vidinfo.rowbytes = fb_width * gfxvidinfo.pixbytes; -#else - picasso_vidinfo.rowbytes = picasso_img->bytes_per_line; -#endif - picasso_vidinfo.extra_mem = 1; + picasso_vidinfo.pixbytes = bit_unit >> 3; if (screen_is_picasso) set_window_for_picasso (); @@ -1455,30 +1799,112 @@ 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; + } else { + current_width = gfxvidinfo.width; + current_height = gfxvidinfo.height; + } + graphics_subinit (); if (on) - set_window_for_picasso (); + DX_SetPalette (0, 256); +} + +uae_u8 *gfx_lock_picasso (void) +{ +#ifdef USE_DGA_EXTENSION + if (dgamode) + return fb_addr; else - set_window_for_amiga (); +#endif + return pic_dinfo.ximg->data; } +void gfx_unlock_picasso (void) +{ +} +#endif -void begindrawing (void) +int lockscr (void) { + return 1; } -void enddrawing (void) +void unlockscr (void) { } -uae_u8 *lockscr (void) +static void handle_mousegrab (void) { -#ifdef USE_DGA_EXTENSION - return fb_addr; -#else - return picasso_img->data; -#endif + if (grabbed) { + XUngrabPointer (display, CurrentTime); + XUndefineCursor (display, mywin); + 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 unlockscr (void) + +static void handle_inhibit (void) { + toggle_inhibit_frame (IHF_SCROLLLOCK); +} + +#include "gensound.h" +#include "sounddep/sound.h" +#include "events.h" +#include "audio.h" + +static void handle_interpol (void) +{ + if (currprefs.sound_interpol == 0) { + currprefs.sound_interpol = 1; + printf ("Interpol on: rh\n"); + } + else if (currprefs.sound_interpol == 1) { + currprefs.sound_interpol = 2; + printf ("Interpol on: crux\n"); + } + else { + currprefs.sound_interpol = 0; + printf ("Interpol off\n"); + } +} + +static void framerate_up (void) +{ + if (currprefs.gfx_framerate < 20) + changed_prefs.gfx_framerate = currprefs.gfx_framerate + 1; +} + +static void framerate_down (void) +{ + if (currprefs.gfx_framerate > 1) + changed_prefs.gfx_framerate = currprefs.gfx_framerate - 1; +} + +static void handle_modeswitch (void) +{ + changed_prefs.gfx_afullscreen = changed_prefs.gfx_pfullscreen = !dgamode; +} + +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)); } -#endif