Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/ui/ui-drv/x11/ui_x11.c
diff options
context:
space:
mode:
authorBernie Innocenti <bernie@codewiz.org>2010-05-03 21:53:47 (GMT)
committer Bernie Innocenti <bernie@codewiz.org>2010-05-03 21:53:47 (GMT)
commit1030dc837b10a03a02a85d5504cbeec168ce49e2 (patch)
tree698eefa87ac437deaf36a4141b326f8ce7986692 /src/ui/ui-drv/x11/ui_x11.c
Import XaoS r489 (trunk after version 3.5)
Diffstat (limited to 'src/ui/ui-drv/x11/ui_x11.c')
-rw-r--r--src/ui/ui-drv/x11/ui_x11.c597
1 files changed, 597 insertions, 0 deletions
diff --git a/src/ui/ui-drv/x11/ui_x11.c b/src/ui/ui-drv/x11/ui_x11.c
new file mode 100644
index 0000000..9b5daa3
--- /dev/null
+++ b/src/ui/ui-drv/x11/ui_x11.c
@@ -0,0 +1,597 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include "xlib.h"
+#ifdef MITSHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+#endif
+#include <fconfig.h>
+#include <ui.h>
+xlibparam xparams = { 0, 0, 0, 0, NULL, -1 };
+
+static int allocated;
+Cursor normal, xwait, replay;
+
+struct ui_driver x11_driver;
+static xdisplay *d;
+static char *size;
+static int Xsync;
+static int busy;
+static int sharedcolormap;
+#if 0
+static char *selection;
+#endif
+#ifdef MITSHM
+static int Completion;
+#endif
+#ifdef AMIGA
+#define XFlush(x) while(0)
+#endif
+
+static void x11_setpaletterange(ui_palette p, int s, int e)
+{
+ xsetpaletterange(d, p, s, e);
+}
+
+static int x11_set_color(int r, int g, int b, int init)
+{
+ if (init)
+ xfree_colors(d);
+ return (xalloc_color(d, r * 256, g * 256, b * 256, init));
+}
+
+static void x11_print(int x, int y, CONST char *text)
+{
+ xmoveto(d, x, y + x11_driver.textheight - 2);
+ xouttext(d, text);
+
+}
+
+static void x11_flush(void)
+{
+ XFlush(d->display);
+}
+
+static int display;
+static int flipped = 0;
+static void x11_display(void)
+{
+ XFlush(d->display);
+#ifdef MITSHM
+ if (d->SharedMemFlag) {
+ if (busy) {
+ display = 1;
+ return;
+ }
+ busy++;
+ display = 0;
+ }
+#endif
+ if (Xsync)
+ XSync(d->display, 0);
+ if (flipped)
+ xflip_buffers(d), flipped = 0;
+ draw_screen(d);
+#ifdef MITSHM
+ if (d->SharedMemFlag) {
+ XSync(d->display, 0);
+ }
+#endif
+}
+
+static void x11_flip_buffers(void)
+{
+ flipped ^= 1;
+}
+
+static void x11_free_buffers(char *b1, char *b2)
+{
+ if (allocated) {
+ XSync(d->display, 0);
+ allocated = 0;
+ free_image(d);
+ }
+}
+
+static int x11_alloc_buffers(char **b1, char **b2)
+{
+ if (!allocated) {
+ XSync(d->display, 0);
+ allocated = 1;
+ if (!alloc_image(d)) {
+ return (0);
+ }
+ xflip_buffers(d);
+ }
+ *b1 = d->vbuff;
+ *b2 = d->back;
+ flipped = 0;
+#if 0
+ if (d->SharedMemFlag) {
+ x11_driver.flags |= UI_KEEP_BUFFER;
+ }
+#endif
+ return (d->linewidth);
+}
+
+static void x11_getsize(int *w, int *h)
+{
+ XSync(d->display, 0);
+ xupdate_size(d);
+ *w = d->width;
+ *h = d->height;
+}
+
+static void x11_processevents(int wait, int *mx, int *my, int *mb, int *k)
+{
+ static int mousex = 100, mousey = 0;
+ static int iflag = 0;
+ static unsigned int mousebuttons = 0;
+ static int resized;
+ XEvent ev;
+
+
+ if (XPending(d->display) || busy >= 2 || wait) {
+ do {
+ XNextEvent(d->display, &ev);
+ switch (ev.type) {
+ case ClientMessage:
+ if ((int) ev.xclient.format == 32
+ && ev.xclient.data.l[0] == wmDeleteWindow)
+ ui_quit();
+ break;
+ case ButtonRelease:
+ mousex = ev.xbutton.x;
+ mousey = ev.xbutton.y;
+ switch (ev.xbutton.button) {
+ case 1:
+ mousebuttons &= ~BUTTON1;
+ break;
+ case 2:
+ mousebuttons &= ~BUTTON2;
+ break;
+ case 3:
+ mousebuttons &= ~BUTTON3;
+ break;
+ }
+ break;
+ case ButtonPress:
+ mousex = ev.xbutton.x;
+ mousey = ev.xbutton.y;
+ if (!
+ (mousex < 0 || mousey < 0 || mousex > (int) d->width
+ || mousey > (int) d->height)) {
+ switch (ev.xbutton.button) {
+ case 1:
+ mousebuttons |= BUTTON1;
+ break;
+ case 2:
+ mousebuttons |= BUTTON2;
+ break;
+ case 3:
+ mousebuttons |= BUTTON3;
+ break;
+ }
+ }
+ break;
+ case MotionNotify:
+ mousex = ev.xmotion.x;
+ mousey = ev.xmotion.y;
+ mousebuttons =
+ ev.xmotion.state & (BUTTON1 | BUTTON2 | BUTTON3);
+ break;
+ case Expose:
+ if (resized)
+ break;
+ x11_display();
+ break;
+ case ResizeRequest:
+ XResizeWindow(d->display, d->window,
+ ev.xresizerequest.width,
+ ev.xresizerequest.height);
+ XResizeWindow(d->display, d->parent_window,
+ ev.xresizerequest.width,
+ ev.xresizerequest.height);
+ XSync(d->display, 0);
+ resized = 2;
+ ui_resize();
+ resized = 0;
+ break;
+
+ case ConfigureNotify:
+ {
+ int oldw = d->width, oldh = d->height;
+ XSync(d->display, 0);
+ xupdate_size(d);
+ if ((int) d->width != oldw || (int) d->height != oldh) {
+ resized = 2;
+ ui_resize();
+ resized = 0;
+ }
+ }
+ break;
+ case KeyRelease:
+ {
+ switch (XLookupKeysym(&ev.xkey, 0)) {
+ case XK_Left:
+ iflag &= ~1;
+ break;
+ case XK_Right:
+ iflag &= ~2;
+ break;
+ case XK_Up:
+ iflag &= ~4;
+ break;
+ case XK_Down:
+ iflag &= ~8;
+ break;
+ }
+ }
+ break;
+ case KeyPress:
+ {
+ KeySym ksym;
+ switch (ksym = XLookupKeysym(&ev.xkey, 0)) {
+ case XK_Left:
+ iflag |= 1;
+ ui_key(UIKEY_LEFT);
+ break;
+ case XK_Right:
+ iflag |= 2;
+ ui_key(UIKEY_RIGHT);
+ break;
+ case XK_Up:
+ iflag |= 4;
+ ui_key(UIKEY_UP);
+ break;
+ case XK_Down:
+ iflag |= 8;
+ ui_key(UIKEY_DOWN);
+ break;
+#ifdef XK_Page_Up
+ case XK_Page_Up:
+ iflag |= 4;
+ ui_key(UIKEY_PGUP);
+ break;
+ case XK_Page_Down:
+ iflag |= 8;
+ ui_key(UIKEY_PGDOWN);
+ break;
+#endif
+ case XK_Escape:
+ ui_key(UIKEY_ESC);
+ case XK_BackSpace:
+ ui_key(UIKEY_BACKSPACE);
+ break; /* This statement was missing.
+ I'm not sure if this is needed
+ because new X drivers handle
+ UIKEY_BACKSPACE better or
+ double backspaces were problems
+ in earlier versions of XaoS, too.
+ -- Zoltan, 2004-10-30 */
+ default:
+ {
+ CONST char *name;
+ char buff[256];
+ if (ksym == XK_F1)
+ name = "h";
+ else {
+ name = buff;
+ buff[XLookupString
+ (&ev.xkey, buff, 256, &ksym, NULL)] =
+ 0;
+ }
+ if (strlen(name) == 1) {
+ if (ui_key(*name) == 2) {
+ return;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+#ifdef MITSHM
+ if (ev.xany.type == Completion) {
+ busy--;
+ if (display)
+ x11_display();
+ }
+#endif
+ break;
+ }
+ }
+ while (busy >= 2 || /*XEventsQueued (d->display, QueuedAlready) */
+ XPending(d->display));
+ }
+ *mx = mousex;
+ *my = mousey;
+ *mb = mousebuttons;
+ *k = iflag;
+}
+
+/*static int defined; */
+static void x11_cursor(int mode)
+{
+ /*if(defined)
+ XUndefineCursor(d->display,d->window),defined=0; */
+ switch (mode) {
+ case NORMALMOUSE:
+ XDefineCursor(d->display, d->window, normal);
+ /*defined=1; */
+ break;
+ case WAITMOUSE:
+ XDefineCursor(d->display, d->window, xwait);
+ /*defined=1; */
+ break;
+ case REPLAYMOUSE:
+ XDefineCursor(d->display, d->window, replay);
+ /*defined=1; */
+ break;
+ }
+ XFlush(d->display);
+}
+
+#if 0
+static Atom atom;
+void x11_copy()
+{
+ if (slection)
+ free(selection), selection = NULL;
+ selection = ui_getpos();
+ atom = XInternAtom(d->display, "image/x-xaos.position", False);
+ printf("%i\n", atom);
+ XSetSelectionOwner(d->display, atom, d->window, CurrentTime);
+}
+#endif
+static int x11_init(void)
+{
+ if (xparams.windowid != -1)
+ xparams.rootwindow = xparams.fullscreen = 0;
+ if (xparams.fullscreen || xparams.rootwindow)
+ sharedcolormap = 1; /*private colormap is broken in fullscreen
+ mode (at least at my X) */
+ xparams.privatecolormap = !sharedcolormap;
+ if (xparams.display == NULL) { /*solaris stuff */
+ xparams.display = getenv("DISPLAY");
+ }
+ if (size != NULL) {
+ int x, y;
+ sscanf(size, "%ix%i", &x, &y);
+ if (x < 0)
+ x = XSIZE;
+ if (y < 0)
+ y = YSIZE;
+ d = xalloc_display("XaoS", x, y, &xparams);
+ } else
+ d = xalloc_display("XaoS", XSIZE, YSIZE, &xparams);
+ if (d == NULL)
+ return 0;
+ /*normal=XCreateFontCursor(d->display,XC_arrow); */
+ normal = XCreateFontCursor(d->display, XC_left_ptr);
+ xwait = XCreateFontCursor(d->display, XC_watch);
+ replay = XCreateFontCursor(d->display, XC_dot);
+ if (d->truecolor || d->privatecolormap)
+ x11_driver.flags &= ~RANDOM_PALETTE_SIZE;
+ if (!alloc_image(d)) {
+ xfree_display(d);
+ return (0);
+ }
+ allocated = 1;
+ switch (d->visual->class) {
+ case StaticGray:
+ if (d->depth == 1) {
+ if (BitmapBitOrder(d->display) == LSBFirst)
+ if (WhitePixel(d->display, d->screen))
+ x11_driver.imagetype = UI_LBITMAP;
+ else
+ x11_driver.imagetype = UI_LIBITMAP;
+ else if (WhitePixel(d->display, d->screen))
+ x11_driver.imagetype = UI_MBITMAP;
+ else
+ x11_driver.imagetype = UI_MIBITMAP;
+ } else {
+ /*Warning! this is untested. I believe it works */
+ /*x11_driver.set_color = x11_set_color; */
+ x11_driver.palettestart = 0;
+ x11_driver.paletteend = 256;
+ x11_driver.maxentries = 256;
+ x11_driver.imagetype = UI_GRAYSCALE;
+ }
+ break;
+ case StaticColor:
+ smallcolor:
+ {
+ int end = 256;
+ int start = 0;
+ int entries = d->visual->map_entries;
+ if (d->visual->class == TrueColor) {
+ entries = (int) (d->image[0]->red_mask |
+ d->image[0]->green_mask |
+ d->image[0]->blue_mask);
+ }
+ x11_driver.imagetype = UI_FIXEDCOLOR;
+ if (end > entries)
+ end = entries;
+ if (end < 64)
+ start = 0;
+ x11_driver.set_range = x11_setpaletterange;
+ x11_driver.palettestart = start;
+ x11_driver.paletteend = end;
+ x11_driver.maxentries = end - start;
+ }
+ break;
+ case PseudoColor:
+ case GrayScale:
+ if (d->privatecolormap) {
+ int end = 256;
+ int start = 16;
+ if (end > d->visual->map_entries)
+ end = d->visual->map_entries;
+ if (end < 64)
+ start = 0;
+ x11_driver.set_range = x11_setpaletterange;
+ x11_driver.palettestart = start;
+ x11_driver.paletteend = end;
+ x11_driver.maxentries = end - start;
+ } else {
+ int end = 256;
+ if (end > d->visual->map_entries)
+ end = d->visual->map_entries;
+ x11_driver.set_color = x11_set_color, x11_driver.flags |=
+ RANDOM_PALETTE_SIZE;
+ x11_driver.palettestart = 0;
+ x11_driver.paletteend = end;
+ x11_driver.maxentries = end;
+ }
+ break;
+ case TrueColor:
+ x11_driver.rmask = d->image[0]->red_mask;
+ x11_driver.gmask = d->image[0]->green_mask;
+ x11_driver.bmask = d->image[0]->blue_mask;
+ {
+ unsigned char c[4];
+ int order = MSBFirst;
+ *(unsigned short *) c = 0xff;
+ if (c[0] == (unsigned char) 0xff)
+ order = LSBFirst;
+ if (order != d->image[0]->byte_order) {
+ int shift = 32 - d->image[0]->bits_per_pixel;
+#define SWAPE(c) (((c&0xffU)<<24)|((c&0xff00U)<<8)|((c&0xff0000U)>>8)|((c&0xff000000U)>>24))
+ x11_driver.rmask = SWAPE(x11_driver.rmask) >> shift;
+ x11_driver.gmask = SWAPE(x11_driver.gmask) >> shift;
+ x11_driver.bmask = SWAPE(x11_driver.bmask) >> shift;
+ }
+ }
+ switch (d->image[0]->bits_per_pixel) {
+ case 8:
+ goto smallcolor;
+ case 16:
+ x11_driver.imagetype = UI_TRUECOLOR16;
+ break;
+ case 24:
+ x11_driver.imagetype = UI_TRUECOLOR24;
+ break;
+ case 32:
+ x11_driver.imagetype = UI_TRUECOLOR;
+ break;
+ default:
+ printf("Fatal error:unsupported bits per pixel!\n");
+ }
+ }
+ x11_driver.maxwidth = XDisplayWidth(d->display, d->screen);
+ x11_driver.maxheight = XDisplayHeight(d->display, d->screen);
+ x11_driver.width =
+ ((double) ((unsigned int) XDisplayWidthMM(d->display, d->screen)))
+ / x11_driver.maxwidth / 10.0;
+ x11_driver.height =
+ ((double) ((unsigned int) XDisplayHeightMM(d->display, d->screen)))
+ / x11_driver.maxheight / 10.0;
+ x11_driver.textheight = xsetfont(d, "fixed");
+ x11_driver.textwidth =
+ d->font_struct->max_bounds.rbearing -
+ d->font_struct->min_bounds.lbearing;
+#ifdef MITSHM
+ Completion = XShmGetEventBase(d->display) + ShmCompletion;
+#endif
+ if (d->privatecolormap) {
+ x11_driver.flags |= PALETTE_ROTATION | ROTATE_INSIDE_CALCULATION;
+ }
+ return (1);
+}
+
+static void x11_uninitialise(void)
+{
+#if 0
+ if (selection)
+ free(selection), selection = NULL;
+#endif
+ xfree_colors(d);
+ xfree_display(d);
+}
+
+static void x11_getmouse(int *x, int *y, int *b)
+{
+ int rootx, rooty;
+ Window rootreturn, childreturn;
+ XQueryPointer(d->display, d->window,
+ &rootreturn, &childreturn,
+ &rootx, &rooty, x, y, (unsigned int *) b);
+}
+
+static CONST struct params params[] = {
+ {"", P_HELP, NULL, "X11 driver options:"},
+ {"-display", P_STRING, &xparams.display, "Select display"},
+ {"-size", P_STRING, &size, "Select size of window (WIDTHxHEIGHT)."},
+ {"-sync", P_SWITCH, &Xsync,
+ "Generate sync signals before looking for events. This\n\t\t\thelps on old and buggy HP-UX X servers."},
+ {"-shared", P_SWITCH, &sharedcolormap,
+ "Use shared colormap on pseudocolor display."},
+ {"-usedefault", P_SWITCH, &xparams.usedefault,
+ "Use default visual if autodetection causes troubles."},
+ {"-nomitshm", P_SWITCH, &xparams.nomitshm,
+ "Disable MITSHM extension."},
+ {"-fullscreen", P_SWITCH, &xparams.fullscreen,
+ "Enable fullscreen mode."},
+ {"-windowid", P_NUMBER, &xparams.windowid, "Use selected window."},
+ {"-window-id", P_NUMBER, &xparams.windowid, "Use selected window."},
+ {"-root", P_SWITCH, &xparams.rootwindow, "Use root window."},
+ {NULL, 0, NULL, NULL}
+};
+
+struct ui_driver x11_driver = {
+ "X11",
+ x11_init,
+ x11_getsize,
+ x11_processevents,
+ x11_getmouse,
+ x11_uninitialise,
+ NULL,
+ NULL,
+ x11_print,
+ x11_display,
+ x11_alloc_buffers,
+ x11_free_buffers,
+ x11_flip_buffers,
+ x11_cursor,
+ x11_flush,
+ 8,
+ 8,
+ params,
+ RESOLUTION | PIXELSIZE | NOFLUSHDISPLAY /*| UPDATE_AFTER_RESIZE */ ,
+ 0.0, 0.0,
+ 0, 0,
+ UI_C256,
+ 16, 254, 254 - 16
+};
+
+#endif