00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "windowpreview_p.h"
00022
00023 #include <QPainter>
00024 #include <QVarLengthArray>
00025
00026 #include <kwindowsystem.h>
00027 #include <kdebug.h>
00028
00029 #include <plasma/framesvg.h>
00030
00031 #ifdef Q_WS_X11
00032 #include <QX11Info>
00033
00034 #include <X11/Xlib.h>
00035 #include <fixx11h.h>
00036 #endif
00037
00038 namespace Plasma {
00039
00040 bool WindowPreview::previewsAvailable()
00041 {
00042 if (!KWindowSystem::compositingActive()) {
00043 return false;
00044 }
00045 #ifdef Q_WS_X11
00046
00047
00048 Display *dpy = QX11Info::display();
00049 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_PREVIEW", False);
00050 int cnt;
00051 Atom *list = XListProperties(dpy, DefaultRootWindow(dpy), &cnt);
00052 if (list != NULL) {
00053 bool ret = (qFind(list, list + cnt, atom) != list + cnt);
00054 XFree(list);
00055 return ret;
00056 }
00057 #endif
00058 return false;
00059 }
00060
00061 WindowPreview::WindowPreview(QWidget *parent)
00062 : QWidget(parent)
00063 {
00064 m_background = new Plasma::FrameSvg(this);
00065 m_background->setImagePath("widgets/frame");
00066 m_background->setElementPrefix("raised");
00067 }
00068
00069 void WindowPreview::setWindowIds(const QList<WId> wids)
00070 {
00071 if (!previewsAvailable()) {
00072 setMinimumSize(0,0);
00073 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00074 ids.clear();
00075 return;
00076 }
00077 ids = wids;
00078 readWindowSizes();
00079 QSize s(sizeHint());
00080 if (s.isValid()) {
00081 setFixedSize(sizeHint());
00082 }
00083 }
00084
00085 QList<WId> WindowPreview::windowIds() const
00086 {
00087 return ids;
00088 }
00089
00090 QSize WindowPreview::sizeHint() const
00091 {
00092 if (ids.size() == 0) {
00093 return QSize();
00094 }
00095 if (!windowSizes.size() == 0) {
00096 readWindowSizes();
00097 }
00098
00099 int maxHeight = 0;
00100 int totalWidth = 0;
00101 foreach (QSize s, windowSizes) {
00102 if (s.height() > maxHeight) {
00103 maxHeight = s.height();
00104 }
00105
00106 totalWidth += s.width();
00107 }
00108
00109 QSize s(totalWidth, maxHeight);
00110
00111 qreal left, top, right, bottom;
00112 m_background->getMargins(left, top, right, bottom);
00113
00114 s.scale(WINDOW_WIDTH*windowSizes.size(), WINDOW_HEIGHT, Qt::KeepAspectRatio);
00115
00116 s = s + QSize(left+right+WINDOW_MARGIN*(windowSizes.size()-1), top+bottom);
00117
00118 return s;
00119 }
00120
00121 void WindowPreview::readWindowSizes() const
00122 {
00123 windowSizes.clear();
00124 foreach (WId id, ids) {
00125 #ifdef Q_WS_X11
00126 if (id > 0) {
00127 KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry|NET::WMFrameExtents);
00128 windowSizes.append(info.frameGeometry().size());
00129 } else {
00130 windowSizes.append(QSize());
00131 }
00132 #else
00133 windowSizes.append(QSize());
00134 #endif
00135 }
00136 }
00137
00138 bool WindowPreview::isEmpty() const
00139 {
00140 foreach (WId id, ids) {
00141 if (id != 0) {
00142 return false;
00143 }
00144 }
00145
00146 return true;
00147 }
00148
00149 void WindowPreview::setInfo()
00150 {
00151 #ifdef Q_WS_X11
00152 Display *dpy = QX11Info::display();
00153 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_PREVIEW", False);
00154 if (isEmpty()) {
00155 XDeleteProperty(dpy, parentWidget()->winId(), atom);
00156 return;
00157 }
00158
00159 if (windowSizes.size() == 0) {
00160 readWindowSizes();
00161 }
00162
00163 if (windowSizes.size() == 0) {
00164 XDeleteProperty(dpy, parentWidget()->winId(), atom);
00165 return;
00166 }
00167
00168 Q_ASSERT(parentWidget()->isWindow());
00169
00170 QSize thumbnailSize = sizeHint();
00171 thumbnailSize.scale(size(), Qt::KeepAspectRatio);
00172 m_background->resizeFrame(thumbnailSize);
00173
00174 qreal left, top, right, bottom;
00175 m_background->getMargins(left, top, right, bottom);
00176 QRect thumbnailRect = geometry().adjusted(left, top, -right, -bottom);
00177
00178 const int numWindows = ids.size();
00179
00180 m_thumbnailRects.clear();
00181 int x = thumbnailRect.x();
00182
00183 foreach (QSize s, windowSizes) {
00184 s.scale((qreal)(thumbnailRect.width()-WINDOW_MARGIN*(numWindows-1))/numWindows, thumbnailRect.height(), Qt::KeepAspectRatio);
00185 int y = thumbnailRect.y() + (thumbnailRect.height() - s.height())/2;
00186 m_thumbnailRects.append(QRect(QPoint(x,y), s));
00187 x += s.width() + WINDOW_MARGIN;
00188 }
00189
00190 QVarLengthArray<long, 1024> data(1 + (6 * numWindows));
00191 data[0] = numWindows;
00192
00193 for (int i = 0; i < numWindows; ++i) {
00194 const int start = (i * 6) + 1;
00195 const QRect thumbnailRect = m_thumbnailRects[i];
00196
00197 data[start] = 5;
00198 data[start+1] = ids[i];
00199 data[start+2] = thumbnailRect.x();
00200 data[start+3] = thumbnailRect.y();
00201 data[start+4] = thumbnailRect.width();
00202 data[start+5] = thumbnailRect.height();
00203 }
00204
00205 XChangeProperty(dpy, parentWidget()->winId(), atom, atom, 32, PropModeReplace,
00206 reinterpret_cast<unsigned char *>(data.data()), data.size());
00207 #endif
00208 }
00209
00210 void WindowPreview::paintEvent(QPaintEvent *e)
00211 {
00212 Q_UNUSED(e)
00213 #ifdef Q_WS_X11
00214 QPainter painter(this);
00215
00216 qreal left, top, right, bottom;
00217 m_background->getMargins(left, top, right, bottom);
00218
00219 foreach (QRect r, m_thumbnailRects) {
00220 kWarning()<<r;
00221 m_background->resizeFrame(r.size()+QSize(left+right, top+bottom));
00222 m_background->paintFrame(&painter, r.topLeft()-pos()-QPoint(left,top));
00223 }
00224 #endif
00225 }
00226
00227 }
00228
00229 #include "windowpreview_p.moc"