// Copyright (C) 1996 Keith Whitwell. // This file may only be copied under the terms of the GNU Library General // Public License - see the file COPYING in the lib3d distribution. #include #include #include #include #include #include #include #include #include #include "XHandler.H" // This is a completely private class. Noone else knows about it. // Shhh... class XShmDevice : public XDevice { public: XShmDevice( Exemplar ); XShmDevice( uint width, uint height, uint depth ); XShmDevice( Display *, Window ); ~XShmDevice(); const char *getName() const { return "XShmDevice"; } void notifyResize(); void notifyExpose( uint, uint, uint, uint ); void swapBuffers(); protected: Device *clone( uint width, uint height, uint depth ); XDevice *clone( Display *, Window ); int estimateSpeed() const { return 10; } void createImage(); void destroyImage(); private: XShmSegmentInfo shmInfo; XImage *xImage; int attached; }; // This is how we advertize it. XShmDevice::XShmDevice( Exemplar e ) : XDevice(e), xImage(0), attached(false) { Device::registerChildClass( this ); XDevice::registerChildClass( this ); } Device * XShmDevice::clone( uint width, uint height, uint depth ) { return new XShmDevice( width, height, depth ); } XDevice * XShmDevice::clone( Display *display, Window window ) { return new XShmDevice( display, window ); } static XShmDevice advertisement( Device::exemplar ); // The real implementation follows: extern "C" Bool XShmQueryExtension( Display * ); XShmDevice::XShmDevice(uint width, uint height, uint min_depth) : XDevice(width, height, min_depth), xImage(0), // imageWidth(this->width), // imageHeight(this->height), attached(false) { if (isBad()) return; createImage(); } XShmDevice::XShmDevice(Display *display, Window window) : XDevice(display, window), xImage(0), // imageWidth(width), // imageHeight(height), attached(false) { if (isBad()) return; createImage(); } void XShmDevice::createImage() { shmInfo.shmid = -1; shmInfo.shmaddr = (char *)-1; shmInfo.readOnly = False; XHandler::set( display ); if (XShmQueryExtension(display) == false || (xImage = XShmCreateImage(display, visual, depth, ZPixmap, NULL, &shmInfo, width, height )) == 0 || (shmInfo.shmid = shmget(IPC_PRIVATE, width * height * pixelSize, IPC_CREAT|0777 )) < 0 || (shmInfo.shmaddr = xImage->data = (char *)shmat( shmInfo.shmid, 0, 0 )) == (char *)-1 || (attached = XShmAttach( display, &shmInfo )) == 0 || XHandler::unset()) { debug() << "Failed to create XShmDevice" << endlog; setBad(); XHandler::unset(); return; } shmctl( shmInfo.shmid, IPC_RMID, 0 ); // Make it private. frameBuf = (uchar *)xImage->data; } void XShmDevice::destroyImage() { if (isActive()) { if (xImage != 0) XDestroyImage( xImage ); if (shmInfo.shmid >= 0) shmctl( shmInfo.shmid, IPC_RMID, 0 ); if (shmInfo.shmaddr != (char *)-1) shmdt( shmInfo.shmaddr ); if (attached) XShmDetach(display, &shmInfo); } } void XShmDevice::notifyResize() { XDevice::notifyResize(); if (1) { destroyImage(); createImage(); if_debug debug() << *this << endl; } } void XShmDevice::notifyExpose( uint xn, uint yn, uint xx, uint yx ) { if (xx <= width && yx <= height) { if_debug { debug() << "Exposing x:"<