зеркало из https://github.com/mozilla/gecko-dev.git
Bug 630813 part.2 Store native modifier key information r=karlt
This commit is contained in:
Родитель
0f720d7f56
Коммит
7909dd1140
|
@ -345,10 +345,100 @@ namespace widget {
|
|||
|
||||
KeymapWrapper* KeymapWrapper::sInstance = nsnull;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
||||
/* static */ const char*
|
||||
KeymapWrapper::GetModifierName(Modifier aModifier)
|
||||
{
|
||||
switch (aModifier) {
|
||||
case CAPS_LOCK: return "CapsLock";
|
||||
case NUM_LOCK: return "NumLock";
|
||||
case SCROLL_LOCK: return "ScrollLock";
|
||||
case SHIFT: return "Shift";
|
||||
case CTRL: return "Ctrl";
|
||||
case ALT: return "Alt";
|
||||
case SUPER: return "Super";
|
||||
case HYPER: return "Hyper";
|
||||
case META: return "Meta";
|
||||
case ALTGR: return "AltGr";
|
||||
case NOT_MODIFIER: return "NotModifier";
|
||||
default: return "InvalidValue";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PR_LOGGING
|
||||
|
||||
/* static */ KeymapWrapper::Modifier
|
||||
KeymapWrapper::GetModifierForGDKKeyval(guint aGdkKeyval)
|
||||
{
|
||||
switch (aGdkKeyval) {
|
||||
case GDK_Caps_Lock: return CAPS_LOCK;
|
||||
case GDK_Num_Lock: return NUM_LOCK;
|
||||
case GDK_Scroll_Lock: return SCROLL_LOCK;
|
||||
case GDK_Shift_L:
|
||||
case GDK_Shift_R: return SHIFT;
|
||||
case GDK_Control_L:
|
||||
case GDK_Control_R: return CTRL;
|
||||
case GDK_Alt_L:
|
||||
case GDK_Alt_R: return ALT;
|
||||
case GDK_Super_L:
|
||||
case GDK_Super_R: return SUPER;
|
||||
case GDK_Hyper_L:
|
||||
case GDK_Hyper_R: return HYPER;
|
||||
case GDK_Meta_L:
|
||||
case GDK_Meta_R: return META;
|
||||
case GDK_ISO_Level3_Shift:
|
||||
case GDK_Mode_switch: return ALTGR;
|
||||
default: return NOT_MODIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
KeymapWrapper::GetModifierMask(Modifier aModifier) const
|
||||
{
|
||||
switch (aModifier) {
|
||||
case CAPS_LOCK:
|
||||
return GDK_LOCK_MASK;
|
||||
case NUM_LOCK:
|
||||
return mModifierMasks[INDEX_NUM_LOCK];
|
||||
case SCROLL_LOCK:
|
||||
return mModifierMasks[INDEX_SCROLL_LOCK];
|
||||
case SHIFT:
|
||||
return GDK_SHIFT_MASK;
|
||||
case CTRL:
|
||||
return GDK_CONTROL_MASK;
|
||||
case ALT:
|
||||
return mModifierMasks[INDEX_ALT];
|
||||
case SUPER:
|
||||
return mModifierMasks[INDEX_SUPER];
|
||||
case HYPER:
|
||||
return mModifierMasks[INDEX_HYPER];
|
||||
case META:
|
||||
return mModifierMasks[INDEX_META];
|
||||
case ALTGR:
|
||||
return mModifierMasks[INDEX_ALTGR];
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
KeymapWrapper::ModifierKey*
|
||||
KeymapWrapper::GetModifierKey(guint aHardwareKeycode)
|
||||
{
|
||||
for (PRUint32 i = 0; i < mModifierKeys.Length(); i++) {
|
||||
ModifierKey& key = mModifierKeys[i];
|
||||
if (key.mHardwareKeycode == aHardwareKeycode) {
|
||||
return &key;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* static */ KeymapWrapper*
|
||||
KeymapWrapper::GetInstance()
|
||||
{
|
||||
if (sInstance) {
|
||||
sInstance->Init();
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
|
@ -374,6 +464,151 @@ KeymapWrapper::KeymapWrapper() :
|
|||
// This is necessary for catching the destroying timing.
|
||||
g_object_weak_ref(G_OBJECT(mGdkKeymap),
|
||||
(GWeakNotify)OnDestroyKeymap, this);
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
void
|
||||
KeymapWrapper::Init()
|
||||
{
|
||||
if (mInitialized) {
|
||||
return;
|
||||
}
|
||||
mInitialized = true;
|
||||
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): Init, mGdkKeymap=%p",
|
||||
this, mGdkKeymap));
|
||||
|
||||
mModifierKeys.Clear();
|
||||
memset(mModifierMasks, 0, sizeof(mModifierMasks));
|
||||
|
||||
InitBySystemSettings();
|
||||
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): Init, CapsLock=0x%X, NumLock=0x%X, "
|
||||
"ScrollLock=0x%X, AltGr=0x%X, Shift=0x%X, Ctrl=0x%X, Alt=0x%X, "
|
||||
"Meta=0x%X, Super=0x%X, Hyper=0x%X",
|
||||
this,
|
||||
GetModifierMask(CAPS_LOCK), GetModifierMask(NUM_LOCK),
|
||||
GetModifierMask(SCROLL_LOCK), GetModifierMask(ALTGR),
|
||||
GetModifierMask(SHIFT), GetModifierMask(CTRL),
|
||||
GetModifierMask(ALT), GetModifierMask(META),
|
||||
GetModifierMask(SUPER), GetModifierMask(HYPER)));
|
||||
}
|
||||
|
||||
void
|
||||
KeymapWrapper::InitBySystemSettings()
|
||||
{
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): InitBySystemSettings, mGdkKeymap=%p",
|
||||
this, mGdkKeymap));
|
||||
|
||||
Display* display =
|
||||
gdk_x11_display_get_xdisplay(gdk_display_get_default());
|
||||
|
||||
int min_keycode = 0;
|
||||
int max_keycode = 0;
|
||||
XDisplayKeycodes(display, &min_keycode, &max_keycode);
|
||||
|
||||
int keysyms_per_keycode = 0;
|
||||
KeySym* xkeymap = XGetKeyboardMapping(display, min_keycode,
|
||||
max_keycode - min_keycode + 1,
|
||||
&keysyms_per_keycode);
|
||||
if (!xkeymap) {
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): InitBySystemSettings, "
|
||||
"Failed due to null xkeymap", this));
|
||||
return;
|
||||
}
|
||||
|
||||
XModifierKeymap* xmodmap = XGetModifierMapping(display);
|
||||
if (!xmodmap) {
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): InitBySystemSettings, "
|
||||
"Failed due to null xmodmap", this));
|
||||
XFree(xkeymap);
|
||||
return;
|
||||
}
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): InitBySystemSettings, min_keycode=%d, "
|
||||
"max_keycode=%d, keysyms_per_keycode=%d, max_keypermod=%d",
|
||||
this, min_keycode, max_keycode, keysyms_per_keycode,
|
||||
xmodmap->max_keypermod));
|
||||
|
||||
// The modifiermap member of the XModifierKeymap structure contains 8 sets
|
||||
// of max_keypermod KeyCodes, one for each modifier in the order Shift,
|
||||
// Lock, Control, Mod1, Mod2, Mod3, Mod4, and Mod5.
|
||||
// Only nonzero KeyCodes have meaning in each set, and zero KeyCodes are
|
||||
// ignored.
|
||||
|
||||
// Note that two or more modifiers may use one modifier flag. E.g.,
|
||||
// on Ubuntu 10.10, Alt and Meta share the Mod1 in default settings.
|
||||
// And also Super and Hyper share the Mod4.
|
||||
|
||||
const PRUint32 map_size = 8 * xmodmap->max_keypermod;
|
||||
for (PRUint32 i = 0; i < map_size; i++) {
|
||||
KeyCode keycode = xmodmap->modifiermap[i];
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): InitBySystemSettings, "
|
||||
" i=%d, keycode=0x%08X",
|
||||
this, i, keycode));
|
||||
if (!keycode || keycode < min_keycode || keycode > max_keycode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ModifierKey* modifierKey = GetModifierKey(keycode);
|
||||
if (!modifierKey) {
|
||||
modifierKey = mModifierKeys.AppendElement(ModifierKey(keycode));
|
||||
}
|
||||
|
||||
const KeySym* syms =
|
||||
xkeymap + (keycode - min_keycode) * keysyms_per_keycode;
|
||||
const PRUint32 bit = i / xmodmap->max_keypermod;
|
||||
modifierKey->mMask |= 1 << bit;
|
||||
for (PRInt32 j = 0; j < keysyms_per_keycode; j++) {
|
||||
Modifier modifier = GetModifierForGDKKeyval(syms[j]);
|
||||
PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
|
||||
("KeymapWrapper(%p): InitBySystemSettings, "
|
||||
" bit=%d, j=%d, syms[j]=%s(0x%X), modifier=%s",
|
||||
this, bit, j, gdk_keyval_name(syms[j]), syms[j],
|
||||
GetModifierName(modifier)));
|
||||
|
||||
ModifierIndex index;
|
||||
switch (modifier) {
|
||||
case NUM_LOCK:
|
||||
index = INDEX_NUM_LOCK;
|
||||
break;
|
||||
case SCROLL_LOCK:
|
||||
index = INDEX_SCROLL_LOCK;
|
||||
break;
|
||||
case ALT:
|
||||
index = INDEX_ALT;
|
||||
break;
|
||||
case SUPER:
|
||||
index = INDEX_SUPER;
|
||||
break;
|
||||
case HYPER:
|
||||
index = INDEX_HYPER;
|
||||
break;
|
||||
case META:
|
||||
index = INDEX_META;
|
||||
break;
|
||||
case ALTGR:
|
||||
index = INDEX_ALTGR;
|
||||
break;
|
||||
default:
|
||||
// NOTE: We always use GDK_SHIFT_MASK, GDK_CONTROL_MASK and
|
||||
// GDK_LOCK_MASK for SHIFT, CTRL and CAPS_LOCK.
|
||||
// This is standard manners of GTK application.
|
||||
continue;
|
||||
}
|
||||
mModifierMasks[index] |= 1 << bit;
|
||||
}
|
||||
}
|
||||
|
||||
XFreeModifiermap(xmodmap);
|
||||
XFree(xkeymap);
|
||||
}
|
||||
|
||||
KeymapWrapper::~KeymapWrapper()
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#define __nsGdkKeyUtils_h__
|
||||
|
||||
#include "nsEvent.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
|
@ -63,6 +64,30 @@ namespace widget {
|
|||
|
||||
class KeymapWrapper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Modifier is list of modifiers which we support in widget level.
|
||||
*/
|
||||
enum Modifier {
|
||||
NOT_MODIFIER = 0x0000,
|
||||
CAPS_LOCK = 0x0001,
|
||||
NUM_LOCK = 0x0002,
|
||||
SCROLL_LOCK = 0x0004,
|
||||
SHIFT = 0x0008,
|
||||
CTRL = 0x0010,
|
||||
ALT = 0x0020,
|
||||
SUPER = 0x0040,
|
||||
HYPER = 0x0080,
|
||||
META = 0x0100,
|
||||
ALTGR = 0x0200
|
||||
};
|
||||
|
||||
/**
|
||||
* Modifiers is used for combination of Modifier.
|
||||
* E.g., |Modifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl.
|
||||
*/
|
||||
typedef PRUint32 Modifiers;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
@ -77,6 +102,63 @@ protected:
|
|||
|
||||
bool mInitialized;
|
||||
|
||||
/**
|
||||
* Initializing methods.
|
||||
*/
|
||||
void Init();
|
||||
void InitBySystemSettings();
|
||||
|
||||
/**
|
||||
* mModifierKeys stores each hardware key information.
|
||||
*/
|
||||
struct ModifierKey {
|
||||
guint mHardwareKeycode;
|
||||
guint mMask;
|
||||
|
||||
ModifierKey(guint aHardwareKeycode) :
|
||||
mHardwareKeycode(aHardwareKeycode), mMask(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
nsTArray<ModifierKey> mModifierKeys;
|
||||
|
||||
/**
|
||||
* GetModifierKey() returns modifier key information of the hardware
|
||||
* keycode. If the key isn't a modifier key, returns NULL.
|
||||
*/
|
||||
ModifierKey* GetModifierKey(guint aHardwareKeycode);
|
||||
|
||||
/**
|
||||
* mModifierMasks is bit masks for each modifier. The index should be one
|
||||
* of ModifierIndex values.
|
||||
*/
|
||||
enum ModifierIndex {
|
||||
INDEX_NUM_LOCK,
|
||||
INDEX_SCROLL_LOCK,
|
||||
INDEX_ALT,
|
||||
INDEX_SUPER,
|
||||
INDEX_HYPER,
|
||||
INDEX_META,
|
||||
INDEX_ALTGR,
|
||||
COUNT_OF_MODIFIER_INDEX
|
||||
};
|
||||
guint mModifierMasks[COUNT_OF_MODIFIER_INDEX];
|
||||
|
||||
guint GetModifierMask(Modifier aModifier) const;
|
||||
|
||||
/**
|
||||
* @param aGdkKeyval A GDK defined modifier key value such as
|
||||
* GDK_Shift_L.
|
||||
* @return Returns Modifier values for aGdkKeyval.
|
||||
* If the given key code isn't a modifier key,
|
||||
* returns NOT_MODIFIER.
|
||||
*/
|
||||
static Modifier GetModifierForGDKKeyval(guint aGdkKeyval);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static const char* GetModifierName(Modifier aModifier);
|
||||
#endif // PR_LOGGING
|
||||
|
||||
/**
|
||||
* mGdkKeymap is a wrapped instance by this class.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче