Decoration can announce whether it currently requires an alpha channel
A decoration can provide the AbilityAnnounceAlphaChannel in addition to AbilityUsesAlphaChannel. If this ability is provided the decoration can enable/disable the use of the alpha channel through setAlphaEnabled(). The base idea behind this mechanism is to be able to tell the compositor that currently alpha is not needed. An example is the maximized state in which the decoration is fully opaque so that there is no need to use the translucency code path which would render all windows behind the deco. In addition also the blur effect honors this setting so that behind a known opaque decoration no blurring is performed. Oxygen is adjusted to disable translucency in maximized state and Aurorae is adjusted to allow themes to enable/disable translucency. For Plastik translucency and with that also blurring is disabled. REVIEW: 106810
This commit is contained in:
parent
e66eb08140
commit
9308028fa4
21 changed files with 195 additions and 10 deletions
14
client.cpp
14
client.cpp
|
@ -2422,6 +2422,20 @@ NET::WindowType Client::windowType(bool direct, int supportedTypes) const
|
|||
return wt;
|
||||
}
|
||||
|
||||
bool Client::decorationHasAlpha() const
|
||||
{
|
||||
if (!decoration || !workspace()->decorationHasAlpha()) {
|
||||
// either no decoration or decoration has alpha disabled
|
||||
return false;
|
||||
}
|
||||
if (workspace()->decorationSupportsAnnounceAlpha()) {
|
||||
return decoration->isAlphaEnabled();
|
||||
} else {
|
||||
// decoration has alpha enabled and does not support alpha announcement
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "client.moc"
|
||||
|
|
6
client.h
6
client.h
|
@ -274,6 +274,10 @@ class Client
|
|||
* Use with care!
|
||||
**/
|
||||
Q_PROPERTY(bool blocksCompositing READ isBlockingCompositing WRITE setBlockingCompositing NOTIFY blockingCompositingChanged)
|
||||
/**
|
||||
* Whether the decoration is currently using an alpha channel.
|
||||
**/
|
||||
Q_PROPERTY(bool decorationHasAlpha READ decorationHasAlpha)
|
||||
public:
|
||||
Client(Workspace* ws);
|
||||
Window wrapperId() const;
|
||||
|
@ -607,6 +611,8 @@ public:
|
|||
|
||||
QRegion decorationPendingRegion() const;
|
||||
|
||||
bool decorationHasAlpha() const;
|
||||
|
||||
enum CoordinateMode {
|
||||
DecorationRelative, // Relative to the top left corner of the decoration
|
||||
WindowRelative // Relative to the top left corner of the window
|
||||
|
|
|
@ -180,6 +180,7 @@ bool AuroraeFactory::supports(Ability ability) const
|
|||
switch (ability) {
|
||||
case AbilityAnnounceButtons:
|
||||
case AbilityUsesAlphaChannel:
|
||||
case AbilityAnnounceAlphaChannel:
|
||||
case AbilityButtonMenu:
|
||||
case AbilityButtonSpacer:
|
||||
case AbilityExtendIntoClientArea:
|
||||
|
@ -238,6 +239,7 @@ AuroraeClient::AuroraeClient(KDecorationBridge *bridge, KDecorationFactory *fact
|
|||
connect(AuroraeFactory::instance(), SIGNAL(buttonsChanged()), SIGNAL(buttonsChanged()));
|
||||
connect(AuroraeFactory::instance(), SIGNAL(configChanged()), SIGNAL(configChanged()));
|
||||
connect(AuroraeFactory::instance(), SIGNAL(titleFontChanged()), SIGNAL(fontChanged()));
|
||||
connect(m_item, SIGNAL(alphaChanged()), SLOT(slotAlphaChanged()));
|
||||
}
|
||||
|
||||
AuroraeClient::~AuroraeClient()
|
||||
|
@ -273,6 +275,7 @@ void AuroraeClient::init()
|
|||
pal2.setColor(widget()->backgroundRole(), Qt::transparent);
|
||||
widget()->setPalette(pal2);
|
||||
m_scene->addItem(m_item);
|
||||
slotAlphaChanged();
|
||||
|
||||
AuroraeFactory::instance()->theme()->setCompositingActive(compositingActive());
|
||||
}
|
||||
|
@ -505,6 +508,8 @@ void AuroraeClient::themeChanged()
|
|||
m_item->setHeight(m_scene->sceneRect().height());
|
||||
}
|
||||
m_scene->addItem(m_item);
|
||||
connect(m_item, SIGNAL(alphaChanged()), SLOT(slotAlphaChanged()));
|
||||
slotAlphaChanged();
|
||||
}
|
||||
|
||||
int AuroraeClient::doubleClickInterval() const
|
||||
|
@ -556,6 +561,17 @@ QVariant AuroraeClient::readConfig(const QString &key, const QVariant &defaultVa
|
|||
return config->group(AuroraeFactory::instance()->currentThemeName()).readEntry(key, defaultValue);
|
||||
}
|
||||
|
||||
void AuroraeClient::slotAlphaChanged()
|
||||
{
|
||||
QVariant alphaProperty = m_item->property("alpha");
|
||||
if (alphaProperty.isValid() && alphaProperty.canConvert<bool>()) {
|
||||
setAlphaEnabled(alphaProperty.toBool());
|
||||
} else {
|
||||
// by default all Aurorae themes use the alpha channel
|
||||
setAlphaEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Aurorae
|
||||
|
||||
extern "C"
|
||||
|
|
|
@ -171,6 +171,7 @@ private slots:
|
|||
void doCloseWindow();
|
||||
void doTitlebarDblClickOperation();
|
||||
void doMaximzie(int button);
|
||||
void slotAlphaChanged();
|
||||
|
||||
private:
|
||||
QGraphicsView *m_view;
|
||||
|
|
|
@ -17,6 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
import QtQuick 1.1
|
||||
|
||||
Item {
|
||||
signal alphaChanged()
|
||||
|
||||
property int paddingLeft
|
||||
property int paddingRight
|
||||
property int paddingTop
|
||||
|
@ -29,6 +31,9 @@ Item {
|
|||
property int borderRightMaximized
|
||||
property int borderTopMaximized
|
||||
property int borderBottomMaximized
|
||||
property bool alpha: true
|
||||
onAlphaChanged: alphaChanged()
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
|
|
@ -94,6 +94,7 @@ Decoration {
|
|||
paddingRight: 0
|
||||
paddingBottom: 0
|
||||
paddingTop: 0
|
||||
alpha: false
|
||||
Rectangle {
|
||||
color: root.titleBarColor
|
||||
anchors {
|
||||
|
|
|
@ -125,6 +125,8 @@ namespace Oxygen
|
|||
|
||||
}
|
||||
|
||||
setAlphaEnabled(!isMaximized());
|
||||
|
||||
_initialized = true;
|
||||
|
||||
// first reset is needed to store Oxygen configuration
|
||||
|
@ -1257,6 +1259,7 @@ namespace Oxygen
|
|||
void Client::maximizeChange( void )
|
||||
{
|
||||
if( hasSizeGrip() ) sizeGrip().setVisible( !( isShade() || isMaximized() ) );
|
||||
setAlphaEnabled(!isMaximized());
|
||||
KCommonDecorationUnstable::maximizeChange();
|
||||
}
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ namespace Oxygen
|
|||
return true;
|
||||
|
||||
case AbilityUsesAlphaChannel:
|
||||
case AbilityAnnounceAlphaChannel:
|
||||
return true;
|
||||
|
||||
// tabs
|
||||
|
|
|
@ -207,7 +207,7 @@ QRegion BlurEffect::blurRegion(const EffectWindow *w) const
|
|||
if (value.isValid()) {
|
||||
const QRegion appRegion = qvariant_cast<QRegion>(value);
|
||||
if (!appRegion.isEmpty()) {
|
||||
if (w->hasDecoration() && effects->decorationSupportsBlurBehind()) {
|
||||
if (w->decorationHasAlpha() && effects->decorationSupportsBlurBehind()) {
|
||||
region = w->shape();
|
||||
region -= w->decorationInnerRect();
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ QRegion BlurEffect::blurRegion(const EffectWindow *w) const
|
|||
// for the whole window.
|
||||
region = w->shape();
|
||||
}
|
||||
} else if (w->hasDecoration() && effects->decorationSupportsBlurBehind()) {
|
||||
} else if (w->decorationHasAlpha() && effects->decorationSupportsBlurBehind()) {
|
||||
// If the client hasn't specified a blur region, we'll only enable
|
||||
// the effect behind the decoration.
|
||||
region = w->shape();
|
||||
|
|
|
@ -1281,6 +1281,10 @@ void KCommonDecoration::setKeepBelow(bool set)
|
|||
{
|
||||
return wrapper->setKeepBelow(set);
|
||||
}
|
||||
void KCommonDecoration::setAlphaEnabled(bool enabled)
|
||||
{
|
||||
wrapper->wrapSetAlphaEnabled(enabled);
|
||||
}
|
||||
// *** end of wrapping of everything from KDecoration *** //
|
||||
|
||||
const KDecoration* KCommonDecoration::decoration() const
|
||||
|
|
|
@ -355,6 +355,19 @@ public:
|
|||
protected:
|
||||
virtual void timerEvent(QTimerEvent *event);
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* A decoration providing AbilityAnnounceAlphaChannel can use this method to enable/disable the
|
||||
* use of alpha channel. This is useful if for a normal window the decoration renders its own
|
||||
* shadows or round corners and thus needs alpha channel. But in maximized state the decoration
|
||||
* is fully opaque. By disabling the alpha channel the Compositor can optimize the rendering.
|
||||
*
|
||||
* @param enabled If @c true alpha channel is enabled, if @c false alpha channel is disabled
|
||||
* @see KDecoration::setAlphaEnabled
|
||||
* @since 4.10
|
||||
**/
|
||||
void setAlphaEnabled(bool enabled);
|
||||
|
||||
private Q_SLOTS:
|
||||
/* look out for buttons that have been destroyed. */
|
||||
void objDestroyed(QObject *obj);
|
||||
|
|
|
@ -121,3 +121,8 @@ void KCommonDecorationWrapper::padding(int &left, int &right, int &top, int &bot
|
|||
bottom = decoration->layoutMetric(KCommonDecoration::LM_OuterPaddingBottom);
|
||||
}
|
||||
|
||||
void KCommonDecorationWrapper::wrapSetAlphaEnabled(bool enabled)
|
||||
{
|
||||
setAlphaEnabled(enabled);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ public:
|
|||
virtual void reset(unsigned long changed);
|
||||
|
||||
virtual void padding(int &left, int &right, int &top, int &bottom) const;
|
||||
|
||||
void wrapSetAlphaEnabled(bool enabled);
|
||||
private:
|
||||
KCommonDecoration* decoration;
|
||||
};
|
||||
|
|
|
@ -54,13 +54,23 @@ inheriting KCommonDecoration and adding the new API matching KDecoration2.
|
|||
|
||||
*/
|
||||
|
||||
class KDecorationPrivate
|
||||
{
|
||||
public:
|
||||
KDecorationPrivate()
|
||||
: alphaEnabled(false)
|
||||
{
|
||||
}
|
||||
bool alphaEnabled;
|
||||
};
|
||||
|
||||
KDecorationOptions* KDecoration::options_;
|
||||
|
||||
KDecoration::KDecoration(KDecorationBridge* bridge, KDecorationFactory* factory)
|
||||
: bridge_(bridge),
|
||||
w_(NULL),
|
||||
factory_(factory)
|
||||
factory_(factory),
|
||||
d(new KDecorationPrivate())
|
||||
{
|
||||
factory->addDecoration(this);
|
||||
}
|
||||
|
@ -69,6 +79,7 @@ KDecoration::~KDecoration()
|
|||
{
|
||||
factory()->removeDecoration(this);
|
||||
delete w_;
|
||||
delete d;
|
||||
}
|
||||
|
||||
const KDecorationOptions* KDecoration::options()
|
||||
|
@ -391,6 +402,19 @@ QRect KDecoration::transparentRect() const
|
|||
return QRect();
|
||||
}
|
||||
|
||||
void KDecoration::setAlphaEnabled(bool enabled)
|
||||
{
|
||||
if (d->alphaEnabled == enabled) {
|
||||
return;
|
||||
}
|
||||
d->alphaEnabled = enabled;
|
||||
emit alphaEnabledChanged(enabled);
|
||||
}
|
||||
|
||||
bool KDecoration::isAlphaEnabled() const
|
||||
{
|
||||
return d->alphaEnabled;
|
||||
}
|
||||
|
||||
KDecorationUnstable::KDecorationUnstable(KDecorationBridge* bridge, KDecorationFactory* factory)
|
||||
: KDecoration(bridge, factory)
|
||||
|
|
|
@ -220,6 +220,8 @@ public:
|
|||
/// @since 4.4
|
||||
AbilityUsesBlurBehind = 3003, ///< The decoration wants the background to be blurred, when the blur plugin is enabled.
|
||||
/// @since 4.6
|
||||
AbilityAnnounceAlphaChannel = 4004, ///< The decoration can tell whether it currently uses an alpha channel or not. Requires AbilityUsesAlphaChannel.
|
||||
/// @since 4.10
|
||||
// Tabbing
|
||||
AbilityTabbing = 4000, ///< The decoration supports tabbing
|
||||
// TODO colors for individual button types
|
||||
|
@ -706,6 +708,22 @@ public:
|
|||
*/
|
||||
void processMousePressEvent(QMouseEvent* e);
|
||||
|
||||
/**
|
||||
* Whether the alpha channel is currently enabled. The value of this property is
|
||||
* only relevant in case the decoration provides the AbilityAnnounceAlphaChannel.
|
||||
*
|
||||
* The compositor can make use of this information to optimize the rendering of the
|
||||
* decoration.
|
||||
*
|
||||
* The default value of this property is @c false. That means if a decoration wants to make
|
||||
* use alpha channel it has to call setAlphaEnabled with @c true.
|
||||
*
|
||||
* @see setAlphaEnabled
|
||||
* @see alphaEnabledChanged
|
||||
* @since 4.10
|
||||
**/
|
||||
bool isAlphaEnabled() const;
|
||||
|
||||
// requests to decoration
|
||||
|
||||
/**
|
||||
|
@ -790,6 +808,17 @@ Q_SIGNALS:
|
|||
*/
|
||||
void keepBelowChanged(bool);
|
||||
|
||||
/**
|
||||
* This signal is emitted whenever the decoration changes it's alpha enabled
|
||||
* change. Only relevant in case the decoration provides AbilityAnnounceAlphaChannel.
|
||||
*
|
||||
* @param enabled The new state of alpha channel usage
|
||||
* @see setAlphaEnabled
|
||||
* @see isAlphaEnabled
|
||||
* @since 4.10
|
||||
**/
|
||||
void alphaEnabledChanged(bool enabled);
|
||||
|
||||
public:
|
||||
/**
|
||||
* This method is not any more invoked from KWin core since version 4.8.
|
||||
|
@ -941,6 +970,20 @@ public Q_SLOTS:
|
|||
*/
|
||||
void emitKeepBelowChanged(bool below);
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* A decoration providing AbilityAnnounceAlphaChannel can use this method to enable/disable the
|
||||
* use of alpha channel. This is useful if for a normal window the decoration renders its own
|
||||
* shadows or round corners and thus needs alpha channel. But in maximized state the decoration
|
||||
* is fully opaque. By disabling the alpha channel the Compositor can optimize the rendering.
|
||||
*
|
||||
* @param enabled If @c true alpha channel is enabled, if @c false alpha channel is disabled
|
||||
* @see isAlphaEnabled
|
||||
* @see alphaEnabledChanged
|
||||
* @since 4.10
|
||||
**/
|
||||
void setAlphaEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
KDecorationBridge* bridge_;
|
||||
QWidget* w_;
|
||||
|
|
|
@ -736,6 +736,7 @@ WINDOW_HELPER_DEFAULT(bool, acceptsFocus, "wantsInput", true) // We don't actual
|
|||
WINDOW_HELPER_DEFAULT(QPixmap, icon, "icon", QPixmap())
|
||||
WINDOW_HELPER_DEFAULT(bool, isSkipSwitcher, "skipSwitcher", false)
|
||||
WINDOW_HELPER_DEFAULT(bool, isCurrentTab, "isCurrentTab", false)
|
||||
WINDOW_HELPER_DEFAULT(bool, decorationHasAlpha, "decorationHasAlpha", false)
|
||||
|
||||
#undef WINDOW_HELPER_DEFAULT
|
||||
|
||||
|
|
|
@ -1320,6 +1320,11 @@ class KWIN_EXPORT EffectWindow : public QObject
|
|||
Q_PROPERTY(QStringList activities READ activities)
|
||||
Q_PROPERTY(bool onCurrentActivity READ isOnCurrentActivity)
|
||||
Q_PROPERTY(bool onAllActivities READ isOnAllActivities)
|
||||
/**
|
||||
* Whether the decoration currently uses an alpha channel.
|
||||
* @since 4.10
|
||||
**/
|
||||
Q_PROPERTY(bool decorationHasAlpha READ decorationHasAlpha)
|
||||
public:
|
||||
/** Flags explaining why painting should be disabled */
|
||||
enum {
|
||||
|
@ -1407,6 +1412,7 @@ public:
|
|||
*/
|
||||
virtual QRect decorationInnerRect() const = 0;
|
||||
bool hasDecoration() const;
|
||||
bool decorationHasAlpha() const;
|
||||
virtual QByteArray readProperty(long atom, long type, int format) const = 0;
|
||||
virtual void deleteProperty(long atom) const = 0;
|
||||
|
||||
|
|
16
scene.cpp
16
scene.cpp
|
@ -258,8 +258,22 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
|
|||
|
||||
// Clip out the decoration for opaque windows; the decoration is drawn in the second pass
|
||||
if (w->isOpaque()) {
|
||||
Client *c = NULL;
|
||||
if (topw->isClient()) {
|
||||
c = static_cast<Client*>(topw);
|
||||
}
|
||||
// the window is fully opaque
|
||||
data.clip = w->clientShape().translated(w->x(), w->y());
|
||||
if (c && c->decorationHasAlpha()) {
|
||||
// decoration uses alpha channel, so we may not exclude it in clipping
|
||||
data.clip = w->clientShape().translated(w->x(), w->y());
|
||||
} else {
|
||||
// decoration is fully opaque
|
||||
if (c && c->isShade()) {
|
||||
data.clip = QRegion();
|
||||
} else {
|
||||
data.clip = w->shape().translated(w->x(), w->y());
|
||||
}
|
||||
}
|
||||
} else if (topw->hasAlpha() && topw->opacity() == 1.0) {
|
||||
// the window is partially opaque
|
||||
data.clip = (w->clientShape() & topw->opaqueRegion().translated(topw->clientPos())).translated(w->x(), w->y());
|
||||
|
|
|
@ -1247,6 +1247,7 @@ GLTexture *SceneOpenGL::Window::textureForType(SceneOpenGL::Window::TextureType
|
|||
//***************************************
|
||||
SceneOpenGL2Window::SceneOpenGL2Window(Toplevel *c)
|
||||
: SceneOpenGL::Window(c)
|
||||
, m_blendingEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1284,8 +1285,18 @@ void SceneOpenGL2Window::prepareStates(TextureType type, qreal opacity, qreal br
|
|||
// setup blending of transparent windows
|
||||
bool opaque = isOpaque() && opacity == 1.0;
|
||||
bool alpha = toplevel->hasAlpha() || type != Content;
|
||||
if (type != Content)
|
||||
opaque = false;
|
||||
if (type != Content) {
|
||||
if (type == Shadow) {
|
||||
opaque = false;
|
||||
} else {
|
||||
if (opacity == 1.0 && toplevel->isClient()) {
|
||||
opaque = !(static_cast<Client*>(toplevel)->decorationHasAlpha());
|
||||
} else {
|
||||
// TODO: add support in Deleted
|
||||
opaque = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!opaque) {
|
||||
glEnable(GL_BLEND);
|
||||
if (options->isColorCorrected()) {
|
||||
|
@ -1299,6 +1310,7 @@ void SceneOpenGL2Window::prepareStates(TextureType type, qreal opacity, qreal br
|
|||
}
|
||||
}
|
||||
}
|
||||
m_blendingEnabled = !opaque;
|
||||
|
||||
const qreal rgb = brightness * opacity;
|
||||
const qreal a = opacity;
|
||||
|
@ -1313,13 +1325,12 @@ void SceneOpenGL2Window::prepareStates(TextureType type, qreal opacity, qreal br
|
|||
|
||||
void SceneOpenGL2Window::restoreStates(TextureType type, qreal opacity, qreal brightness, qreal saturation, int screen)
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(opacity);
|
||||
Q_UNUSED(brightness);
|
||||
Q_UNUSED(saturation);
|
||||
Q_UNUSED(screen);
|
||||
bool opaque = isOpaque() && opacity == 1.0;
|
||||
if (type != Content)
|
||||
opaque = false;
|
||||
if (!opaque) {
|
||||
if (m_blendingEnabled) {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
ShaderManager::instance()->getBoundShader()->setUniform(GLShader::AlphaToOne, 0);
|
||||
|
|
|
@ -288,6 +288,12 @@ protected:
|
|||
virtual void endRenderWindow(const WindowPaintData &data);
|
||||
virtual void prepareStates(TextureType type, qreal opacity, qreal brightness, qreal saturation, int screen);
|
||||
virtual void restoreStates(TextureType type, qreal opacity, qreal brightness, qreal saturation, int screen);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Whether prepareStates enabled blending and restore states should disable again.
|
||||
**/
|
||||
bool m_blendingEnabled;
|
||||
};
|
||||
|
||||
#ifdef KWIN_HAVE_OPENGL_1
|
||||
|
|
|
@ -440,6 +440,7 @@ public:
|
|||
bool hasDecorationShadows() const;
|
||||
Qt::Corner decorationCloseButtonCorner();
|
||||
bool decorationHasAlpha() const;
|
||||
bool decorationSupportsAnnounceAlpha() const;
|
||||
bool decorationSupportsTabbing() const; // Returns true if the decoration supports tabs.
|
||||
bool decorationSupportsFrameOverlap() const;
|
||||
bool decorationSupportsBlurBehind() const;
|
||||
|
@ -1133,6 +1134,14 @@ inline bool Workspace::decorationHasAlpha() const
|
|||
return mgr->factory()->supports(AbilityUsesAlphaChannel);
|
||||
}
|
||||
|
||||
inline bool Workspace::decorationSupportsAnnounceAlpha() const
|
||||
{
|
||||
if (!hasDecorationPlugin()) {
|
||||
return false;
|
||||
}
|
||||
return mgr->factory()->supports(AbilityAnnounceAlphaChannel);
|
||||
}
|
||||
|
||||
inline bool Workspace::decorationSupportsTabbing() const
|
||||
{
|
||||
if (!hasDecorationPlugin()) {
|
||||
|
|
Loading…
Reference in a new issue