14#include <QDBusConnection>
16Q_LOGGING_CATEGORY(KWIN_HIGHLIGHTWINDOW,
"kwin_effect_highlightwindow", QtWarningMsg)
22 : m_easingCurve(QEasingCurve::Linear)
23 , m_fadeDuration(animationTime(150))
24 , m_monitorWindow(nullptr)
38 QDBusConnection::sessionBus().registerObject(QStringLiteral(
"/org/kde/KWin/HighlightWindow"),
39 QStringLiteral(
"org.kde.KWin.HighlightWindow"),
41 QDBusConnection::ExportScriptableContents);
42 QDBusConnection::sessionBus().registerService(QStringLiteral(
"org.kde.KWin.HighlightWindow"));
47 QDBusConnection::sessionBus().unregisterService(QStringLiteral(
"org.kde.KWin.HighlightWindow"));
56static bool isHighlightWindow(EffectWindow *window)
58 return window->isNormalWindow() || window->isDialog();
63 QList<EffectWindow *> effectWindows;
64 effectWindows.reserve(windows.count());
65 for (
const auto &window : windows) {
67 effectWindows.append(effectWindow);
68 }
else if (
auto effectWindow =
effects->
findWindow(window.toLong()); effectWindow) {
69 effectWindows.append(effectWindow);
77 if (!m_highlightedWindows.isEmpty()) {
80 if (m_highlightedWindows.contains(w)) {
84 for (
const WId &
id : std::as_const(m_highlightedIds)) {
86 const quint64 animationId = startHighlightAnimation(w);
91 if (isHighlightWindow(w)) {
92 const quint64 animationId = startGhostAnimation(w);
101 if (m_monitorWindow == w) {
102 finishHighlighting();
108 m_animations.remove(w);
113 if (a != m_atom || m_atom == XCB_ATOM_NONE) {
119 if (byteData.length() < 1) {
121 if (!addedWindow || w != addedWindow) {
122 finishHighlighting();
126 auto *data =
reinterpret_cast<uint32_t *
>(byteData.data());
130 finishHighlighting();
135 int length = byteData.length() /
sizeof(data[0]);
138 m_highlightedWindows.clear();
139 m_highlightedIds.clear();
140 for (
int i = 0; i < length; i++) {
141 m_highlightedIds << data[i];
144 qCDebug(KWIN_HIGHLIGHTWINDOW) <<
"Invalid window targetted for highlight. Requested:" << data[i];
147 m_highlightedWindows.append(foundWin);
154 finishHighlighting();
157 prepareHighlighting();
160void HighlightWindowEffect::prepareHighlighting()
164 if (!isHighlightWindow(window)) {
167 if (isHighlighted(window)) {
168 startHighlightAnimation(window);
170 startGhostAnimation(window);
175void HighlightWindowEffect::finishHighlighting()
178 for (EffectWindow *window : windows) {
179 if (isHighlightWindow(window)) {
180 startRevertAnimation(window);
185 if (!m_animations.isEmpty()) {
186 for (quint64 &animationId : m_animations) {
189 m_animations.clear();
192 m_monitorWindow =
nullptr;
193 m_highlightedWindows.clear();
198 if (windows.isEmpty()) {
199 finishHighlighting();
203 m_monitorWindow =
nullptr;
204 m_highlightedWindows.clear();
205 m_highlightedIds.clear();
206 for (
auto w : windows) {
207 m_highlightedWindows << w;
209 prepareHighlighting();
212quint64 HighlightWindowEffect::startGhostAnimation(EffectWindow *window)
214 quint64 &animationId = m_animations[window];
216 retarget(animationId, FPx2(m_ghostOpacity, m_ghostOpacity), m_fadeDuration);
218 const qreal startOpacity = isInitiallyHidden(window) ? 0 : 1;
219 animationId =
set(window,
Opacity, 0, m_fadeDuration, FPx2(m_ghostOpacity, m_ghostOpacity),
220 m_easingCurve, 0, FPx2(startOpacity, startOpacity),
false,
false);
225quint64 HighlightWindowEffect::startHighlightAnimation(EffectWindow *window)
227 quint64 &animationId = m_animations[window];
229 retarget(animationId, FPx2(1.0, 1.0), m_fadeDuration);
231 const qreal startOpacity = isInitiallyHidden(window) ? 0 : 1;
232 animationId =
set(window,
Opacity, 0, m_fadeDuration, FPx2(1.0, 1.0),
233 m_easingCurve, 0, FPx2(startOpacity, startOpacity),
false,
false);
238void HighlightWindowEffect::startRevertAnimation(EffectWindow *window)
240 const quint64 animationId = m_animations.take(window);
242 const qreal startOpacity = isHighlighted(window) ? 1 : m_ghostOpacity;
243 const qreal endOpacity = isInitiallyHidden(window) ? 0 : 1;
244 animate(window,
Opacity, 0, m_fadeDuration, FPx2(endOpacity, endOpacity),
245 m_easingCurve, 0, FPx2(startOpacity, startOpacity),
false,
false);
250bool HighlightWindowEffect::isHighlighted(EffectWindow *window)
const
252 return m_highlightedWindows.contains(window);
270 if (arguments.size() != 1) {
279#include "moc_highlightwindow.cpp"
quint64 set(EffectWindow *w, Attribute a, uint meta, int ms, const FPx2 &to, const QEasingCurve &curve=QEasingCurve(), int delay=0, const FPx2 &from=FPx2(), bool fullScreen=false, bool keepAlive=true, GLShader *shader=nullptr)
bool complete(quint64 animationId)
bool retarget(quint64 animationId, FPx2 newTarget, int newRemainingTime=-1)
bool cancel(quint64 animationId)
quint64 animate(EffectWindow *w, Attribute a, uint meta, int ms, const FPx2 &to, const QEasingCurve &curve=QEasingCurve(), int delay=0, const FPx2 &from=FPx2(), bool fullScreen=false, bool keepAlive=true, GLShader *shader=nullptr)
Representation of a window used by/for Effect classes.
bool isOnCurrentDesktop() const
QByteArray readProperty(long atom, long type, int format) const
void propertyNotify(KWin::EffectWindow *w, long atom)
void windowDeleted(KWin::EffectWindow *w)
Q_SCRIPTABLE KWin::EffectWindow * findWindow(WId id) const
void windowClosed(KWin::EffectWindow *w)
QList< EffectWindow * > stackingOrder
QByteArray readRootProperty(long atom, long type, int format) const
xcb_atom_t announceSupportProperty(const QByteArray &propertyName, Effect *effect)
Announces support for the feature with the given name. If no other Effect has announced support for t...
void xcbConnectionChanged()
void windowAdded(KWin::EffectWindow *w)
void slotWindowAdded(KWin::EffectWindow *w)
bool perform(Feature feature, const QVariantList &arguments) override
bool provides(Feature feature) override
void slotWindowDeleted(KWin::EffectWindow *w)
~HighlightWindowEffect() override
Q_SCRIPTABLE void highlightWindows(const QStringList &windows)
void slotPropertyNotify(KWin::EffectWindow *w, long atom, EffectWindow *addedWindow=nullptr)
void slotWindowClosed(KWin::EffectWindow *w)