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, 2> 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, 2> data(2); 00137 data[0] = -1; 00138 00139 switch (location) { 00140 case LeftEdge: 00141 data[1] = 0; 00142 break; 00143 case TopEdge: 00144 data[1] = 1; 00145 break; 00146 case RightEdge: 00147 data[1] = 2; 00148 break; 00149 case BottomEdge: 00150 data[1] = 3; 00151 default: 00152 break; 00153 } 00154 00155 if (location == Desktop || location == Floating) { 00156 XDeleteProperty(dpy, widget->effectiveWinId(), atom); 00157 } else { 00158 XChangeProperty(dpy, widget->effectiveWinId(), atom, atom, 32, PropModeReplace, 00159 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00160 } 00161 #endif 00162 } 00163 00164 QList<QSize> windowSizes(const QList<WId> &ids) 00165 { 00166 QList<QSize> windowSizes; 00167 foreach (WId id, ids) { 00168 #ifdef Q_WS_X11 00169 if (id > 0) { 00170 KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry|NET::WMFrameExtents); 00171 windowSizes.append(info.frameGeometry().size()); 00172 } else { 00173 windowSizes.append(QSize()); 00174 } 00175 #else 00176 windowSizes.append(QSize()); 00177 #endif 00178 } 00179 return windowSizes; 00180 } 00181 00182 void showWindowThumbnails(WId parent, const QList<WId> &windows, const QList<QRect> &rects) 00183 { 00184 if (windows.size() != rects.size()) { 00185 return; 00186 } 00187 #ifdef Q_WS_X11 00188 Display *dpy = QX11Info::display(); 00189 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_PREVIEW", False); 00190 if (windows.isEmpty()) { 00191 XDeleteProperty(dpy, parent, atom); 00192 return; 00193 } 00194 00195 int numWindows = windows.size(); 00196 00197 // 64 is enough for 10 windows and is a nice base 2 number 00198 QVarLengthArray<long, 64> data(1 + (6 * numWindows)); 00199 data[0] = numWindows; 00200 00201 QList<WId>::const_iterator windowsIt; 00202 QList<QRect>::const_iterator rectsIt = rects.constBegin(); 00203 int i = 0; 00204 for (windowsIt = windows.constBegin(); windowsIt != windows.constEnd(); ++windowsIt) { 00205 00206 const int start = (i * 6) + 1; 00207 const QRect thumbnailRect = (*rectsIt); 00208 00209 data[start] = 5; 00210 data[start+1] = (*windowsIt); 00211 data[start+2] = thumbnailRect.x(); 00212 data[start+3] = thumbnailRect.y(); 00213 data[start+4] = thumbnailRect.width(); 00214 data[start+5] = thumbnailRect.height(); 00215 ++rectsIt; 00216 ++i; 00217 } 00218 00219 XChangeProperty(dpy, parent, atom, atom, 32, PropModeReplace, 00220 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00221 #endif 00222 } 00223 00224 void presentWindows(WId controller, const QList<WId> &ids) 00225 { 00226 #ifdef Q_WS_X11 00227 const int numWindows = ids.count(); 00228 QVarLengthArray<long, 32> data(numWindows); 00229 int actualCount = 0; 00230 00231 for (int i = 0; i < numWindows; ++i) { 00232 data[i] = ids.at(i); 00233 ++actualCount; 00234 00235 } 00236 00237 if (actualCount != numWindows) { 00238 data.resize(actualCount); 00239 } 00240 00241 if (!data.isEmpty()) { 00242 Display *dpy = QX11Info::display(); 00243 Atom atom = XInternAtom(dpy, "_KDE_PRESENT_WINDOWS_GROUP", False); 00244 XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace, 00245 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00246 } 00247 #endif 00248 } 00249 00250 void presentWindows(WId controller, int desktop) 00251 { 00252 #ifdef Q_WS_X11 00253 QVarLengthArray<long, 1> data(1); 00254 data[0] = desktop; 00255 Display *dpy = QX11Info::display(); 00256 Atom atom = XInternAtom(dpy, "_KDE_PRESENT_WINDOWS_DESKTOP", False); 00257 XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace, 00258 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00259 #endif 00260 } 00261 00262 void highlightWindows(WId controller, const QList<WId> &ids) 00263 { 00264 #ifdef Q_WS_X11 00265 const int numWindows = ids.count(); 00266 Display *dpy = QX11Info::display(); 00267 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_HIGHLIGHT", False); 00268 00269 if (numWindows == 0) { 00270 Atom atom = XInternAtom(dpy, "_KDE_WINDOW_HIGHLIGHT", False); 00271 XDeleteProperty(dpy, controller, atom); 00272 } 00273 00274 QVarLengthArray<long, 32> data(numWindows); 00275 int actualCount = 0; 00276 00277 for (int i = 0; i < numWindows; ++i) { 00278 data[i] = ids.at(i); 00279 ++actualCount; 00280 00281 } 00282 00283 if (actualCount != numWindows) { 00284 data.resize(actualCount); 00285 } 00286 00287 if (!data.isEmpty()) { 00288 XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace, 00289 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00290 } 00291 #endif 00292 } 00293 00294 void overrideShadow(WId window, bool override) 00295 { 00296 #ifdef Q_WS_X11 00297 Display *dpy = QX11Info::display(); 00298 Atom atom = XInternAtom( dpy, "_KDE_SHADOW_OVERRIDE", False ); 00299 if (!override) { 00300 XDeleteProperty(dpy, window, atom); 00301 } else { 00302 QVarLengthArray<long, 1> data(1); 00303 data[0] = 1; 00304 XChangeProperty(dpy, window, atom, atom, 32, PropModeReplace, 00305 reinterpret_cast<unsigned char *>(data.data()), data.size()); 00306 } 00307 #endif 00308 } 00309 00310 void enableBlurBehind(WId window, bool enable, const QRegion ®ion) 00311 { 00312 #ifdef Q_WS_X11 00313 Display *dpy = QX11Info::display(); 00314 Atom atom = XInternAtom(dpy, "_KDE_NET_WM_BLUR_BEHIND_REGION", False); 00315 00316 if (enable) { 00317 QVector<QRect> rects = region.rects(); 00318 QVector<unsigned long> data; 00319 foreach (const QRect &r, rects) { 00320 data << r.x() << r.y() << r.width() << r.height(); 00321 } 00322 00323 XChangeProperty(dpy, window, atom, XA_CARDINAL, 32, PropModeReplace, 00324 reinterpret_cast<const unsigned char *>(data.constData()), data.size()); 00325 } else { 00326 XDeleteProperty(dpy, window, atom); 00327 } 00328 #endif 00329 } 00330 00331 void markAsDashboard(WId window) 00332 { 00333 #ifdef Q_WS_X11 00334 XClassHint classHint; 00335 classHint.res_name = DASHBOARD_WIN_NAME; 00336 classHint.res_class = DASHBOARD_WIN_CLASS; 00337 XSetClassHint(QX11Info::display(), window, &classHint); 00338 #endif 00339 } 00340 00341 } 00342 00343 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:51:37 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:51:37 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.