2009-07-26 20:58:27 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2009 Marco Martin <notmart@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Library General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this program; if not, write to the
|
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "windoweffects.h"
|
|
|
|
#include <QVarLengthArray>
|
|
|
|
|
2009-07-28 17:54:17 +02:00
|
|
|
#include <kwindowsystem.h>
|
2009-07-26 20:58:27 +02:00
|
|
|
|
2010-08-09 16:51:34 +02:00
|
|
|
#include "theme.h"
|
|
|
|
|
2009-07-30 13:09:45 +02:00
|
|
|
#ifdef Q_WS_X11
|
2010-07-23 21:52:20 +02:00
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <QX11Info>
|
|
|
|
|
|
|
|
#define DASHBOARD_WIN_NAME "dashboard"
|
|
|
|
#define DASHBOARD_WIN_CLASS "dashboard"
|
2009-07-30 13:09:45 +02:00
|
|
|
#endif
|
|
|
|
|
2009-07-26 20:58:27 +02:00
|
|
|
namespace Plasma
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace WindowEffects
|
|
|
|
{
|
|
|
|
|
2009-10-09 16:40:03 +02:00
|
|
|
//FIXME: check if this works for any atom?
|
|
|
|
bool isEffectAvailable(Effect effect)
|
|
|
|
{
|
2010-08-09 16:51:34 +02:00
|
|
|
if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
|
2009-10-09 16:40:03 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
QString effectName;
|
|
|
|
|
|
|
|
switch (effect) {
|
|
|
|
case Slide:
|
|
|
|
effectName = "_KDE_SLIDE";
|
|
|
|
break;
|
|
|
|
case WindowPreview:
|
|
|
|
effectName = "_KDE_WINDOW_PREVIEW";
|
|
|
|
break;
|
2009-10-21 12:51:36 +02:00
|
|
|
case PresentWindows:
|
|
|
|
effectName = "_KDE_PRESENT_WINDOWS_DESKTOP";
|
|
|
|
break;
|
|
|
|
case PresentWindowsGroup:
|
|
|
|
effectName = "_KDE_PRESENT_WINDOWS_GROUP";
|
|
|
|
break;
|
2009-10-31 11:58:06 +01:00
|
|
|
case HighlightWindows:
|
|
|
|
effectName = "_KDE_WINDOW_HIGHLIGHT";
|
|
|
|
break;
|
2010-01-05 20:57:44 +01:00
|
|
|
case OverrideShadow:
|
|
|
|
effectName = "_KDE_SHADOW_OVERRIDE";
|
2010-03-06 19:15:55 +01:00
|
|
|
break;
|
|
|
|
case BlurBehind:
|
2010-03-22 23:04:08 +01:00
|
|
|
effectName = "_KDE_NET_WM_BLUR_BEHIND_REGION";
|
2010-03-06 19:15:55 +01:00
|
|
|
break;
|
2010-07-23 21:52:20 +02:00
|
|
|
case Dashboard:
|
|
|
|
// TODO: Better namespacing for atoms
|
|
|
|
effectName = "_WM_EFFECT_KDE_DASHBOARD";
|
|
|
|
break;
|
2009-10-09 16:40:03 +02:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// hackish way to find out if KWin has the effect enabled,
|
|
|
|
// TODO provide proper support
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom(dpy, effectName.toLatin1(), False);
|
|
|
|
int cnt;
|
|
|
|
Atom *list = XListProperties(dpy, DefaultRootWindow(dpy), &cnt);
|
|
|
|
if (list != NULL) {
|
|
|
|
bool ret = (qFind(list, list + cnt, atom) != list + cnt);
|
|
|
|
XFree(list);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-07-28 03:33:31 +02:00
|
|
|
void slideWindow(WId id, Plasma::Location location, int offset)
|
2009-07-26 20:58:27 +02:00
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom( dpy, "_KDE_SLIDE", False );
|
2011-11-30 13:43:52 +01:00
|
|
|
QVarLengthArray<long, 2> data(2);
|
2009-07-26 20:58:27 +02:00
|
|
|
|
2009-07-27 23:53:36 +02:00
|
|
|
data[0] = offset;
|
|
|
|
|
2009-07-26 20:58:27 +02:00
|
|
|
switch (location) {
|
|
|
|
case LeftEdge:
|
|
|
|
data[1] = 0;
|
|
|
|
break;
|
|
|
|
case TopEdge:
|
|
|
|
data[1] = 1;
|
|
|
|
break;
|
|
|
|
case RightEdge:
|
|
|
|
data[1] = 2;
|
|
|
|
break;
|
|
|
|
case BottomEdge:
|
|
|
|
data[1] = 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (location == Desktop || location == Floating) {
|
|
|
|
XDeleteProperty(dpy, id, atom);
|
|
|
|
} else {
|
|
|
|
XChangeProperty(dpy, id, atom, atom, 32, PropModeReplace,
|
|
|
|
reinterpret_cast<unsigned char *>(data.data()), data.size());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-07-28 15:50:48 +02:00
|
|
|
void slideWindow(QWidget *widget, Plasma::Location location)
|
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom( dpy, "_KDE_SLIDE", False );
|
2011-11-30 13:43:52 +01:00
|
|
|
QVarLengthArray<long, 2> data(2);
|
2011-12-10 22:37:23 +01:00
|
|
|
data[0] = -1;
|
2009-07-28 15:50:48 +02:00
|
|
|
|
|
|
|
switch (location) {
|
|
|
|
case LeftEdge:
|
|
|
|
data[1] = 0;
|
|
|
|
break;
|
|
|
|
case TopEdge:
|
|
|
|
data[1] = 1;
|
|
|
|
break;
|
|
|
|
case RightEdge:
|
|
|
|
data[1] = 2;
|
|
|
|
break;
|
|
|
|
case BottomEdge:
|
|
|
|
data[1] = 3;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (location == Desktop || location == Floating) {
|
|
|
|
XDeleteProperty(dpy, widget->effectiveWinId(), atom);
|
|
|
|
} else {
|
|
|
|
XChangeProperty(dpy, widget->effectiveWinId(), atom, atom, 32, PropModeReplace,
|
|
|
|
reinterpret_cast<unsigned char *>(data.data()), data.size());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-10-09 16:40:03 +02:00
|
|
|
QList<QSize> windowSizes(const QList<WId> &ids)
|
|
|
|
{
|
|
|
|
QList<QSize> windowSizes;
|
|
|
|
foreach (WId id, ids) {
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
if (id > 0) {
|
|
|
|
KWindowInfo info = KWindowSystem::windowInfo(id, NET::WMGeometry|NET::WMFrameExtents);
|
|
|
|
windowSizes.append(info.frameGeometry().size());
|
|
|
|
} else {
|
|
|
|
windowSizes.append(QSize());
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
windowSizes.append(QSize());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return windowSizes;
|
|
|
|
}
|
|
|
|
|
|
|
|
void showWindowThumbnails(WId parent, const QList<WId> &windows, const QList<QRect> &rects)
|
|
|
|
{
|
|
|
|
if (windows.size() != rects.size()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom(dpy, "_KDE_WINDOW_PREVIEW", False);
|
|
|
|
if (windows.isEmpty()) {
|
|
|
|
XDeleteProperty(dpy, parent, atom);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int numWindows = windows.size();
|
|
|
|
|
2011-11-30 13:43:52 +01:00
|
|
|
// 64 is enough for 10 windows and is a nice base 2 number
|
|
|
|
QVarLengthArray<long, 64> data(1 + (6 * numWindows));
|
2009-10-09 16:40:03 +02:00
|
|
|
data[0] = numWindows;
|
|
|
|
|
|
|
|
QList<WId>::const_iterator windowsIt;
|
|
|
|
QList<QRect>::const_iterator rectsIt = rects.constBegin();
|
|
|
|
int i = 0;
|
|
|
|
for (windowsIt = windows.constBegin(); windowsIt != windows.constEnd(); ++windowsIt) {
|
|
|
|
|
|
|
|
const int start = (i * 6) + 1;
|
|
|
|
const QRect thumbnailRect = (*rectsIt);
|
|
|
|
|
|
|
|
data[start] = 5;
|
|
|
|
data[start+1] = (*windowsIt);
|
|
|
|
data[start+2] = thumbnailRect.x();
|
|
|
|
data[start+3] = thumbnailRect.y();
|
|
|
|
data[start+4] = thumbnailRect.width();
|
|
|
|
data[start+5] = thumbnailRect.height();
|
|
|
|
++rectsIt;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
|
|
|
XChangeProperty(dpy, parent, atom, atom, 32, PropModeReplace,
|
|
|
|
reinterpret_cast<unsigned char *>(data.data()), data.size());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-12-27 23:16:11 +01:00
|
|
|
void presentWindows(WId controller, const QList<WId> &ids)
|
2009-10-21 12:51:36 +02:00
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
const int numWindows = ids.count();
|
|
|
|
QVarLengthArray<long, 32> data(numWindows);
|
|
|
|
int actualCount = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < numWindows; ++i) {
|
|
|
|
data[i] = ids.at(i);
|
|
|
|
++actualCount;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actualCount != numWindows) {
|
|
|
|
data.resize(actualCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom(dpy, "_KDE_PRESENT_WINDOWS_GROUP", False);
|
2009-12-27 23:16:11 +01:00
|
|
|
XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace,
|
2009-10-21 12:51:36 +02:00
|
|
|
reinterpret_cast<unsigned char *>(data.data()), data.size());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-12-27 23:16:11 +01:00
|
|
|
void presentWindows(WId controller, int desktop)
|
2009-10-21 12:51:36 +02:00
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
2011-11-30 13:43:52 +01:00
|
|
|
QVarLengthArray<long, 1> data(1);
|
2009-10-21 12:51:36 +02:00
|
|
|
data[0] = desktop;
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom(dpy, "_KDE_PRESENT_WINDOWS_DESKTOP", False);
|
2009-12-27 23:16:11 +01:00
|
|
|
XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace,
|
2009-10-21 12:51:36 +02:00
|
|
|
reinterpret_cast<unsigned char *>(data.data()), data.size());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-10-31 11:58:06 +01:00
|
|
|
void highlightWindows(WId controller, const QList<WId> &ids)
|
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
const int numWindows = ids.count();
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom(dpy, "_KDE_WINDOW_HIGHLIGHT", False);
|
|
|
|
|
|
|
|
if (numWindows == 0) {
|
|
|
|
Atom atom = XInternAtom(dpy, "_KDE_WINDOW_HIGHLIGHT", False);
|
|
|
|
XDeleteProperty(dpy, controller, atom);
|
|
|
|
}
|
|
|
|
|
|
|
|
QVarLengthArray<long, 32> data(numWindows);
|
|
|
|
int actualCount = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < numWindows; ++i) {
|
|
|
|
data[i] = ids.at(i);
|
|
|
|
++actualCount;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (actualCount != numWindows) {
|
|
|
|
data.resize(actualCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data.isEmpty()) {
|
|
|
|
XChangeProperty(dpy, controller, atom, atom, 32, PropModeReplace,
|
|
|
|
reinterpret_cast<unsigned char *>(data.data()), data.size());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-01-06 17:00:53 +01:00
|
|
|
void overrideShadow(WId window, bool override)
|
2010-01-05 20:57:44 +01:00
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
Display *dpy = QX11Info::display();
|
|
|
|
Atom atom = XInternAtom( dpy, "_KDE_SHADOW_OVERRIDE", False );
|
|
|
|
if (!override) {
|
|
|
|
XDeleteProperty(dpy, window, atom);
|
|
|
|
} else {
|
2011-11-30 13:43:52 +01:00
|
|
|
QVarLengthArray<long, 1> data(1);
|
|
|
|
data[0] = 1;
|
2010-01-05 20:57:44 +01:00
|
|
|
XChangeProperty(dpy, window, atom, atom, 32, PropModeReplace,
|
|
|
|
reinterpret_cast<unsigned char *>(data.data()), data.size());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-03-06 19:15:55 +01:00
|
|
|
void enableBlurBehind(WId window, bool enable, const QRegion ®ion)
|
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
Display *dpy = QX11Info::display();
|
2010-03-22 23:04:08 +01:00
|
|
|
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_BLUR_BEHIND_REGION", False);
|
2010-03-06 19:15:55 +01:00
|
|
|
|
|
|
|
if (enable) {
|
|
|
|
QVector<QRect> rects = region.rects();
|
2010-05-25 19:30:23 +02:00
|
|
|
QVector<unsigned long> data;
|
|
|
|
foreach (const QRect &r, rects) {
|
2010-03-06 19:15:55 +01:00
|
|
|
data << r.x() << r.y() << r.width() << r.height();
|
|
|
|
}
|
|
|
|
|
|
|
|
XChangeProperty(dpy, window, atom, XA_CARDINAL, 32, PropModeReplace,
|
|
|
|
reinterpret_cast<const unsigned char *>(data.constData()), data.size());
|
|
|
|
} else {
|
|
|
|
XDeleteProperty(dpy, window, atom);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-07-23 21:52:20 +02:00
|
|
|
void markAsDashboard(WId window)
|
|
|
|
{
|
|
|
|
#ifdef Q_WS_X11
|
|
|
|
XClassHint classHint;
|
|
|
|
classHint.res_name = DASHBOARD_WIN_NAME;
|
|
|
|
classHint.res_class = DASHBOARD_WIN_CLASS;
|
|
|
|
XSetClassHint(QX11Info::display(), window, &classHint);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-07-26 20:58:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|