Skip to content
Commits on Source (3)
compiz (2:0.9.12.2+hypra9) jessie; urgency=medium
[ Colomban Wendling ]
* Fix colorfilter and neg negative filters regarding alpha.
* showmouse: Rewrite guides drawing to be affected by neg and colorfilter.
-- Alex ARNAUD <alexarnaud@hypra.fr> Fri, 03 May 2019 13:29:05 +0200
compiz (2:0.9.12.2+hypra8) jessie; urgency=medium
[ Colomban Wendling ]
......
void blueish_filter_fragment () {
vec3 color = vec3(1.0, 1.0, 1.0) - gl_FragColor.rgb;
color.b = clamp(0.8 + color.b, 0.0, 1.0);
gl_FragColor.rgb = color;
if (gl_FragColor.a > 0.0) {
vec3 color = vec3(1.0, 1.0, 1.0) - (gl_FragColor.rgb / gl_FragColor.a);
color.b = clamp(0.8 + color.b, 0.0, 1.0);
gl_FragColor.rgb = color * gl_FragColor.a;
}
}
void negative_green_fragment () {
gl_FragColor.rgb = vec3(0, 1.0 - gl_FragColor.g, 0);
if (gl_FragColor.a > 0.0) {
gl_FragColor.rgb = vec3(0, (1.0 - gl_FragColor.g / gl_FragColor.a) * gl_FragColor.a, 0);
}
}
......@@ -105,7 +105,9 @@ vec3 negative_lightness_hsl_to_rgb(vec3 hsl) {
}
void negative_lightness_fragment() {
vec3 hsl = negative_lightness_rgb_to_hsl(gl_FragColor.rgb);
hsl.b = 1.0 - hsl.b; // invert L
gl_FragColor.rgb = negative_lightness_hsl_to_rgb(hsl);
if (gl_FragColor.a > 0.0) {
vec3 hsl = negative_lightness_rgb_to_hsl(gl_FragColor.rgb / gl_FragColor.a);
hsl.b = 1.0 - hsl.b; // invert L
gl_FragColor.rgb = negative_lightness_hsl_to_rgb(hsl) * gl_FragColor.a;
}
}
void negative_fragment () {
vec3 color = vec3(1.0, 1.0, 1.0) - gl_FragColor.rgb;
gl_FragColor.rgb = color;
if (gl_FragColor.a > 0.0) {
vec3 color = vec3(1.0, 1.0, 1.0) - (gl_FragColor.rgb / gl_FragColor.a);
gl_FragColor.rgb = color * gl_FragColor.a;
}
}
......@@ -22,11 +22,13 @@
#include "neg.h"
static std::string fragment_function = " \n\
void neg_fragment () { \n\
vec3 color = vec3(1.0, 1.0, 1.0) - gl_FragColor.rgb; \n\
gl_FragColor = vec4(color, gl_FragColor.a); \n\
} \n\
static std::string fragment_function = " \n\
void neg_fragment () { \n\
if (gl_FragColor.a > 0.0) { \n\
vec3 color = vec3(1.0, 1.0, 1.0) - gl_FragColor.rgb / gl_FragColor.a; \n\
gl_FragColor.rgb = color * gl_FragColor.a; \n\
} \n\
} \n\
";
COMPIZ_PLUGIN_20090315 (neg, NegPluginVTable);
......
......@@ -2,4 +2,7 @@ find_package (Compiz REQUIRED)
include (CompizPlugin)
compiz_plugin (showmouse PLUGINDEPS composite opengl mousepoll)
compiz_plugin (showmouse
PLUGINDEPS composite opengl mousepoll
PKGDEPS cairo cairo-xlib
LIBRARIES Xrender)
......@@ -27,8 +27,17 @@
*
*/
#include <cairo/cairo-xlib.h>
#include "showmouse.h"
#include <X11/Xatom.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/shape.h>
#include <core/atoms.h>
COMPIZ_PLUGIN_20090315 (showmouse, ShowmousePluginVTable);
/* 3 vertices per triangle, 2 triangles per particle */
......@@ -487,6 +496,14 @@ ShowmouseScreen::doDamageRegion ()
void
ShowmouseScreen::positionUpdate (const CompPoint &p)
{
if (optionGetGuideThickness () > 0)
{
cairo_t *cr = overlayWindow.createCairoContext ();
paintGuides (cr, p);
cairo_destroy (cr);
}
mousePos = p;
}
......@@ -499,7 +516,7 @@ ShowmouseScreen::preparePaint (int f_time)
pollHandle.start ();
}
if (active && !ps.active)
if (active && !ps.active && optionGetEmitters () > 0)
{
ps.initParticles (optionGetNumParticles ());
ps.slowdown = optionGetSlowdown ();
......@@ -528,7 +545,7 @@ ShowmouseScreen::preparePaint (int f_time)
doDamageRegion ();
}
if (active)
if (active && optionGetEmitters () > 0)
genNewParticles (f_time);
cScreen->preparePaint (f_time);
......@@ -537,7 +554,7 @@ ShowmouseScreen::preparePaint (int f_time)
void
ShowmouseScreen::donePaint ()
{
if (active || (ps.active))
if (ps.active)
doDamageRegion ();
if (!active && pollHandle.active ())
......@@ -570,63 +587,337 @@ ShowmouseScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
drawGuides (sTransform);
if (optionGetEmitters () > 0)
ps.drawParticles (sTransform);
ps.drawParticles (sTransform);
return status;
}
/* copied from Wallpaper plugin */
static Visual *
findArgbVisual (Display *dpy,
int screen)
{
XVisualInfo temp;
int nvi;
temp.screen = screen;
temp.depth = 32;
temp.c_class = TrueColor;
XVisualInfo *xvi = XGetVisualInfo (dpy,
VisualScreenMask |
VisualDepthMask |
VisualClassMask,
&temp,
&nvi);
if (!xvi)
return 0;
Visual *visual = 0;
XRenderPictFormat *format;
for (int i = 0; i < nvi; ++i)
{
format = XRenderFindVisualFormat (dpy, xvi[i].visual);
if (format->type == PictTypeDirect && format->direct.alphaMask)
{
visual = xvi[i].visual;
break;
}
}
XFree (xvi);
return visual;
}
OverlayWindow::OverlayWindow (CompScreen *screen) :
screen (screen),
mWindow (0),
mSurface (0),
xOffset (0),
yOffset (0)
{
}
OverlayWindow::~OverlayWindow ()
{
if (mWindow)
XDestroyWindow (screen->dpy (), mWindow);
if (mSurface)
cairo_surface_destroy (mSurface);
}
XID
OverlayWindow::window (bool create)
{
if (!mWindow && create)
{
Display *dpy = screen->dpy ();
XSizeHints xsh;
XWMHints xwmh;
XClassHint xch;
Atom state[] = {
Atoms::winStateAbove,
Atoms::winStateSticky,
Atoms::winStateSkipTaskbar,
Atoms::winStateSkipPager,
};
XSetWindowAttributes attr;
Visual *visual;
XserverRegion region;
visual = findArgbVisual (dpy, screen->screenNum ());
if (!visual)
return None;
xsh.flags = PSize | PPosition | PWinGravity;
xsh.width = screen->width ();
xsh.height = screen->height ();
xsh.win_gravity = StaticGravity;
xwmh.flags = InputHint;
xwmh.input = 0;
xch.res_name = (char *)"compiz";
xch.res_class = (char *)"mouselocalizer-window";
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap (dpy, screen->root (),
visual, AllocNone);
attr.override_redirect = true;
mWindow =
XCreateWindow (dpy, screen->root (),
0, 0,
(unsigned) xsh.width, (unsigned) xsh.height, 0,
32, InputOutput, visual,
CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect, &attr);
XSelectInput (dpy, mWindow, ExposureMask | StructureNotifyMask);
XSetWMProperties (dpy, mWindow, NULL, NULL,
programArgv, programArgc,
&xsh, &xwmh, &xch);
XChangeProperty (dpy, mWindow,
Atoms::winState,
XA_ATOM, 32, PropModeReplace,
(unsigned char *) state,
sizeof state / sizeof *state);
XChangeProperty (dpy, mWindow,
Atoms::winType,
XA_ATOM, 32, PropModeReplace,
(unsigned char *) &Atoms::winTypeUtil, 1);
screen->setWindowProp (mWindow, Atoms::winDesktop, 0xffffffff);
/* make the window an output-only window by having no shape for input */
region = XFixesCreateRegion (dpy, NULL, 0);
XFixesSetWindowShapeRegion (dpy, mWindow, ShapeBounding, 0, 0, None);
XFixesSetWindowShapeRegion (dpy, mWindow, ShapeInput, 0, 0, region);
XFixesDestroyRegion (dpy, region);
mSurface = cairo_xlib_surface_create (dpy,
mWindow, visual,
xsh.width, xsh.height);
}
return mWindow;
}
void
ShowmouseScreen::drawLine (const GLMatrix &transform,
double x1, double y1, double x2, double y2,
unsigned short *color)
OverlayWindow::handleEvent (XEvent *event)
{
switch (event->type)
{
case ConfigureNotify:
if (event->xconfigure.window == mWindow)
{
xOffset = event->xconfigure.x;
yOffset = event->xconfigure.y;
}
break;
case MapNotify:
if (event->xmap.window == mWindow)
{
XWindowAttributes attr;
XGetWindowAttributes (event->xmap.display, event->xmap.window, &attr);
xOffset = attr.x;
yOffset = attr.y;
}
else if (mWindow)
XRaiseWindow (screen->dpy (), mWindow);
break;
}
}
cairo_t *
OverlayWindow::createCairoContext ()
{
GLVertexBuffer *stream = GLVertexBuffer::streamingBuffer ();
GLfloat vertices[6] =
{GLfloat(x1), GLfloat(y1), GLfloat(0), GLfloat(x2), GLfloat(y2), GLfloat(0)};
if (! mSurface)
window (true);
cairo_t *cr = cairo_create (mSurface);
cairo_translate (cr, -xOffset, -yOffset);
stream->begin (GL_LINES);
stream->addColors (1, color);
stream->addVertices (2, vertices);
if (stream->end ())
stream->render (transform);
return cr;
}
void
ShowmouseScreen::drawGuides (const GLMatrix &transform)
{
unsigned short *color = optionGetGuideColor ();
float x = mousePos.x ();
float y = mousePos.y ();
float thickness = optionGetGuideThickness ();
float r = optionGetGuideEmptyRadius ();
// If the thickness is zero we don't have to draw, but we should
// still mark the region where the guides should be as damaged --
// this is useful when thickness has just been changed.
if (thickness > 0)
{
glLineWidth (thickness);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
drawLine (transform, x, 0, x, y - r, color);
drawLine (transform, x, y + r, x, screen->height (), color);
drawLine (transform, 0, y, x - r, y, color);
drawLine (transform, x + r, y, screen->width (), y, color);
glDisable (GL_BLEND);
}
OverlayWindow::show ()
{
XMapWindow (screen->dpy (), window (true));
}
// This has to be manually synchronized with the maximum value in
// showmouse.xml.in. The code generated from the XML file keeps
// the value private.
thickness = 20;
cScreen->damageRegion (CompRegion(0, y - thickness / 2 - 1,
screen->width (), thickness + 1));
cScreen->damageRegion (CompRegion(x - thickness / 2 - 1, 0,
thickness + 1, screen->height ()));
void
OverlayWindow::hide ()
{
if (mWindow)
XUnmapWindow (screen->dpy (), mWindow);
}
/*
* Shapes the crosshairs on the cairo context. This can be used for
* painting, clipping or anything else that requires a Cairo shape.
*/
void
ShowmouseScreen::shapeGuides (cairo_t *cr, const CompPoint &pos)
{
int thickness = optionGetGuideThickness ();
int empty_radius = optionGetGuideEmptyRadius ();
int x = pos.x ();
int y = pos.y ();
cairo_rectangle (cr,
0,
y - thickness / 2,
x - empty_radius,
thickness);
cairo_rectangle (cr,
x + empty_radius,
y - thickness / 2,
screen->width () - x - empty_radius,
thickness);
cairo_rectangle (cr,
x - thickness / 2,
0,
thickness,
y - empty_radius);
cairo_rectangle (cr,
x - thickness / 2,
y + empty_radius,
thickness,
screen->height () - y - empty_radius);
}
void
ShowmouseScreen::paintGuides (cairo_t *cr, const CompPoint &newPos)
{
unsigned short *color = optionGetGuideColor ();
shapeGuides (cr, mousePos);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_fill (cr);
shapeGuides (cr, newPos);
cairo_set_source_rgba (cr,
color[0] / 65535.0,
color[1] / 65535.0,
color[2] / 65535.0,
color[3] / 65535.0);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_fill (cr);
}
void
ShowmouseScreen::showOverlayWindow ()
{
screen->handleEventSetEnabled (this, true);
overlayWindow.show ();
}
void
ShowmouseScreen::hideOverlayWindow ()
{
overlayWindow.hide ();
screen->handleEventSetEnabled (this, false);
}
void
ShowmouseScreen::clearOverlayWindow ()
{
cairo_t *cr = overlayWindow.createCairoContext ();
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
paintGuides (cr, mousePos);
cairo_destroy (cr);
}
void
ShowmouseScreen::handleEvent (XEvent *event)
{
screen->handleEvent (event);
overlayWindow.handleEvent (event);
switch (event->type)
{
case Expose:
if (active && event->xexpose.window == overlayWindow.window ())
{
cairo_t *cr = overlayWindow.createCairoContext ();
cairo_rectangle (cr, event->xexpose.x, event->xexpose.y,
event->xexpose.width, event->xexpose.height);
cairo_clip (cr);
paintGuides (cr, mousePos);
cairo_destroy (cr);
}
break;
}
}
void
ShowmouseScreen::setActive (bool newActive)
{
if (active == newActive)
return;
active = newActive;
if (active)
{
toggleFunctions (true);
gScreen->glPaintOutputSetEnabled (gScreen, true);
if (! pollHandle.active ())
{
/* we need a valid initial mouse position right away,
* possibly before next Compiz paint, so retrieve it */
mousePos = MousePoller::getCurrentPosition ();
}
showOverlayWindow ();
/* in case we re-show, we don't always get an EXPOSE event,
* so force an initial redraw */
clearOverlayWindow ();
}
else
{
doDamageRegion ();
gScreen->glPaintOutputSetEnabled (gScreen, false);
hideOverlayWindow ();
}
}
bool
......@@ -634,11 +925,7 @@ ShowmouseScreen::terminate (CompAction *action,
CompAction::State state,
CompOption::Vector options)
{
active = false;
doDamageRegion ();
gScreen->glPaintOutputSetEnabled (gScreen, false);
setActive (false);
return true;
}
......@@ -648,23 +935,14 @@ ShowmouseScreen::initiate (CompAction *action,
CompAction::State state,
CompOption::Vector options)
{
if (active)
return terminate (action, state, options);
active = true;
toggleFunctions (true);
gScreen->glPaintOutputSetEnabled (gScreen, true);
setActive (! active);
return true;
}
bool ShowmouseScreen::checkStartup () {
if (optionGetActivateAtStartup()) {
active = true;
toggleFunctions (true);
gScreen->glPaintOutputSetEnabled (gScreen, true);
setActive (true);
}
timeoutHandle.stop();
return false;
......@@ -676,8 +954,10 @@ ShowmouseScreen::ShowmouseScreen (CompScreen *screen) :
cScreen (CompositeScreen::get (screen)),
gScreen (GLScreen::get (screen)),
active (false),
rot (0.0f)
rot (0.0f),
overlayWindow (screen)
{
ScreenInterface::setHandler (screen, false);
CompositeScreenInterface::setHandler (cScreen, false);
GLScreenInterface::setHandler (gScreen, false);
......@@ -699,6 +979,10 @@ ShowmouseScreen::ShowmouseScreen (CompScreen *screen) :
optionSetInitiateEdgeTerminate (boost::bind (&ShowmouseScreen::terminate,
this, _1, _2, _3));
optionSetGuideThicknessNotify (boost::bind (&ShowmouseScreen::clearOverlayWindow, this));
optionSetGuideEmptyRadiusNotify (boost::bind (&ShowmouseScreen::clearOverlayWindow, this));
optionSetGuideColorNotify (boost::bind (&ShowmouseScreen::clearOverlayWindow, this));
timeoutHandle.setTimes (1, 2);
timeoutHandle.setCallback (boost::bind (&ShowmouseScreen::checkStartup, this));
......
......@@ -105,22 +105,45 @@ class ParticleSystem
finiParticles ();
};
class OverlayWindow
{
private:
CompScreen *screen;
XID mWindow;
cairo_surface_t *mSurface;
/* offset of our window relative to the root, in order to avoid
* offset between crosshairs and actual mouse in case our
* window didn't get placed at 0,0 */
int xOffset;
int yOffset;
public:
OverlayWindow (CompScreen *);
~OverlayWindow ();
XID
window (bool create = false);
void
handleEvent (XEvent *event);
cairo_t *
createCairoContext ();
void
show ();
void
hide ();
};
class ShowmouseScreen :
public ScreenInterface,
public PluginClassHandler <ShowmouseScreen, CompScreen>,
public ShowmouseOptions,
public CompositeScreenInterface,
public GLScreenInterface
{
private:
void
drawGuides (const GLMatrix &transform);
void
drawLine (const GLMatrix &transform,
double x1, double y1, double x2, double y2,
unsigned short *color);
public:
ShowmouseScreen (CompScreen *);
......@@ -140,6 +163,8 @@ class ShowmouseScreen :
MousePoller pollHandle;
CompTimer timeoutHandle;
OverlayWindow overlayWindow;
bool checkStartup ();
void
......@@ -161,9 +186,30 @@ class ShowmouseScreen :
void
doDamageRegion ();
void
shapeGuides (cairo_t *cr,
const CompPoint &newPos);
void
paintGuides (cairo_t *cr,
const CompPoint &newPos);
void
showOverlayWindow ();
void
hideOverlayWindow ();
void
clearOverlayWindow ();
void
handleEvent (XEvent *event);
void
positionUpdate (const CompPoint &p);
void
setActive (bool newActive);
bool
terminate (CompAction *action,
CompAction::State state,
......