add screen inversion through XF86VidModeSetGammaRamp or XRRSetCrtcGamma

use opengl invert effect as fallback

REVIEW: 104371
This commit is contained in:
Thomas Lübking 2012-03-23 02:06:46 +01:00
parent 1d00436ea4
commit ab86f0e837
8 changed files with 95 additions and 10 deletions

View file

@ -270,12 +270,12 @@ void EffectsHandlerImpl::postPaintWindow(EffectWindow* w)
// no special final code
}
bool EffectsHandlerImpl::provides(Effect::Feature ef)
Effect *EffectsHandlerImpl::provides(Effect::Feature ef)
{
for (int i = 0; i < loaded_effects.size(); ++i)
if (loaded_effects.at(i).second->provides(ef))
return true;
return false;
return loaded_effects.at(i).second;
return NULL;
}
void EffectsHandlerImpl::drawWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)

View file

@ -57,7 +57,7 @@ public:
virtual void postPaintWindow(EffectWindow* w);
virtual void paintEffectFrame(EffectFrame* frame, QRegion region, double opacity, double frameOpacity);
bool provides(Effect::Feature ef);
Effect *provides(Effect::Feature ef);
virtual void drawWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);

View file

@ -48,7 +48,7 @@ InvertEffect::InvertEffect()
KAction* a = (KAction*)actionCollection->addAction("Invert");
a->setText(i18n("Toggle Invert Effect"));
a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::META + Qt::Key_I));
connect(a, SIGNAL(triggered(bool)), this, SLOT(toggle()));
connect(a, SIGNAL(triggered(bool)), this, SLOT(toggleScreenInversion()));
KAction* b = (KAction*)actionCollection->addAction("InvertWindow");
b->setText(i18n("Toggle Invert Effect on Window"));
@ -143,7 +143,7 @@ void InvertEffect::slotWindowClosed(EffectWindow* w)
m_windows.removeOne(w);
}
void InvertEffect::toggle()
void InvertEffect::toggleScreenInversion()
{
m_allWindows = !m_allWindows;
effects->addRepaintFull();
@ -163,6 +163,11 @@ bool InvertEffect::isActive() const
return m_valid && (m_allWindows || !m_windows.isEmpty());
}
bool InvertEffect::provides(Feature f)
{
return f == ScreenInversion;
}
} // namespace
#include "invert.moc"

View file

@ -45,11 +45,12 @@ public:
virtual void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time);
virtual void paintEffectFrame(KWin::EffectFrame* frame, QRegion region, double opacity, double frameOpacity);
virtual bool isActive() const;
virtual bool provides(Feature);
static bool supported();
public slots:
void toggle();
void toggleScreenInversion();
void toggleWindow();
void slotWindowClosed(KWin::EffectWindow *w);

View file

@ -191,6 +191,7 @@ a->setText(i18n("Miscellaneous"));
DEF(I18N_NOOP("Kill Window"), Qt::CTRL + Qt::ALT + Qt::Key_Escape, slotKillWindow());
DEF(I18N_NOOP("Block Global Shortcuts"), 0, slotDisableGlobalShortcuts());
DEF(I18N_NOOP("Suspend Compositing"), Qt::SHIFT + Qt::ALT + Qt::Key_F12, slotToggleCompositing());
DEF(I18N_NOOP("Invert Screen Colors"), 0, slotInvertScreen());
#undef DEF
#undef DEF2

View file

@ -320,8 +320,7 @@ public:
};
enum Feature {
Nothing = 0, Resize, GeometryTip,
Outline
Nothing = 0, Resize, GeometryTip, Outline, ScreenInversion
};
/**
@ -415,7 +414,7 @@ public:
/**
* Called on Transparent resizes.
* return true if your effect substitutes the XOR rubberband
* return true if your effect substitutes questioned feature
*/
virtual bool provides(Feature);

View file

@ -44,6 +44,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KActivities/Info>
#endif
#include <X11/extensions/Xrandr.h>
#ifndef KWIN_NO_XF86VM
#include <X11/extensions/xf86vmode.h>
#endif
#include <fixx11h.h>
#include <QPushButton>
#include <QSlider>
@ -1615,6 +1619,80 @@ void Workspace::slotWindowResize()
performWindowOperation(active_client, Options::UnrestrictedResizeOp);
}
void Workspace::slotInvertScreen()
{
bool succeeded = false;
//BEGIN Xrandr inversion - does atm NOT work with the nvidia blob
XRRScreenResources *res = XRRGetScreenResources(display(), active_client ? active_client->window() : rootWindow());
if (res) {
for (int j = 0; j < res->ncrtc; ++j) {
XRRCrtcGamma *gamma = XRRGetCrtcGamma(display(), res->crtcs[j]);
if (gamma && gamma->size) {
kDebug(1212) << "inverting screen using XRRSetCrtcGamma";
const int half = gamma->size / 2 + 1;
unsigned short swap;
for (int i = 0; i < half; ++i) {
#define INVERT(_C_) swap = gamma->_C_[i]; gamma->_C_[i] = gamma->_C_[gamma->size - 1 - i]; gamma->_C_[gamma->size - 1 - i] = swap
INVERT(red);
INVERT(green);
INVERT(blue);
#undef INVERT
}
XRRSetCrtcGamma(display(), res->crtcs[j], gamma);
XRRFreeGamma(gamma);
succeeded = true;
}
}
XRRFreeScreenResources(res);
}
if (succeeded)
return;
//BEGIN XF86VidMode inversion - only works if optionally libXxf86vm is linked
#ifndef KWIN_NO_XF86VM
int size = 0;
// TODO: this doesn't work with screen numbers in twinview - probably relevant only for multihead?
const int scrn = 0; // active_screen
if (XF86VidModeGetGammaRampSize(display(), scrn, &size)) {
unsigned short *red, *green, *blue;
red = new unsigned short[size];
green = new unsigned short[size];
blue = new unsigned short[size];
if (XF86VidModeGetGammaRamp(display(), scrn, size, red, green, blue)) {
kDebug(1212) << "inverting screen using XF86VidModeSetGammaRamp";
const int half = size / 2 + 1;
unsigned short swap;
for (int i = 0; i < half; ++i) {
swap = red[i]; red[i] = red[size - 1 - i]; red[size - 1 - i] = swap;
swap = green[i]; green[i] = green[size - 1 - i]; green[size - 1 - i] = swap;
swap = blue[i]; blue[i] = blue[size - 1 - i]; blue[size - 1 - i] = swap;
}
XF86VidModeSetGammaRamp(display(), scrn, size, red, green, blue);
succeeded = true;
}
delete [] red;
delete [] green;
delete [] blue;
}
if (succeeded)
return;
#endif
//BEGIN effect plugin inversion - atm only works with OpenGL and has an overhead to it
if (effects) {
if (Effect *inverter = static_cast<EffectsHandlerImpl*>(effects)->provides(Effect::ScreenInversion)) {
kDebug(1212) << "inverting screen using Effect plugin";
QMetaObject::invokeMethod(inverter, "toggleScreenInversion", Qt::DirectConnection);
}
}
if (!succeeded)
kDebug(1212) << "sorry - neither Xrandr, nor XF86VidModeSetGammaRamp worked and there's no inversion supplying effect plugin either";
}
#undef USABLE_ACTIVE_CLIENT
void Client::setShortcut(const QString& _cut)

View file

@ -622,6 +622,7 @@ public slots:
void slotSetupWindowShortcut();
void setupWindowShortcutDone(bool);
void slotToggleCompositing();
void slotInvertScreen();
void updateClientArea();
void suspendCompositing();