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 #ifdef Q_WS_X11
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 unsigned char *pixmap_id = 0;
00145 Atom type;
00146
00147 XGetWindowProperty(qt_xdisplay(), winId(), ev->property, 0, 1, false,
00148 d->pixmap, &type, &format, &nitems, &ldummy,
00149 &pixmap_id);
00150
00151 if (nitems != 1 || !pixmap_id)
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 void *drawable_id = (void *) pixmap_id;
00161 Drawable pixmap = *(Drawable*) drawable_id;
00162
00163 Status status = XGetGeometry(qt_xdisplay(), pixmap, &root, &dummy, &dummy, &width, &height, &udummy, &udummy);
00164
00165 if (status == BadDrawable)
00166 return false;
00167
00168 if (d->rect.isEmpty())
00169 {
00170 QPixmap::resize(width, height);
00171 XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
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
00182
00183
00184
00185 QPoint origin(0, 0);
00186 if( d->rect.topLeft().x() < 0 || d->rect.topLeft().y() < 0 ) {
00187
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 XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00210 xa, ya, t1w+origin.x(), t1h+origin.y(), origin.x(), origin.y() );
00211 XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00212 0, ya, tw-t1w, t1h, t1w, 0);
00213 XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00214 xa, 0, t1w, th-t1h, 0, t1h);
00215 XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
00216 0, 0, tw-t1w, th-t1h, t1w, t1h);
00217
00218 XFree(pixmap_id);
00219
00220 d->selection = None;
00221 XDeleteProperty(qt_xdisplay(), winId(), ev->property);
00222 emit done(true);
00223 return true;
00224 }
00225
00226
00227 #include "ksharedpixmap.moc"
00228 #endif