ksharedpixmap.cpp
00001 /* vi: ts=8 sts=4 sw=4 00002 * 00003 * 00004 * This file is part of the KDE libraries. 00005 * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org> 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * Shared pixmap client for KDE. 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> // for abs 00030 00031 #include <X11/Xlib.h> 00032 00033 // Make sure to include all this X-based shit before we clean up the mess. 00034 // Needed for --enable-final. Not needed by this file itself! 00035 #include <X11/Xutil.h> 00036 #ifdef HAVE_MITSHM 00037 #include <X11/extensions/XShm.h> 00038 #endif 00039 00040 #include <netwm.h> 00041 00042 // Clean up the mess 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 // already active 00103 return false; 00104 00105 QPixmap::resize(0, 0); // invalidate 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 // Read pixmap handle from ev->property 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 // 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 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