Newer
Older
/*
* Copyright © 2007 Novell, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Novell, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
* Novell, Inc. makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: David Reveman <davidr@novell.com>
*/
#include <stdlib.h>
#include <string.h>
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH
#include <core/screen.h>
#include <core/window.h>
#include "privatescreen.h"
#include "privatewindow.h"
class CoreExp : public CompMatch::Expression {
public:
typedef enum {
TypeXid,
TypeState,
TypeOverride,
TypeRGBA,
{
if (str.compare (0, 4, "xid=") == 0)
{
mType = TypeXid;
priv.val = strtol (str.substr (4).c_str (), NULL, 0);
}
else if (str.compare (0, 6, "state=") == 0)
{
using ::compiz::private_screen::windowStateFromString;
priv.uval = windowStateFromString(str.substr (6).c_str ());
}
else if (str.compare (0, 18, "override_redirect=") == 0)
mType = TypeOverride;
priv.val = strtol (str.substr (18).c_str (), NULL, 0);
else if (str.compare (0, 5, "rgba=") == 0)
{
mType = TypeRGBA;
priv.val = strtol (str.substr (5).c_str (), NULL, 0);
size_t offset = (str.compare (0, 5, "type=") == 0) ? 5 : 0;
priv.uval = PrivateWindow::windowTypeFromString (
str.substr (offset).c_str ());
bool evaluate (const CompWindow *w) const
{
switch (mType)
{
case TypeXid:
return ((unsigned int) priv.val == w->id ());
case TypeState:
return (priv.uval & w->state ());
case TypeOverride:
{
bool overrideRedirect = w->overrideRedirect ();
return ((priv.val == 1 && overrideRedirect) ||
(priv.val == 0 && !overrideRedirect));
}
case TypeRGBA:
return ((priv.val && w->alpha ()) ||
(!priv.val && !w->alpha ()));
case TypeType:
return (priv.uval & w->wmType ());
}
return true;
}
Type mType;
CompPrivate priv;
};
CompScreen::matchInitExp (const CompString& str)
WRAPABLE_HND_FUNCTN_RETURN (CompMatch::Expression *, matchInitExp, str);
return _matchInitExp (str);
}
CompScreenImpl::_matchInitExp (const CompString& str)
}
static void
matchUpdateMatchOptions (CompOption::Vector& options)
foreach (CompOption &option, options)
switch (option.type ()) {
case CompOption::TypeMatch:
option.value ().match ().update ();
break;
case CompOption::TypeList:
if (option.value ().listType () == CompOption::TypeMatch)
{
foreach (CompOption::Value &value, option.value ().list ())
value.match ().update ();
}
}
}
void
CompScreen::matchExpHandlerChanged ()
WRAPABLE_HND_FUNCTN (matchExpHandlerChanged);
_matchExpHandlerChanged ();
}
CompScreenImpl::_matchExpHandlerChanged ()
foreach (CompPlugin *p, CompPlugin::getPlugins ())
CompOption::Vector &options = p->vTable->getOptions ();
matchUpdateMatchOptions (options);
CompScreen::matchPropertyChanged (CompWindow *w)
WRAPABLE_HND_FUNCTN (matchPropertyChanged, w);
_matchPropertyChanged (w);
}
void
CompScreenImpl::_matchPropertyChanged (CompWindow *w)
static void
matchResetOps (MatchOp::List &list)
matchResetOps (dynamic_cast <MatchGroupOp *> (op)->op);
break;
case MatchOp::TypeExp:
if (exp && exp->e)
exp->e.reset ();
break;
default:
break;
}
}
}
static bool
matchOpsEqual (MatchOp::List &list1,
MatchOp::List &list2)
MatchGroupOp *g1, *g2;
MatchExpOp *e1, *e2;
MatchOp::List::iterator it1 = list1.begin (), it2 = list2.begin ();
if (list1.size () != list2.size ())
return false;
g1 = dynamic_cast<MatchGroupOp *> (*it1);
g2 = dynamic_cast<MatchGroupOp *> (*it2);
if (!matchOpsEqual (g1->op, g2->op))
return false;
break;
case MatchOp::TypeExp:
e1 = dynamic_cast<MatchExpOp *> (*it1);
e2 = dynamic_cast<MatchExpOp *> (*it2);
if (e1->value != e2->value)
return false;
break;
default:
break;
}
static unsigned int
nextIndex (CompString &str,
unsigned int i)
{
while (str[i] == '\\')
if (str[++i] != '\0')
i++;
return i;
}
static CompString
strndupValue (CompString str)
{
unsigned int i, j, n = str.length ();
/* count trialing white spaces */
i = j = 0;
while (i < n)
{
if (str[i] != ' ')
{
j = 0;
if (str[i] == '\\')
i++;
}
else
{
j++;
}
/* remove trialing white spaces */
n -= j;
i = j = 0;
for (;;)
{
if (str[i] == '\\')
i++;
value += str[i++];
if (i >= n)
{
return value;
}
}
}
Add match expressions from string. Special characters are
'(', ')', '!', '&', '|'. Escape character is '\'.
Example:
"type=desktop | !type=dock"
"!type=dock & (state=fullscreen | state=shaded)"
static void
matchAddFromString (MatchOp::List &list,
CompString str)
int j, i = 0;
int flags = 0;
while (str[i] != '\0')
{
while (str[i] == ' ')
i++;
if (str[i] == '!')
{
i++;
while (str[i] == ' ')
i++;
}
if (str[i] == '(')
{
int level = 1;
int length;
while (str[j] != '\0')
{
if (str[j] == '(')
{
level++;
}
else if (str[j] == ')')
{
level--;
if (level == 0)
break;
}
j = nextIndex (str, ++j);
}
length = j - i;
MatchGroupOp *group = new MatchGroupOp ();
matchAddFromString (group->op, str.substr (i, length));
group->flags = flags;
while (str[j] != '\0' && str[j] != '|' && str[j] != '&')
j++;
}
else
{
j = i;
while (str[j] != '\0' && str[j] != '|' && str[j] != '&')
j = nextIndex (str, ++j);
{
}
}
i = j;
if (str[i] != '\0')
{
if (str[i] == '&')
i++;
}
}
MC Return
committed
if (!list.empty ())
static CompString
matchOpsToString (MatchOp::List &list)
CompString value (""), group;
group =
matchOpsToString (dynamic_cast <MatchGroupOp *> (op)->op);
if (group.length ())
{
if (value.length ())
{
value += "!";
value += "(" + group + ") ";
}
break;
case MatchOp::TypeExp:
if (value.length ())
value += ((op->flags & MATCH_OP_AND_MASK) ? "& " : "| ");
value += dynamic_cast <MatchExpOp *> (op)->value;
value += " ";
break;
default:
break;
if (!value.empty ())
value.erase (value.length () - 1);
static void
matchUpdateOps (MatchOp::List &list)
matchUpdateOps (dynamic_cast <MatchGroupOp *> (op)->op);
break;
case MatchOp::TypeExp:
if (exp && screen)
exp->e.reset (screen->matchInitExp (exp->value));
break;
default:
break;
}
}
}
static bool
matchEvalOps (MatchOp::List &list,
const CompWindow *w)
bool value, result = false;
MatchExpOp *exp;
{
/* fast evaluation */
{
/* result will never be true */
if (!result)
}
else
{
/* result will always be true */
if (result)
value =
matchEvalOps (dynamic_cast <MatchGroupOp *> (op)->op, w);
break;
case MatchOp::TypeExp:
if (exp->e.get ())
value = exp->e->evaluate (w);
else
value = true;
break;
default:
value = true;
break;
value = !value;
result = (result && value);
else
result = (result || value);
}
return result;
}
MatchOp::MatchOp () :
flags (0)
MatchExpOp::MatchExpOp () :
value (""),
e ()
{
}
MatchExpOp::MatchExpOp (const MatchExpOp &ex) :
value (ex.value),
e (ex.e)
{
MatchGroupOp::MatchGroupOp () :
op (0)
{
}
MatchGroupOp::MatchGroupOp (const MatchGroupOp &gr) :
op (0)
{
*this = gr;
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
}
MatchGroupOp::~MatchGroupOp ()
{
foreach (MatchOp *o, op)
delete o;
}
MatchGroupOp &
MatchGroupOp::operator= (const MatchGroupOp &gr)
{
MatchGroupOp *gop;
MatchExpOp *eop;
foreach (MatchOp *o, op)
delete o;
op.clear ();
foreach (MatchOp *o, gr.op)
{
switch (o->type ())
{
case MatchOp::TypeGroup:
gop = new MatchGroupOp (dynamic_cast <MatchGroupOp &> (*o));
op.push_back (gop);
break;
case MatchOp::TypeExp:
eop = new MatchExpOp (dynamic_cast <MatchExpOp &> (*o));
op.push_back (eop);
break;
default:
PrivateMatch::PrivateMatch () :
CompMatch::CompMatch () :
priv (new PrivateMatch ())
}
CompMatch::CompMatch (const CompString str) :
priv (new PrivateMatch ())
{
matchAddFromString (priv->op.op, str);
}
CompMatch::CompMatch (const CompMatch &match) :
priv (new PrivateMatch ())
{
priv->op = match.priv->op;
}
CompMatch::~CompMatch ()
{
delete priv;
CompMatch::update ()
matchResetOps (priv->op.op);
matchUpdateOps (priv->op.op);
CompMatch::evaluate (const CompWindow *window) const
{
return matchEvalOps (priv->op.op, window);
}
{
return matchOpsToString (priv->op.op);
}
bool
CompMatch::isEmpty () const
{
return (*this == emptyMatch);
}
CompMatch &
CompMatch::operator= (const CompMatch &match)
CompMatch &
CompMatch::operator&= (const CompMatch &match)
{
MatchGroupOp *g1 = new MatchGroupOp (priv->op);
MatchGroupOp *g2 = new MatchGroupOp (match.priv->op);
priv->op.op.push_back (g1);
priv->op.op.push_back (g2);
CompMatch &
CompMatch::operator|= (const CompMatch &match)
MatchGroupOp *g1 = new MatchGroupOp (priv->op);
MatchGroupOp *g2 = new MatchGroupOp (match.priv->op);
priv->op.op.push_back (g1);
priv->op.op.push_back (g2);
const CompMatch &
CompMatch::operator& (const CompMatch &match)
return CompMatch (*this) &= match;
}
const CompMatch &
CompMatch::operator| (const CompMatch &match)
{
return CompMatch (*this) |= match;
}
const CompMatch &
CompMatch::operator! ()
{
g->flags ^= MATCH_OP_NOT_MASK;
priv->op = MatchGroupOp ();
return *this;
}
CompMatch &
CompMatch::operator= (const CompString &str)
{
matchAddFromString (priv->op.op, str);
return *this;
}
CompMatch &
CompMatch::operator&= (const CompString &str)
{
*this &= CompMatch (str);
return *this;
}
CompMatch &
CompMatch::operator|= (const CompString &str)
{
*this |= CompMatch (str);
return *this;
}
const CompMatch &
CompMatch::operator& (const CompString &str)
{
}
const CompMatch &
CompMatch::operator| (const CompString &str)
{
CompMatch::operator== (const CompMatch &match) const
return matchOpsEqual (priv->op.op, match.priv->op.op);
bool
CompMatch::operator!= (const CompMatch &match) const
{
return !(*this == match);
}