Commit 90e77a93 authored by Martin Flöser's avatar Martin Flöser

[effects] Support xcbConnectionChanged for support properties

Summary:
Several effects announce a support property atom on the root window. This
change forwards the KWin::Application's signal that the xcbConnection
changed to the EffectsHandler so that the effects can respond to it.

All effects which announce a support property connect to this new signal
and re-announce the property. In case the xcb connection died (future
XWayland crashing case) it is set to XCB_ATOM_NONE by that. In case the
xcb connection got created (future delayed XWayland startup) the atom is
set to the proper value.

In addition all usages of the support properties are guarded, so that no
nonesense actions are performed if the support property is XCB_ATOM_NONE.

Test Plan: Only compile tested as we don't have XFree KWin yet

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D7761
parent 4fa41165
......@@ -231,6 +231,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
m_managedProperties.insert(*it, atom);
registerPropertyType(atom, true);
}
emit xcbConnectionChanged();
}
);
......
......@@ -58,6 +58,13 @@ ContrastEffect::ContrastEffect()
connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*)));
connect(effects, SIGNAL(propertyNotify(KWin::EffectWindow*,long)), this, SLOT(slotPropertyNotify(KWin::EffectWindow*,long)));
connect(effects, SIGNAL(screenGeometryChanged(QSize)), this, SLOT(slotScreenGeometryChanged()));
connect(effects, &EffectsHandler::xcbConnectionChanged, this,
[this] {
if (shader && shader->isValid()) {
net_wm_contrast_region = effects->announceSupportProperty(s_contrastAtomName, this);
}
}
);
// Fetch the contrast regions for all windows
foreach (EffectWindow *window, effects->stackingOrder())
......@@ -92,27 +99,30 @@ void ContrastEffect::updateContrastRegion(EffectWindow *w)
{
QRegion region;
float colorTransform[16];
QByteArray value;
if (net_wm_contrast_region != XCB_ATOM_NONE) {
value = w->readProperty(net_wm_contrast_region, net_wm_contrast_region, 32);
if (value.size() > 0 && !((value.size() - (16 * sizeof(uint32_t))) % ((4 * sizeof(uint32_t))))) {
const uint32_t *cardinals = reinterpret_cast<const uint32_t*>(value.constData());
const float *floatCardinals = reinterpret_cast<const float*>(value.constData());
unsigned int i = 0;
for (; i < ((value.size() - (16 * sizeof(uint32_t)))) / sizeof(uint32_t);) {
int x = cardinals[i++];
int y = cardinals[i++];
int w = cardinals[i++];
int h = cardinals[i++];
region += QRect(x, y, w, h);
}
const QByteArray value = w->readProperty(net_wm_contrast_region, net_wm_contrast_region, 32);
if (value.size() > 0 && !((value.size() - (16 * sizeof(uint32_t))) % ((4 * sizeof(uint32_t))))) {
const uint32_t *cardinals = reinterpret_cast<const uint32_t*>(value.constData());
const float *floatCardinals = reinterpret_cast<const float*>(value.constData());
unsigned int i = 0;
for (; i < ((value.size() - (16 * sizeof(uint32_t)))) / sizeof(uint32_t);) {
int x = cardinals[i++];
int y = cardinals[i++];
int w = cardinals[i++];
int h = cardinals[i++];
region += QRect(x, y, w, h);
}
for (unsigned int j = 0; j < 16; ++j) {
colorTransform[j] = floatCardinals[i + j];
}
for (unsigned int j = 0; j < 16; ++j) {
colorTransform[j] = floatCardinals[i + j];
QMatrix4x4 colorMatrix(colorTransform);
m_colorMatrices[w] = colorMatrix;
}
QMatrix4x4 colorMatrix(colorTransform);
m_colorMatrices[w] = colorMatrix;
}
KWayland::Server::SurfaceInterface *surf = w->surface();
......@@ -159,7 +169,7 @@ void ContrastEffect::slotWindowDeleted(EffectWindow *w)
void ContrastEffect::slotPropertyNotify(EffectWindow *w, long atom)
{
if (w && atom == net_wm_contrast_region) {
if (w && atom == net_wm_contrast_region && net_wm_contrast_region != XCB_ATOM_NONE) {
updateContrastRegion(w);
}
}
......
......@@ -73,6 +73,13 @@ BlurEffect::BlurEffect()
connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*)));
connect(effects, SIGNAL(propertyNotify(KWin::EffectWindow*,long)), this, SLOT(slotPropertyNotify(KWin::EffectWindow*,long)));
connect(effects, SIGNAL(screenGeometryChanged(QSize)), this, SLOT(slotScreenGeometryChanged()));
connect(effects, &EffectsHandler::xcbConnectionChanged, this,
[this] {
if (shader && shader->isValid() && target->valid()) {
net_wm_blur_region = effects->announceSupportProperty(s_blurAtomName, this);
}
}
);
// Fetch the blur regions for all windows
foreach (EffectWindow *window, effects->stackingOrder())
......@@ -116,16 +123,19 @@ void BlurEffect::reconfigure(ReconfigureFlags flags)
void BlurEffect::updateBlurRegion(EffectWindow *w) const
{
QRegion region;
const QByteArray value = w->readProperty(net_wm_blur_region, XCB_ATOM_CARDINAL, 32);
if (value.size() > 0 && !(value.size() % (4 * sizeof(uint32_t)))) {
const uint32_t *cardinals = reinterpret_cast<const uint32_t*>(value.constData());
for (unsigned int i = 0; i < value.size() / sizeof(uint32_t);) {
int x = cardinals[i++];
int y = cardinals[i++];
int w = cardinals[i++];
int h = cardinals[i++];
region += QRect(x, y, w, h);
QByteArray value;
if (net_wm_blur_region != XCB_ATOM_NONE) {
value = w->readProperty(net_wm_blur_region, XCB_ATOM_CARDINAL, 32);
if (value.size() > 0 && !(value.size() % (4 * sizeof(uint32_t)))) {
const uint32_t *cardinals = reinterpret_cast<const uint32_t*>(value.constData());
for (unsigned int i = 0; i < value.size() / sizeof(uint32_t);) {
int x = cardinals[i++];
int y = cardinals[i++];
int w = cardinals[i++];
int h = cardinals[i++];
region += QRect(x, y, w, h);
}
}
}
......@@ -171,7 +181,7 @@ void BlurEffect::slotWindowDeleted(EffectWindow *w)
void BlurEffect::slotPropertyNotify(EffectWindow *w, long atom)
{
if (w && atom == net_wm_blur_region) {
if (w && atom == net_wm_blur_region && net_wm_blur_region != XCB_ATOM_NONE) {
updateBlurRegion(w);
CacheEntry it = windows.find(w);
if (it != windows.end()) {
......
......@@ -33,6 +33,11 @@ HighlightWindowEffect::HighlightWindowEffect()
connect(effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*)));
connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*)));
connect(effects, SIGNAL(propertyNotify(KWin::EffectWindow*,long)), this, SLOT(slotPropertyNotify(KWin::EffectWindow*,long)));
connect(effects, &EffectsHandler::xcbConnectionChanged, this,
[this] {
m_atom = effects->announceSupportProperty("_KDE_WINDOW_HIGHLIGHT", this);
}
);
}
HighlightWindowEffect::~HighlightWindowEffect()
......@@ -131,7 +136,7 @@ void HighlightWindowEffect::slotWindowDeleted(EffectWindow* w)
void HighlightWindowEffect::slotPropertyNotify(EffectWindow* w, long a, EffectWindow *addedWindow)
{
if (a != m_atom)
if (a != m_atom || m_atom == XCB_ATOM_NONE)
return; // Not our atom
// if the window is null, the property was set on the root window - see events.cpp
......
......@@ -57,6 +57,11 @@ KscreenEffect::KscreenEffect()
{
initConfig<KscreenConfig>();
connect(effects, SIGNAL(propertyNotify(KWin::EffectWindow*,long)), SLOT(propertyNotify(KWin::EffectWindow*,long)));
connect(effects, &EffectsHandler::xcbConnectionChanged, this,
[this] {
m_atom = effects->announceSupportProperty(QByteArrayLiteral("_KDE_KWIN_KSCREEN_SUPPORT"), this);
}
);
reconfigure(ReconfigureAll);
}
......@@ -119,7 +124,7 @@ void KscreenEffect::paintWindow(EffectWindow *w, int mask, QRegion region, Windo
void KscreenEffect::propertyNotify(EffectWindow *window, long int atom)
{
if (window || atom != m_atom) {
if (window || atom != m_atom || m_atom == XCB_ATOM_NONE) {
return;
}
QByteArray byteData = effects->readRootProperty(m_atom, XCB_ATOM_CARDINAL, 32);
......@@ -169,7 +174,7 @@ void KscreenEffect::switchState()
m_state = StateNormal;
value = 0l;
}
if (value != -1l) {
if (value != -1l && m_atom != XCB_ATOM_NONE) {
xcb_change_property(xcbConnection(), XCB_PROP_MODE_REPLACE, x11RootWindow(), m_atom, XCB_ATOM_CARDINAL, 32, 1, &value);
}
}
......
......@@ -66,8 +66,12 @@ PresentWindowsEffect::PresentWindowsEffect()
, m_exposeClassAction(new QAction(this))
{
initConfig<PresentWindowsConfig>();
m_atomDesktop = effects->announceSupportProperty("_KDE_PRESENT_WINDOWS_DESKTOP", this);
m_atomWindows = effects->announceSupportProperty("_KDE_PRESENT_WINDOWS_GROUP", this);
auto announceSupportProperties = [this] {
m_atomDesktop = effects->announceSupportProperty("_KDE_PRESENT_WINDOWS_DESKTOP", this);
m_atomWindows = effects->announceSupportProperty("_KDE_PRESENT_WINDOWS_GROUP", this);
};
announceSupportProperties();
connect(effects, &EffectsHandler::xcbConnectionChanged, this, announceSupportProperties);
QAction* exposeAction = m_exposeAction;
exposeAction->setObjectName(QStringLiteral("Expose"));
......@@ -829,6 +833,9 @@ void PresentWindowsEffect::grabbedKeyboardEvent(QKeyEvent *e)
// Atom handling
void PresentWindowsEffect::slotPropertyNotify(EffectWindow* w, long a)
{
if (m_atomDesktop == XCB_ATOM_NONE && m_atomWindows == XCB_ATOM_NONE) {
return;
}
if (!w || (a != m_atomDesktop && a != m_atomWindows))
return; // Not our atom
......@@ -1617,9 +1624,9 @@ void PresentWindowsEffect::setActive(bool active)
// destroy atom on manager window
if (m_managerWindow) {
if (m_mode == ModeSelectedDesktop)
if (m_mode == ModeSelectedDesktop && m_atomDesktop != XCB_ATOM_NONE)
m_managerWindow->deleteProperty(m_atomDesktop);
else if (m_mode == ModeWindowGroup)
else if (m_mode == ModeWindowGroup && m_atomWindows != XCB_ATOM_NONE)
m_managerWindow->deleteProperty(m_atomWindows);
m_managerWindow = NULL;
}
......
......@@ -48,6 +48,11 @@ SlidingPopupsEffect::SlidingPopupsEffect()
connect(effects, SIGNAL(propertyNotify(KWin::EffectWindow*,long)), this, SLOT(slotPropertyNotify(KWin::EffectWindow*,long)));
connect(effects, &EffectsHandler::windowShown, this, &SlidingPopupsEffect::startForShow);
connect(effects, &EffectsHandler::windowHidden, this, &SlidingPopupsEffect::slotWindowClosed);
connect(effects, &EffectsHandler::xcbConnectionChanged, this,
[this] {
mAtom = effects->announceSupportProperty(QByteArrayLiteral("_KDE_SLIDE"), this);
}
);
reconfigure(ReconfigureAll);
}
......@@ -273,7 +278,9 @@ void SlidingPopupsEffect::postPaintWindow(EffectWindow* w)
void SlidingPopupsEffect::slotWindowAdded(EffectWindow *w)
{
//X11
slotPropertyNotify(w, mAtom);
if (mAtom != XCB_ATOM_NONE) {
slotPropertyNotify(w, mAtom);
}
//Wayland
if (auto surf = w->surface()) {
......@@ -354,7 +361,7 @@ void SlidingPopupsEffect::slotWindowDeleted(EffectWindow* w)
void SlidingPopupsEffect::slotPropertyNotify(EffectWindow* w, long a)
{
if (!w || a != mAtom)
if (!w || a != mAtom || mAtom == XCB_ATOM_NONE)
return;
QByteArray data = w->readProperty(mAtom, mAtom, 32);
......
......@@ -1682,6 +1682,18 @@ Q_SIGNALS:
**/
void windowDataChanged(KWin::EffectWindow *w, int role);
/**
* The xcb connection changed, either a new xcbConnection got created or the existing one
* got destroyed.
* Effects can use this to refetch the properties they want to set.
*
* When the xcbConnection changes also the @link{x11RootWindow} becomes invalid.
* @see xcbConnection
* @see x11RootWindow
* @since 5.11
**/
void xcbConnectionChanged();
protected:
QVector< EffectPair > loaded_effects;
//QHash< QString, EffectFactory* > effect_factories;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment