00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "x11embedcontainer.h"
00023 #include "x11embedpainter.h"
00024 #include "fdoselectionmanager.h"
00025
00026
00027 #include <KDebug>
00028
00029
00030 #include <QtCore/QTime>
00031 #include <QtCore/QTimer>
00032 #include <QtGui/QPainter>
00033 #include <QtGui/QPaintEngine>
00034 #include <QtGui/QX11Info>
00035
00036
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
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
00125 } else {
00126
00127 }
00128 #endif
00129
00130
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
00152
00153
00154
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
00190
00191 QPixmap pixmap(size());
00192 if (pixmap.paintEngine()->type() != QPaintEngine::X11) {
00193 #if defined(HAVE_XCOMPOSITE)
00194
00195
00196 Display *dpy = x11Info().display();
00197
00198
00199
00200 Pixmap pixmap = XCompositeNameWindowPixmap(dpy, clientWinId());
00201 XImage *ximage = XGetImage(dpy, pixmap, 0, 0, width(), height(), AllPlanes, ZPixmap);
00202 XFreePixmap(dpy, pixmap);
00203
00204 if (!ximage)
00205 return;
00206
00207
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"