• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Applets

x11embedcontainer.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   x11embedcontainer.cpp                                                 *
00003  *                                                                         *
00004  *   Copyright (C) 2008 Jason Stubbs <jasonbstubbs@gmail.com>              *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  *   This program is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU General Public License for more details.                          *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU General Public License     *
00017  *   along with this program; if not, write to the                         *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
00020  ***************************************************************************/
00021 
00022 #include "x11embedcontainer.h"
00023 #include "x11embedpainter.h"
00024 #include "fdoselectionmanager.h"
00025 
00026 // KDE
00027 #include <KDebug>
00028 
00029 // Qt
00030 #include <QtCore/QTime>
00031 #include <QtCore/QTimer>
00032 #include <QtGui/QPainter>
00033 #include <QtGui/QPaintEngine>
00034 #include <QtGui/QX11Info>
00035 
00036 // Xlib
00037 #include <config-X11.h>
00038 
00039 #include <X11/Xlib.h>
00040 #include <X11/extensions/Xrender.h>
00041 
00042 #ifdef HAVE_XCOMPOSITE
00043 #  include <X11/extensions/Xcomposite.h>
00044 #endif
00045 
00046 
00047 namespace SystemTray
00048 {
00049 
00050 class X11EmbedContainer::Private
00051 {
00052 public:
00053     Private(X11EmbedContainer *q)
00054         : q(q),
00055           picture(None),
00056           updatesEnabled(true)
00057     {
00058     }
00059 
00060     ~Private()
00061     {
00062         if (picture) {
00063            XRenderFreePicture(QX11Info::display(), picture);
00064         }
00065     }
00066 
00067     X11EmbedContainer *q;
00068 
00069     XWindowAttributes attr;
00070     Picture picture;
00071     bool updatesEnabled;
00072 };
00073 
00074 
00075 X11EmbedContainer::X11EmbedContainer(QWidget *parent)
00076     : QX11EmbedContainer(parent),
00077       d(new Private(this))
00078 {
00079     connect(this, SIGNAL(clientIsEmbedded()),
00080             this, SLOT(ensureValidSize()));
00081 }
00082 
00083 
00084 X11EmbedContainer::~X11EmbedContainer()
00085 {
00086     FdoSelectionManager::manager()->removeDamageWatch(this);
00087     delete d;
00088 }
00089 
00090 
00091 void X11EmbedContainer::embedSystemTrayClient(WId clientId)
00092 {
00093     Display *display = QX11Info::display();
00094 
00095     if (!XGetWindowAttributes(display, clientId, &d->attr)) {
00096         emit error(QX11EmbedContainer::Unknown);
00097         return;
00098     }
00099 
00100     XSetWindowAttributes sAttr;
00101     sAttr.background_pixel = BlackPixel(display, DefaultScreen(display));
00102     sAttr.border_pixel = BlackPixel(display, DefaultScreen(display));
00103     sAttr.colormap = d->attr.colormap;
00104 
00105     WId parentId = parentWidget() ? parentWidget()->winId() : DefaultRootWindow(display);
00106     Window winId = XCreateWindow(display, parentId, 0, 0, d->attr.width, d->attr.height,
00107                                  0, d->attr.depth, InputOutput, d->attr.visual,
00108                                  CWBackPixel | CWBorderPixel | CWColormap, &sAttr);
00109     create(winId);
00110 
00111 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XFIXES) && defined(HAVE_XDAMAGE)
00112     XRenderPictFormat *format = XRenderFindVisualFormat(display, d->attr.visual);
00113     if (format && format->type == PictTypeDirect && format->direct.alphaMask &&
00114         FdoSelectionManager::manager()->haveComposite())
00115     {
00116         // Redirect ARGB windows to offscreen storage so we can composite them ourselves
00117         XRenderPictureAttributes attr;
00118         attr.subwindow_mode = IncludeInferiors;
00119 
00120         d->picture = XRenderCreatePicture(display, clientId, format, CPSubwindowMode, &attr);
00121         XCompositeRedirectSubwindows(display, winId, CompositeRedirectManual);
00122         FdoSelectionManager::manager()->addDamageWatch(this, clientId);
00123 
00124         //kDebug() << "Embedded client uses an ARGB visual -> compositing.";
00125     } else {
00126         //kDebug() << "Embedded client is not using an ARGB visual.";
00127     }
00128 #endif
00129 
00130     // repeat everything from QX11EmbedContainer's ctor that might be relevant
00131     setFocusPolicy(Qt::StrongFocus);
00132     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00133     setAcceptDrops(true);
00134     setEnabled(false);
00135 
00136     XSelectInput(display, winId,
00137                  KeyPressMask | KeyReleaseMask |
00138                  ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
00139                  KeymapStateMask |
00140                  PointerMotionMask |
00141                  EnterWindowMask | LeaveWindowMask |
00142                  FocusChangeMask |
00143                  ExposureMask |
00144                  StructureNotifyMask |
00145                  SubstructureNotifyMask);
00146 
00147     XFlush(display);
00148 
00149     embedClient(clientId);
00150 
00151     // FIXME: This checks that the client is still valid. Qt won't pick it up
00152     // if the client closes before embedding completes. However, what happens
00153     // if the close happens after this point? Should checks happen on a timer
00154     // until embedding completes perhaps?
00155     if (!XGetWindowAttributes(QX11Info::display(), clientId, &d->attr)) {
00156         emit error(QX11EmbedContainer::Unknown);
00157         return;
00158     }
00159 }
00160 
00161 
00162 void X11EmbedContainer::ensureValidSize()
00163 {
00164     QSize s = QSize(qBound(minimumSize().width(), width(), maximumSize().width()),
00165                     qBound(minimumSize().height(), height(), maximumSize().height()));
00166     resize(s);
00167 }
00168 
00169 
00170 void X11EmbedContainer::setUpdatesEnabled(bool enabled)
00171 {
00172     d->updatesEnabled = enabled;
00173 }
00174 
00175 
00176 void X11EmbedContainer::paintEvent(QPaintEvent *event)
00177 {
00178     Q_UNUSED(event);
00179 
00180     if (!d->updatesEnabled) {
00181         return;
00182     }
00183 
00184     if (!d->picture) {
00185         FdoSelectionManager::painter()->updateContainer(this);
00186         return;
00187     }
00188 
00189     // Taking a detour via a QPixmap is unfortunately the only way we can get
00190     // the window contents into Qt's backing store.
00191     QPixmap pixmap(size());
00192     if (pixmap.paintEngine()->type() != QPaintEngine::X11) {
00193 #if defined(HAVE_XCOMPOSITE)
00194         // If we're using the raster or OpenGL graphics systems, a QPixmap isn't an X pixmap,
00195         // so we have to get the window contents into a QImage and then draw that.
00196         Display *dpy = x11Info().display();
00197 
00198         // XXX We really should keep a cached copy of the image client side, and only
00199         //     update it in response to a damage event.
00200         Pixmap pixmap = XCompositeNameWindowPixmap(dpy, clientWinId());
00201         XImage *ximage = XGetImage(dpy, pixmap, 0, 0, width(), height(), AllPlanes, ZPixmap);
00202         XFreePixmap(dpy, pixmap);
00203         // We actually check if we get the image from X11 since clientWinId can be any arbiter window (with crazy XWindowAttribute and the pixmap associated is bad)
00204         if (!ximage)
00205             return;
00206         // This is safe to do since we only composite ARGB32 windows, and PictStandardARGB32
00207         // matches QImage::Format_ARGB32_Premultiplied.
00208         QImage image((const uchar*)ximage->data, ximage->width, ximage->height, ximage->bytes_per_line,
00209                      QImage::Format_ARGB32_Premultiplied);
00210 
00211         QPainter p(this);
00212         p.drawImage(0, 0, image);
00213 
00214         XDestroyImage(ximage);
00215 #endif
00216     } else {
00217         pixmap.fill(Qt::transparent);
00218 
00219         XRenderComposite(x11Info().display(), PictOpSrc, d->picture, None, pixmap.x11PictureHandle(),
00220                          0, 0, 0, 0, 0, 0, width(), height());
00221 
00222         QPainter p(this);
00223         p.drawPixmap(0, 0, pixmap);
00224     }
00225 }
00226 
00227 void X11EmbedContainer::setBackgroundPixmap(QPixmap background)
00228 {
00229     if (!clientWinId()) {
00230         return;
00231     }
00232 
00233     Display *display = QX11Info::display();
00234     Pixmap bg = XCreatePixmap(display, clientWinId(), width(), height(), d->attr.depth);
00235 
00236     XRenderPictFormat *format = XRenderFindVisualFormat(display, d->attr.visual);
00237     Picture picture = XRenderCreatePicture(display, bg, format, 0, 0);
00238 
00239     XRenderComposite(display, PictOpSrc, background.x11PictureHandle(),
00240                      None, picture, 0, 0, 0, 0, 0, 0, width(), height());
00241 
00242     XSetWindowBackgroundPixmap(display, clientWinId(), bg);
00243 
00244     XRenderFreePicture(display, picture);
00245     XFreePixmap(display, bg);
00246 
00247     XClearArea(display, clientWinId(), 0, 0, 0, 0, True);
00248 }
00249 
00250 }
00251 
00252 #include "x11embedcontainer.moc"

Applets

Skip menu "Applets"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal