add screen inversion through XF86VidModeSetGammaRamp or XRRSetCrtcGamma
use opengl invert effect as fallback REVIEW: 104371
This commit is contained in:
parent
1d00436ea4
commit
ab86f0e837
8 changed files with 95 additions and 10 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -622,6 +622,7 @@ public slots:
|
|||
void slotSetupWindowShortcut();
|
||||
void setupWindowShortcutDone(bool);
|
||||
void slotToggleCompositing();
|
||||
void slotInvertScreen();
|
||||
|
||||
void updateClientArea();
|
||||
void suspendCompositing();
|
||||
|
|
Loading…
Reference in a new issue