00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "config.h"
00015
00016 #include <qrect.h>
00017 #include <qsize.h>
00018 #include <qstring.h>
00019 #include <qpixmap.h>
00020 #include <qwindowdefs.h>
00021 #include <qwidget.h>
00022
00023 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00024
00025 #include <kapplication.h>
00026 #include <krootprop.h>
00027 #include <ksharedpixmap.h>
00028 #include <kdebug.h>
00029 #include <stdlib.h>
00030
00031 #include <X11/Xlib.h>
00032
00033
00034
00035 #include <X11/Xutil.h>
00036 #ifdef HAVE_MITSHM
00037 #include <X11/extensions/XShm.h>
00038 #endif
00039
00040 #include <netwm.h>
00041
00042
00043
00044 #undef Bool
00045 #undef Above
00046 #undef Below
00047 #undef KeyPress
00048 #undef KeyRelease
00049 #undef FocusOut
00050
00055 class KSharedPixmapPrivate
00056 {
00057 public:
00058 Atom pixmap;
00059 Atom target;
00060 Atom selection;
00061 QRect rect;
00062 };
00063
00064 KSharedPixmap::KSharedPixmap()
00065 : QWidget(0L, "shpixmap comm window")
00066 {
00067 d = new KSharedPixmapPrivate;
00068 init();
00069 }
00070
00071
00072 KSharedPixmap::~KSharedPixmap()
00073 {
00074 delete d;
00075 }
00076
00077
00078 void KSharedPixmap::init()
00079 {
00080 d->pixmap = XInternAtom(qt_xdisplay(), "PIXMAP", false);
00081 QCString atom;
00082 atom.sprintf("target prop for window %lx", static_cast<unsigned long int>(winId()));
00083 d->target = XInternAtom(qt_xdisplay(), atom.data(), false);
00084 d->selection = None;
00085 }
00086
00087
00088 bool KSharedPixmap::isAvailable(const QString & name) const
00089 {
00090 QString str = QString("KDESHPIXMAP:%1").arg(name);
00091 Atom sel = XInternAtom(qt_xdisplay(), str.latin1(), true);
00092 if (sel == None)
00093 return false;
00094 return XGetSelectionOwner(qt_xdisplay(), sel) != None;
00095 }
00096
00097
00098 bool KSharedPixmap::loadFromShared(const QString & name, const QRect & rect)
00099 {
00100 d->rect = rect;
00101 if (d->selection != None)
00102
00103 return false;
00104
00105 QPixmap::resize(0, 0);
00106
00107 QString str = QString("KDESHPIXMAP:%1").arg(name);
00108 d->selection = XInternAtom(qt_xdisplay(), str.latin1(), true);
00109 if (d->selection == None)
00110 return false;
00111 if (XGetSelectionOwner(qt_xdisplay(), d->selection) == None)
00112 {
00113 d->selection = None;
00114 return false;
00115 }
00116
00117 XConvertSelection(qt_xdisplay(), d->selection, d->pixmap, d->target,
00118 winId(), CurrentTime);
00119 return true;
00120 }
00121
00122
00123 bool KSharedPixmap::x11Event(XEvent *event)
00124 {
00125 if (event->type != SelectionNotify)
00126 return false;
00127
00128 XSelectionEvent *ev = &event->xselection;
00129 if (ev->selection != d->selection)
00130 return false;
00131
00132 if ((ev->target != d->pixmap) || (ev->property == None))
00133 {
00134 kdWarning(270) << k_funcinfo << "illegal selection notify event.\n";
00135 d->selection = None;
00136 emit done(false);
00137 return true;
00138 }
00139
00140
00141
00142 int dummy, format;
00143 unsigned long nitems, ldummy;
00144 Drawable *pixmap_id;
00145 Atom type;
00146
00147 XGetWindowProperty(qt_xdisplay(), winId(), ev->property, 0, 1, false,
00148 d->pixmap, &type, &format, &nitems, &ldummy,
00149 (unsigned char **) &pixmap_id);
00150
00151 if (nitems != 1)
00152 {
00153 kdWarning(270) << k_funcinfo << "could not read property, nitems = " << nitems << "\n";
00154 emit done(false);
00155 return true;
00156 }
00157
00158 Window root;
00159 unsigned int width, height, udummy;
00160 XGetGeometry(qt_xdisplay(), *pixmap_id, &root, &dummy, &dummy, &width,
00161 &height, &udummy, &udummy);
00162
00163 if (d->rect.isEmpty())
00164 {
00165 QPixmap::resize(width, height);
00166 XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00167 0, 0, width, height, 0, 0);
00168
00169 XFree(pixmap_id);
00170 XDeleteProperty(qt_xdisplay(), winId(), ev->property);
00171 d->selection = None;
00172 emit done(true);
00173 return true;
00174 }
00175
00176
00177
00178
00179
00180 QPoint origin(0, 0);
00181 if( d->rect.topLeft().x() < 0 || d->rect.topLeft().y() < 0 ) {
00182
00183 QPoint tl = d->rect.topLeft();
00184 QPoint br = d->rect.bottomRight();
00185 if( tl.x() < 0 ) {
00186 origin.setX( abs( tl.x() ) );
00187 tl.setX( 0 );
00188 }
00189 if( tl.y() < 0 ) {
00190 origin.setY( abs( tl.y() ) );
00191 tl.setY( 0 );
00192 }
00193 QRect adjustedRect( tl, br );
00194 d->rect = adjustedRect;
00195 }
00196
00197 unsigned w = d->rect.width(), h = d->rect.height();
00198 unsigned tw = QMIN(width, w), th = QMIN(height, h);
00199 unsigned xa = d->rect.x() % width, ya = d->rect.y() % height;
00200 unsigned t1w = QMIN(width-xa,tw), t1h = QMIN(height-ya,th);
00201
00202 QPixmap::resize( tw+origin.x(), th+origin.y() );
00203
00204 XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00205 xa, ya, t1w+origin.x(), t1h+origin.y(), origin.x(), origin.y() );
00206 XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00207 0, ya, tw-t1w, t1h, t1w, 0);
00208 XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00209 xa, 0, t1w, th-t1h, 0, t1h);
00210 XCopyArea(qt_xdisplay(), *pixmap_id, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00211 0, 0, tw-t1w, th-t1h, t1w, t1h);
00212
00213 XFree(pixmap_id);
00214
00215 d->selection = None;
00216 XDeleteProperty(qt_xdisplay(), winId(), ev->property);
00217 emit done(true);
00218 return true;
00219 }
00220
00221
00222 #include "ksharedpixmap.moc"
00223 #endif