On Sat, Feb 7, 2009 at 12:38 PM, Sam Spilsbury <[email protected]> wrote:
> On Sat, Feb 7, 2009 at 12:22 AM, Sam Spilsbury <[email protected]> wrote:
>> Hi,
>>
>> This patch allows for modifier handling to be used by other plugins.
>> It contains some simple functions to update core's modifier map, get
>> the ignored mod mask, convert virtual to real mod masks and get
>> modifiers for a keycode. It is necessary for so that plugins like
>> VPSwitch can handle modifier key events in X without having to
>> re-implement code to understand those keycodes.
>>
>> This should hopefully be useful for snap as well.
>>
>> Cheers,
>>
>> Sam
>>
>> --
>> Sam Spilsbury
>>
>
> Hi,
>
> Attached are some revised patched. They add the modifierhandler.cpp
> and modifierhandler.h files.
>
> Danny suggested that the modHandler object did not belong in the
> PrivateScreen class (and have a getter in CompScreen). I evaluated the
> code and do not think this makes sense because modHandler depends the
> CompScreen *screen variable to be initialized and also uses some of
> it's internal methods.
>
> Cheers,
>
> Sam
>
> --
> Sam Spilsbury
>

And in sending the mail, I forgot to attach the patches. They are
attached to this one.

Cheers,

Sam

-- 
Sam Spilsbury
From 2a0e942650f337e9fe24d08dbd128b990fc6b7dd Mon Sep 17 00:00:00 2001
From: Sam Spilsbury <[email protected]>
Date: Fri, 6 Feb 2009 21:33:58 +0900
Subject: [PATCH] Separate Modifier handling into a separate class

---
 include/composite/composite.h |    3 -
 include/core/CMakeLists.txt   |    3 +-
 include/core/screen.h         |    4 +
 src/CMakeLists.txt            |    3 +-
 src/event.cpp                 |   25 +++---
 src/plugin.cpp                |    5 +
 src/privatescreen.h           |   12 +---
 src/screen.cpp                |  177 +++-------------------------------------
 8 files changed, 42 insertions(+), 190 deletions(-)

