kdeui Library API Documentation

ksharedpixmap.cpp

00001 /* vi: ts=8 sts=4 sw=4
00002  *
00003  * $Id: ksharedpixmap.cpp,v 1.15 2002/08/13 17:10:12 coolo Exp $
00004  *
00005  * This file is part of the KDE libraries.
00006  * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Library General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2 of the License, or (at your option) any later version.
00012  *
00013  * Shared pixmap client for KDE.
00014  */
00015 #include "config.h"
00016 
00017 #include <qrect.h>
00018 #include <qsize.h>
00019 #include <qstring.h>
00020 #include <qpixmap.h>
00021 #include <qwindowdefs.h>
00022 #include <qwidget.h>
00023 
00024 #ifndef Q_WS_QWS
00025 
00026 #include <kapplication.h>
00027 #include <krootprop.h>
00028 #include <ksharedpixmap.h>
00029 #include <kdebug.h>
00030 #include <stdlib.h> // for abs
00031 
00032 #include <X11/Xlib.h>
00033 
00034 // Make sure to include all this X-based shit before we clean up the mess.
00035 // Needed for --enable-final. Not needed by this file itself!
00036 #include <X11/Xutil.h>
00037 #ifdef HAVE_MITSHM
00038 #include <X11/extensions/XShm.h>
00039 #endif
00040 
00041 #include <netwm.h>
00042 
00043 // Clean up the mess
00044 
00045 #undef Bool
00046 #undef Above
00047 #undef Below
00048 #undef KeyPress
00049 #undef KeyRelease
00050 #undef FocusOut
00051 
00056 class KSharedPixmapPrivate
00057 {
00058 public:
00059   Atom pixmap;
00060   Atom target;
00061   Atom selection;
00062   QRect rect;
00063 };
00064 
00065 KSharedPixmap::KSharedPixmap()
00066     : QWidget(0L, "shpixmap comm window")
00067 {
00068     d = new KSharedPixmapPrivate;
00069     init();
00070 }
00071 
00072 
00073 KSharedPixmap::~KSharedPixmap()
00074 {
00075     delete d;
00076 }
00077 
00078 
00079 void KSharedPixmap::init()
00080 {
00081     d->pixmap = XInternAtom(qt_xdisplay(), "PIXMAP", false);
00082     QCString atom;
00083     atom.sprintf("target prop for window %lx", static_cast<unsigned long int>(winId()));
00084     d->target = XInternAtom(qt_xdisplay(), atom.data(), false);
00085     d->selection = None;
00086 }
00087 
00088 
00089 bool KSharedPixmap::isAvailable(const QString & name) const
00090 {
00091     QString str = QString("KDESHPIXMAP:%1").arg(name);
00092     Atom sel = XInternAtom(qt_xdisplay(), str.latin1(), true);
00093     if (sel == None)
00094     return false;
00095     return XGetSelectionOwner(qt_xdisplay(), sel) != None;
00096 }
00097 
00098 
00099 bool KSharedPixmap::loadFromShared(const QString & name, const QRect & rect)
00100 {
00101     if (d->selection != None)
00102     // already active
00103     return false;
00104 
00105     d->rect = rect;
00106     QPixmap::resize(0, 0); // invalidate
00107 
00108     QString str = QString("KDESHPIXMAP:%1").arg(name);
00109     d->selection = XInternAtom(qt_xdisplay(), str.latin1(), true);
00110     if (d->selection == None)
00111     return false;
00112     if (XGetSelectionOwner(qt_xdisplay(), d->selection) == None)
00113     {
00114     d->selection = None;
00115     return false;
00116     }
00117 
00118     XConvertSelection(qt_xdisplay(), d->selection, d->pixmap, d->target,
00119         winId(), CurrentTime);
00120     return true;
00121 }
00122 
00123 
00124 bool KSharedPixmap::x11Event(XEvent *event)
00125 {
00126     if (event->type != SelectionNotify)
00127     return false;
00128 
00129     XSelectionEvent *ev = &event->xselection;
00130     if (ev->selection != d->selection)
00131     return false;
00132 
00133     if ((ev->target != d->pixmap) || (ev->property == None))
00134     {
00135     kdWarning(270) << k_funcinfo << "illegal selection notify event.\n";
00136     d->selection = None;
00137     emit done(false);
00138     return true;
00139     }
00140 
00141     // Read pixmap handle from ev->property
00142 
00143     int dummy, format;
00144     unsigned long nitems, ldummy;
00145     Drawable *pixmap_id;
00146     Atom type;
00147 
00148     XGetWindowProperty(qt_xdisplay(), winId(), ev->property, 0, 1, false,
00149         d->pixmap, &type, &format, &nitems, &ldummy,
00150         (unsigned char **) &pixmap_id);
00151 
00152     if (nitems != 1)
00153     {
00154     kdWarning(270) << k_funcinfo << "could not read property, nitems = " << nitems << "\n";
00155     emit done(false);
00156     return true;
00157     }
00158 
00159     Window root;
00160     unsigned int width, height, udummy;
00161     XGetGeometry(qt_xdisplay(), *pixmap_id, &root, &dummy, &dummy, &width,
00162         &height, &udummy, &udummy);
00163 
00164     if (d->rect.isEmpty())
00165     {
00166     QPixmap::resize(width, height);
00167 #if QT_VERSION < 300
00168     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(),
00169 #else
00170     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00171 #endif
00172         0, 0, width, height, 0, 0);
00173 
00174         XFree(pixmap_id);
00175     XDeleteProperty(qt_xdisplay(), winId(), ev->property);
00176     d->selection = None;
00177     emit done(true);
00178     return true;
00179     }
00180 
00181     // Do some more processing here: Generate a tile that can be used as a
00182     // background tile for the rectangle "rect".
00183 
00184     //Check for origin off screen
00185     QPoint origin(0, 0);
00186     if(  d->rect.topLeft().x() < 0 ||  d->rect.topLeft().y() < 0 ) {
00187         //Save the offset and relocate the rect corners
00188         QPoint tl = d->rect.topLeft();
00189         QPoint br = d->rect.bottomRight();
00190         if( tl.x() < 0 ) {
00191             origin.setX( abs( tl.x() ) );
00192             tl.setX( 0 );
00193         }
00194         if( tl.y() < 0 ) {
00195             origin.setY( abs( tl.y() ) );
00196             tl.setY( 0 );
00197         }
00198         QRect adjustedRect( tl, br );
00199         d->rect = adjustedRect;
00200     }
00201 
00202     unsigned w = d->rect.width(), h = d->rect.height();
00203     unsigned tw = QMIN(width, w), th = QMIN(height, h);
00204     unsigned xa = d->rect.x() % width, ya = d->rect.y() % height;
00205     unsigned t1w = QMIN(width-xa,tw), t1h = QMIN(height-ya,th);
00206 
00207     QPixmap::resize( tw+origin.x(), th+origin.y() );
00208 
00209 #if QT_VERSION < 300
00210     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(),
00211             xa, ya, t1w+origin.x(), t1h+origin.y(), origin.x(), origin.y() );
00212     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(),
00213         0, ya, tw-t1w, t1h, t1w, 0);
00214     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(),
00215         xa, 0, t1w, th-t1h, 0, t1h);
00216     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(),
00217         0, 0, tw-t1w, th-t1h, t1w, t1h);
00218 #else
00219     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00220             xa, ya, t1w+origin.x(), t1h+origin.y(), origin.x(), origin.y() );
00221     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00222         0, ya, tw-t1w, t1h, t1w, 0);
00223     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00224         xa, 0, t1w, th-t1h, 0, t1h);
00225     XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00226         0, 0, tw-t1w, th-t1h, t1w, t1h);
00227 #endif
00228 
00229     XFree(pixmap_id);
00230 
00231     d->selection = None;
00232     XDeleteProperty(qt_xdisplay(), winId(), ev->property);
00233     emit done(true);
00234     return true;
00235 }
00236 
00237 
00238 #include "ksharedpixmap.moc"
00239 #endif
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:15:05 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001