diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -338,6 +338,12 @@ **/ 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/platform.cpp b/platform.cpp --- a/platform.cpp +++ b/platform.cpp @@ -22,6 +22,7 @@ #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 @@ 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/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -62,6 +62,8 @@ 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/plugins/platforms/x11/standalone/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -29,14 +29,16 @@ #if HAVE_X11_XINPUT #include "xinputintegration.h" #endif +#include "abstract_client.h" #include "eglonxbackend.h" #include "keyboard_input.h" #include "logging.h" #include "screens_xrandr.h" #include "screenedges_filter.h" #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 @@ 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/useractions.cpp b/useractions.cpp --- a/useractions.cpp +++ b/useractions.cpp @@ -1705,54 +1705,7 @@ 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