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 }