Newer
Older
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cassert>
#include <core/option.h>
#include <core/action.h>
#include <core/screen.h>
#include "privateaction.h"
namespace ca = compiz::actions;
struct _Modifier
{
const char *name;
int modifier;
} modifiers[] =
{
{ "<Shift>", ShiftMask },
{ "<Control>", ControlMask },
{ "<Primary>", ControlMask },
{ "<Mod1>", Mod1Mask },
{ "<Mod2>", Mod2Mask },
{ "<Mod3>", Mod3Mask },
{ "<Mod4>", Mod4Mask },
{ "<Mod5>", Mod5Mask },
{ "<Alt>", CompAltMask },
{ "<Meta>", CompMetaMask },
{ "<Super>", CompSuperMask },
{ "<Hyper>", CompHyperMask },
{ "<ModeSwitch>", CompModeSwitchMask }
};
#define N_MODIFIERS (sizeof (modifiers) / sizeof (struct _Modifier))
struct _Edge
{
const char *name;
const char *modifierName;
} edges[] =
{
{ "Left", "<LeftEdge>" },
{ "Right", "<RightEdge>" },
{ "Top", "<TopEdge>" },
{ "Bottom", "<BottomEdge>" },
{ "TopLeft", "<TopLeftEdge>" },
{ "TopRight", "<TopRightEdge>" },
{ "BottomLeft", "<BottomLeftEdge>" },
{ "BottomRight", "<BottomRightEdge>" }
};
static CompString
modifiersToString (unsigned int modMask)
for (unsigned int i = 0; i < N_MODIFIERS; ++i)
{
if (modMask & modifiers[i].modifier)
binding += modifiers[i].name;
modMask &= ~modifiers[i].modifier;
}
}
return binding;
}
static unsigned int
stringToModifiers (const CompString &str)
{
unsigned int mods = 0;
for (unsigned int i = 0; i < N_MODIFIERS; ++i)
if (str.find (modifiers[i].name) != std::string::npos)
mods |= modifiers[i].modifier;
return mods;
}
static unsigned int
bindingStringToEdgeMask (CompString str)
{
unsigned int edgeMask = 0;
for (int i = 0; i < SCREEN_EDGE_NUM; ++i)
if (str.find (edges[i].modifierName) != std::string::npos)
edgeMask |= 1 << i;
return edgeMask;
}
static CompString
edgeMaskToBindingString (unsigned int edgeMask)
for (int i = 0; i < SCREEN_EDGE_NUM; ++i)
if (edgeMask & (1 << i))
binding += edges[i].modifierName;
return binding;
}
CompAction::KeyBinding::KeyBinding () :
mModifiers (0),
mKeycode (0)
{
}
CompAction::KeyBinding::KeyBinding (const KeyBinding& k) :
mModifiers (k.mModifiers),
mKeycode (k.mKeycode)
{
}
CompAction::KeyBinding::KeyBinding (int keycode,
unsigned int modifiers) :
mModifiers (modifiers),
mKeycode (keycode)
{
}
CompAction::KeyBinding::modifiers () const
{
return mModifiers;
}
int
CompAction::KeyBinding::keycode () const
{
return mKeycode;
}
bool
CompAction::KeyBinding::fromString (const CompString &str)
/* This assertion is a regression test for LP: #930412 */
assert (screen);
if (!screen)
return false;
unsigned int mods = stringToModifiers (str);
size_t start = 0;
size_t pos = str.rfind ('>');
if (pos != std::string::npos)
while (start < str.size () && !isalnum (str[start]))
++start;
{
if (mods)
{
mKeycode = 0;
mModifiers = mods;
return true;
}
return false;
}
CompString sStr = str.substr (start);
KeySym keysym = XStringToKeysym (sStr.c_str ());
if (keysym != NoSymbol)
{
KeyCode keycode;
keycode = XKeysymToKeycode (screen->dpy (), keysym);
if (keycode)
{
mKeycode = keycode;
mModifiers = mods;
return true;
}
}
if (sStr.compare (0, 2, "0x") == 0)
{
mKeycode = strtol (sStr.c_str (), NULL, 0);
mModifiers = mods;
return true;
}
return false;
}
CompString
CompAction::KeyBinding::toString () const
if (!screen)
return "";
CompString binding = modifiersToString (mModifiers);
if (mKeycode != 0)
{
KeySym keysym = XKeycodeToKeysym (screen->dpy (), mKeycode, 0);
char *keyname = XKeysymToString (keysym);
if (keyname)
binding += keyname;
else
binding += compPrintf ("0x%x", mKeycode);
}
return binding;
}
bool
CompAction::KeyBinding::operator== (const KeyBinding &k) const
{
return mKeycode == k.mKeycode && mModifiers == k.mModifiers;
}
bool
CompAction::KeyBinding::operator!= (const KeyBinding &k) const
{
return !(*this == k);
}
CompAction::ButtonBinding::ButtonBinding () :
mModifiers (0),
mButton (0)
{
}
CompAction::ButtonBinding::ButtonBinding (const ButtonBinding& b) :
mModifiers (b.mModifiers),
mButton (b.mButton)
{
}
CompAction::ButtonBinding::ButtonBinding (int button, unsigned int modifiers) :
mModifiers (modifiers),
mButton (button)
{
}
CompAction::ButtonBinding::modifiers () const
{
return mModifiers;
}
int
CompAction::ButtonBinding::button () const
{
return mButton;
}
bool
CompAction::ButtonBinding::fromString (const CompString &str)
unsigned int mods = stringToModifiers (str);
size_t start = 0;
size_t pos = str.rfind ('>');
if (pos != std::string::npos)
while (start < str.size () && !isalnum (str[start]))
++start;
if (start != str.size () && str.compare (start, 6, "Button") == 0)
if (sscanf (str.substr (start + 6).c_str (), "%d", &buttonNum) == 1)
{
mButton = buttonNum;
mModifiers = mods;
return true;
}
}
return false;
}
CompString
CompAction::ButtonBinding::toString () const
{
if (!mModifiers && !mButton)
return "";
CompString binding = modifiersToString (mModifiers);
binding += compPrintf ("Button%d", mButton);
return binding;
}
bool
CompAction::ButtonBinding::operator== (const ButtonBinding &b) const
{
return mButton == b.mButton && mModifiers == b.mModifiers;
}
bool
CompAction::ButtonBinding::operator!= (const ButtonBinding &b) const
{
return !(*this == b);
}
CompAction::CompAction () :
priv (new PrivateAction ())
{
}
CompAction::CompAction (const CompAction & a) :
priv (new PrivateAction (*a.priv))
{
}
CompAction::~CompAction ()
{
delete priv;
}
CompAction::CallBack
{
return priv->initiate;
}
CompAction::CallBack
CompAction::terminate () const
{
return priv->terminate;
}
void
CompAction::setInitiate (const CompAction::CallBack &initiate)
{
priv->initiate = initiate;
}
void
CompAction::setTerminate (const CompAction::CallBack &terminate)
{
priv->terminate = terminate;
}
CompAction::State
{
return priv->state;
}
CompAction::BindingType
{
return priv->type;
}
CompAction::KeyBinding &
CompAction::key ()
{
return priv->key;
}
const CompAction::KeyBinding &
CompAction::key () const
{
return priv->key;
}
void
CompAction::setKey (const CompAction::KeyBinding &key)
{
priv->key = key;
if (key.modifiers () || key.keycode ())
priv->type = CompAction::BindingTypeKey;
else
priv->type = CompAction::BindingTypeNone;
}
CompAction::ButtonBinding &
CompAction::button ()
{
return priv->button;
}
const CompAction::ButtonBinding &
CompAction::button () const
{
return priv->button;
}
void
CompAction::setButton (const CompAction::ButtonBinding &button)
{
priv->button = button;
if (button.modifiers () || button.button ())
{
if (priv->edgeMask)
priv->type = CompAction::BindingTypeEdgeButton;
else
priv->type = CompAction::BindingTypeButton;
}
else
priv->type = CompAction::BindingTypeNone;
}
{
return priv->edgeMask;
}
void
CompAction::setEdgeMask (unsigned int edge)
{
priv->edgeMask = edge;
if (priv->type == CompAction::BindingTypeEdgeButton ||
priv->type == CompAction::BindingTypeButton)
{
if (priv->edgeMask)
priv->type = CompAction::BindingTypeEdgeButton;
else
priv->type = CompAction::BindingTypeButton;
}
{
return priv->bell;
}
void
CompAction::setBell (bool bell)
{
priv->bell = bell;
}
void
CompAction::setState (CompAction::State state)
{
priv->state = state;
}
void
CompAction::copyState (const CompAction &action)
{
priv->terminate = action.priv->terminate;
memcpy (&priv->priv, &action.priv->priv, sizeof (CompPrivate));
}
bool
Thomas Voß
committed
CompAction::operator== (const CompAction& val) const
if (priv->state != val.priv->state ||
priv->type != val.priv->type ||
priv->key.modifiers () != val.priv->key.modifiers () ||
priv->key.keycode () != val.priv->key.keycode () ||
priv->button.modifiers () != val.priv->button.modifiers () ||
priv->button.button () != val.priv->button.button () ||
priv->bell != val.priv->bell ||
priv->edgeMask != val.priv->edgeMask ||
memcmp (&priv->priv, &val.priv->priv, sizeof (CompPrivate)) != 0)
return false;
return true;
}
CompAction &
CompAction::operator= (const CompAction &action)
{
if (this == &action)
return *this;
delete priv;
priv = new PrivateAction (*action.priv);
bool
CompAction::keyFromString (const CompString &str)
bool retval = priv->key.fromString (str);
if (retval)
priv->type = CompAction::BindingTypeKey;
else
{
priv->type = CompAction::BindingTypeNone;
if (str == "Disabled")
retval = true;
}
return retval;
bool
CompAction::buttonFromString (const CompString &str)
bool retval = priv->button.fromString (str);
if (retval)
priv->edgeMask = bindingStringToEdgeMask (str);
if (priv->edgeMask)
priv->type = CompAction::BindingTypeEdgeButton;
else
priv->type = CompAction::BindingTypeButton;
}
else
{
priv->type = CompAction::BindingTypeNone;
if (str == "Disabled")
retval = true;
return retval;
bool
CompAction::edgeMaskFromString (const CompString &str)
for (int i = 0; i < SCREEN_EDGE_NUM; ++i)
while ((pos = str.find (edgeToString (i), pos)) != std::string::npos)
{
if (pos > 0 && isalnum (str[pos - 1]))
{
++pos;
continue;
}
pos += edgeToString (i).size ();
if (pos < str.size () && isalnum (str[pos]))
continue;
edgeMask |= 1 << i;
}
}
priv->edgeMask = edgeMask;
return (edgeMask != 0 || str.empty ());
CompAction::keyToString () const
CompString binding = priv->key.toString ();
return "Disabled";
return binding;
}
CompString
CompAction::buttonToString () const
CompString edge;
CompString binding = modifiersToString (priv->button.modifiers ());
binding += edgeMaskToBindingString (priv->edgeMask);
binding += compPrintf ("Button%d", priv->button.button ());
return "Disabled";
return binding;
}
CompString
CompAction::edgeMaskToString () const
for (int i = 0; i < SCREEN_EDGE_NUM; ++i)
{
if (priv->edgeMask & (1 << i))
{
edge += edgeToString (i);
}
}
return edge;
}
CompString
CompAction::edgeToString (unsigned int edge)
{
Sam Spilsbury
committed
bool
Sam Spilsbury
committed
{
return priv->active;
}
void
}
void
ca::setActionActiveState (const CompAction &action,
bool active)
}
PrivateAction::PrivateAction () :
initiate (),
state (0),
type (0),
key (),
button (),
bell (false),
edgeMask (0),
active (false)
{
memset (&priv, 0, sizeof (CompPrivate));
}
PrivateAction::PrivateAction (const PrivateAction &a) :
initiate (a.initiate),
state (a.state),
type (a.type),
key (a.key),
button (a.button),
bell (a.bell),
edgeMask (a.edgeMask),
active (a.active)
{
memcpy (&priv, &a.priv, sizeof (CompPrivate));
}
CompAction::Vector &
noActions ()
{
static CompAction::Vector v;
return v;
}