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 }