Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/ui/ui-drv/x11/xlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/ui-drv/x11/xlib.c')
-rw-r--r--src/ui/ui-drv/x11/xlib.c663
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