/*----------------------------------------------------------------------------*\
| Copyright (C) 2009 - Rafael de O. Lopes Gonçalves and André Shoji Asato |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.|
\*----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <compiz-core.h>
#include <compiz-mousepoll.h>
#include "visocor_options.h"
#include "visocor.h"
int visocorDisplayPrivateIndex;
int visocorCorePrivateIndex;
/* debug function */
void visocorPrintf(CompLogLevel level, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char logInfo[BUFSIZ];
if (vsnprintf(logInfo, BUFSIZ, fmt, args) < 0) {
va_end(args);
return;
}
logMessage(PLUGIN_NAME, level, logInfo);
va_end(args);
}
void visocorToggleWindowToState(CompWindow * w, VisocorWindowState state) {
VISOCOR_WINDOW(w);
vw->lastState = vw->currentState;
vw->currentState = state;
if (matchEval(visocorGetExcludeMatch(w->screen), w))
vw->currentState = OFF;
/*repainting */
addWindowDamage(w);
}
void visocorDamageAllWindows(CompScreen * s) {
CompWindow *w;
for (w = s->windows; w; w = w->next) {
if (w) {
addWindowDamage(w);
}
}
}
CompScreen * visocorFindScreen(CompDisplay * d, CompOption * option,
int nOption) {
CompScreen *s;
Window xid;
xid = getIntOptionNamed(option, nOption, "root", 0);
s = findScreenAtDisplay(d, xid);
return s;
}
CompWindow * visocorFindWindow(CompDisplay * d, CompOption * option,
int nOption) {
CompWindow * w;
Window xid;
xid = getIntOptionNamed(option, nOption, "window", 0);
w = findWindowAtDisplay(d, xid);
return w;
}
static void VISOCORDrawWindowTexture(CompWindow * w, CompTexture * texture,
const FragmentAttrib * attrib, unsigned int mask) {
VISOCOR_SCREEN(w->screen);
VISOCOR_WINDOW(w);
if (vw->currentState != OFF && (texture->name == w->texture->name)) {
if (w->screen->fragmentProgram) {
FragmentAttrib fa = *attrib;
/*aloca 1 argumento de programa*/
int param = allocFragmentParameters(&fa, 2);
int function = 0;
if (vw->currentState == FILTER) {
function = getVisocorFilterFragmentFunction(w->screen, texture,
param);
} else {
function = getVisocorSlicerFragmentFunction(w->screen, texture,
param);
}
if (function) {
addFragmentFunction(&fa, function);
}
UNWRAP(vs, w->screen, drawWindowTexture);
(*w->screen->drawWindowTexture)(w, texture, &fa, mask);
WRAP(vs, w->screen, drawWindowTexture, VISOCORDrawWindowTexture)
;
} else {
logMessage(PLUGIN_NAME, CompLogLevelError,
"not w->screen->fragmentProgram");
}
} else {
UNWRAP(vs, w->screen, drawWindowTexture);
(*w->screen->drawWindowTexture)(w, texture, attrib, mask);
WRAP(vs, w->screen, drawWindowTexture, VISOCORDrawWindowTexture)
;
}
}
static void VISOCORWindowAdd(CompScreen * s, CompWindow * w) {
if (matchEval(visocorGetVisocorMatch(s), w)) {
visocorToggleWindowToState(w, FILTER);
}
}
static void VISOCORScreenOptionChanged(CompScreen * s, CompOption * opt,
VisocorScreenOptions num) {
visocorPrintf(CompLogLevelDebug, "option %d changed", num);
switch (num) {
case VisocorScreenOptionVisocorMatch:
case VisocorScreenOptionExcludeMatch: {
CompWindow *w;
for (w = s->windows; w; w = w->next) {
Bool notExclude;
VISOCOR_WINDOW(w);
notExclude = matchEval(visocorGetVisocorMatch(s), w);
notExclude = notExclude && !matchEval(visocorGetExcludeMatch(s), w);
if (!notExclude && vw->currentState != OFF)
visocorToggleWindowToState(w, OFF);
}
}
break;
default:
break;
}
visocorDamageAllWindows(s);
}
static void visocorObjectAdd(CompObject * parent, CompObject * object) {
static ObjectAddProc dispTab[] = { (ObjectAddProc) 0, /* CoreAdd */
(ObjectAddProc) 0, /* DisplayAdd */
(ObjectAddProc) 0, /* ScreenAdd */
(ObjectAddProc) VISOCORWindowAdd };
VISOCOR_CORE(&core);
UNWRAP(vc, &core, objectAdd);
(*core.objectAdd)(parent, object);
WRAP(vc, &core, objectAdd, visocorObjectAdd);
DISPATCH(object, dispTab, ARRAY_SIZE(dispTab), (parent, object));
}
static Bool VISOCORInitCore(CompPlugin * p, CompCore * c) {
VISOCORCore *vc;
if (!checkPluginABI("core", CORE_ABIVERSION))
return FALSE;
if (!checkPluginABI("mousepoll", MOUSEPOLL_ABIVERSION))
return FALSE;
vc = malloc(sizeof(VISOCORCore));
if (!vc)
return FALSE;
visocorDisplayPrivateIndex = allocateDisplayPrivateIndex();
if (visocorDisplayPrivateIndex < 0) {
free(vc);
return FALSE;
}
WRAP(vc, c, objectAdd, visocorObjectAdd);
c->base.privates[visocorCorePrivateIndex].ptr = vc;
return TRUE;
}
static void VISOCORFiniCore(CompPlugin * p, CompCore * c) {
VISOCOR_CORE(c);
freeDisplayPrivateIndex(visocorDisplayPrivateIndex);
UNWRAP(vc, c, objectAdd);
free(vc);
}
static Bool visocorReset(CompDisplay *d, CompAction *action,
CompActionState state, CompOption *option, int nOption) {
CompScreen * s;
for (s = d->screens; s; s = s->next) {
VISOCOR_SCREEN(s);
CompWindow * w;
for (w = s->windows; w; w = w->next) {
if (w) {
visocorToggleWindowToState(w, OFF);
}
}
visocorResetFilter(vs);
}
return TRUE;
}
static Bool VISOCORInitDisplay(CompPlugin * p, CompDisplay * d) {
VISOCORDisplay *nd;
int mousePoolIndex;
nd = malloc(sizeof(VISOCORDisplay));
if (!nd)
return FALSE;
if (!getPluginDisplayIndex(d, "mousepoll", &mousePoolIndex))
return FALSE;
nd->screenPrivateIndex = allocateScreenPrivateIndex(d);
if (nd->screenPrivateIndex < 0) {
free(nd);
return FALSE;
}
visocorSetIncreaseButtonInitiate(d, visocorIncreaseFilter);
visocorSetDecreaseButtonInitiate(d, visocorDecreaseFilter);
visocorSetWindowToggleKeyInitiate(d, visocorToggleFilter);
visocorSetMousepollClickKeyInitiate(d,
visocorMousepollClickKeyInitiateSlice);
visocorSetMousepollClickKeyTerminate(d,
visocorMousepollClickKeyTerminateSlice);
visocorSetScreenResetKeyInitiate(d, visocorReset);
d->base.privates[visocorDisplayPrivateIndex].ptr = nd;
nd->mousepollFunc = d->base.privates[mousePoolIndex].ptr;
return TRUE;
}
static void VISOCORFiniDisplay(CompPlugin * p, CompDisplay * d) {
VISOCOR_DISPLAY(d);
freeScreenPrivateIndex(d, vd->screenPrivateIndex);
free(vd);
}
static Bool VISOCORInitScreen(CompPlugin * p, CompScreen * s) {
VISOCORScreen *vs;
int i;
VISOCOR_DISPLAY(s->display);
vs = malloc(sizeof(VISOCORScreen));
if (!vs)
return FALSE;
vs->windowPrivateIndex = allocateWindowPrivateIndex(s);
if (vs->windowPrivateIndex < 0) {
free(vs);
return FALSE;
}
visocorResetFilter(vs);
for (i = 0; i < MAX_FRAGMENT_FUNCTIONS; i++) {
vs->visocorFunctions[0][i] = 0;
vs->visocorFunctions[1][i] = 0;
}
visocorSetVisocorMatchNotify(s, VISOCORScreenOptionChanged);
visocorSetExcludeMatchNotify(s, VISOCORScreenOptionChanged);
WRAP(vs, s, drawWindowTexture, VISOCORDrawWindowTexture);
s->base.privates[vd->screenPrivateIndex].ptr = vs;
vs->pollHandle = 0;
visocorDamageAllWindows(s);
return TRUE;
}
static void VISOCORFiniScreen(CompPlugin * p, CompScreen * s) {
int i;
VISOCOR_SCREEN(s);
VISOCOR_DISPLAY(s);
freeWindowPrivateIndex(s, vs->windowPrivateIndex);
UNWRAP(vs, s, drawWindowTexture);
for (i = 0; i < MAX_FRAGMENT_FUNCTIONS; i++) {
if (vs->visocorFunctions[0][i]) {
destroyFragmentFunction(s, vs->visocorFunctions[0][i]);
}
if (vs->visocorFunctions[1][i]) {
destroyFragmentFunction(s, vs->visocorFunctions[1][i]);
}
}
if (vs->pollHandle)
(*vd->mousepollFunc->removePositionPolling)(s, vs->pollHandle);
free(vs);
}
static Bool VISOCORInitWindow(CompPlugin * p, CompWindow * w) {
VISOCORWindow *vw;
VISOCOR_SCREEN(w->screen);
vw = malloc(sizeof(VISOCORWindow));
if (!vw)
return FALSE;
vw->currentState = OFF;
vw->lastState = OFF;
w->base.privates[vs->windowPrivateIndex].ptr = vw;
return TRUE;
}
static void VISOCORFiniWindow(CompPlugin * p, CompWindow * w) {
VISOCOR_WINDOW(w);
free(vw);
}
static Bool VISOCORInit(CompPlugin * p) {
visocorCorePrivateIndex = allocateCorePrivateIndex();
if (visocorCorePrivateIndex < 0)
return FALSE;
return TRUE;
}
static void VISOCORFini(CompPlugin * p) {
freeCorePrivateIndex(visocorCorePrivateIndex);
}
static CompBool VISOCORInitObject(CompPlugin * p, CompObject * o) {
static InitPluginObjectProc dispTab[] = {
(InitPluginObjectProc) VISOCORInitCore,
(InitPluginObjectProc) VISOCORInitDisplay,
(InitPluginObjectProc) VISOCORInitScreen,
(InitPluginObjectProc) VISOCORInitWindow };
RETURN_DISPATCH(o, dispTab, ARRAY_SIZE(dispTab), TRUE, (p, o))
;}
static void VISOCORFiniObject(CompPlugin * p, CompObject * o) {
static FiniPluginObjectProc dispTab[] = {
(FiniPluginObjectProc) VISOCORFiniCore,
(FiniPluginObjectProc) VISOCORFiniDisplay,
(FiniPluginObjectProc) VISOCORFiniScreen,
(FiniPluginObjectProc) VISOCORFiniWindow };
DISPATCH(o, dispTab, ARRAY_SIZE(dispTab), (p, o));
}
CompPluginVTable VISOCORVTable = { "visocor", 0, VISOCORInit, VISOCORFini,
VISOCORInitObject, VISOCORFiniObject, 0, 0, };
CompPluginVTable *
getCompPluginInfo(void) {
return &VISOCORVTable;
}