8#include "windoweffects.h"
11#include <QExposeEvent>
12#include <QGuiApplication>
14#include <qpa/qplatformwindow_p.h>
16#include <QWaylandClientExtensionTemplate>
17#include <qwaylandclientextension.h>
19#include "qwayland-blur.h"
20#include "qwayland-contrast.h"
21#include "qwayland-slide.h"
23#include "surfacehelper.h"
25#include <wayland-client-protocol.h>
27static wl_region *createRegion(
const QRegion ®ion)
29 QPlatformNativeInterface *native = qGuiApp->platformNativeInterface();
33 auto compositor =
reinterpret_cast<wl_compositor *
>(native->nativeResourceForIntegration(QByteArrayLiteral(
"compositor")));
37 auto wl_region = wl_compositor_create_region(compositor);
38 for (
const auto &rect : region) {
39 wl_region_add(wl_region, rect.x(), rect.y(), rect.width(), rect.height());
44class BlurManager :
public QWaylandClientExtensionTemplate<BlurManager>,
public QtWayland::org_kde_kwin_blur_manager
48 : QWaylandClientExtensionTemplate<BlurManager>(1)
53class Blur :
public QObject,
public QtWayland::org_kde_kwin_blur
58 , QtWayland::org_kde_kwin_blur(object)
68class ContrastManager :
public QWaylandClientExtensionTemplate<ContrastManager>,
public QtWayland::org_kde_kwin_contrast_manager
72 : QWaylandClientExtensionTemplate<ContrastManager>(2)
77class Contrast :
public QObject,
public QtWayland::org_kde_kwin_contrast
80 Contrast(struct ::org_kde_kwin_contrast *
object,
QObject *
parent)
82 , QtWayland::org_kde_kwin_contrast(object)
92class SlideManager :
public QWaylandClientExtensionTemplate<SlideManager>,
public QtWayland::org_kde_kwin_slide_manager
96 : QWaylandClientExtensionTemplate<SlideManager>(1)
101class Slide :
public QObject,
public QtWayland::org_kde_kwin_slide
106 , QtWayland::org_kde_kwin_slide(object)
116WindowEffects::WindowEffects()
118 , KWindowEffectsPrivate()
120 m_blurManager =
new BlurManager();
121 m_contrastManager =
new ContrastManager();
122 m_slideManager =
new SlideManager();
128 connect(m_blurManager, &BlurManager::activeChanged,
this, [
this] {
129 for (
auto it = m_blurRegions.constBegin(); it != m_blurRegions.constEnd(); ++it) {
130 installBlur(it.key(), m_blurManager->isActive(), *it);
134 connect(m_contrastManager, &ContrastManager::activeChanged,
this, [
this] {
135 for (
auto it = m_backgroundConstrastRegions.constBegin(); it != m_backgroundConstrastRegions.constEnd(); ++it) {
136 if (m_contrastManager->isActive()) {
137 installContrast(it.key(),
true, it->contrast, it->intensity, it->saturation, it->region);
139 installContrast(it.key(),
false);
144 connect(m_slideManager, &SlideManager::activeChanged,
this, [
this] {
145 for (
auto it = m_slideMap.constBegin(); it != m_slideMap.constEnd(); ++it) {
146 if (m_slideManager->isActive()) {
147 installSlide(it.key(), it->location, it->offset);
149 installSlide(it.key(), KWindowEffects::SlideFromLocation::NoEdge, 0);
155WindowEffects::~WindowEffects()
157 delete m_blurManager;
158 delete m_contrastManager;
159 delete m_slideManager;
162void WindowEffects::trackWindow(
QWindow *window)
164 if (!m_windowWatchers.
contains(window)) {
168 m_blurRegions.
remove(window);
169 resetContrast(window);
170 m_backgroundConstrastRegions.
remove(window);
171 m_slideMap.
remove(window);
172 m_windowWatchers.
remove(window);
174 m_windowWatchers[
window] << conn;
175 auto waylandWindow =
window->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
177 auto conn =
connect(waylandWindow, &QNativeInterface::Private::QWaylandWindow::surfaceDestroyed,
this, [
this, window]() {
179 resetContrast(window);
181 m_windowWatchers[
window] << conn;
186void WindowEffects::releaseWindow(
QWindow *window)
188 if (!m_blurRegions.
contains(window) && !m_backgroundConstrastRegions.
contains(window) && !m_slideMap.
contains(window)) {
189 for (
const auto &conn : m_windowWatchers[window]) {
193 m_windowWatchers.
remove(window);
198template<
typename MapType>
199void replaceValue(MapType &map,
typename MapType::key_type key,
typename MapType::mapped_type value)
201 if (
auto oldValue =
map.take(key)) {
202 oldValue->deleteLater();
209void WindowEffects::resetBlur(
QWindow *window, Blur *blur)
211 replaceValue(m_blurs, window, blur);
214void WindowEffects::resetContrast(
QWindow *window, Contrast *contrast)
216 replaceValue(m_contrasts, window, contrast);
219bool WindowEffects::eventFilter(
QObject *watched,
QEvent *event)
223 if (!window || !
window->isExposed()) {
228 auto it = m_blurRegions.
constFind(window);
229 if (it != m_blurRegions.
constEnd()) {
230 installBlur(window,
true, *it);
234 auto it = m_backgroundConstrastRegions.
constFind(window);
235 if (it != m_backgroundConstrastRegions.
constEnd()) {
236 installContrast(window,
true, it->contrast, it->intensity, it->saturation, it->region);
242 installSlide(window, it->location, it->offset);
249bool WindowEffects::isEffectAvailable(KWindowEffects::Effect effect)
252 case KWindowEffects::BackgroundContrast:
253 return m_contrastManager->isActive();
254 case KWindowEffects::BlurBehind:
255 return m_blurManager->isActive();
256 case KWindowEffects::Slide:
257 return m_slideManager->isActive();
263void WindowEffects::slideWindow(
QWindow *window, KWindowEffects::SlideFromLocation location,
int offset)
265 if (location != KWindowEffects::SlideFromLocation::NoEdge) {
266 m_slideMap[
window] = SlideData{
272 m_slideMap.
remove(window);
273 releaseWindow(window);
276 installSlide(window, location, offset);
279void WindowEffects::installSlide(
QWindow *window, KWindowEffects::SlideFromLocation location,
int offset)
281 if (!m_slideManager->isActive()) {
284 wl_surface *surface = surfaceForWindow(window);
286 if (location != KWindowEffects::SlideFromLocation::NoEdge) {
287 auto slide =
new Slide(m_slideManager->create(surface), window);
289 Slide::location convertedLoc;
291 case KWindowEffects::SlideFromLocation::TopEdge:
292 convertedLoc = Slide::location::location_top;
294 case KWindowEffects::SlideFromLocation::LeftEdge:
295 convertedLoc = Slide::location::location_left;
297 case KWindowEffects::SlideFromLocation::RightEdge:
298 convertedLoc = Slide::location::location_right;
300 case KWindowEffects::SlideFromLocation::BottomEdge:
302 convertedLoc = Slide::location::location_bottom;
306 slide->set_location(convertedLoc);
307 slide->set_offset(offset);
310 m_slideManager->unset(surface);
315void WindowEffects::enableBlurBehind(
QWindow *window,
bool enable,
const QRegion ®ion)
319 m_blurRegions[
window] = region;
322 m_blurRegions.
remove(window);
323 releaseWindow(window);
326 installBlur(window, enable, region);
329void WindowEffects::installBlur(
QWindow *window,
bool enable,
const QRegion ®ion)
331 if (!m_blurManager->isActive()) {
335 wl_surface *surface = surfaceForWindow(window);
339 auto wl_region = createRegion(region);
343 auto blur =
new Blur(m_blurManager->create(surface), window);
344 blur->set_region(wl_region);
346 wl_region_destroy(wl_region);
347 resetBlur(window, blur);
350 m_blurManager->unset(surface);
355void WindowEffects::enableBackgroundContrast(
QWindow *window,
bool enable, qreal contrast, qreal intensity, qreal saturation,
const QRegion ®ion)
359 m_backgroundConstrastRegions[
window].contrast = contrast;
360 m_backgroundConstrastRegions[
window].intensity = intensity;
361 m_backgroundConstrastRegions[
window].saturation = saturation;
362 m_backgroundConstrastRegions[
window].region = region;
364 resetContrast(window);
365 m_backgroundConstrastRegions.
remove(window);
366 releaseWindow(window);
369 installContrast(window, enable, contrast, intensity, saturation, region);
372void WindowEffects::installContrast(
QWindow *window,
bool enable, qreal contrast, qreal intensity, qreal saturation,
const QRegion ®ion)
374 if (!m_contrastManager->isActive()) {
378 wl_surface *surface = surfaceForWindow(window);
381 auto wl_region = createRegion(region);
385 auto backgroundContrast =
new Contrast(m_contrastManager->create(surface), window);
386 backgroundContrast->set_region(wl_region);
387 backgroundContrast->set_contrast(wl_fixed_from_double(contrast));
388 backgroundContrast->set_intensity(wl_fixed_from_double(intensity));
389 backgroundContrast->set_saturation(wl_fixed_from_double(saturation));
390 backgroundContrast->commit();
391 wl_region_destroy(wl_region);
392 resetContrast(window, backgroundContrast);
394 resetContrast(window);
395 m_contrastManager->unset(surface);
400#include "moc_windoweffects.cpp"
QVariant location(const QVariant &res)
const_iterator constEnd() const const
const_iterator constFind(const Key &key) const const
bool contains(const Key &key) const const
bool remove(const Key &key)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
bool disconnect(const QMetaObject::Connection &connection)
virtual bool event(QEvent *e)
void installEventFilter(QObject *filterObj)
QObject * parent() const const
T qobject_cast(QObject *object)
void removeEventFilter(QObject *obj)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)