diff --git a/effects/maximize/package/contents/code/maximize.js b/effects/maximize/package/contents/code/maximize.js --- a/effects/maximize/package/contents/code/maximize.js +++ b/effects/maximize/package/contents/code/maximize.js @@ -17,25 +17,47 @@ along with this program. If not, see . *********************************************************************/ /*global effect, effects, animate, animationTime, Effect*/ + +// This effect depends on order in which windowGeometryShapeChanged +// and windowMaximizedStateChanged signals are emitted. That order +// is different for X11 and Wayland clients: +// +// On X11, those signals are emitted in the following order(for both +// maximize and restore): +// * windowGeometryShapeChanged +// * windowGeometryShapeChanged +// * windowGeometryShapeChanged +// * windowMaximizedStateChanged +// +// we usually care only about geometries in the last windowGeometryShapeChanged. +// The maximize animation should be started after windowMaximizedStateChanged +// has been emitted. +// +// On Wayland, those signals are emitted in different order for both maximize +// and restore: +// +// maximize: +// * windowGeometryShapeChanged +// * windowGeometryShapeChanged +// * windowMaximizedStateChanged +// * windowGeometryShapeChanged +// +// restore: +// * windowGeometryShapeChanged +// * windowMaximizedStateChanged +// * windowGeometryShapeChanged +// +// in both cases, we care only about geometries in the last windowGeometryShapeChanged +// signal. Thus, the maximize animation should be started after that signal is emitted. + var maximizeEffect = { duration: animationTime(250), loadConfig: function () { "use strict"; maximizeEffect.duration = animationTime(250); }, - maximizeChanged: function (window) { - "use strict"; - if (!window.oldGeometry) { - return; - } + startAnimation: function (window, oldGeometry, newGeometry) { window.setData(Effect.WindowForceBlurRole, true); - var oldGeometry, newGeometry; - oldGeometry = window.oldGeometry; - newGeometry = window.geometry; - if (oldGeometry.width == newGeometry.width && oldGeometry.height == newGeometry.height) - oldGeometry = window.olderGeometry; - window.olderGeometry = window.oldGeometry; - window.oldGeometry = newGeometry; window.maximizeAnimation1 = animate({ window: window, duration: maximizeEffect.duration, @@ -73,10 +95,20 @@ }); } }, - restoreForceBlurState: function(window) { - window.setData(Effect.WindowForceBlurRole, null); + maximizeChangedX11: function (window) { + "use strict"; + if (!window.oldGeometry) { + return; + } + var oldGeometry = window.oldGeometry; + var newGeometry = window.geometry; + if (oldGeometry.width == newGeometry.width && oldGeometry.height == newGeometry.height) + oldGeometry = window.olderGeometry; + window.olderGeometry = window.oldGeometry; + window.oldGeometry = newGeometry; + maximizeEffect.startAnimation(window, oldGeometry, newGeometry); }, - geometryChange: function (window, oldGeometry) { + geometryChangedX11: function (window, oldGeometry) { "use strict"; if (window.maximizeAnimation1) { if (window.geometry.width != window.oldGeometry.width || @@ -92,10 +124,40 @@ window.oldGeometry = window.geometry; window.olderGeometry = oldGeometry; }, + maximizeChangedWayland: function (window) { + "use strict"; + window.waylandCanStartAnimation = true; + }, + geometryChangedWayland: function (window, oldGeometry) { + "use strict"; + if (window.waylandCanStartAnimation) { + delete window.waylandCanStartAnimation; + maximizeEffect.startAnimation(window, oldGeometry, window.geometry); + } + }, + maximizeChanged: function (window) { + "use strict"; + if (window.waylandClient) { + maximizeEffect.maximizeChangedWayland(window); + } else { + maximizeEffect.maximizeChangedX11(window); + } + }, + geometryChanged: function (window, oldGeometry) { + "use strict"; + if (window.waylandClient) { + maximizeEffect.geometryChangedWayland(window, oldGeometry); + } else { + maximizeEffect.geometryChangedX11(window, oldGeometry); + } + }, + restoreForceBlurState: function(window) { + window.setData(Effect.WindowForceBlurRole, null); + }, init: function () { "use strict"; effect.configChanged.connect(maximizeEffect.loadConfig); - effects.windowGeometryShapeChanged.connect(maximizeEffect.geometryChange); + effects.windowGeometryShapeChanged.connect(maximizeEffect.geometryChanged); effects.windowMaximizedStateChanged.connect(maximizeEffect.maximizeChanged); effect.animationEnded.connect(maximizeEffect.restoreForceBlurState); } diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1963,6 +1963,19 @@ * @since 5.10 */ Q_PROPERTY(bool unresponsive READ isUnresponsive) + + /** + * Whether this client is an X11 client. + * @since 5.XX + **/ + Q_PROPERTY(bool x11Client READ isX11Client) + + /** + * Whether this client is a Wayland client. + * @since 5.XX + **/ + Q_PROPERTY(bool waylandClient READ isWaylandClient) + public: /** Flags explaining why painting should be disabled */ enum { @@ -2214,6 +2227,16 @@ */ bool isUnresponsive() const; + /** + * @since 5.XX + **/ + bool isX11Client() const; + + /** + * @since 5.XX + **/ + bool isWaylandClient() const; + /** * Can be used to by effects to store arbitrary data in the EffectWindow. * diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -775,6 +775,8 @@ EffectWindow *q; bool managed = false; + bool x11Client; + bool waylandClient; }; EffectWindow::Private::Private(EffectWindow *q) @@ -794,6 +796,9 @@ // an instance of Deleted becomes parent of the EffectWindow, effects // can still figure out whether it is/was a managed window. d->managed = parent->property("managed").value(); + + d->waylandClient = qstrcmp(parent->metaObject()->className(), "KWin::ShellClient") == 0; + d->x11Client = !d->waylandClient; // parent can be either X11 or Wayland client. } EffectWindow::~EffectWindow() @@ -991,6 +996,15 @@ return d->managed; } +bool EffectWindow::isX11Client() const +{ + return d->x11Client; +} + +bool EffectWindow::isWaylandClient() const +{ + return d->waylandClient; +} //**************************************** // EffectWindowGroup