diff options
Diffstat (limited to 'src/ui/ui-drv/x11/xlib.c')
-rw-r--r-- | src/ui/ui-drv/x11/xlib.c | 663 |
1 files changed, 663 insertions, 0 deletions
diff --git a/src/ui/ui-drv/x11/xlib.c b/src/ui/ui-drv/x11/xlib.c new file mode 100644 index 0000000..87308b8 --- /dev/null +++ b/src/ui/ui-drv/x11/xlib.c @@ -0,0 +1,663 @@ +/* + * XaoS, a fast portable realtime fractal zoomer + * Copyright (C) 1996,1997 by + * + * Jan Hubicka (hubicka@paru.cas.cz) + * Thomas Marsh (tmarsh@austin.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "aconfig.h" +#ifdef X11_DRIVER +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <config.h> +#ifndef NO_MALLOC_H +#include <malloc.h> +#endif +#include "xlib.h" +#ifdef AMIGA +#define XFlush(x) while(0) +#endif + +#define chkalloc(n) if (!n) fprintf(stderr, "out of memory\n"), exit(-1) + +extern int prog_argc; +extern char **prog_argv; +Atom wmDeleteWindow; + +int xupdate_size(xdisplay * d) +{ + int tmp; + Window wtmp; + unsigned int width = d->width, height = d->height; + XSync(d->display, False); + XGetGeometry(d->display, d->window, &wtmp, &tmp, &tmp, &d->width, + &d->height, (unsigned int *) &tmp, (unsigned int *) &tmp); + if (d->width != width || d->height != height) + return 1; + return 0; +} + +void xflip_buffers(xdisplay * d) +{ + d->back = d->vbuffs[d->current]; + d->current ^= 1; + d->vbuff = d->vbuffs[d->current]; +} + + +void draw_screen(xdisplay * d) +{ +#ifdef MITSHM + if (d->SharedMemFlag) { + XShmPutImage(d->display, d->window, d->gc, d->image[d->current], 0, + 0, 0, 0, d->bwidth, d->bheight, True); + } else +#endif + XPutImage(d->display, d->window, d->gc, d->image[d->current], 0, 0, + 0, 0, d->bwidth, d->bheight); + /*XFlush(d->display); *//*gives small rest to X but degrades perofrmance + too much */ + d->screen_changed = 0; +} + +#ifdef MITSHM +int alloc_shm_image(xdisplay * new) +{ + register char *ptr; + int temp, size = 0, i; + ptr = DisplayString(new->display); + if (!ptr || (*ptr == ':') || !strncmp(ptr, "localhost:", 10) || + !strncmp(ptr, "unix:", 5) || !strncmp(ptr, "local:", 6)) { + new->SharedMemOption = + XQueryExtension(new->display, "MIT-SHM", &temp, &temp, &temp); + } else { + new->SharedMemOption = False; + return 0; + } + new->SharedMemFlag = False; + + if (new->SharedMemFlag) { + XShmDetach(new->display, &new->xshminfo[0]); + XShmDetach(new->display, &new->xshminfo[1]); + new->image[0]->data = (char *) NULL; + new->image[1]->data = (char *) NULL; + shmdt(new->xshminfo[0].shmaddr); + shmdt(new->xshminfo[1].shmaddr); + } + for (i = 0; i < 2; i++) { + if (new->SharedMemOption) { + new->SharedMemFlag = False; + new->image[i] = + XShmCreateImage(new->display, new->visual, new->depth, + new->depth == 1 ? XYBitmap : ZPixmap, NULL, + &new->xshminfo[i], new->width, + new->height); + if (new->image[i]) { + temp = + new->image[i]->bytes_per_line * + (new->image[i]->height + 150); + new->linewidth = new->image[i]->bytes_per_line; + if (temp > size) + size = temp; + new->xshminfo[i].shmid = + shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); + if (new->xshminfo[i].shmid != -1) { + errno = 0; + new->xshminfo[i].shmaddr = + (char *) shmat(new->xshminfo[i].shmid, 0, 0); + if (!errno) { + new->image[i]->data = new->xshminfo[i].shmaddr; + new->data[i] = new->vbuffs[i] = + (char *) new->image[i]->data; + new->xshminfo[i].readOnly = True; + + new->SharedMemFlag = + XShmAttach(new->display, &new->xshminfo[i]); + XSync(new->display, False); + if (!new->SharedMemFlag) { + XDestroyImage(new->image[i]); + new->image[i] = (XImage *) NULL; + new->SharedMemFlag = 0; + return 0; + } + } + /* Always Destroy Shared Memory Ident */ + shmctl(new->xshminfo[i].shmid, IPC_RMID, 0); + } + if (!new->SharedMemFlag) { + XDestroyImage(new->image[i]); + new->image[i] = (XImage *) NULL; + new->SharedMemFlag = 0; + return 0; + } + } else { + new->SharedMemFlag = 0; + return 0; + } + } else { + new->SharedMemFlag = 0; + return 0; + } + } + new->current = 0; + xflip_buffers(new); + return 1; +} + +void free_shm_image(xdisplay * d) +{ + if (d->SharedMemFlag) { + XDestroyImage(d->image[0]); + XDestroyImage(d->image[1]); + XShmDetach(d->display, &d->xshminfo[0]); + XShmDetach(d->display, &d->xshminfo[1]); + shmdt(d->xshminfo[0].shmaddr); + shmdt(d->xshminfo[1].shmaddr); + } +} + +#endif + +int alloc_image(xdisplay * d) +{ + int i; + d->bwidth = d->width; + d->bheight = d->height; +#ifdef MITSHM + if (!d->params->nomitshm && d->depth != 1 && alloc_shm_image(d)) { + return 1; + } +#endif + for (i = 0; i < 2; i++) { + + d->image[i] = + XCreateImage(d->display, d->visual, d->depth, + d->depth == 1 ? XYBitmap : ZPixmap, 0, NULL, + d->width, d->height, 32, 0); + if (d->image[i] == NULL) { + printf("Out of memory for image..exiting\n"); + exit(-1); + } + d->image[i]->data = + malloc(d->image[i]->bytes_per_line * d->height); + if (d->image[i]->data == NULL) { + printf("Out of memory for image buffers..exiting\n"); + exit(-1); + } + { + unsigned char c[4]; + int byteexact = 0; + *(unsigned short *) c = 0xff; + if ((!(d->image[i]->red_mask & ~0xffU) + || !(d->image[i]->red_mask & ~0xff00U) + || !(d->image[i]->red_mask & ~0xff0000U) + || !(d->image[i]->red_mask & ~0xff000000U)) + && (!(d->image[i]->green_mask & ~0xffU) + || !(d->image[i]->green_mask & ~0xff00U) + || !(d->image[i]->green_mask & ~0xff0000U) + || !(d->image[i]->green_mask & ~0xff000000U)) + && (!(d->image[i]->blue_mask & ~0xffU) + || !(d->image[i]->blue_mask & ~0xff00U) + || !(d->image[i]->blue_mask & ~0xff0000U) + || !(d->image[i]->blue_mask & ~0xff000000U))) + byteexact = 1; + if (!byteexact) { + /*Make endianity correct */ + if (c[0] == (unsigned char) 0xff) { + if (d->image[i]->byte_order != LSBFirst) { + d->image[i]->byte_order = LSBFirst; + /*XInitImage(d->image[i]); */ + } + } else { + if (d->image[i]->byte_order != MSBFirst) { + d->image[i]->byte_order = MSBFirst; + /*XInitImage(d->image[i]); */ + } + } + } + } + d->data[i] = d->vbuffs[i] = (char *) d->image[i]->data; + d->linewidth = d->image[i]->bytes_per_line; + } + xflip_buffers(d); + return 1; +} + +void free_image(xdisplay * d) +{ +#ifdef MITSHM + if (d->SharedMemFlag) { + free_shm_image(d); + return; + } +#endif + XDestroyImage(d->image[0]); + XDestroyImage(d->image[1]); +} + +#define MAX(x,y) ((x)>(y)?(x):(y)) + + +xdisplay *xalloc_display(CONST char *s, int x, int y, xlibparam * params) +{ + xdisplay *new; + Visual *defaultvisual; + XVisualInfo vis; + int found; + int i; + + XClassHint classHint; + XWMHints *hints; + char **faked_argv; + + new = (xdisplay *) calloc(sizeof(xdisplay), 1); + chkalloc(new); + new->display = XOpenDisplay(params->display); + if (!new->display) { + free((void *) new); + return NULL; + } + new->screen = DefaultScreen(new->display); + + new->attributes = + (XSetWindowAttributes *) malloc(sizeof(XSetWindowAttributes)); + chkalloc(new->attributes); + new->attributes->background_pixel = + BlackPixel(new->display, new->screen); + new->attributes->border_pixel = BlackPixel(new->display, new->screen); + new->attributes->event_mask = ButtonPressMask | StructureNotifyMask | + ButtonReleaseMask | PointerMotionMask | KeyPressMask | + ExposureMask | KeyReleaseMask; + + + new->attr_mask = CWBackPixel | CWEventMask; + if (params->fullscreen || params->rootwindow) { + new->attributes->override_redirect = True; + new->attr_mask |= CWOverrideRedirect; + } else + new->attr_mask |= CWBorderPixel; + new->class = InputOutput; + new->xcolor.n = 0; + new->parent_window = RootWindow(new->display, new->screen); + defaultvisual = DefaultVisual(new->display, new->screen); + new->params = params; + + found = 0; + for (i = 31; i > 13 && !found; i--) + if (XMatchVisualInfo + (new->display, new->screen, i, TrueColor, &vis)) { + found = 1; + } + if (defaultvisual->class != StaticGray + && defaultvisual->class != GrayScale) { + for (i = 8; i && !found; i--) + if (XMatchVisualInfo + (new->display, new->screen, i, PseudoColor, &vis)) { + found = 1; + } + for (i = 8; i && !found; i--) + if (XMatchVisualInfo + (new->display, new->screen, i, StaticColor, &vis)) { + found = 1; + } + for (i = 8; i && !found; i--) + if (XMatchVisualInfo + (new->display, new->screen, i, TrueColor, &vis)) { + found = 1; + } + } + if (!found + && XMatchVisualInfo(new->display, new->screen, 8, StaticGray, + &vis)) { + found = 1; + } + for (i = 8; i && !found; i--) + if (XMatchVisualInfo + (new->display, new->screen, i, GrayScale, &vis)) { + found = 1; + } + if (!found + && XMatchVisualInfo(new->display, new->screen, 1, StaticGray, + &vis)) { + found = 8; + } + if (!found || params->fullscreen || params->rootwindow) { + new->visual = defaultvisual; + new->depth = DefaultDepth(new->display, new->screen); + } else { + new->visual = vis.visual; + new->depth = vis.depth; + } + + switch (new->visual->class) { + case StaticColor: + case StaticGray: + smallcolor: + new->truecolor = 0; + new->fixedcolormap = 1; + break; + case PseudoColor: + case GrayScale: + if (new->depth <= 8) { + new->truecolor = 0; + new->fixedcolormap = 0; + } else { + goto visuals; + } + break; + case TrueColor: + new->truecolor = 1; + new->fixedcolormap = 1; + if (new->depth <= 8) + goto smallcolor; + if (new->depth > 32) { + goto visuals; + } + break; + default: + visuals: + printf + ("Unusuported visual. Please contact authors. Maybe it will be supported in next release:)\n"); + return (NULL); + } + new->privatecolormap = params->privatecolormap; + new->attributes->colormap = new->defaultcolormap = + DefaultColormap(new->display, new->screen); + if (new->visual->visualid != defaultvisual->visualid) { + new->privatecolormap = 1; + } + if ( /*!new->fixedcolormap && */ new->privatecolormap) { + unsigned long pixels[256]; + int i; + new->attributes->colormap = + XCreateColormap(new->display, + RootWindow(new->display, new->screen), + new->visual, AllocNone); + if (new->visual->visualid == defaultvisual->visualid + && new->visual->class == PseudoColor) { + XAllocColorCells(new->display, new->attributes->colormap, 1, 0, + 0, pixels, MAX(new->visual->map_entries, + 256)); + for (i = 0; i < 16; i++) { + new->xcolor.c[i].pixel = pixels[i]; + } + XQueryColors(new->display, new->defaultcolormap, new->xcolor.c, + 16); + XStoreColors(new->display, new->attributes->colormap, + new->xcolor.c, 16); + } + } + new->colormap = new->attributes->colormap; + new->attr_mask |= CWColormap; + + new->window_name = (char *) s; + new->height = y; + new->width = x; + new->border_width = 2; + new->lastx = 0; + new->lasty = 0; + new->font_struct = (XFontStruct *) NULL; + + if (params->fullscreen || params->rootwindow) { + Window wtmp; + int tmp; + /* Get size of the root window */ + XGetGeometry(new->display, RootWindow(new->display, new->screen), &wtmp, &tmp, &tmp, &new->width, &new->height, (unsigned int *) &tmp, /* border width */ + (unsigned int *) &tmp); /* depth */ + new->border_width = 0; + } + + if (params->windowid != -1) { + Window wtmp; + int tmp; + + new->parent_window = params->windowid; + XGetGeometry(new->display, new->parent_window, &wtmp, &tmp, &tmp, &new->width, &new->height, (unsigned int *) &tmp, /* border width */ + (unsigned int *) &tmp); /* depth */ + XSelectInput(new->display, new->parent_window, ResizeRedirectMask); + } + if (params->rootwindow) + new->window = RootWindow(new->display, new->screen); + else + new->window = XCreateWindow(new->display, new->parent_window, 0, 0, + new->width, new->height, + new->border_width, new->depth, + new->class, new->visual, + new->attr_mask, new->attributes); + + classHint.res_name = (char *) "xaos"; + classHint.res_class = (char *) "XaoS"; + hints = XAllocWMHints(); + hints->initial_state = NormalState; + hints->window_group = new->window; + hints->flags = (WindowGroupHint | StateHint); + + { + int fake = 0; + + if (prog_argc < 2) + fake = 1; + + if (fake == 0) + if (strcmp(prog_argv[prog_argc - 2], "-driver") && + strcmp(prog_argv[prog_argc - 1], "x11")) + fake = 1; + + if (fake) { + int i; + faked_argv = + (char **) malloc((prog_argc + 2) * sizeof(char *)); + for (i = 0; i < prog_argc; i++) + faked_argv[i] = prog_argv[i]; + faked_argv[prog_argc] = (char *) "-driver"; + faked_argv[prog_argc + 1] = (char *) "x11"; + + XSetWMProperties(new->display, new->window, NULL, NULL, + faked_argv, prog_argc + 2, NULL, hints, + &classHint); + + free(faked_argv); + } else + XSetWMProperties(new->display, new->window, NULL, NULL, + prog_argv, prog_argc, NULL, hints, + &classHint); + } + XSetIconName(new->display, new->window, "xaos"); + + wmDeleteWindow = XInternAtom(new->display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(new->display, new->window, &wmDeleteWindow, 1); + + new->gc = XCreateGC(new->display, new->window, 0L, &(new->xgcvalues)); + XSetBackground(new->display, new->gc, + BlackPixel(new->display, new->screen)); + XSetForeground(new->display, new->gc, + WhitePixel(new->display, new->screen)); + XStoreName(new->display, new->window, new->window_name); + XMapWindow(new->display, new->window); + if (params->fullscreen || params->rootwindow) + XSetInputFocus(new->display, new->window, RevertToNone, + CurrentTime); + + return (new); +} + +void xsetcolor(xdisplay * d, int col) +{ + switch (col) { + case 0: + XSetForeground(d->display, d->gc, + BlackPixel(d->display, d->screen)); + break; + case 1: + XSetForeground(d->display, d->gc, + WhitePixel(d->display, d->screen)); + break; + default: + if ((col - 2) > d->xcolor.n) { + fprintf(stderr, "color error\n"); + exit(-1); + } + XSetForeground(d->display, d->gc, d->xcolor.c[col - 2].pixel); + break; + } +} + +void xsetpaletterange(xdisplay * d, ui_palette c, int start, int end) +{ + int i; + if (d->visual->class == StaticColor || d->visual->class == TrueColor) { + for (i = start; i < end; i++) + d->xcolor.c[i].pixel = i; + XQueryColors(d->display, d->colormap, d->xcolor.c + start, + end - start); + for (i = start; i < end; i++) { + c[i - start][0] = d->xcolor.c[i].red / 256; + c[i - start][1] = d->xcolor.c[i].green / 256; + c[i - start][2] = d->xcolor.c[i].blue / 256; + } + + } else { + for (i = start; i < end; i++) { + d->xcolor.c[i].pixel = i; + d->xcolor.c[i].flags = DoRed | DoGreen | DoBlue; + d->xcolor.c[i].red = c[i - start][0] * 256; + d->xcolor.c[i].green = c[i - start][1] * 256; + d->xcolor.c[i].blue = c[i - start][2] * 256; + } + XStoreColors(d->display, d->colormap, d->xcolor.c + start, + end - start); + } +} + +int xalloc_color(xdisplay * d, int r, int g, int b, int readwrite) +{ + d->xcolor.n++; + d->xcolor.c[d->xcolor.n - 1].flags = DoRed | DoGreen | DoBlue; + d->xcolor.c[d->xcolor.n - 1].red = r; + d->xcolor.c[d->xcolor.n - 1].green = g; + d->xcolor.c[d->xcolor.n - 1].blue = b; + d->xcolor.c[d->xcolor.n - 1].pixel = d->xcolor.n - 1; + if ((readwrite && !d->fixedcolormap) || d->privatecolormap) { + unsigned long cell; + if (d->privatecolormap) { + cell = d->xcolor.c[d->xcolor.n - 1].pixel += 16; + if ((int) d->xcolor.c[d->xcolor.n - 1].pixel >= + d->visual->map_entries) { + d->xcolor.n--; + return (-1); + } + } else { + if (!XAllocColorCells + (d->display, d->colormap, 0, 0, 0, &cell, 1)) { + d->xcolor.n--; + if (d->xcolor.n <= 32) + printf + ("Colormap is too full! close some colorfull applications or use -private\n"); + return (-1); + } + d->xcolor.c[d->xcolor.n - 1].pixel = cell; + } + XStoreColor(d->display, d->colormap, + &(d->xcolor.c[d->xcolor.n - 1])); + return ((int) cell); + } + if (!XAllocColor + (d->display, d->colormap, &(d->xcolor.c[d->xcolor.n - 1]))) { + d->xcolor.n--; + if (d->xcolor.n <= 32) + printf + ("Colormap is too full! close some colorfull aplications or use -private\n"); + return (-1); + } + d->pixels[d->xcolor.n - 1] = d->xcolor.c[d->xcolor.n - 1].pixel; + return (d->depth != + 8 ? d->xcolor.n - 1 : (int) d->xcolor.c[d->xcolor.n - + 1].pixel); +} + +void xfree_colors(xdisplay * d) +{ + unsigned long pixels[256]; + int i; + for (i = 0; i < d->xcolor.n; i++) + pixels[i] = d->xcolor.c[i].pixel; + if (!d->privatecolormap) + XFreeColors(d->display, d->colormap, pixels, d->xcolor.n, 0); + d->xcolor.n = 0; +} + +void xfree_display(xdisplay * d) +{ + XSync(d->display, 0); + if (d->font_struct != (XFontStruct *) NULL) { + XFreeFont(d->display, d->font_struct); + } + XUnmapWindow(d->display, d->window); + XDestroyWindow(d->display, d->window); + XCloseDisplay(d->display); + free((void *) d->attributes); + free((void *) d); +} + +void xclear_screen(xdisplay * d) +{ + XClearWindow(d->display, d->window); + d->screen_changed = 1; +} + +void xmoveto(xdisplay * d, int x, int y) +{ + d->lastx = x, d->lasty = y; +} + +int xsetfont(xdisplay * d, CONST char *font_name) +{ + + if (d->font_struct != (XFontStruct *) NULL) { + XFreeFont(d->display, d->font_struct); + } + d->font_struct = XLoadQueryFont(d->display, font_name); + XSetFont(d->display, d->gc, d->font_struct->fid); + if (!d->font_struct) { + fprintf(stderr, "could not load font: %s\n", font_name); + exit(-1); + } + return (d->font_struct->max_bounds.ascent + + d->font_struct->max_bounds.descent); +} + +void xouttext(xdisplay * d, CONST char *string) +{ + int sz; + + sz = (int) strlen(string); + XDrawImageString(d->display, d->window, d->gc, d->lastx, d->lasty, + string, sz); +} + +void xresize(xdisplay * d, XEvent * ev) +{ + XSync(d->display, False); + d->width = ev->xconfigure.width; + d->height = ev->xconfigure.height; +} + +#endif |