Logo Search packages:      
Sourcecode: xaos version File versions  Download package

ui_x11.c

/* 
 *     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);
              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.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."},
  {"-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

Generated by  Doxygen 1.6.0   Back to index