Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

XGraphicsSystem.cc

Go to the documentation of this file.
00001 /*
00002     File:           XGraphicsSystem.cc
00003 
00004     Function:       See header file
00005 
00006     Author(s):      Andrew Willmott
00007 
00008     Copyright:      (c) 1995-2000, Andrew Willmott
00009 
00010     Notes:          
00011 */
00012 
00013 #include "gcl/XGraphicsSystem.h"
00014 
00015 #include <sys/time.h>
00016 #include <sys/types.h>
00017 
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 #include <iostream.h>
00021 #include <errno.h>
00022 
00023 #ifdef GCL_XSHM
00024 #define Bool int
00025 #include <sys/ipc.h>
00026 #include <sys/shm.h>
00027 #include <X11/extensions/XShm.h>
00028 #undef Bool
00029 #endif
00030 
00031 #define DBG_COUT if (0) cerr
00032 
00033 /*
00034     Design notes:
00035 
00036     -   XGraphicsSystem implements raw, standalone X windows.  We must
00037         make allowance here for our windows being used in other higher
00038         level toolkits, though -- e.g., the forms package.  This is the
00039         rationale for CreateWindow() etc. not being a method of the
00040         X*Pane classes.
00041 
00042     -   Currently only supports images in 16/24-bit truecolor.  This is
00043         because X has no high-level API for colour management, no support
00044         for converting between bit depths, no support for almost
00045         anything except network sockets and useless error messages.
00046 
00047         Just how bad is the wretched X11? Consider that there's 307
00048         lines of code in this file to support what can be done with a
00049         one-line "CopyBits" call in any other graphical OS. And parts of
00050         that code have to handle completely undocumented features. Now,
00051         consider that that code is replicated in almost any X11 app that
00052         does image manipulation.
00053 
00054         ACM TOG '98 has an article on how to do sane colour management
00055         with X. The scheme it proposes is remarkably similar to what the
00056         Mac was doing in the late 80's, but the author seems to be
00057         unaware of that.
00058 
00059         If it becomes necessary to do generic support for all different
00060         visual types, prob. best to require something like gtk+/imlib,
00061         which I believe includes the colour management routines from
00062         XmHTML.
00063 
00064  */
00065 
00066 // --- XWindows-specific Graphics System... -----------------------------------
00067 
00068 Bool XGraphicsSystem::finished = false;
00069 
00070 #ifdef GCL_XSHM
00071 static Bool gShmError = false;
00072 static XErrorHandler gOldHandler = 0;
00073 static Int ShmErrHandler(Display *dpy, XErrorEvent *error)
00074 {
00075     gShmError = true;
00076     return 0;
00077 }
00078 #endif
00079 
00080 XGraphicsSystem::XGraphicsSystem() : hasGC(false), sharedOn(true), 
00081             remoteChecked(false)
00082 //  Initialise the system
00083 {
00084     itsEventsMask = 
00085         StructureNotifyMask | KeyPressMask | ButtonPressMask | ExposureMask;
00086 
00087     display = XOpenDisplay(0);
00088     
00089     if (display == 0)
00090     {
00091         cerr << "FATAL: Can't open connection to X W**dows server." << endl;
00092         cerr << "(Check the DISPLAY environment variable.)" << endl;
00093         exit(1);
00094     }
00095 
00096 #ifdef GCL_XSHM
00097     if (!XShmQueryExtension(display))
00098         sharedOn = false;
00099 #endif
00100 
00101 #ifdef DEBUG
00102     XSynchronize(display, True);
00103 #endif  
00104 }
00105 
00106 XGraphicsSystem::~XGraphicsSystem()
00107 {
00108 }
00109 
00110 Void XGraphicsSystem::Spin()
00111 {
00112     XEvent      event;
00113     Int         i;
00114     
00115     // handle all outstanding events for our windows
00116     for (i = 0; i < paneList.NumItems(); i++)
00117         while (XCheckWindowEvent(display, paneList[i]->paneXID, 
00118                 ButtonPressMask | KeyPressMask | ExposureMask, &event))
00119             paneList[i]->XHandleEvent(&event);
00120 }
00121 
00122 Bool XGraphicsSystem::RunFor(Float time)
00123 {
00124     struct timeval  timeOut;
00125     Int             displayFD = ConnectionNumber(display);
00126     fd_set          readSet;
00127 
00128     timeOut.tv_sec = (Long) time;
00129     timeOut.tv_usec = (Long) ((time - timeOut.tv_sec) * 1e6);
00130 
00131     FD_ZERO(&readSet);
00132     FD_SET(displayFD, &readSet);
00133 
00134     select(displayFD + 1, &readSet, 0, 0, &timeOut);
00135 
00136     Spin();
00137 
00138     return(finished);
00139 }
00140 
00141 Void XGraphicsSystem::Run()
00142 {
00143     XEvent      event;
00144     Int         i;
00145 
00146     finished = false;
00147 
00148     while (!finished)
00149     {
00150         XMaskEvent(display, 
00151                 ButtonPressMask | KeyPressMask | ExposureMask, &event);
00152 
00153         for (i = 0; i < paneList.NumItems(); i++)
00154             if (paneList[i]->paneXID == event.xany.window)
00155             {
00156                 paneList[i]->XHandleEvent(&event);
00157                 break;
00158             }
00159         if (i == paneList.NumItems())
00160             cerr << "*** Unhandled X event for window " << event.xany.window << endl;
00161     }
00162 }
00163 
00164 Void XGraphicsSystem::SignalDone()
00165 {
00166     finished = true;
00167 }
00168 
00169 Void XGraphicsSystem::GetMouse(XEventPane *xpane,
00170     Int *x, Int *y, UInt *keyState)
00171 {
00172     Int     x1, x2;
00173     Window  d1, d2;
00174     
00175     XQueryPointer(display, xpane->paneXID, &d1, &d2, &x1, &x2, x, y, keyState);
00176 }
00177 
00178 static int WaitForNotify(Display *display, XEvent *event, char *arg)
00179 {
00180     return((event->type == MapNotify) && (event->xmap.window == (Window) arg));
00181 }
00182 
00183 Void XGraphicsSystem::CreateWindow(XEventPane *xpane, StrConst title, 
00184         Int width, Int height)
00185 {
00186     XSetWindowAttributes    windowAttributes;
00187     XEvent                  event;
00188     Colormap                colourMap;
00189     XVisualInfo             *theVisualInfo;
00190                 
00191     xpane->width = width;
00192     xpane->height = height;
00193     xpane->xgs = this;
00194 
00195     theVisualInfo = xpane->GetVisualInfo();
00196 
00197     colourMap = XCreateColormap(display,
00198         RootWindow(display, theVisualInfo->screen), theVisualInfo->visual, 
00199         AllocNone);
00200 
00201     windowAttributes.colormap = colourMap;
00202     windowAttributes.border_pixel = 0;
00203     
00204     windowAttributes.event_mask = itsEventsMask; 
00205 
00206     xpane->paneXID = XCreateWindow(display,
00207         RootWindow(display, theVisualInfo->screen), 0, 0, width, height,
00208         0, theVisualInfo->depth, InputOutput, theVisualInfo->visual,
00209         CWBorderPixel | CWColormap | CWEventMask, &windowAttributes);
00210 
00211     XMapWindow(display, xpane->paneXID);
00212 
00213     //  Wait for notify...
00214 
00215     XIfEvent(display, &event, WaitForNotify, (char *) xpane->paneXID);
00216     
00217     //  Create a graphics context if it hasn't been done before...
00218     
00219     if (!hasGC) 
00220         theGC = XCreateGC(display, xpane->paneXID, 0, 0);
00221 
00222     xpane->Init();
00223 
00224     XStoreName(display, xpane->paneXID, title);
00225     XSetIconName(display, xpane->paneXID, title);
00226     
00227     paneList.Append(xpane);
00228 }
00229 
00230 Void XGraphicsSystem::CreateSubwindow(XEventPane *xpane, Window parent,
00231         Int x, Int y, Int width, Int height)
00232 //  Create a sub-window in the parent window.
00233 {
00234     XSetWindowAttributes    windowAttributes;
00235     XEvent                  event;
00236     Colormap                colourMap;
00237     XVisualInfo             *theVisualInfo;
00238     
00239     xpane->width = width;
00240     xpane->height = height;
00241     xpane->xgs = this;
00242 
00243     theVisualInfo = xpane->GetVisualInfo();
00244         
00245     colourMap = XCreateColormap(display,
00246         RootWindow(display, theVisualInfo->screen), theVisualInfo->visual,
00247         AllocNone);
00248 
00249     windowAttributes.colormap = colourMap;
00250     windowAttributes.border_pixel = 0;
00251     windowAttributes.event_mask = itsEventsMask;
00252 
00253     xpane->paneXID = XCreateWindow(display,
00254         parent, x, y, width, height,
00255         0, theVisualInfo->depth, InputOutput, theVisualInfo->visual,
00256         CWBorderPixel | CWColormap | CWEventMask, &windowAttributes);
00257 
00258     XMapWindow(display, xpane->paneXID);
00259 
00260     //  Wait for notify...
00261 
00262     XIfEvent(display, &event, WaitForNotify, (char *) xpane->paneXID);
00263     
00264     //  Create a graphics context if it hasn't been done before...
00265     
00266     if (!hasGC) 
00267         theGC = XCreateGC(display, xpane->paneXID, 0, 0);
00268 
00269     xpane->Init();
00270 }
00271 
00272 Void XGraphicsSystem::CreateOffscreen(XOffscreenPane *xpane, Int width, Int height)
00273 //  Create an offscreen buffer.
00274 {
00275     XVisualInfo             *theVisualInfo;
00276     
00277     xpane->xgs = this;
00278     xpane->width = width;
00279     xpane->height = height;
00280 
00281     theVisualInfo = xpane->GetVisualInfo();
00282 
00283     //  Create the Pixmap
00284     
00285     xpane->paneXID = XCreatePixmap(display, RootWindow(display,
00286         theVisualInfo->screen), width, height, theVisualInfo->depth);
00287                                 
00288     xpane->Init();
00289 }
00290 
00291 Void XGraphicsSystem::DumpVisualInfo()
00292 {
00293     XVisualInfo *vi;
00294     Int         items, i;
00295 
00296     vi = XGetVisualInfo(display, 0, 0, &items);
00297     
00298     for (i = 0; i < items; i++)
00299     {
00300         printf("default visual %d: class %d, depth %d, id %d\n",
00301                i, vi[i].c_class, vi[i].depth, vi[i].visualid);
00302         printf("masks: %08x %08x %08x\n",
00303                vi[i].red_mask,
00304                vi[i].green_mask,
00305                vi[i].blue_mask);
00306         printf("bits per channel: %d\n",
00307                vi[i].bits_per_rgb);
00308     }   
00309 }
00310 
00311 
00312 // --- SXImage class ----------------------------------------------------------
00313 
00314 
00315 struct SXImage
00316 // container class for XImage to deal with all the X11 shared memory stuff
00317 {
00318     Void                CreateFrom(XPane *xpane, const Image &img);
00319     Void                Destroy();
00320 
00321     Void                WriteImage24(const Image &img, 
00322                             XVisualInfo *theVisualInfo, RGBAPixel *buffer);
00323     Void                WriteImage16(const Image &img, 
00324                             XVisualInfo *theVisualInfo, RGBAPixel *buffer);
00325     Void                WriteImage15(const Image &img, 
00326                             XVisualInfo *theVisualInfo, RGBAPixel *buffer);
00327     
00328     XImage              *ximg;
00329     XGraphicsSystem     *xgs;
00330 #ifdef GCL_XSHM
00331     Bool                isShared;
00332     XShmSegmentInfo     shmInfo;
00333 #endif
00334 };
00335 
00336 
00337 Void SXImage::WriteImage24(const Image &img, XVisualInfo *theVisualInfo,
00338                             RGBAPixel *buffer)
00339 {
00340     Int             x, y;
00341     ULong           pixel;
00342     UInt32          *xbuf = ((UInt32*) ximg->data);
00343     Int             chn[3];
00344 
00345     if (theVisualInfo->red_mask == 0xFF0000
00346         && theVisualInfo->green_mask == 0x00FF00
00347         && theVisualInfo->blue_mask == 0x0000FF)
00348     {
00349         chn[0] = rgba_B; chn[1] = rgba_G; chn[2] = rgba_R;
00350     }
00351     else if (theVisualInfo->red_mask == 0x0000FF
00352         && theVisualInfo->green_mask == 0x00FF00
00353         && theVisualInfo->blue_mask == 0xFF0000)
00354     {
00355         chn[0] = rgba_R; chn[1] = rgba_G; chn[2] = rgba_B;
00356     }
00357     else
00358     {
00359         _Error(String().Printf("Can't handle pixel format: rgb = [%04x:%04x:%04x]",
00360             theVisualInfo->red_mask, theVisualInfo->green_mask,
00361             theVisualInfo->blue_mask));
00362     }
00363 
00364     for (y = img.Height() - 1; y >= 0; y--) 
00365     {
00366         img.GetRGBASpan(y, 0, img.Width(), buffer);
00367         for (x = 0; x < img.Width(); x++) 
00368         {
00369             pixel = 
00370                 buffer[x].ch[chn[0]] | 
00371                 buffer[x].ch[chn[1]] << 8 |
00372                 buffer[x].ch[chn[2]] << 16;
00373             xbuf[x] = pixel;
00374         }
00375         xbuf = (UInt32*) (((Char *) xbuf) + ximg->bytes_per_line);
00376     }
00377 }
00378 
00379 Void SXImage::WriteImage16(const Image &img, XVisualInfo *theVisualInfo,
00380                             RGBAPixel *buffer)
00381 {
00382     Int             x, y;
00383     ULong           pixel;
00384     UInt16          *xbuf = (UInt16*) ximg->data;
00385     Int             chn[3];
00386 
00387     if (theVisualInfo->red_mask == 0xF800
00388         && theVisualInfo->green_mask == 0x07E0
00389         && theVisualInfo->blue_mask == 0x001F)
00390     {
00391         chn[0] = rgba_B; chn[1] = rgba_G; chn[2] = rgba_R;
00392     }
00393     else if (theVisualInfo->red_mask == 0x001F
00394         && theVisualInfo->green_mask == 0x07E0
00395         && theVisualInfo->blue_mask == 0xF800)
00396     {
00397         chn[0] = rgba_R; chn[1] = rgba_G; chn[2] = rgba_B;
00398     }
00399     else
00400     {
00401         _Error(String().Printf("Can't handle pixel format: rgb = [%04x:%04x:%04x]",
00402             theVisualInfo->red_mask, theVisualInfo->green_mask,
00403             theVisualInfo->blue_mask));
00404     }
00405 
00406     for (y = img.Height() - 1; y >= 0; y--) 
00407     {
00408         img.GetRGBASpan(y, 0, img.Width(), buffer);
00409         for (x = 0; x < img.Width(); x++) 
00410         {
00411             pixel = 
00412                 (buffer[x].ch[chn[0]] >> 3) | 
00413                 (buffer[x].ch[chn[1]] >> 2) << 5 |
00414                 (buffer[x].ch[chn[2]] >> 3) << 11;
00415             xbuf[x] = pixel;
00416         }
00417         xbuf = (UInt16*) (((Char *) xbuf) + ximg->bytes_per_line);
00418     }
00419 }
00420 
00421 Void SXImage::WriteImage15(const Image &img, XVisualInfo *theVisualInfo,
00422                             RGBAPixel *buffer)
00423 {
00424     Int             x, y;
00425     ULong           pixel;
00426     UInt16          *xbuf = (UInt16*) ximg->data;
00427     Int             chn[3];
00428 
00429     if (theVisualInfo->red_mask == 0x7C00
00430         && theVisualInfo->green_mask == 0x03E0
00431         && theVisualInfo->blue_mask == 0x001F)
00432     {
00433         chn[0] = rgba_B; chn[1] = rgba_G; chn[2] = rgba_R;
00434     }
00435     else if (theVisualInfo->red_mask == 0x001F
00436         && theVisualInfo->green_mask == 0x03E0
00437         && theVisualInfo->blue_mask == 0x7C00)
00438     {
00439         chn[0] = rgba_R; chn[1] = rgba_G; chn[2] = rgba_B;
00440     }
00441     else
00442     {
00443         _Error(String().Printf("Can't handle pixel format: rgb = [%04x:%04x:%04x]",
00444             theVisualInfo->red_mask, theVisualInfo->green_mask,
00445             theVisualInfo->blue_mask));
00446     }
00447 
00448     for (y = img.Height() - 1; y >= 0; y--) 
00449     {
00450         img.GetRGBASpan(y, 0, img.Width(), buffer);
00451         for (x = 0; x < img.Width(); x++) 
00452         {
00453             pixel = 
00454                 (buffer[x].ch[chn[0]] >> 3) | 
00455                 (buffer[x].ch[chn[1]] >> 3) << 5 |
00456                 (buffer[x].ch[chn[2]] >> 3) << 10;
00457             xbuf[x] = pixel;
00458         }
00459         xbuf = (UInt16*) (((Char *) xbuf) + ximg->bytes_per_line);
00460     }
00461 }
00462 
00463 const Int kLocBufSize = 1024;
00464 
00465 
00466 Void SXImage::CreateFrom(XPane *xpane, const Image &img)
00467 // Convert an Image into the X equivalent so we can blat it to an
00468 // X pixmap/window.
00469 // This is incredibly annoying: we have to support all the different depths
00470 // ourselves, plus different bit arrangements (RGB, BGR, 5/5/5, 5/6/5).
00471 // Theoretically we even have to support GBR, GRB, etc., but I've never 
00472 // seen those in real life...
00473 //
00474 // Currently: supports 24 & 16/15-bit TrueColor "only".
00475 {
00476     XVisualInfo     *theVisualInfo;
00477     RGBAPixel       bufferLocal[kLocBufSize];
00478     RGBAPixel       *buffer;
00479     
00480     theVisualInfo = xpane->GetVisualInfo();
00481     xgs = xpane->xgs;
00482 
00483     // XXX cache ximg here
00484     // need to do it on a per-visual basis: small hash table or summat.
00485 
00486     // first, this is X11, so we have to stuff around with shared memory
00487 
00488 #ifdef GCL_XSHM
00489     isShared = false;
00490     
00491     if (xgs->sharedOn)
00492         do
00493         {
00494             ximg = XShmCreateImage(xgs->display,
00495                                    theVisualInfo->visual,
00496                                    theVisualInfo->depth,
00497                                    ZPixmap, 0, &shmInfo, img.Width(), img.Height());
00498             
00499             shmInfo.shmid = shmget(IPC_PRIVATE, ximg->bytes_per_line * ximg->height,
00500                                         IPC_CREAT | 0777);
00501             if (shmInfo.shmid < 0)
00502             {
00503                 _Warning(String().Printf(
00504                     "(SXImage) Shared memory error %d (shmget)", errno));
00505                 XDestroyImage(ximg);
00506                 xgs->sharedOn = false;
00507                 break;
00508             }
00509 
00510             shmInfo.shmaddr = (char *) shmat(shmInfo.shmid, (Void*) 0, 0);
00511 
00512             if (shmInfo.shmaddr == (Void*)(-1)) 
00513             {
00514                 _Warning("(SXImage) Shared memory error (shmat)");
00515                 XDestroyImage(ximg);
00516                 if (shmctl(shmInfo.shmid, IPC_RMID, 0) < 0)
00517                     _Warning("(SXImage) Shared memory error (shmctl)");
00518                 xgs->sharedOn = false;
00519                 break;
00520             }
00521             ximg->data = shmInfo.shmaddr;
00522 
00523             XSync(xgs->display, False);
00524             // the only way to check if we're on a remote display --
00525             // catch the resulting X11 error!
00526             if (!xgs->remoteChecked)
00527                 if (!gOldHandler)
00528                     gOldHandler = XSetErrorHandler(ShmErrHandler);  
00529 
00530             XShmAttach(xgs->display, &shmInfo);
00531 
00532             if (!xgs->remoteChecked)
00533             {
00534                 XSync(xgs->display, False);
00535                 if (gOldHandler)
00536                     XSetErrorHandler(gOldHandler);
00537                 gOldHandler = 0;
00538                 xgs->remoteChecked = true;
00539                 if (gShmError)
00540                 {
00541                     xgs->sharedOn = false;
00542                     break;
00543                 }
00544             }
00545             isShared = true;
00546         }
00547         while (false);
00548     
00549     if (!isShared)
00550     {
00551 #endif
00552 
00553     ximg = XCreateImage(xgs->display, theVisualInfo->visual, 
00554                         theVisualInfo->depth, 
00555                         ZPixmap, 0, 0, img.Width(), 
00556                         img.Height(), 32, 0);
00557 
00558     ximg->data = (char*) malloc(ximg->bytes_per_line * img.Height());
00559 
00560 #ifdef GCL_XSHM
00561     }
00562 #endif 
00563 
00564 /*
00565  * Only some smug prick from MIT would put this in front of the XImage 
00566  * manipulation routines in Xutil.h:
00567  * 
00568  * These macros are used to give some sugar to the image routines so that
00569  * naive people are more comfortable with them.
00570  * 
00571  */
00572 
00573     // pitiful conversion code
00574     // but then we shouldn't have to be doing this in the first place
00575 
00576     if (img.Width() > kLocBufSize)
00577     {
00578         buffer = new RGBAPixel[img.Width()];
00579         if (!buffer)
00580         {
00581             _Warning("(SXImage) out of memory");
00582             return;
00583         }   
00584     }
00585     else
00586         buffer = bufferLocal;
00587         
00588     
00589     if (theVisualInfo->depth == 24)
00590         WriteImage24(img, theVisualInfo, buffer);
00591     else if (theVisualInfo->depth == 16)
00592         WriteImage16(img, theVisualInfo, buffer);
00593     else if (theVisualInfo->depth == 15)
00594         WriteImage15(img, theVisualInfo, buffer);
00595     else
00596         _Error(String().Printf("(SXImage) unsupported bit depth %d", theVisualInfo->depth));
00597 
00598     if (img.Width() > kLocBufSize)
00599         delete[] buffer;
00600 }
00601 
00602 Void SXImage::Destroy()
00603 {
00604 #ifdef GCL_XSHM
00605     if (isShared)
00606     {
00607         XSync(xgs->display, False);
00608         XShmDetach(xgs->display, &shmInfo);
00609         XDestroyImage(ximg);
00610         if (shmdt(shmInfo.shmaddr) < 0)
00611             _Warning("(SXImage) Shared memory error (shmdt)");
00612         if (shmctl(shmInfo.shmid, IPC_RMID, 0) < 0)
00613             _Warning("(SXImage) Shared memory error (shmctl)");
00614     }
00615     else
00616 #endif
00617         XDestroyImage(ximg);
00618 }
00619 
00620 
00621 // --- XPane class ------------------------------------------------------------
00622 
00623 
00624 XVisualInfo *XPane::sVisualInfo = 0;
00625 
00626 XPane::XPane() : xgs(0)
00627 {
00628 }
00629 
00630 Void XPane::Init()
00631 {
00632 }
00633 
00634 XVisualInfo *XPane::GetVisualInfo()
00635 {
00636     if (!sVisualInfo)
00637     {
00638         Int         items, i, maxDepth = 0;
00639         XVisualInfo *vi;
00640 
00641         vi = XGetVisualInfo(xgs->display, 0, 0, &items);
00642     
00643         if (vi == 0)
00644             _Error("Can't obtain a visual for standard XPane");
00645 
00646         // find max depth visual
00647         for (i = 0; i < items; i++)
00648         {
00649             if (vi[i].depth > maxDepth)
00650             {
00651                 maxDepth = vi[i].depth;
00652                 sVisualInfo = vi + i;
00653             }
00654         }   
00655 
00656     }
00657 
00658     return(sVisualInfo);
00659 }
00660 
00661 Void XPane::CopyFrom(XPane &from)
00662 {
00663     XCopyArea(xgs->display, from.paneXID, paneXID,
00664         from.xgs->theGC, 0, 0, from.width, from.height, 0, 0);
00665 }
00666 
00667 Void XPane::PutImage(Image &img, Int x, Int y)
00668 {
00669     SXImage sximg;
00670 
00671     sximg.CreateFrom(this, img);
00672     XPutImage(xgs->display, paneXID, xgs->theGC, sximg.ximg, 0, 0, x, y,
00673               img.Width(), img.Height());
00674     sximg.Destroy();
00675 }
00676 
00677 XPane::~XPane()
00678 {
00679     DBG_COUT << "freeing XPane " << this << endl;
00680 }
00681 
00682 
00683 // --- XOffscreenPane class ---------------------------------------------------
00684 
00685 XOffscreenPane::XOffscreenPane() : XPane()
00686 {
00687 }
00688 
00689 XOffscreenPane::~XOffscreenPane()
00690 {
00691     if (xgs)
00692     {
00693         DBG_COUT << "freeing pixmap " << this << endl;
00694         XFreePixmap(xgs->display, paneXID);
00695     }
00696 }
00697 
00698 // --- XEventPane class -------------------------------------------------------
00699 
00700 Void XEventPane::XHandleEvent(XEvent *event)
00701 {   
00702     if (event->type == Expose)
00703         HandleExpose();
00704     else if (event->type == KeyPress)   
00705     {
00706         Char    temp[8];
00707         Int     c;
00708         
00709         // pin-heads.
00710         c = XLookupString((XKeyEvent *) event, temp,
00711             sizeof(temp) - 1, NULL, NULL);
00712         temp[c] = 0;
00713         if (c == 1)
00714             HandleKey(temp[0]);
00715     }
00716     else if (event->type == ButtonPress)
00717     {
00718         XButtonEvent    *be = (XButtonEvent*) event;
00719         UInt            keyState = be->state;
00720         Int             modifiers = 0;
00721 
00722         if (keyState & ShiftMask)
00723             modifiers |= wmShift;
00724         if (keyState & ControlMask)
00725             modifiers |= wmControl;
00726         if (keyState & Mod1Mask)
00727             modifiers |= wmAlt;
00728         if (be->button == 1)
00729             modifiers |= wmButton1;
00730         else if (be->button == 2)
00731             modifiers |= wmButton2;
00732         else if (be->button == 3)
00733             modifiers |= wmButton3;
00734         
00735         TrackMouse(be->x, be->y, modifiers);
00736     }
00737 }
00738 
00739 Void XEventPane::GetMouse(Int &x, Int &y, Int &modifiers)
00740 {
00741     UInt keyState;
00742 
00743     xgs->GetMouse(this, &x, &y, &keyState);
00744 
00745     modifiers = 0;
00746     if (keyState & ShiftMask)
00747         modifiers |= wmShift;
00748     if (keyState & ControlMask)
00749         modifiers |= wmControl;
00750     if (keyState & Mod1Mask)
00751         modifiers |= wmAlt;
00752     if (keyState & Button1Mask)
00753         modifiers |= wmButton1;
00754     if (keyState & Button2Mask)
00755         modifiers |= wmButton2;
00756     if (keyState & Button3Mask)
00757         modifiers |= wmButton3;
00758 };
00759 
00760 Void XEventPane::HandleKey(Char c)
00761 {
00762     if (c == 0x1B || c == 'q')
00763         xgs->SignalDone();
00764 }
00765 
00766 Void XEventPane::HandleExpose()
00767 {
00768 }
00769 
00770 Void XEventPane::TrackMouse(Int sx, Int sy, Int modifiers)
00771 {
00772 }
00773 
00774 XEventPane::~XEventPane()
00775 {   
00776     DBG_COUT << "deleting xeventpane " << this << endl;
00777     if (xgs)
00778     {
00779         Int i;
00780         
00781         for (i = 0; i < xgs->paneList.NumItems(); i++)
00782             if (xgs->paneList[i] == this)
00783                 xgs->paneList.Delete(i, 1);
00784                 
00785         XDestroyWindow(xgs->display, paneXID);
00786     }
00787 
00788 }
00789 
00790 Void XEventPane::Resize(Int x, Int y)
00791 {
00792     XResizeWindow(xgs->display, paneXID, x, y);
00793 }
00794 
00795 Void XEventPane::Show()
00796 {
00797     XMapWindow(xgs->display, paneXID);
00798 }
00799 
00800 Void XEventPane::Hide()
00801 {
00802     XUnmapWindow(xgs->display, paneXID);
00803 }
00804 
00805 Void XEventPane::SetTitle(StrConst title)
00806 {
00807     XStoreName(xgs->display, paneXID, title);
00808     XSetIconName(xgs->display, paneXID, title);
00809 }
00810 
00811 // --- XBackedPane class ------------------------------------------------------
00812 
00813 XBackedPane::XBackedPane() : XEventPane(), backPane(0)
00814 {
00815 }
00816 
00817 Void XBackedPane::Attach(XPane *pane)
00818 {
00819     backPane = pane;
00820 }
00821 
00822 Void XBackedPane::HandleExpose()
00823 {
00824     if (backPane)
00825         CopyFrom(*backPane);
00826 }

Generated at Sat Aug 5 00:17:05 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000