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

AltStyle によって変換されたページ (->オリジナル) /