/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2011 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, 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 General Public License along with this program. If not, see . *********************************************************************/ #include "shadow.h" // kwin #include "atoms.h" #include "toplevel.h" #ifdef KWIN_HAVE_OPENGL_COMPOSITING #include "scene_opengl.h" #endif namespace KWin { Shadow::Shadow(Toplevel *toplevel) : QObject(toplevel) , m_topLevel(toplevel) { } Shadow::~Shadow() { } Shadow *Shadow::createShadow(Toplevel *toplevel) { if (!effects) { return NULL; } QVector data = Shadow::readX11ShadowProperty(toplevel->window()); if (!data.isEmpty()) { Shadow *shadow = NULL; if (effects->compositingType() == OpenGLCompositing) { #ifdef KWIN_HAVE_OPENGL_COMPOSITING shadow = new SceneOpenGLShadow(toplevel); #endif } if (shadow) { shadow->init(data); } return shadow; } else { return NULL; } } QVector< long > Shadow::readX11ShadowProperty(WId id) { QVector ret; Atom type; int format, status; unsigned long nitems = 0; unsigned long extra = 0; unsigned char *data = 0; status = XGetWindowProperty(display(), id, atoms->kde_net_wm_shadow, 0, 12, false, XA_CARDINAL, &type, &format, &nitems, &extra, &data); if (status == Success && type == XA_CARDINAL && format == 32 && nitems == 12) { long* shadow = reinterpret_cast< long* >(data); ret.reserve(12); for (int i=0; i<12; ++i) { ret << shadow[i]; } XFree(data); } return ret; } void Shadow::init(const QVector< long > &data) { for (int i=0; iwidth(), m_topOffset); const QRect rightRect(m_topLevel->width(), - m_topOffset, m_rightOffset, m_topLevel->height() + m_topOffset + m_bottomOffset); const QRect bottomRect(0, m_topLevel->height(), m_topLevel->width(), m_bottomOffset); const QRect leftRect(- m_leftOffset, - m_topOffset, m_leftOffset, m_topLevel->height() + m_topOffset + m_bottomOffset); m_shadowRegion = QRegion(topRect).united(rightRect).united(bottomRect).united(leftRect); buildQuads(); } void Shadow::buildQuads() { // prepare window quads m_shadowQuads.clear(); const QRect topRect(QPoint(0, 0), m_shadowElements[ShadowElementTop].size()); const QRect topRightRect(QPoint(0, 0), m_shadowElements[ShadowElementTopRight].size()); const QRect rightRect(QPoint(0, 0), m_shadowElements[ShadowElementRight].size()); const QRect bottomRightRect(QPoint(0, 0), m_shadowElements[ShadowElementBottomRight].size()); const QRect bottomRect(QPoint(0, 0), m_shadowElements[ShadowElementBottom].size()); const QRect bottomLeftRect(QPoint(0, 0), m_shadowElements[ShadowElementBottomLeft].size()); const QRect leftRect(QPoint(0, 0), m_shadowElements[ShadowElementLeft].size()); const QRect topLeftRect(QPoint(0, 0), m_shadowElements[ShadowElementTopLeft].size()); WindowQuad topLeftQuad(WindowQuadShadowTopLeft); topLeftQuad[ 0 ] = WindowVertex(-m_leftOffset, -m_topOffset, 0.0, 0.0); topLeftQuad[ 1 ] = WindowVertex(-m_leftOffset + topLeftRect.width(), -m_topOffset, 1.0, 0.0); topLeftQuad[ 2 ] = WindowVertex(-m_leftOffset + topLeftRect.width(), -m_topOffset + topLeftRect.height(), 1.0, 1.0); topLeftQuad[ 3 ] = WindowVertex(-m_leftOffset, -m_topOffset + topLeftRect.height(), 0.0, 1.0); m_shadowQuads.append(topLeftQuad); WindowQuad topQuad(WindowQuadShadowTop); topQuad[ 0 ] = WindowVertex(-m_leftOffset + topLeftRect.width(), -m_topOffset, 0.0, 0.0); topQuad[ 1 ] = WindowVertex(m_topLevel->width() + m_rightOffset - topRightRect.width(), -m_topOffset, 1.0, 0.0); topQuad[ 2 ] = WindowVertex(m_topLevel->width() + m_rightOffset - topRightRect.width(), -m_topOffset + topRect.height(), 1.0, 1.0); topQuad[ 3 ] = WindowVertex(-m_leftOffset + topLeftRect.width(), -m_topOffset + topRect.height(), 0.0, 1.0); m_shadowQuads.append(topQuad); WindowQuad topRightQuad(WindowQuadShadowTopRight); topRightQuad[ 0 ] = WindowVertex(m_topLevel->width() + m_rightOffset - topRightRect.width(), -m_topOffset, 0.0, 0.0); topRightQuad[ 1 ] = WindowVertex(m_topLevel->width() + m_rightOffset, -m_topOffset, 1.0, 0.0); topRightQuad[ 2 ] = WindowVertex(m_topLevel->width() + m_rightOffset, -m_topOffset + topRightRect.height(), 1.0, 1.0); topRightQuad[ 3 ] = WindowVertex(m_topLevel->width() + m_rightOffset - topRightRect.width(), -m_topOffset + topRightRect.height(), 0.0, 1.0); m_shadowQuads.append(topRightQuad); WindowQuad rightQuad(WindowQuadShadowRight); rightQuad[ 0 ] = WindowVertex(m_topLevel->width() + m_rightOffset - rightRect.width(), -m_topOffset + topRightRect.height(), 0.0, 0.0); rightQuad[ 1 ] = WindowVertex(m_topLevel->width() + m_rightOffset, -m_topOffset + topRightRect.height(), 1.0, 0.0); rightQuad[ 2 ] = WindowVertex(m_topLevel->width() + m_rightOffset, m_topLevel->height() + m_bottomOffset - bottomRightRect.height(), 1.0, 1.0); rightQuad[ 3 ] = WindowVertex(m_topLevel->width() + m_rightOffset - rightRect.width(), m_topLevel->height() + m_bottomOffset - bottomRightRect.height(), 0.0, 1.0); m_shadowQuads.append(rightQuad); WindowQuad bottomRightQuad(WindowQuadShadowBottomRight); bottomRightQuad[ 0 ] = WindowVertex(m_topLevel->width() + m_rightOffset - bottomRightRect.width(), m_topLevel->height() + m_bottomOffset - bottomRightRect.height(), 0.0, 0.0); bottomRightQuad[ 1 ] = WindowVertex(m_topLevel->width() + m_rightOffset, m_topLevel->height() + m_bottomOffset - bottomRightRect.height(), 1.0, 0.0); bottomRightQuad[ 2 ] = WindowVertex(m_topLevel->width() + m_rightOffset, m_topLevel->height() + m_bottomOffset, 1.0, 1.0); bottomRightQuad[ 3 ] = WindowVertex(m_topLevel->width() + m_rightOffset - bottomRightRect.width(), m_topLevel->height() + m_bottomOffset, 0.0, 1.0); m_shadowQuads.append(bottomRightQuad); WindowQuad bottomQuad(WindowQuadShadowBottom); bottomQuad[ 0 ] = WindowVertex(-m_leftOffset + bottomLeftRect.width(), m_topLevel->height() + m_bottomOffset - bottomRect.height(), 0.0, 0.0); bottomQuad[ 1 ] = WindowVertex(m_topLevel->width() + m_rightOffset - bottomRightRect.width(), m_topLevel->height() + m_bottomOffset - bottomRect.height(), 1.0, 0.0); bottomQuad[ 2 ] = WindowVertex(m_topLevel->width() + m_rightOffset - bottomRightRect.width(), m_topLevel->height() + m_bottomOffset, 1.0, 1.0); bottomQuad[ 3 ] = WindowVertex(-m_leftOffset + bottomLeftRect.width(), m_topLevel->height() + m_bottomOffset, 0.0, 1.0); m_shadowQuads.append(bottomQuad); WindowQuad bottomLeftQuad(WindowQuadShadowBottomLeft); bottomLeftQuad[ 0 ] = WindowVertex(-m_leftOffset, m_topLevel->height() + m_bottomOffset - bottomLeftRect.height(), 0.0, 0.0); bottomLeftQuad[ 1 ] = WindowVertex(-m_leftOffset + bottomLeftRect.width(), m_topLevel->height() + m_bottomOffset - bottomLeftRect.height(), 1.0, 0.0); bottomLeftQuad[ 2 ] = WindowVertex(-m_leftOffset + bottomLeftRect.width(), m_topLevel->height() + m_bottomOffset, 1.0, 1.0); bottomLeftQuad[ 3 ] = WindowVertex(-m_leftOffset, m_topLevel->height() + m_bottomOffset, 0.0, 1.0); m_shadowQuads.append(bottomLeftQuad); WindowQuad leftQuad(WindowQuadShadowLeft); leftQuad[ 0 ] = WindowVertex(-m_leftOffset, -m_topOffset + topLeftRect.height(), 0.0, 0.0); leftQuad[ 1 ] = WindowVertex(-m_leftOffset + leftRect.width(), -m_topOffset + topLeftRect.height(), 1.0, 0.0); leftQuad[ 2 ] = WindowVertex(-m_leftOffset + leftRect.width(), m_topLevel->height() + m_bottomOffset - bottomLeftRect.height(), 1.0, 1.0); leftQuad[ 3 ] = WindowVertex(-m_leftOffset, m_topLevel->height() + m_bottomOffset - bottomLeftRect.height(), 0.0, 1.0); m_shadowQuads.append(leftQuad); } bool Shadow::updateShadow() { QVector data = Shadow::readX11ShadowProperty(m_topLevel->window()); if (data.isEmpty()) { return false; } init(data); return true; } } // namespace