Plasma
windoweffects.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright 2009 Marco Martin <notmart@gmail.com> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU Library General Public License as 00006 * published by the Free Software Foundation; either version 2, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this program; if not, write to the 00016 * Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "windoweffects.h" 00021 #include <QVarLengthArray> 00022 00023 #include <kwindowsystem.h> 00024 00025 #include "theme.h" 00026 00027 #ifdef Q_WS_X11 00028 #include <X11/Xlib.h> 00029 #include <X11/Xatom.h> 00030 #include <X11/Xutil.h> 00031 #include <QX11Info> 00032 00033 #define DASHBOARD_WIN_NAME "dashboard" 00034 #define DASHBOARD_WIN_CLASS "dashboard" 00035 #endif 00036 00037 namespace Plasma 00038 { 00039 00040 namespace WindowEffects 00041 { 00042 00043 //FIXME: check if this works for any atom? 00044 bool isEffectAvailable(Effect effect) 00045 { 00046 if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) { 00047 return false; 00048 } 00049 #ifdef Q_WS_X11 00050 QString effectName; 00051 00052 switch (effect) { 00053 case Slide: 00054 effectName = "_KDE_SLIDE"; 00055 break; 00056 case WindowPreview: 00057 effectName = "_KDE_WINDOW_PREVIEW"; 00058 break; 00059 case PresentWindows: 00060 effectName = "_KDE_PRESENT_WINDOWS_DESKTOP"; 00061 break; 00062 case PresentWindowsGroup: 00063 effectName = "_KDE_PRESENT_WINDOWS_GROUP"; 00064 break; 00065 case HighlightWindows: 00066 effectName = "_KDE_WINDOW_HIGHLIGHT"; 00067 break; 00068 case OverrideShadow: 00069 effectName = "_KDE_SHADOW_OVERRIDE"; 00070 break; 00071 case BlurBehind: 00072 effectName = "_KDE_NET_WM_BLUR_BEHIND_REGION"; 00073 break; 00074 case Dashboard: 00075 // TODO: Better namespacing for atoms 00076 effectName = "_WM_EFFECT_KDE_DASHBOARD"; 00077 break; 00078 default: 00079 return false; 00080 } 00081 00082 // hackish way to find out if KWin has the effect enabled, 00083 // TODO provide proper support 00084 Display *dpy = QX11Info::display(); 00085 Atom atom = XInternAtom(dpy, effectName.toLatin1(), False); 00086 int cnt; 00087 Atom *list = XListProperties(dpy, DefaultRootWindow(dpy), &cnt); 00088 if (list != NULL) { 00089 bool ret = (qFind(list, list + cnt, atom) != list + cnt); 00090 XFree(list); 00091 return ret; 00092 } 00093 #endif 00094 return false; 00095 } 00096 00097 void slideWindow(WId id, Plasma::Location location, int offset) 00098 { 00099 #ifdef Q_WS_X11 00100 Display *dpy = QX11Info::display(); 00101 Atom atom = XInternAtom( dpy, "_KDE_SLIDE", False ); 00102 QVarLengthArray<long, 1024> data(2); 00103 00104 data[0] = offset; 00105 00106 switch (location) { 00107 case LeftEdge: 00108 data[1] = 0; 00109 break; 00110 case TopEdge: 00111 data[1] = 1; 00112 break; 00113 case RightEdge: 00114 data[1] = 2; 00115 break; 00116 case BottomEdge: 00117 data[1] = 3; 00118 default: 00119 break; 00120 } 00121 00122 if (location == Desktop || location == Floating) { 00123 XDeleteProperty(dpy, id, atom); 00124 } else { 00125 XChangeProperty(dpy, id, atom, atom, 32, PropModeReplace, 00126 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00127 } 00128 #endif 00129 } 00130 00131 void slideWindow(QWidget *widget, Plasma::Location location) 00132 { 00133 #ifdef Q_WS_X11 00134 Display *dpy = QX11Info::display(); 00135 Atom atom = XInternAtom( dpy, "_KDE_SLIDE", False ); 00136 QVarLengthArray<long, 1024> data(2); 00137 00138 switch (location) { 00139 case LeftEdge: 00140 data[0] = widget->geometry().left(); 00141 data[1] = 0; 00142 break; 00143 case TopEdge: 00144 data[0] = widget->geometry().top(); 00145 data[1] = 1; 00146 break; 00147 case RightEdge: 00148 data[0] = widget->geometry().right(); 00149 data[1] = 2; 00150 break; 00151 case BottomEdge: 00152 data[0] = widget->geometry().bottom(); 00153 data[1] = 3; 00154 default: 00155 break; 00156 } 00157 00158 if (location == Desktop || location == Floating) { 00159 XDeleteProperty(dpy, widget->effectiveWinId(), atom); 00160 } else { 00161 XChangeProperty(dpy, widget->effectiveWinId(), atom, atom, 32, PropModeReplace, 00162 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00163 } 00164 #endif 00165 } 00166 00167 QList<QSize> windowSizes(const QList<WId> &ids) 00168 { 00169 QList<QSize> windowSizes; 00170 foreach (WId id, ids) { 00171 #ifdef Q_WS_X11 00172 if (id > 0) { 00173 KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry|NET::WMFrameExtents); 00174 windowSizes.append(info.frameGeometry().size()); 00175 } else { 00176 windowSizes.append(QSize()); 00177 } 00178 #else 00179 windowSizes.append(QSize()); 00180 #endif 00181 } 00182 return windowSizes; 00183 } 00184 00185 void showWindowThumbnails(WId parent, const QList<WId> &windows, const QList<QRect> &rects) 00186 { 00187 if (windows.size() != rects.size()) { 00188 return; 00189 } 00190 #ifdef Q_WS_X11 00191 Display *dpy = QX11Info::display(); 00192 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_PREVIEW", False); 00193 if (windows.isEmpty()) { 00194 XDeleteProperty(dpy, parent, atom); 00195 return; 00196 } 00197 00198 int numWindows = windows.size(); 00199 00200 QVarLengthArray<long, 1024> data(1 + (6 * numWindows)); 00201 data[0] = numWindows; 00202 00203 QList<WId>::const_iterator windowsIt; 00204 QList<QRect>::const_iterator rectsIt = rects.constBegin(); 00205 int i = 0; 00206 for (windowsIt = windows.constBegin(); windowsIt != windows.constEnd(); ++windowsIt) { 00207 00208 const int start = (i * 6) + 1; 00209 const QRect thumbnailRect = (*rectsIt); 00210 00211 data[start] = 5; 00212 data[start+1] = (*windowsIt); 00213 data[start+2] = thumbnailRect.x(); 00214 data[start+3] = thumbnailRect.y(); 00215 data[start+4] = thumbnailRect.width(); 00216 data[start+5] = thumbnailRect.height(); 00217 ++rectsIt; 00218 ++i; 00219 } 00220 00221 XChangeProperty(dpy, parent, atom, atom, 32, PropModeReplace, 00222 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00223 #endif 00224 } 00225 00226 void presentWindows(WId controller, const QList<WId> &ids) 00227 { 00228 #ifdef Q_WS_X11 00229 const int numWindows = ids.count(); 00230 QVarLengthArray<long, 32> data(numWindows); 00231 int actualCount = 0; 00232 00233 for (int i = 0; i < numWindows; ++i) { 00234 data[i] = ids.at(i); 00235 ++actualCount; 00236 00237 } 00238 00239 if (actualCount != numWindows) { 00240 data.resize(actualCount); 00241 } 00242 00243 if (!data.isEmpty()) { 00244 Display *dpy = QX11Info::display(); 00245 Atom atom = XInternAtom(dpy, "_KDE_PRESENT_WINDOWS_GROUP", False); 00246 XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace, 00247 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00248 } 00249 #endif 00250 } 00251 00252 void presentWindows(WId controller, int desktop) 00253 { 00254 #ifdef Q_WS_X11 00255 QVarLengthArray<long, 32> data(1); 00256 data[0] = desktop; 00257 Display *dpy = QX11Info::display(); 00258 Atom atom = XInternAtom(dpy, "_KDE_PRESENT_WINDOWS_DESKTOP", False); 00259 XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace, 00260 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00261 #endif 00262 } 00263 00264 void highlightWindows(WId controller, const QList<WId> &ids) 00265 { 00266 #ifdef Q_WS_X11 00267 const int numWindows = ids.count(); 00268 Display *dpy = QX11Info::display(); 00269 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_HIGHLIGHT", False); 00270 00271 if (numWindows == 0) { 00272 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_HIGHLIGHT", False); 00273 XDeleteProperty(dpy, controller, atom); 00274 } 00275 00276 QVarLengthArray<long, 32> data(numWindows); 00277 int actualCount = 0; 00278 00279 for (int i = 0; i < numWindows; ++i) { 00280 data[i] = ids.at(i); 00281 ++actualCount; 00282 00283 } 00284 00285 if (actualCount != numWindows) { 00286 data.resize(actualCount); 00287 } 00288 00289 if (!data.isEmpty()) { 00290 XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace, 00291 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00292 } 00293 #endif 00294 } 00295 00296 void overrideShadow(WId window, bool override) 00297 { 00298 #ifdef Q_WS_X11 00299 Display *dpy = QX11Info::display(); 00300 Atom atom = XInternAtom( dpy, "_KDE_SHADOW_OVERRIDE", False ); 00301 QVarLengthArray<long, 1024> data(1); 00302 data[0] = 1; 00303 00304 if (!override) { 00305 XDeleteProperty(dpy, window, atom); 00306 } else { 00307 XChangeProperty(dpy, window, atom, atom, 32, PropModeReplace, 00308 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00309 } 00310 #endif 00311 } 00312 00313 void enableBlurBehind(WId window, bool enable, const QRegion ®ion) 00314 { 00315 #ifdef Q_WS_X11 00316 Display *dpy = QX11Info::display(); 00317 Atom atom = XInternAtom(dpy, "_KDE_NET_WM_BLUR_BEHIND_REGION", False); 00318 00319 if (enable) { 00320 QVector<QRect> rects = region.rects(); 00321 QVector<unsigned long> data; 00322 foreach (const QRect &r, rects) { 00323 data << r.x() << r.y() << r.width() << r.height(); 00324 } 00325 00326 XChangeProperty(dpy, window, atom, XA_CARDINAL, 32, PropModeReplace, 00327 reinterpret_cast<const unsigned char *>(data.constData()), data.size()); 00328 } else { 00329 XDeleteProperty(dpy, window, atom); 00330 } 00331 #endif 00332 } 00333 00334 void markAsDashboard(WId window) 00335 { 00336 #ifdef Q_WS_X11 00337 XClassHint classHint; 00338 classHint.res_name = DASHBOARD_WIN_NAME; 00339 classHint.res_class = DASHBOARD_WIN_CLASS; 00340 XSetClassHint(QX11Info::display(), window, &classHint); 00341 #endif 00342 } 00343 00344 } 00345 00346 }
KDE 4.6 API Reference