diff --git a/include/composite/composite.h b/include/composite/composite.h
index dc6a597..3f15364 100644
--- a/include/composite/composite.h
+++ b/include/composite/composite.h
@@ -1,6 +1,3 @@
-
-
-
 /*
  * Copyright © 2008 Dennis Kasprzyk
  * Copyright © 2007 Novell, Inc.
diff --git a/include/core/CMakeLists.txt b/include/core/CMakeLists.txt
index dc94393..81b8a53 100644
--- a/include/core/CMakeLists.txt
+++ b/include/core/CMakeLists.txt
@@ -5,6 +5,7 @@ set (_headers
     icon.h
     match.h
     metadata.h
+    modifierhandler.h
     option.h
     output.h
     plugin.h
@@ -24,4 +25,4 @@ set (_headers
 install (
     FILES ${_headers}
     DESTINATION ${includedir}/compiz/core
-)
\ No newline at end of file
+)
diff --git a/include/core/screen.h b/include/core/screen.h
index c30da1f..1114ab5 100644
--- a/include/core/screen.h
+++ b/include/core/screen.h
@@ -36,6 +36,7 @@
 #include <core/match.h>
 #include <core/privates.h>
 #include <core/region.h>
+#include <core/modifierhandler.h>
 
 class CompScreen;
 class PrivateScreen;
@@ -178,6 +179,8 @@ class CompScreen :
 
 	int syncEvent ();
 
+	ModifierHandler modHandler ();
+
 	SnDisplay * snDisplay ();
 	
 	Window activeWindow ();
@@ -359,6 +362,7 @@ class CompScreen :
 	friend class CompTimer;
 	friend class CompWindow;
 	friend class PrivateWindow;
+	friend class ModifierHandler;
 
     private:
 	PrivateScreen *priv;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2bf2db4..32c48b5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -39,6 +39,7 @@ add_executable (compiz
     point.cpp
     windowgeometry.cpp
     icon.cpp
+    modifierhandler.cpp
 )
 
 target_link_libraries (
@@ -48,4 +49,4 @@ target_link_libraries (
 install (
     TARGETS compiz
     DESTINATION ${exec_prefix}
-)
\ No newline at end of file
+)
diff --git a/src/event.cpp b/src/event.cpp
index 1aab5ac..53fbea3 100644
--- a/src/event.cpp
+++ b/src/event.cpp
@@ -146,7 +146,8 @@ PrivateScreen::triggerButtonPressBindings (CompOption::Vector &options,
 {
     CompAction::State state = CompAction::StateInitButton;
     CompAction        *action;
-    unsigned int      modMask = REAL_MOD_MASK & ~ignoredModMask;
+    unsigned int      ignored = mModHandler.ignoredModMask ();
+    unsigned int      modMask = REAL_MOD_MASK & ~ignored;
     unsigned int      bindMods;
     unsigned int      edge = 0;
 
@@ -181,7 +182,7 @@ PrivateScreen::triggerButtonPressBindings (CompOption::Vector &options,
 	{
 	    if (action->button ().button () == (int) event->button)
 	    {
-		bindMods = virtualToRealModMask (
+		bindMods = mModHandler.virtualToRealModMask (
 		    action->button ().modifiers ());
 
 		if ((bindMods & modMask) == (event->state & modMask))
@@ -198,7 +199,7 @@ PrivateScreen::triggerButtonPressBindings (CompOption::Vector &options,
 		if ((action->button ().button () == (int) event->button) &&
 		    (action->edgeMask () & edge))
 		{
-		    bindMods = virtualToRealModMask (
+		    bindMods = mModHandler.virtualToRealModMask (
 			action->button ().modifiers ());
 
 		    if ((bindMods & modMask) == (event->state & modMask))
@@ -246,7 +247,7 @@ PrivateScreen::triggerKeyPressBindings (CompOption::Vector &options,
 {
     CompAction::State state = 0;
     CompAction	      *action;
-    unsigned int      modMask = REAL_MOD_MASK & ~ignoredModMask;
+    unsigned int      modMask = REAL_MOD_MASK & ~mModHandler.ignoredModMask ();
     unsigned int      bindMods;
 
     if (event->keycode == escapeKeyCode)
@@ -276,7 +277,7 @@ PrivateScreen::triggerKeyPressBindings (CompOption::Vector &options,
 	if (isInitiateBinding (option, CompAction::BindingTypeKey,
 			       state, &action))
 	{
-	    bindMods = virtualToRealModMask (
+	    bindMods = mModHandler.virtualToRealModMask (
 		action->key ().modifiers ());
 
 	    if (action->key ().keycode () == (int) event->keycode)
@@ -304,11 +305,11 @@ PrivateScreen::triggerKeyReleaseBindings (CompOption::Vector &options,
 {
     CompAction::State state = CompAction::StateTermKey;
     CompAction        *action;
-    unsigned int      modMask = REAL_MOD_MASK & ~ignoredModMask;
+    unsigned int      modMask = REAL_MOD_MASK & ~mModHandler.ignoredModMask ();
     unsigned int      bindMods;
     unsigned int      mods;
 
-    mods = keycodeToModifiers (event->keycode);
+    mods = mModHandler.keycodeToModifiers (event->keycode);
     if (!xkbEvent && !mods)
 	return false;
 
@@ -317,7 +318,7 @@ PrivateScreen::triggerKeyReleaseBindings (CompOption::Vector &options,
 	if (isTerminateBinding (option, CompAction::BindingTypeKey,
 				state, &action))
 	{
-	    bindMods = virtualToRealModMask (action->key ().modifiers ());
+	    bindMods = mModHandler.virtualToRealModMask (action->key ().modifiers ());
 
 	    if ((bindMods & modMask) == 0)
 	    {
@@ -345,7 +346,7 @@ PrivateScreen::triggerStateNotifyBindings (CompOption::Vector  &options,
 {
     CompAction::State state;
     CompAction        *action;
-    unsigned int      modMask = REAL_MOD_MASK & ~ignoredModMask;
+    unsigned int      modMask = REAL_MOD_MASK & ~mModHandler.ignoredModMask ();
     unsigned int      bindMods;
 
     if (event->event_type == KeyPress)
@@ -360,7 +361,7 @@ PrivateScreen::triggerStateNotifyBindings (CompOption::Vector  &options,
 		if (action->key ().keycode () == 0)
 		{
 		    bindMods =
-			virtualToRealModMask (action->key ().modifiers ());
+			mModHandler.virtualToRealModMask (action->key ().modifiers ());
 
 		    if ((event->mods & modMask & bindMods) == bindMods)
 		    {
@@ -380,7 +381,7 @@ PrivateScreen::triggerStateNotifyBindings (CompOption::Vector  &options,
 	    if (isTerminateBinding (option, CompAction::BindingTypeKey,
 				    state, &action))
 	    {
-		bindMods = virtualToRealModMask (action->key ().modifiers ());
+		bindMods = mModHandler.virtualToRealModMask (action->key ().modifiers ());
 
 		if ((event->mods & modMask & bindMods) != bindMods)
 		{
@@ -1477,7 +1478,7 @@ CompScreen::handleEvent (XEvent *event)
 	}
 	break;
     case MappingNotify:
-	priv->updateModifierMappings ();
+	priv->mModHandler.updateModifierMappings ();
 	break;
     case MapRequest:
 	w = findWindow (event->xmaprequest.window);
diff --git a/src/plugin.cpp b/src/plugin.cpp
index 61765f5..b29814d 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -190,6 +190,11 @@ dlloaderLoadPlugin (CompPlugin *p,
 	return cloaderLoadPlugin (p, path, name);
     }
 
+    error = dlerror ();
+
+    if (error)
+	fprintf (stderr, "errors while loading plugin %s:\n        %s\n", name, error);
+
     free (file);
 
     p->devPrivate.ptr = dlhand;
diff --git a/src/privatescreen.h b/src/privatescreen.h
index f5699b1..4fb97b8 100644
--- a/src/privatescreen.h
+++ b/src/privatescreen.h
@@ -319,12 +319,6 @@ class PrivateScreen {
 
 	void updateScreenInfo ();
 
-	void updateModifierMappings ();
-
-	unsigned int virtualToRealModMask (unsigned int modMask);
-
-	unsigned int keycodeToModifiers (int keycode);
-
 	Window getActiveWindow (Window root);
 
 	int getWmState (Window id);
@@ -423,6 +417,8 @@ class PrivateScreen {
 
 	std::vector<XineramaScreenInfo> screenInfo;
 
+	ModifierHandler mModHandler;
+
 	SnDisplay *snDisplay;
 
 	unsigned int lastPing;
@@ -433,10 +429,6 @@ class PrivateScreen {
 	Window below;
 	char   displayString[256];
 
-	XModifierKeymap *modMap;
-	unsigned int    modMask[CompModNum];
-	unsigned int    ignoredModMask;
-
 	KeyCode escapeKeyCode;
 	KeyCode returnKeyCode;
 
diff --git a/src/screen.cpp b/src/screen.cpp
index 642cf10..d0a0871 100644
--- a/src/screen.cpp
+++ b/src/screen.cpp
@@ -61,11 +61,6 @@
 #include "privatescreen.h"
 #include "privatewindow.h"
 
-static unsigned int virtualModMask[] = {
-    CompAltMask, CompMetaMask, CompSuperMask, CompHyperMask,
-    CompModeSwitchMask, CompNumLockMask, CompScrollLockMask
-};
-
 bool inHandleEvent = false;
 
 CompScreen *targetScreen = NULL;
@@ -586,12 +581,6 @@ const CompMetadata::OptionInfo coreOptionInfo[COMP_OPTION_NUM] = {
     { "focus_prevention_match", "match", 0, 0, 0 }
 };
 
-static const int maskTable[] = {
-    ShiftMask, LockMask, ControlMask, Mod1Mask,
-    Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
-};
-static const int maskTableSize = sizeof (maskTable) / sizeof (int);
-
 static int errors = 0;
 
 static int
@@ -692,6 +681,11 @@ CompScreen::syncEvent ()
     return priv->syncEvent;
 }
 
+ModifierHandler
+CompScreen::modHandler ()
+{
+    return priv->mModHandler;
+}
 
 SnDisplay *
 CompScreen::snDisplay ()
@@ -891,142 +885,6 @@ CompScreen::setOption (const char        *name,
 }
 
 void
-PrivateScreen::updateModifierMappings ()
-{
-    unsigned int    modMask[CompModNum];
-    int		    i, minKeycode, maxKeycode, keysymsPerKeycode = 0;
-    KeySym*         key;
-
-    for (i = 0; i < CompModNum; i++)
-	modMask[i] = 0;
-
-    XDisplayKeycodes (this->dpy, &minKeycode, &maxKeycode);
-    key = XGetKeyboardMapping (this->dpy,
-			       minKeycode, (maxKeycode - minKeycode + 1),
-			       &keysymsPerKeycode);
-
-    if (this->modMap)
-	XFreeModifiermap (this->modMap);
-
-    this->modMap = XGetModifierMapping (this->dpy);
-    if (this->modMap && this->modMap->max_keypermod > 0)
-    {
-	KeySym keysym;
-	int    index, size, mask;
-
-	size = maskTableSize * this->modMap->max_keypermod;
-
-	for (i = 0; i < size; i++)
-	{
-	    if (!this->modMap->modifiermap[i])
-		continue;
-
-	    index = 0;
-	    do
-	    {
-		keysym = XKeycodeToKeysym (this->dpy,
-					   this->modMap->modifiermap[i],
-					   index++);
-	    } while (!keysym && index < keysymsPerKeycode);
-
-	    if (keysym)
-	    {
-		mask = maskTable[i / this->modMap->max_keypermod];
-
-		if (keysym == XK_Alt_L ||
-		    keysym == XK_Alt_R)
-		{
-		    modMask[CompModAlt] |= mask;
-		}
-		else if (keysym == XK_Meta_L ||
-			 keysym == XK_Meta_R)
-		{
-		    modMask[CompModMeta] |= mask;
-		}
-		else if (keysym == XK_Super_L ||
-			 keysym == XK_Super_R)
-		{
-		    modMask[CompModSuper] |= mask;
-		}
-		else if (keysym == XK_Hyper_L ||
-			 keysym == XK_Hyper_R)
-		{
-		    modMask[CompModHyper] |= mask;
-		}
-		else if (keysym == XK_Mode_switch)
-		{
-		    modMask[CompModModeSwitch] |= mask;
-		}
-		else if (keysym == XK_Scroll_Lock)
-		{
-		    modMask[CompModScrollLock] |= mask;
-		}
-		else if (keysym == XK_Num_Lock)
-		{
-		    modMask[CompModNumLock] |= mask;
-		}
-	    }
-	}
-
-	for (i = 0; i < CompModNum; i++)
-	{
-	    if (!modMask[i])
-		modMask[i] = CompNoMask;
-	}
-
-	if (memcmp (modMask, this->modMask, sizeof (modMask)))
-	{
-	    memcpy (this->modMask, modMask, sizeof (modMask));
-
-	    this->ignoredModMask = LockMask |
-		(modMask[CompModNumLock]    & ~CompNoMask) |
-		(modMask[CompModScrollLock] & ~CompNoMask);
-
-	    this->updatePassiveKeyGrabs ();
-	}
-    }
-
-    if (key)
-	XFree (key);
-}
-
-unsigned int
-PrivateScreen::virtualToRealModMask (unsigned int modMask)
-{
-    int i;
-
-    for (i = 0; i < CompModNum; i++)
-    {
-	if (modMask & virtualModMask[i])
-	{
-	    modMask &= ~virtualModMask[i];
-	    modMask |= this->modMask[i];
-	}
-    }
-
-    return modMask;
-}
-
-unsigned int
-PrivateScreen::keycodeToModifiers (int keycode)
-{
-    unsigned int mods = 0;
-    int mod, k;
-
-    for (mod = 0; mod < maskTableSize; mod++)
-    {
-	for (k = 0; k < modMap->max_keypermod; k++)
-	{
-	    if (modMap->modifiermap[mod *
-		modMap->max_keypermod + k] == keycode)
-		mods |= maskTable[mod];
-	}
-    }
-
-    return mods;
-}
-
-void
 PrivateScreen::processEvents ()
 {
     XEvent event;
@@ -3005,9 +2863,9 @@ PrivateScreen::grabUngrabKeys (unsigned int modifiers,
 
     CompScreen::checkForError (dpy);
 
-    for (ignore = 0; ignore <= ignoredModMask; ignore++)
+    for (ignore = 0; ignore <= mModHandler.ignoredModMask (); ignore++)
     {
-	if (ignore & ~ignoredModMask)
+	if (ignore & ~mModHandler.ignoredModMask ())
 	    continue;
 
 	if (keycode != 0)
@@ -3020,15 +2878,15 @@ PrivateScreen::grabUngrabKeys (unsigned int modifiers,
 	    {
 		if (modifiers & (1 << mod))
 		{
-		    for (k = mod * modMap->max_keypermod;
-			 k < (mod + 1) * modMap->max_keypermod;
+		    for (k = mod * mModHandler.modMap ()->max_keypermod;
+			 k < (mod + 1) * mModHandler.modMap ()->max_keypermod;
 			 k++)
 		    {
-			if (modMap->modifiermap[k])
+			if (mModHandler.modMap ()->modifiermap[k])
 			{
 			    grabUngrabOneKey ((modifiers & ~(1 << mod)) |
 					      ignore,
-					      modMap->modifiermap[k],
+					      mModHandler.modMap ()->modifiermap[k],
 					      grab);
 			}
 		    }
@@ -3050,7 +2908,7 @@ PrivateScreen::addPassiveKeyGrab (CompAction::KeyBinding &key)
     unsigned int                 mask;
     std::list<KeyGrab>::iterator it;
 
-    mask = virtualToRealModMask (key.modifiers ());
+    mask = mModHandler.virtualToRealModMask (key.modifiers ());
 
     for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
     {
@@ -3085,7 +2943,7 @@ PrivateScreen::removePassiveKeyGrab (CompAction::KeyBinding &key)
     unsigned int                 mask;
     std::list<KeyGrab>::iterator it;
 
-    mask = virtualToRealModMask (key.modifiers ());
+    mask = mModHandler.virtualToRealModMask (key.modifiers ());
 
     for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
     {
@@ -4408,7 +4266,7 @@ CompScreen::init (const char *name)
 
     XSetErrorHandler (errorHandler);
 
-    priv->updateModifierMappings ();
+    priv->mModHandler.updateModifierMappings ();
 
     priv->snDisplay = sn_display_new (dpy, NULL, NULL);
     if (!priv->snDisplay)
@@ -4792,9 +4650,6 @@ CompScreen::~CompScreen ()
     XSync (priv->dpy, False);
     XCloseDisplay (priv->dpy);
 
-    if (priv->modMap)
-	XFreeModifiermap (priv->modMap);
-
     if (priv->watchPollFds)
 	free (priv->watchPollFds);
 
@@ -4816,8 +4671,6 @@ PrivateScreen::PrivateScreen (CompScreen *screen) :
     screenInfo (0),
     activeWindow (0),
     below (None),
-    modMap (0),
-    ignoredModMask (LockMask),
     autoRaiseTimer (),
     autoRaiseWindow (0),
     edgeDelayTimer (),
@@ -4855,8 +4708,6 @@ PrivateScreen::PrivateScreen (CompScreen *screen) :
     initialized (false),
     opt (COMP_OPTION_NUM)
 {
-    for (int i = 0; i < CompModNum; i++)
-	modMask[i] = CompNoMask;
     memset (history, 0, sizeof (history));
     gettimeofday (&lastTimeout, 0);
 }
-- 
1.5.6

From cc49cd29b925439cb5ff31e70a4436331fc5df6c Mon Sep 17 00:00:00 2001
From: Sam Spilsbury <[email protected]>
Date: Sat, 7 Feb 2009 12:30:30 +0900
Subject: [PATCH] Add modifier handler files

---
 include/core/modifierhandler.h |   89 +++++++++++++++++
 src/modifierhandler.cpp        |  204 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 293 insertions(+), 0 deletions(-)
 create mode 100644 include/core/modifierhandler.h
 create mode 100644 src/modifierhandler.cpp

diff --git a/include/core/modifierhandler.h b/include/core/modifierhandler.h
new file mode 100644
index 0000000..6c1ef21
--- /dev/null
+++ b/include/core/modifierhandler.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <[email protected]>
+ *          David Reveman <[email protected]>
+ *	    Sam Spilsbury <[email protected]>
+ */
+
+#include <core/core.h>
+
+class ModifierHandler
+{
+    public:
+
+	ModifierHandler ();
+	~ModifierHandler ();
+
+	typedef enum
+	{
+	    Alt = 1,
+	    Meta,
+	    Super,
+	    Hyper,
+	    ModeSwitch,
+	    NumLock,
+	    ScrollLock,
+	    ModNum
+	} Modifier;
+
+	typedef enum
+	{
+	    AltMask        = (1 << 16),
+	    MetaMask       = (1 << 17),
+	    SuperMask      = (1 << 18),
+	    HyperMask      = (1 << 19),
+	    ModeSwitchMask = (1 << 20),
+	    NumLockMask    = (1 << 21),
+	    ScrollLockMask = (1 << 22),
+	    NoMask         = (1 << 25),
+	} ModMask;
+
+    public:
+
+	unsigned int keycodeToModifiers (int keycode);
+
+	void updateModifierMappings ();
+
+	unsigned int virtualToRealModMask (unsigned int modMask);
+
+	unsigned int modMask (Modifier);
+
+	unsigned int ignoredModMask ();
+
+	XModifierKeymap * modMap ();
+
+	friend class CompScreen;
+
+    private:
+
+        static const unsigned int virtualModMask[7];
+
+	static const int maskTable[8];
+
+	static const int maskTableSize = 8;
+
+	ModMask    mModMask[ModNum];
+	unsigned int    mIgnoredModMask;
+	XModifierKeymap *mModMap;
+};
diff --git a/src/modifierhandler.cpp b/src/modifierhandler.cpp
new file mode 100644
index 0000000..9990e3b
--- /dev/null
+++ b/src/modifierhandler.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <[email protected]>
+ *          David Reveman <[email protected]>
+ *	    Sam Spilsbury <[email protected]>
+ */
+
+#include <core/screen.h>
+#include "privatescreen.h"
+
+const unsigned int ModifierHandler::virtualModMask[7] = {
+            CompAltMask, CompMetaMask, CompSuperMask, CompHyperMask,
+            CompModeSwitchMask, CompNumLockMask, CompScrollLockMask
+};
+
+const int ModifierHandler::maskTable[8] = {
+	    ShiftMask, LockMask, ControlMask, Mod1Mask,
+	    Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
+};
+
+unsigned int
+ModifierHandler::ignoredModMask ()
+{
+    return mIgnoredModMask;
+}
+
+XModifierKeymap *
+ModifierHandler::modMap ()
+{
+    return mModMap;
+}
+
+void
+ModifierHandler::updateModifierMappings ()
+{
+    unsigned int    modMask[CompModNum];
+    int		    i, minKeycode, maxKeycode, keysymsPerKeycode = 0;
+    KeySym*         key;
+
+    for (i = 0; i < CompModNum; i++)
+	modMask[i] = 0;
+
+    XDisplayKeycodes (screen->dpy (), &minKeycode, &maxKeycode);
+    key = XGetKeyboardMapping (screen->dpy (),
+			       minKeycode, (maxKeycode - minKeycode + 1),
+			       &keysymsPerKeycode);
+
+    if (this->mModMap)
+	XFreeModifiermap (this->mModMap);
+
+    this->mModMap = XGetModifierMapping (screen->dpy ());
+    if (this->mModMap && this->mModMap->max_keypermod > 0)
+    {
+	KeySym keysym;
+	int    index, size, mask;
+
+	size = maskTableSize * this->mModMap->max_keypermod;
+
+	for (i = 0; i < size; i++)
+	{
+	    if (!this->mModMap->modifiermap[i])
+		continue;
+
+	    index = 0;
+	    do
+	    {
+		keysym = XKeycodeToKeysym (screen->dpy (),
+					   this->mModMap->modifiermap[i],
+					   index++);
+	    } while (!keysym && index < keysymsPerKeycode);
+
+	    if (keysym)
+	    {
+		mask = maskTable[i / this->mModMap->max_keypermod];
+
+		if (keysym == XK_Alt_L ||
+		    keysym == XK_Alt_R)
+		{
+		    modMask[CompModAlt] |= mask;
+		}
+		else if (keysym == XK_Meta_L ||
+			 keysym == XK_Meta_R)
+		{
+		    modMask[CompModMeta] |= mask;
+		}
+		else if (keysym == XK_Super_L ||
+			 keysym == XK_Super_R)
+		{
+		    modMask[CompModSuper] |= mask;
+		}
+		else if (keysym == XK_Hyper_L ||
+			 keysym == XK_Hyper_R)
+		{
+		    modMask[CompModHyper] |= mask;
+		}
+		else if (keysym == XK_Mode_switch)
+		{
+		    modMask[CompModModeSwitch] |= mask;
+		}
+		else if (keysym == XK_Scroll_Lock)
+		{
+		    modMask[CompModScrollLock] |= mask;
+		}
+		else if (keysym == XK_Num_Lock)
+		{
+		    modMask[CompModNumLock] |= mask;
+		}
+	    }
+	}
+
+	for (i = 0; i < CompModNum; i++)
+	{
+	    if (!modMask[i])
+		modMask[i] = CompNoMask;
+	}
+
+	if (memcmp (modMask, this->mModMask, sizeof (modMask)))
+	{
+	    memcpy (this->mModMask, modMask, sizeof (modMask));
+
+	    this->mIgnoredModMask = LockMask |
+		(modMask[CompModNumLock]    & ~CompNoMask) |
+		(modMask[CompModScrollLock] & ~CompNoMask);
+
+	    screen->priv->updatePassiveKeyGrabs ();
+	}
+    }
+
+    if (key)
+	XFree (key);
+}
+
+unsigned int
+ModifierHandler::virtualToRealModMask (unsigned int modMask)
+{
+    int i;
+
+    for (i = 0; i < CompModNum; i++)
+    {
+	if (modMask & virtualModMask[i])
+	{
+	    modMask &= ~virtualModMask[i];
+	    modMask |= this->mModMask[i];
+	}
+    }
+
+    return modMask;
+}
+
+unsigned int
+ModifierHandler::keycodeToModifiers (int keycode)
+{
+    unsigned int mods = 0;
+    int mod, k;
+
+    for (mod = 0; mod < maskTableSize; mod++)
+    {
+	for (k = 0; k < mModMap->max_keypermod; k++)
+	{
+	    if (mModMap->modifiermap[mod *
+		mModMap->max_keypermod + k] == keycode)
+		mods |= maskTable[mod];
+	}
+    }
+
+    return mods;
+}
+
+ModifierHandler::ModifierHandler () :
+    mIgnoredModMask (LockMask),
+    mModMap (0)
+{
+    for (int i = 0; i < ModNum; i++)
+	mModMask[i] = NoMask;
+}
+
+ModifierHandler::~ModifierHandler ()
+{
+    if (mModMap)
+	XFreeModifiermap (mModMap);
+
+    mModMap = NULL;
+}
-- 
1.5.6

_______________________________________________
Dev mailing list
[email protected]
http://lists.compiz-fusion.org/mailman/listinfo/dev

Reply via email to