diff --git a/platform.cpp b/platform.cpp
index 8400d4b090..b9bb859f0f 100644
--- a/platform.cpp
+++ b/platform.cpp
@@ -22,6 +22,7 @@ along with this program. If not, see .
#include "abstract_egl_backend.h"
#include "composite.h"
#include "cursor.h"
+#include "effects.h"
#include "input.h"
#include "overlaywindow.h"
#include "outline.h"
@@ -487,4 +488,14 @@ Decoration::Renderer *Platform::createDecorationRenderer(Decoration::DecoratedCl
return nullptr;
}
+void Platform::invertScreen()
+{
+ if (effects) {
+ if (Effect *inverter = static_cast(effects)->provides(Effect::ScreenInversion)) {
+ qCDebug(KWIN_CORE) << "inverting screen using Effect plugin";
+ QMetaObject::invokeMethod(inverter, "toggleScreenInversion", Qt::DirectConnection);
+ }
+ }
+}
+
}
diff --git a/platform.h b/platform.h
index 5c55480c5d..4d9fc27162 100644
--- a/platform.h
+++ b/platform.h
@@ -338,6 +338,12 @@ public:
**/
virtual Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client);
+ /**
+ * Platform specific way to invert the screen.
+ * Default implementation invokes the invert effect
+ **/
+ virtual void invertScreen();
+
public Q_SLOTS:
void pointerMotion(const QPointF &position, quint32 time);
void pointerButtonPressed(quint32 button, quint32 time);
diff --git a/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp
index 34cb91cd13..a2924d6862 100644
--- a/plugins/platforms/x11/standalone/x11_platform.cpp
+++ b/plugins/platforms/x11/standalone/x11_platform.cpp
@@ -29,6 +29,7 @@ along with this program. If not, see .
#if HAVE_X11_XINPUT
#include "xinputintegration.h"
#endif
+#include "abstract_client.h"
#include "eglonxbackend.h"
#include "keyboard_input.h"
#include "logging.h"
@@ -37,6 +38,7 @@ along with this program. If not, see .
#include "options.h"
#include "overlaywindow_x11.h"
#include "non_composited_outline.h"
+#include "workspace.h"
#include "x11_decoration_renderer.h"
#include
@@ -356,4 +358,46 @@ Decoration::Renderer *X11StandalonePlatform::createDecorationRenderer(Decoration
return renderer;
}
+void X11StandalonePlatform::invertScreen()
+{
+ using namespace Xcb::RandR;
+ bool succeeded = false;
+
+ if (Xcb::Extensions::self()->isRandrAvailable()) {
+ const auto active_client = workspace()->activeClient();
+ ScreenResources res((active_client && active_client->window() != XCB_WINDOW_NONE) ? active_client->window() : rootWindow());
+
+ if (!res.isNull()) {
+ for (int j = 0; j < res->num_crtcs; ++j) {
+ auto crtc = res.crtcs()[j];
+ CrtcGamma gamma(crtc);
+ if (gamma.isNull()) {
+ continue;
+ }
+ if (gamma->size) {
+ qCDebug(KWIN_CORE) << "inverting screen using xcb_randr_set_crtc_gamma";
+ const int half = gamma->size / 2 + 1;
+
+ uint16_t *red = gamma.red();
+ uint16_t *green = gamma.green();
+ uint16_t *blue = gamma.blue();
+ for (int i = 0; i < half; ++i) {
+ auto invert = [&gamma, i](uint16_t *ramp) {
+ qSwap(ramp[i], ramp[gamma->size - 1 - i]);
+ };
+ invert(red);
+ invert(green);
+ invert(blue);
+ }
+ xcb_randr_set_crtc_gamma(connection(), crtc, gamma->size, red, green, blue);
+ succeeded = true;
+ }
+ }
+ }
+ }
+ if (!succeeded) {
+ Platform::invertScreen();
+ }
+}
+
}
diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h
index 6f0022ffe5..02a4ae15d8 100644
--- a/plugins/platforms/x11/standalone/x11_platform.h
+++ b/plugins/platforms/x11/standalone/x11_platform.h
@@ -62,6 +62,8 @@ public:
OutlineVisual *createOutline(Outline *outline) override;
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client) override;
+ void invertScreen() override;
+
protected:
void doHideCursor() override;
void doShowCursor() override;
diff --git a/useractions.cpp b/useractions.cpp
index 91bb925cb6..124f9b3f8c 100644
--- a/useractions.cpp
+++ b/useractions.cpp
@@ -1705,54 +1705,7 @@ void Workspace::slotWindowResize()
void Workspace::slotInvertScreen()
{
- using namespace Xcb::RandR;
- bool succeeded = false;
-
- if (Xcb::Extensions::self()->isRandrAvailable()) {
- ScreenResources res((active_client && active_client->window() != XCB_WINDOW_NONE) ? active_client->window() : rootWindow());
-
- if (!res.isNull()) {
- for (int j = 0; j < res->num_crtcs; ++j) {
- auto crtc = res.crtcs()[j];
- CrtcGamma gamma(crtc);
- if (gamma.isNull()) {
- continue;
- }
- if (gamma->size) {
- qCDebug(KWIN_CORE) << "inverting screen using xcb_randr_set_crtc_gamma";
- const int half = gamma->size / 2 + 1;
-
- uint16_t *red = gamma.red();
- uint16_t *green = gamma.green();
- uint16_t *blue = gamma.blue();
- for (int i = 0; i < half; ++i) {
- auto invert = [&gamma, i](uint16_t *ramp) {
- qSwap(ramp[i], ramp[gamma->size - 1 - i]);
- };
- invert(red);
- invert(green);
- invert(blue);
- }
- xcb_randr_set_crtc_gamma(connection(), crtc, gamma->size, red, green, blue);
- succeeded = true;
- }
- }
- }
- }
- if (succeeded)
- return;
-
- //BEGIN effect plugin inversion - atm only works with OpenGL and has an overhead to it
- if (effects) {
- if (Effect *inverter = static_cast(effects)->provides(Effect::ScreenInversion)) {
- qCDebug(KWIN_CORE) << "inverting screen using Effect plugin";
- QMetaObject::invokeMethod(inverter, "toggleScreenInversion", Qt::DirectConnection);
- }
- }
-
- if (!succeeded)
- qCDebug(KWIN_CORE) << "sorry - neither Xrandr, nor XF86VidModeSetGammaRamp worked and there's no inversion supplying effect plugin either";
-
+ kwinApp()->platform()->invertScreen();
}
#undef USABLE_ACTIVE_CLIENT