home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / xteddy / xteddy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  10.7 KB  |  356 lines

  1. /* Xteddy - a cuddly bear to place on your desktop. */
  2. /* Copyright Stefan Gustavson, ISY-LiTH, 1994.      */
  3. /* Internet email address: stefang@isy.liu.se       */
  4.  
  5. /* Xpm pixmap manipulation routines for color       */
  6. /* and grayscale teddies are from the Xpm library   */
  7. /* by Arnaud Le Hors, lehors@sophia.inria.fr,       */
  8. /* Copyright 1990-93 GROUPE BULL                    */
  9.  
  10. /* 1994-01-20: First working version (1.0).         */
  11. /* Supports mono, grayscale and color displays.     */
  12.  
  13. #include <X11/Xlib.h>
  14. #include <X11/Xutil.h>
  15. #include <X11/Xos.h>
  16. #include <X11/Xatom.h>
  17. #include <X11/keysym.h>
  18. #include <X11/extensions/shape.h>
  19. #include <X11/cursorfont.h>
  20.  
  21. #if !defined(TRUE)
  22. #define TRUE 1
  23. #endif
  24.  
  25. #ifndef NOXPM
  26. #include <xpm.h>
  27. #endif
  28.  
  29. #include <stdio.h>
  30.  
  31. #include "xteddy_icon.xbm"
  32. #include "xteddy_bw.xbm"
  33. #include "xteddy_mask.xbm"
  34.  
  35. #ifndef NOXPM
  36. #include "xteddy_gray.xpm"
  37. #include "xteddy_color.xpm"
  38. #endif
  39.  
  40. #include "patchlevel.h"
  41.  
  42. static char *progname;
  43. Display *display;
  44. int screen_num;
  45.  
  46. void main(argc, argv)
  47. int argc;
  48. char **argv;
  49. {
  50.   /* Display, window and gc manipulation variables */
  51.   Window win;
  52.   GC gc;
  53.   XSetWindowAttributes setwinattr;
  54.   XGCValues gcvalues;
  55.   unsigned long valuemask, gcvaluemask;
  56.   unsigned int width, height;
  57.   int x,y;
  58.   unsigned int border_width = 0;
  59.   unsigned int display_width, display_height, display_depth;
  60.   char *window_name = "Xteddy";
  61.   char *icon_name = "xteddy";
  62.   Pixmap icon_pixmap, background_pixmap, shape_pixmap;
  63.   XSizeHints size_hints;
  64.   XIconSize *size_list;
  65.   XWMHints wm_hints;
  66.   XClassHint class_hints;
  67.   XTextProperty windowName, iconName;
  68.   int count;
  69.   XEvent report;
  70.   char *display_name = NULL;
  71.   char buffer[20];
  72.   int bufsize = 20;
  73.   KeySym keysym;
  74.   XComposeStatus compose;
  75.   int charcount;
  76.   Cursor cursor;
  77.  
  78. #ifndef NOXPM
  79.   /* Color allocation variables */
  80.   Visual *default_visual;
  81.   Colormap default_cmap;
  82.   XpmAttributes xpmattributes;
  83.   int visual_class;
  84.   XVisualInfo visual_info;
  85.   static char *visual_name[]={ "StaticGray", "GrayScale", "StaticColor",
  86.                   "PseudoColor", "TrueColor", "DirectColor" };
  87. #endif
  88.  
  89.   /* Window movement variables */
  90.   XWindowChanges winchanges;
  91.   Window root, child;
  92.   int offs_x, offs_y, new_x, new_y, tmp_x, tmp_y;
  93.   unsigned int tmp_mask;
  94.   
  95.   progname = argv[0];
  96.  
  97.   /* Connect to X server */
  98.   if ( (display = XOpenDisplay(display_name)) == NULL )
  99.     {
  100.       (void) fprintf(stderr, "%s: Cannot connect to X server %s\n",
  101.              progname, XDisplayName(display_name));
  102.       exit(-1);
  103.     }
  104.  
  105.   /* Set the window size to snugly fit the teddybear pixmap */
  106.   width = xteddy_bw_width;
  107.   height = xteddy_bw_height;
  108.   /* Create the main window */
  109.   x = y = 0;
  110.   win = XCreateSimpleWindow(display, RootWindow(display,screen_num),
  111.                 x,y,width,height,border_width,
  112.                 BlackPixel(display,screen_num),
  113.                 WhitePixel(display,screen_num));
  114.   
  115.   /* Create a GC (Currently not used for any drawing) */
  116.   gcvalues.foreground = BlackPixel(display,screen_num);
  117.   gcvalues.background = WhitePixel(display,screen_num);
  118.   gcvaluemask = GCForeground | GCBackground;
  119.   gc = XCreateGC(display, win, gcvaluemask, &gcvalues);
  120.  
  121.   /* Get screen size and depth */
  122.   screen_num = DefaultScreen(display);
  123.   display_width = DisplayWidth(display, screen_num);
  124.   display_height = DisplayHeight(display, screen_num);
  125.   display_depth = DefaultDepth(display, screen_num);
  126.  
  127. #ifndef NOXPM
  128.   /* Get information about the default visual */
  129.   default_visual = DefaultVisual(display, screen_num);
  130.   default_cmap = DefaultColormap(display, screen_num);
  131. #endif
  132.  
  133. #ifdef NOXPM
  134.   /* Use b/w dithered bitmap no matter what */
  135.   background_pixmap =
  136.     XCreatePixmapFromBitmapData(display, win, xteddy_bw_bits,
  137.                 xteddy_bw_width, xteddy_bw_height,
  138.                 BlackPixel(display, screen_num),
  139.                 WhitePixel(display, screen_num),
  140.                 display_depth);
  141. #else
  142.   /* Check which visual types are supported */
  143.   visual_class = 5;
  144.   while(!XMatchVisualInfo(display, screen_num, display_depth,
  145.               visual_class--, &visual_info));
  146.   visual_class++;
  147. #ifdef DEBUG
  148.   printf("%s: found a %s class visual at default depth.\n",
  149.      progname, visual_name[visual_class]);
  150. #endif
  151.   if (visual_class == StaticGray)
  152.     {
  153.       /* Use b/w dithered bitmap */
  154.       background_pixmap =
  155.     XCreatePixmapFromBitmapData(display, win, xteddy_bw_bits,
  156.                     xteddy_bw_width, xteddy_bw_height,
  157.                     BlackPixel(display, screen_num),
  158.                     WhitePixel(display, screen_num),
  159.                     display_depth);
  160.     }
  161.   else if (visual_class == GrayScale)
  162.     {
  163.       /* Use grayscale pixmap */
  164.       /* This creation of a grayscale pixmap requires the Xpm library */
  165.       xpmattributes.visual = default_visual;
  166.       xpmattributes.colormap = default_cmap;
  167.       xpmattributes.depth = display_depth;
  168.       xpmattributes.valuemask = XpmVisual | XpmColormap | XpmDepth;
  169.       if (XpmCreatePixmapFromData(display, win, xteddy_gray,
  170.                   &background_pixmap, &shape_pixmap,
  171.                   &xpmattributes) < XpmSuccess)
  172.     {
  173.       printf("%s: Failed to allocate grays. Using black-and-white.\n",
  174.          progname);
  175.       background_pixmap =
  176.         XCreatePixmapFromBitmapData(display, win, xteddy_bw_bits,
  177.                     xteddy_bw_width, xteddy_bw_height,
  178.                     BlackPixel(display, screen_num),
  179.                     WhitePixel(display, screen_num),
  180.                     display_depth);
  181.     }
  182.     }
  183.   else /* At least StaticColor - use color pixmap */
  184.     {
  185. #ifdef DEBUG
  186.       if (visual_info.visual != default_visual)
  187.     {
  188.       printf("%s: %s class visual at default depth\n",
  189.          progname, visual_name[visual_class]);
  190.       printf("is not default visual. Continuing anyway...\n");
  191.     }
  192. #endif
  193.       /* This creation of a color pixmap requires the Xpm library */
  194.       xpmattributes.visual = default_visual;
  195.       xpmattributes.colormap = default_cmap;
  196.       xpmattributes.depth = display_depth;
  197.       xpmattributes.valuemask = XpmVisual | XpmColormap | XpmDepth;
  198.       if (XpmCreatePixmapFromData(display, win, xteddy_color,
  199.                   &background_pixmap, &shape_pixmap,
  200.                   &xpmattributes) < XpmSuccess)
  201.     {
  202.       printf("%s: Failed to allocate colors. Using black-and-white.\n",
  203.          progname);
  204.       background_pixmap =
  205.         XCreatePixmapFromBitmapData(display, win, xteddy_bw_bits,
  206.                     xteddy_bw_width, xteddy_bw_height,
  207.                     BlackPixel(display, screen_num),
  208.                     WhitePixel(display, screen_num),
  209.                     display_depth);
  210.     }
  211.     }
  212. #endif
  213.   setwinattr.background_pixmap = background_pixmap;
  214. #ifdef USEWM
  215.   setwinattr.override_redirect = FALSE;
  216. #else
  217.   setwinattr.override_redirect = TRUE;
  218. #endif
  219.   cursor = XCreateFontCursor(display, XC_heart);
  220.   setwinattr.cursor = cursor;
  221.   valuemask = CWBackPixmap | CWOverrideRedirect | CWCursor;
  222.   XChangeWindowAttributes(display, win, valuemask, &setwinattr);
  223.  
  224.   /* Create and set the shape pixmap of the window - requires shape Xext */
  225.   shape_pixmap = XCreateBitmapFromData(display,win, xteddy_mask_bits,
  226.                       xteddy_mask_width, xteddy_mask_height);
  227.   XShapeCombineMask(display, win, ShapeBounding, 0, 0, shape_pixmap, ShapeSet);
  228.  
  229.   /* Get available icon sizes from window manager */
  230.   /* (and then blatantly ignore the result)       */
  231.   if (XGetIconSizes(display, RootWindow(display,screen_num),
  232.             &size_list, &count) == 0)
  233.     {
  234.       /* Window manager didn't set preferred icon sizes - use the default */
  235.       icon_pixmap = XCreateBitmapFromData(display,win, xteddy_icon_bits,
  236.                       xteddy_icon_width, xteddy_icon_height);
  237.     }
  238.   else
  239.     {
  240.       /* Ignore the list and use the default size anyway */
  241.       icon_pixmap = XCreateBitmapFromData(display,win, xteddy_icon_bits,
  242.                       xteddy_icon_width, xteddy_icon_height);
  243.     }
  244.   /* Report size hints and other stuff to the window manager */
  245.   size_hints.min_width = width;
  246.   size_hints.min_height = height;
  247.   size_hints.max_width = width;
  248.   size_hints.max_height = height;
  249.   size_hints.flags = PPosition | PSize | PMinSize | PMaxSize;
  250.   if (XStringListToTextProperty(&window_name, 1, &windowName) == 0)
  251.     {
  252.       (void) fprintf(stderr,
  253.              "%s: structure allocation for windowName failed.\n",
  254.              progname);
  255.       exit(-1);
  256.     }
  257.   if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0)
  258.     {
  259.       (void) fprintf(stderr,
  260.              "%s: structure allocation for iconName failed.\n",
  261.              progname);
  262.       exit(-1);
  263.     }
  264.   wm_hints.initial_state = NormalState;
  265.   wm_hints.input = True;
  266.   wm_hints.icon_pixmap = icon_pixmap;
  267.   wm_hints.flags = StateHint | IconPixmapHint | InputHint;
  268.   
  269.   class_hints.res_name = progname;
  270.   class_hints.res_class = "Xteddy";
  271.   
  272.   XSetWMProperties(display, win, &windowName, &iconName,
  273.            argv, argc, &size_hints, &wm_hints, &class_hints);
  274.  
  275.   /* Select event types wanted */
  276.   XSelectInput(display, win, ExposureMask | KeyPressMask |
  277.            ButtonPressMask | ButtonReleaseMask | StructureNotifyMask |
  278.            ButtonMotionMask | PointerMotionHintMask |
  279.            EnterWindowMask | LeaveWindowMask);
  280.  
  281.   /* Display window */
  282.   XMapWindow(display,win);
  283.  
  284.   /* Get and process the events */
  285.   while (1)
  286.     {
  287.       XNextEvent(display, &report);
  288.       switch(report.type)
  289.     {
  290.     case Expose:
  291.       if (report.xexpose.count != 0)
  292.         break;
  293.       else
  294.         {
  295.           /* No drawing needed - the background pixmap */
  296.           /* is handled automatically by the X server  */
  297.         }
  298.       break;
  299.     case ConfigureNotify:
  300.       /* Window has been resized */
  301.       width = report.xconfigure.width;
  302.       height = report.xconfigure.height;
  303.       break;
  304.     case EnterNotify:
  305.       /* Grab the keyboard while the pointer is in the window */
  306.       XGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync,
  307.             CurrentTime);
  308.       break;
  309.     case LeaveNotify:
  310.       /* Release the keyboard when the pointer leaves the window */
  311.       XUngrabKeyboard(display, CurrentTime);
  312.       break;
  313.     case ButtonPress:
  314.       /* Raise xteddy above sibling windows  */
  315.       XRaiseWindow(display, win);
  316.       /* Remember where the mouse went down */
  317.       XQueryPointer(display, win, &root, &child, &tmp_x, &tmp_y,
  318.             &offs_x, &offs_y, &tmp_mask);
  319.       break;
  320.     case ButtonRelease:
  321.       /* Place xteddy at the new position */
  322.       XQueryPointer(display, win, &root, &child, &new_x, &new_y,
  323.                 &tmp_x, &tmp_y, &tmp_mask);
  324.       winchanges.x = new_x - offs_x;
  325.       winchanges.y = new_y - offs_y;
  326.       XReconfigureWMWindow(display, win, screen_num,
  327.                    CWX | CWY, &winchanges);
  328.       break;
  329.     case MotionNotify:
  330.       /* Move xteddy around with the mouse */
  331.       while (XCheckMaskEvent(display, ButtonMotionMask, &report));
  332.       if (!XQueryPointer(display, report.xmotion.window, &root, &child,
  333.                 &new_x, &new_y, &tmp_x, &tmp_y, &tmp_mask))
  334.         break;
  335.       winchanges.x = new_x - offs_x;
  336.       winchanges.y = new_y - offs_y;
  337.       XReconfigureWMWindow(display, win, screen_num,
  338.                    CWX | CWY, &winchanges);
  339.       break;
  340.     case KeyPress:
  341.       /* Exit on "q" or "Q" */
  342.       charcount = XLookupString(&report, buffer, bufsize,
  343.                     &keysym, &compose);
  344.       if((keysym == XK_Q) || (keysym == XK_q))
  345.         {
  346.           XCloseDisplay(display);
  347.           exit(1);
  348.         }
  349.       break;
  350.     default:
  351.       /* Throw away all other events */
  352.       break;
  353.     } /* end switch */
  354.     } /* end while */
  355. }
  356.