LCOV - code coverage report
Current view: directory - widget/gtk2 - nsGtkKeyUtils.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 323 0 0.0 %
Date: 2012-06-02 Functions: 25 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* vim:expandtab:shiftwidth=4:tabstop=4:
       3                 :  */
       4                 : /* ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is mozilla.org code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is 
      20                 :  * Christopher Blizzard <blizzard@mozilla.org>.  
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2001 
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Masayuki Nakano <masayuki@d-toybox.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "prlog.h"
      42                 : 
      43                 : #include "nsGtkKeyUtils.h"
      44                 : 
      45                 : #include <gdk/gdkkeysyms.h>
      46                 : #ifndef GDK_Sleep
      47                 : #define GDK_Sleep 0x1008ff2f
      48                 : #endif
      49                 : 
      50                 : #include <gdk/gdk.h>
      51                 : #ifdef MOZ_X11
      52                 : #include <gdk/gdkx.h>
      53                 : #endif /* MOZ_X11 */
      54                 : #include "nsGUIEvent.h"
      55                 : #include "keysym2ucs.h"
      56                 : 
      57                 : #ifdef PR_LOGGING
      58                 : PRLogModuleInfo* gKeymapWrapperLog = nsnull;
      59                 : #endif // PR_LOGGING
      60                 : 
      61                 : #include "mozilla/Util.h"
      62                 : 
      63                 : namespace mozilla {
      64                 : namespace widget {
      65                 : 
      66                 : struct KeyPair {
      67                 :     PRUint32 DOMKeyCode;
      68                 :     guint GDKKeyval;
      69                 : };
      70                 : 
      71                 : #define IS_ASCII_ALPHABETICAL(key) \
      72                 :     ((('a' <= key) && (key <= 'z')) || (('A' <= key) && (key <= 'Z')))
      73                 : 
      74                 : //
      75                 : // Netscape keycodes are defined in widget/public/nsGUIEvent.h
      76                 : // GTK keycodes are defined in <gdk/gdkkeysyms.h>
      77                 : //
      78                 : static const KeyPair kKeyPairs[] = {
      79                 :     { NS_VK_CANCEL,     GDK_Cancel },
      80                 :     { NS_VK_BACK,       GDK_BackSpace },
      81                 :     { NS_VK_TAB,        GDK_Tab },
      82                 :     { NS_VK_TAB,        GDK_ISO_Left_Tab },
      83                 :     { NS_VK_CLEAR,      GDK_Clear },
      84                 :     { NS_VK_RETURN,     GDK_Return },
      85                 :     { NS_VK_SHIFT,      GDK_Shift_L },
      86                 :     { NS_VK_SHIFT,      GDK_Shift_R },
      87                 :     { NS_VK_CONTROL,    GDK_Control_L },
      88                 :     { NS_VK_CONTROL,    GDK_Control_R },
      89                 :     { NS_VK_ALT,        GDK_Alt_L },
      90                 :     { NS_VK_ALT,        GDK_Alt_R },
      91                 :     { NS_VK_META,       GDK_Meta_L },
      92                 :     { NS_VK_META,       GDK_Meta_R },
      93                 :     { NS_VK_PAUSE,      GDK_Pause },
      94                 :     { NS_VK_CAPS_LOCK,  GDK_Caps_Lock },
      95                 :     { NS_VK_KANA,       GDK_Kana_Lock },
      96                 :     { NS_VK_KANA,       GDK_Kana_Shift },
      97                 :     { NS_VK_HANGUL,     GDK_Hangul },
      98                 :     // { NS_VK_JUNJA,      GDK_XXX },
      99                 :     // { NS_VK_FINAL,      GDK_XXX },
     100                 :     { NS_VK_HANJA,      GDK_Hangul_Hanja },
     101                 :     { NS_VK_KANJI,      GDK_Kanji },
     102                 :     { NS_VK_ESCAPE,     GDK_Escape },
     103                 :     { NS_VK_CONVERT,    GDK_Henkan },
     104                 :     { NS_VK_NONCONVERT, GDK_Muhenkan },
     105                 :     // { NS_VK_ACCEPT,     GDK_XXX },
     106                 :     { NS_VK_MODECHANGE, GDK_Mode_switch },
     107                 :     { NS_VK_SPACE,      GDK_space },
     108                 :     { NS_VK_PAGE_UP,    GDK_Page_Up },
     109                 :     { NS_VK_PAGE_DOWN,  GDK_Page_Down },
     110                 :     { NS_VK_END,        GDK_End },
     111                 :     { NS_VK_HOME,       GDK_Home },
     112                 :     { NS_VK_LEFT,       GDK_Left },
     113                 :     { NS_VK_UP,         GDK_Up },
     114                 :     { NS_VK_RIGHT,      GDK_Right },
     115                 :     { NS_VK_DOWN,       GDK_Down },
     116                 :     { NS_VK_SELECT,     GDK_Select },
     117                 :     { NS_VK_PRINT,      GDK_Print },
     118                 :     { NS_VK_EXECUTE,    GDK_Execute },
     119                 :     { NS_VK_PRINTSCREEN, GDK_Print },
     120                 :     { NS_VK_INSERT,     GDK_Insert },
     121                 :     { NS_VK_DELETE,     GDK_Delete },
     122                 :     { NS_VK_HELP,       GDK_Help },
     123                 : 
     124                 :     // keypad keys
     125                 :     { NS_VK_LEFT,       GDK_KP_Left },
     126                 :     { NS_VK_RIGHT,      GDK_KP_Right },
     127                 :     { NS_VK_UP,         GDK_KP_Up },
     128                 :     { NS_VK_DOWN,       GDK_KP_Down },
     129                 :     { NS_VK_PAGE_UP,    GDK_KP_Page_Up },
     130                 :     // Not sure what these are
     131                 :     //{ NS_VK_,       GDK_KP_Prior },
     132                 :     //{ NS_VK_,        GDK_KP_Next },
     133                 :     // GDK_KP_Begin is the 5 on the non-numlock keypad
     134                 :     //{ NS_VK_,        GDK_KP_Begin },
     135                 :     { NS_VK_PAGE_DOWN,  GDK_KP_Page_Down },
     136                 :     { NS_VK_HOME,       GDK_KP_Home },
     137                 :     { NS_VK_END,        GDK_KP_End },
     138                 :     { NS_VK_INSERT,     GDK_KP_Insert },
     139                 :     { NS_VK_DELETE,     GDK_KP_Delete },
     140                 : 
     141                 :     { NS_VK_MULTIPLY,   GDK_KP_Multiply },
     142                 :     { NS_VK_ADD,        GDK_KP_Add },
     143                 :     { NS_VK_SEPARATOR,  GDK_KP_Separator },
     144                 :     { NS_VK_SUBTRACT,   GDK_KP_Subtract },
     145                 :     { NS_VK_DECIMAL,    GDK_KP_Decimal },
     146                 :     { NS_VK_DIVIDE,     GDK_KP_Divide },
     147                 :     { NS_VK_RETURN,     GDK_KP_Enter },
     148                 :     { NS_VK_NUM_LOCK,   GDK_Num_Lock },
     149                 :     { NS_VK_SCROLL_LOCK,GDK_Scroll_Lock },
     150                 : 
     151                 :     { NS_VK_COMMA,      GDK_comma },
     152                 :     { NS_VK_PERIOD,     GDK_period },
     153                 :     { NS_VK_SLASH,      GDK_slash },
     154                 :     { NS_VK_BACK_SLASH, GDK_backslash },
     155                 :     { NS_VK_BACK_QUOTE, GDK_grave },
     156                 :     { NS_VK_OPEN_BRACKET, GDK_bracketleft },
     157                 :     { NS_VK_CLOSE_BRACKET, GDK_bracketright },
     158                 :     { NS_VK_SEMICOLON, GDK_colon },
     159                 :     { NS_VK_QUOTE, GDK_apostrophe },
     160                 : 
     161                 :     // context menu key, keysym 0xff67, typically keycode 117 on 105-key (Microsoft) 
     162                 :     // x86 keyboards, located between right 'Windows' key and right Ctrl key
     163                 :     { NS_VK_CONTEXT_MENU, GDK_Menu },
     164                 :     { NS_VK_SLEEP,      GDK_Sleep },
     165                 : 
     166                 :     // NS doesn't have dash or equals distinct from the numeric keypad ones,
     167                 :     // so we'll use those for now.  See bug 17008:
     168                 :     { NS_VK_SUBTRACT, GDK_minus },
     169                 :     { NS_VK_EQUALS, GDK_equal },
     170                 : 
     171                 :     // Some shifted keys, see bug 15463 as well as 17008.
     172                 :     // These should be subject to different keyboard mappings.
     173                 :     { NS_VK_QUOTE, GDK_quotedbl },
     174                 :     { NS_VK_OPEN_BRACKET, GDK_braceleft },
     175                 :     { NS_VK_CLOSE_BRACKET, GDK_braceright },
     176                 :     { NS_VK_BACK_SLASH, GDK_bar },
     177                 :     { NS_VK_SEMICOLON, GDK_semicolon },
     178                 :     { NS_VK_BACK_QUOTE, GDK_asciitilde },
     179                 :     { NS_VK_COMMA, GDK_less },
     180                 :     { NS_VK_PERIOD, GDK_greater },
     181                 :     { NS_VK_SLASH,      GDK_question },
     182                 :     { NS_VK_1, GDK_exclam },
     183                 :     { NS_VK_2, GDK_at },
     184                 :     { NS_VK_3, GDK_numbersign },
     185                 :     { NS_VK_4, GDK_dollar },
     186                 :     { NS_VK_5, GDK_percent },
     187                 :     { NS_VK_6, GDK_asciicircum },
     188                 :     { NS_VK_7, GDK_ampersand },
     189                 :     { NS_VK_8, GDK_asterisk },
     190                 :     { NS_VK_9, GDK_parenleft },
     191                 :     { NS_VK_0, GDK_parenright },
     192                 :     { NS_VK_SUBTRACT, GDK_underscore },
     193                 :     { NS_VK_EQUALS, GDK_plus }
     194                 : };
     195                 : 
     196                 : // map Sun Keyboard special keysyms on to NS_VK keys
     197                 : static const KeyPair kSunKeyPairs[] = {
     198                 :     {NS_VK_F11, 0x1005ff10 }, //Sun F11 key generates SunF36(0x1005ff10) keysym
     199                 :     {NS_VK_F12, 0x1005ff11 }  //Sun F12 key generates SunF37(0x1005ff11) keysym
     200                 : };
     201                 : 
     202                 : #define MOZ_MODIFIER_KEYS "MozKeymapWrapper"
     203                 : 
     204                 : KeymapWrapper* KeymapWrapper::sInstance = nsnull;
     205                 : 
     206                 : #ifdef PR_LOGGING
     207                 : 
     208               0 : static const char* GetBoolName(bool aBool)
     209                 : {
     210               0 :     return aBool ? "TRUE" : "FALSE";
     211                 : }
     212                 : 
     213                 : /* static */ const char*
     214               0 : KeymapWrapper::GetModifierName(Modifier aModifier)
     215                 : {
     216               0 :     switch (aModifier) {
     217               0 :         case CAPS_LOCK:    return "CapsLock";
     218               0 :         case NUM_LOCK:     return "NumLock";
     219               0 :         case SCROLL_LOCK:  return "ScrollLock";
     220               0 :         case SHIFT:        return "Shift";
     221               0 :         case CTRL:         return "Ctrl";
     222               0 :         case ALT:          return "Alt";
     223               0 :         case SUPER:        return "Super";
     224               0 :         case HYPER:        return "Hyper";
     225               0 :         case META:         return "Meta";
     226               0 :         case ALTGR:        return "AltGr";
     227               0 :         case NOT_MODIFIER: return "NotModifier";
     228               0 :         default:           return "InvalidValue";
     229                 :     }
     230                 : }
     231                 : 
     232                 : #endif // PR_LOGGING
     233                 : 
     234                 : /* static */ KeymapWrapper::Modifier
     235               0 : KeymapWrapper::GetModifierForGDKKeyval(guint aGdkKeyval)
     236                 : {
     237               0 :     switch (aGdkKeyval) {
     238               0 :         case GDK_Caps_Lock:        return CAPS_LOCK;
     239               0 :         case GDK_Num_Lock:         return NUM_LOCK;
     240               0 :         case GDK_Scroll_Lock:      return SCROLL_LOCK;
     241                 :         case GDK_Shift_L:
     242               0 :         case GDK_Shift_R:          return SHIFT;
     243                 :         case GDK_Control_L:
     244               0 :         case GDK_Control_R:        return CTRL;
     245                 :         case GDK_Alt_L:
     246               0 :         case GDK_Alt_R:            return ALT;
     247                 :         case GDK_Super_L:
     248               0 :         case GDK_Super_R:          return SUPER;
     249                 :         case GDK_Hyper_L:
     250               0 :         case GDK_Hyper_R:          return HYPER;
     251                 :         case GDK_Meta_L:
     252               0 :         case GDK_Meta_R:           return META;
     253                 :         case GDK_ISO_Level3_Shift:
     254               0 :         case GDK_Mode_switch:      return ALTGR;
     255               0 :         default:                   return NOT_MODIFIER;
     256                 :     }
     257                 : }
     258                 : 
     259                 : guint
     260               0 : KeymapWrapper::GetModifierMask(Modifier aModifier) const
     261                 : {
     262               0 :     switch (aModifier) {
     263                 :         case CAPS_LOCK:
     264               0 :             return GDK_LOCK_MASK;
     265                 :         case NUM_LOCK:
     266               0 :             return mModifierMasks[INDEX_NUM_LOCK];
     267                 :         case SCROLL_LOCK:
     268               0 :             return mModifierMasks[INDEX_SCROLL_LOCK];
     269                 :         case SHIFT:
     270               0 :             return GDK_SHIFT_MASK;
     271                 :         case CTRL:
     272               0 :             return GDK_CONTROL_MASK;
     273                 :         case ALT:
     274               0 :             return mModifierMasks[INDEX_ALT];
     275                 :         case SUPER:
     276               0 :             return mModifierMasks[INDEX_SUPER];
     277                 :         case HYPER:
     278               0 :             return mModifierMasks[INDEX_HYPER];
     279                 :         case META:
     280               0 :             return mModifierMasks[INDEX_META];
     281                 :         case ALTGR:
     282               0 :             return mModifierMasks[INDEX_ALTGR];
     283                 :         default:
     284               0 :             return 0;
     285                 :     }
     286                 : }
     287                 : 
     288                 : KeymapWrapper::ModifierKey*
     289               0 : KeymapWrapper::GetModifierKey(guint aHardwareKeycode)
     290                 : {
     291               0 :     for (PRUint32 i = 0; i < mModifierKeys.Length(); i++) {
     292               0 :         ModifierKey& key = mModifierKeys[i];
     293               0 :         if (key.mHardwareKeycode == aHardwareKeycode) {
     294               0 :             return &key;
     295                 :         }
     296                 :     }
     297               0 :     return nsnull;
     298                 : }
     299                 : 
     300                 : /* static */ KeymapWrapper*
     301               0 : KeymapWrapper::GetInstance()
     302                 : {
     303               0 :     if (sInstance) {
     304               0 :         sInstance->Init();
     305               0 :         return sInstance;
     306                 :     }
     307                 : 
     308               0 :     sInstance = new KeymapWrapper();
     309               0 :     return sInstance;
     310                 : }
     311                 : 
     312               0 : KeymapWrapper::KeymapWrapper() :
     313               0 :     mInitialized(false), mGdkKeymap(gdk_keymap_get_default())
     314                 : {
     315                 : #ifdef PR_LOGGING
     316               0 :     if (!gKeymapWrapperLog) {
     317               0 :         gKeymapWrapperLog = PR_NewLogModule("KeymapWrapperWidgets");
     318                 :     }
     319               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     320                 :         ("KeymapWrapper(%p): Constructor, mGdkKeymap=%p",
     321                 :          this, mGdkKeymap));
     322                 : #endif // PR_LOGGING
     323                 : 
     324               0 :     g_signal_connect(mGdkKeymap, "keys-changed",
     325               0 :                      (GCallback)OnKeysChanged, this);
     326                 : 
     327                 :     // This is necessary for catching the destroying timing.
     328               0 :     g_object_weak_ref(G_OBJECT(mGdkKeymap),
     329               0 :                       (GWeakNotify)OnDestroyKeymap, this);
     330                 : 
     331               0 :     Init();
     332               0 : }
     333                 : 
     334                 : void
     335               0 : KeymapWrapper::Init()
     336                 : {
     337               0 :     if (mInitialized) {
     338               0 :         return;
     339                 :     }
     340               0 :     mInitialized = true;
     341                 : 
     342               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     343                 :         ("KeymapWrapper(%p): Init, mGdkKeymap=%p",
     344                 :          this, mGdkKeymap));
     345                 : 
     346               0 :     mModifierKeys.Clear();
     347               0 :     memset(mModifierMasks, 0, sizeof(mModifierMasks));
     348                 : 
     349               0 :     InitBySystemSettings();
     350                 : 
     351               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     352                 :         ("KeymapWrapper(%p): Init, CapsLock=0x%X, NumLock=0x%X, "
     353                 :          "ScrollLock=0x%X, AltGr=0x%X, Shift=0x%X, Ctrl=0x%X, Alt=0x%X, "
     354                 :          "Meta=0x%X, Super=0x%X, Hyper=0x%X",
     355                 :          this,
     356                 :          GetModifierMask(CAPS_LOCK), GetModifierMask(NUM_LOCK),
     357                 :          GetModifierMask(SCROLL_LOCK), GetModifierMask(ALTGR),
     358                 :          GetModifierMask(SHIFT), GetModifierMask(CTRL),
     359                 :          GetModifierMask(ALT), GetModifierMask(META),
     360                 :          GetModifierMask(SUPER), GetModifierMask(HYPER)));
     361                 : }
     362                 : 
     363                 : void
     364               0 : KeymapWrapper::InitBySystemSettings()
     365                 : {
     366               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     367                 :       ("KeymapWrapper(%p): InitBySystemSettings, mGdkKeymap=%p",
     368                 :        this, mGdkKeymap));
     369                 : 
     370                 :     Display* display =
     371               0 :         gdk_x11_display_get_xdisplay(gdk_display_get_default());
     372                 : 
     373               0 :     int min_keycode = 0;
     374               0 :     int max_keycode = 0;
     375               0 :     XDisplayKeycodes(display, &min_keycode, &max_keycode);
     376                 : 
     377               0 :     int keysyms_per_keycode = 0;
     378                 :     KeySym* xkeymap = XGetKeyboardMapping(display, min_keycode,
     379                 :                                           max_keycode - min_keycode + 1,
     380               0 :                                           &keysyms_per_keycode);
     381               0 :     if (!xkeymap) {
     382               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     383                 :             ("KeymapWrapper(%p): InitBySystemSettings, "
     384                 :              "Failed due to null xkeymap", this));
     385               0 :         return;
     386                 :     }
     387                 : 
     388               0 :     XModifierKeymap* xmodmap = XGetModifierMapping(display);
     389               0 :     if (!xmodmap) {
     390               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     391                 :             ("KeymapWrapper(%p): InitBySystemSettings, "
     392                 :              "Failed due to null xmodmap", this));
     393               0 :         XFree(xkeymap);
     394               0 :         return;
     395                 :     }
     396               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     397                 :         ("KeymapWrapper(%p): InitBySystemSettings, min_keycode=%d, "
     398                 :          "max_keycode=%d, keysyms_per_keycode=%d, max_keypermod=%d",
     399                 :          this, min_keycode, max_keycode, keysyms_per_keycode,
     400                 :          xmodmap->max_keypermod));
     401                 : 
     402                 :     // The modifiermap member of the XModifierKeymap structure contains 8 sets
     403                 :     // of max_keypermod KeyCodes, one for each modifier in the order Shift,
     404                 :     // Lock, Control, Mod1, Mod2, Mod3, Mod4, and Mod5.
     405                 :     // Only nonzero KeyCodes have meaning in each set, and zero KeyCodes are
     406                 :     // ignored.
     407                 : 
     408                 :     // Note that two or more modifiers may use one modifier flag.  E.g.,
     409                 :     // on Ubuntu 10.10, Alt and Meta share the Mod1 in default settings.
     410                 :     //  And also Super and Hyper share the Mod4.
     411                 : 
     412               0 :     const PRUint32 map_size = 8 * xmodmap->max_keypermod;
     413               0 :     for (PRUint32 i = 0; i < map_size; i++) {
     414               0 :         KeyCode keycode = xmodmap->modifiermap[i];
     415               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     416                 :             ("KeymapWrapper(%p): InitBySystemSettings, "
     417                 :              "  i=%d, keycode=0x%08X",
     418                 :              this, i, keycode));
     419               0 :         if (!keycode || keycode < min_keycode || keycode > max_keycode) {
     420               0 :             continue;
     421                 :         }
     422                 : 
     423               0 :         ModifierKey* modifierKey = GetModifierKey(keycode);
     424               0 :         if (!modifierKey) {
     425               0 :             modifierKey = mModifierKeys.AppendElement(ModifierKey(keycode));
     426                 :         }
     427                 : 
     428                 :         const KeySym* syms =
     429               0 :             xkeymap + (keycode - min_keycode) * keysyms_per_keycode;
     430               0 :         const PRUint32 bit = i / xmodmap->max_keypermod;
     431               0 :         modifierKey->mMask |= 1 << bit;
     432               0 :         for (PRInt32 j = 0; j < keysyms_per_keycode; j++) {
     433               0 :             Modifier modifier = GetModifierForGDKKeyval(syms[j]);
     434               0 :             PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     435                 :                 ("KeymapWrapper(%p): InitBySystemSettings, "
     436                 :                  "    bit=%d, j=%d, syms[j]=%s(0x%X), modifier=%s",
     437                 :                  this, bit, j, gdk_keyval_name(syms[j]), syms[j],
     438                 :                  GetModifierName(modifier)));
     439                 : 
     440                 :             ModifierIndex index;
     441               0 :             switch (modifier) {
     442                 :                 case NUM_LOCK:
     443               0 :                     index = INDEX_NUM_LOCK;
     444               0 :                     break;
     445                 :                 case SCROLL_LOCK:
     446               0 :                     index = INDEX_SCROLL_LOCK;
     447               0 :                     break;
     448                 :                 case ALT:
     449               0 :                     index = INDEX_ALT;
     450               0 :                     break;
     451                 :                 case SUPER:
     452               0 :                     index = INDEX_SUPER;
     453               0 :                     break;
     454                 :                 case HYPER:
     455               0 :                     index = INDEX_HYPER;
     456               0 :                     break;
     457                 :                 case META:
     458               0 :                     index = INDEX_META;
     459               0 :                     break;
     460                 :                 case ALTGR:
     461               0 :                     index = INDEX_ALTGR;
     462               0 :                     break;
     463                 :                 default:
     464                 :                     // NOTE: We always use GDK_SHIFT_MASK, GDK_CONTROL_MASK and
     465                 :                     //       GDK_LOCK_MASK for SHIFT, CTRL and CAPS_LOCK.
     466                 :                     //       This is standard manners of GTK application.
     467               0 :                     continue;
     468                 :             }
     469               0 :             mModifierMasks[index] |= 1 << bit;
     470                 :         }
     471                 :     }
     472                 : 
     473               0 :     XFreeModifiermap(xmodmap);
     474               0 :     XFree(xkeymap);
     475                 : }
     476                 : 
     477               0 : KeymapWrapper::~KeymapWrapper()
     478                 : {
     479               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     480                 :         ("KeymapWrapper(%p): Destructor", this));
     481               0 : }
     482                 : 
     483                 : /* static */ void
     484               0 : KeymapWrapper::OnDestroyKeymap(KeymapWrapper* aKeymapWrapper,
     485                 :                                GdkKeymap *aGdkKeymap)
     486                 : {
     487               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     488                 :         ("KeymapWrapper: OnDestroyKeymap, aGdkKeymap=%p, aKeymapWrapper=%p",
     489                 :          aGdkKeymap, aKeymapWrapper));
     490               0 :     MOZ_ASSERT(aKeymapWrapper == sInstance,
     491               0 :                "Desroying unexpected instance");
     492               0 :     delete sInstance;
     493               0 :     sInstance = nsnull;
     494               0 : }
     495                 : 
     496                 : /* static */ void
     497               0 : KeymapWrapper::OnKeysChanged(GdkKeymap *aGdkKeymap,
     498                 :                              KeymapWrapper* aKeymapWrapper)
     499                 : {
     500               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     501                 :         ("KeymapWrapper: OnKeysChanged, aGdkKeymap=%p, aKeymapWrapper=%p",
     502                 :          aGdkKeymap, aKeymapWrapper));
     503                 : 
     504               0 :     MOZ_ASSERT(sInstance == aKeymapWrapper,
     505               0 :                "This instance must be the singleton instance");
     506                 : 
     507                 :     // We cannot reintialize here becasue we don't have GdkWindow which is using
     508                 :     // the GdkKeymap.  We'll reinitialize it when next GetInstance() is called.
     509               0 :     sInstance->mInitialized = false;
     510               0 : }
     511                 : 
     512                 : /* static */ guint
     513               0 : KeymapWrapper::GetCurrentModifierState()
     514                 : {
     515                 :     GdkModifierType modifiers;
     516                 :     gdk_display_get_pointer(gdk_display_get_default(),
     517               0 :                             NULL, NULL, NULL, &modifiers);
     518               0 :     return static_cast<guint>(modifiers);
     519                 : }
     520                 : 
     521                 : /* static */ bool
     522               0 : KeymapWrapper::AreModifiersCurrentlyActive(Modifiers aModifiers)
     523                 : {
     524               0 :     guint modifierState = GetCurrentModifierState();
     525               0 :     return AreModifiersActive(aModifiers, modifierState);
     526                 : }
     527                 : 
     528                 : /* static */ bool
     529               0 : KeymapWrapper::AreModifiersActive(Modifiers aModifiers,
     530                 :                                   guint aModifierState)
     531                 : {
     532               0 :     NS_ENSURE_TRUE(aModifiers, false);
     533                 : 
     534               0 :     KeymapWrapper* keymapWrapper = GetInstance();
     535               0 :     for (PRUint32 i = 0; i < sizeof(Modifier) * 8 && aModifiers; i++) {
     536               0 :         Modifier modifier = static_cast<Modifier>(1 << i);
     537               0 :         if (!(aModifiers & modifier)) {
     538               0 :             continue;
     539                 :         }
     540               0 :         if (!(aModifierState & keymapWrapper->GetModifierMask(modifier))) {
     541               0 :             return false;
     542                 :         }
     543               0 :         aModifiers &= ~modifier;
     544                 :     }
     545               0 :     return true;
     546                 : }
     547                 : 
     548                 : /* static */ void
     549               0 : KeymapWrapper::InitInputEvent(nsInputEvent& aInputEvent,
     550                 :                               guint aModifierState)
     551                 : {
     552               0 :     KeymapWrapper* keymapWrapper = GetInstance();
     553                 : 
     554                 :     aInputEvent.isShift =
     555               0 :         keymapWrapper->AreModifiersActive(SHIFT, aModifierState);
     556                 :     aInputEvent.isControl =
     557               0 :         keymapWrapper->AreModifiersActive(CTRL, aModifierState);
     558                 :     aInputEvent.isAlt =
     559               0 :         keymapWrapper->AreModifiersActive(ALT, aModifierState);
     560                 :     // XXX DOM Meta key should be TRUE only on Mac.  We need to discuss this
     561                 :     //     issue later.
     562               0 :     aInputEvent.isMeta = false;
     563                 : 
     564               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_DEBUG,
     565                 :         ("KeymapWrapper(%p): InitInputEvent, aModifierState=0x%08X "
     566                 :          "aKeyEvent={ isShift=%s, isControl=%s, isAlt=%s, isMeta=%s }",
     567                 :          keymapWrapper, aModifierState,
     568                 :          GetBoolName(aInputEvent.isShift), GetBoolName(aInputEvent.isControl),
     569                 :          GetBoolName(aInputEvent.isAlt), GetBoolName(aInputEvent.isMeta)));
     570               0 : }
     571                 : 
     572                 : /* static */ PRUint32
     573               0 : KeymapWrapper::ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent)
     574                 : {
     575               0 :     guint keyval = aGdkKeyEvent->keyval;
     576                 : 
     577                 :     // First, try to handle alphanumeric input, not listed in nsKeycodes:
     578                 :     // most likely, more letters will be getting typed in than things in
     579                 :     // the key list, so we will look through these first.
     580                 : 
     581                 :     // since X has different key symbols for upper and lowercase letters and
     582                 :     // mozilla does not, convert gdk's to mozilla's
     583               0 :     if (keyval >= GDK_a && keyval <= GDK_z) {
     584               0 :         return keyval - GDK_a + NS_VK_A;
     585                 :     }
     586               0 :     if (keyval >= GDK_A && keyval <= GDK_Z) {
     587               0 :         return keyval - GDK_A + NS_VK_A;
     588                 :     }
     589                 : 
     590                 :     // numbers
     591               0 :     if (keyval >= GDK_0 && keyval <= GDK_9) {
     592               0 :         return keyval - GDK_0 + NS_VK_0;
     593                 :     }
     594                 : 
     595                 :     // keypad numbers
     596               0 :     if (keyval >= GDK_KP_0 && keyval <= GDK_KP_9) {
     597               0 :         return keyval - GDK_KP_0 + NS_VK_NUMPAD0;
     598                 :     }
     599                 : 
     600                 :     // If the keyval indicates it's a modifier key, we should use unshifted
     601                 :     // key's modifier keyval.
     602               0 :     if (GetModifierForGDKKeyval(keyval)) {
     603               0 :         KeymapWrapper* keymapWrapper = GetInstance();
     604                 :         GdkKeymapKey key;
     605               0 :         key.keycode = aGdkKeyEvent->hardware_keycode;
     606               0 :         key.group = aGdkKeyEvent->group;
     607               0 :         key.level = 0;
     608                 :         guint unshiftedKeyval =
     609               0 :             gdk_keymap_lookup_key(keymapWrapper->mGdkKeymap, &key);
     610                 :         // But if the unshifted keyval isn't a modifier key, we shouldn't use
     611                 :         // it.  E.g., Japanese keyboard layout's Shift + Eisu-Toggle key is
     612                 :         // CapsLock.  This is an actual rare case, Windows uses different
     613                 :         // keycode for a physical key for different shift key state.
     614               0 :         if (GetModifierForGDKKeyval(unshiftedKeyval)) {
     615               0 :             keyval = unshiftedKeyval;
     616                 :         }
     617                 :     }
     618                 : 
     619                 :     // map Sun Keyboard special keysyms
     620               0 :     for (PRUint32 i = 0; i < ArrayLength(kSunKeyPairs); i++) {
     621               0 :         if (kSunKeyPairs[i].GDKKeyval == keyval) {
     622               0 :             return kSunKeyPairs[i].DOMKeyCode;
     623                 :         }
     624                 :     }
     625                 : 
     626                 :     // misc other things
     627               0 :     for (PRUint32 i = 0; i < ArrayLength(kKeyPairs); i++) {
     628               0 :         if (kKeyPairs[i].GDKKeyval == keyval) {
     629               0 :             return kKeyPairs[i].DOMKeyCode;
     630                 :         }
     631                 :     }
     632                 : 
     633                 :     // function keys
     634               0 :     if (keyval >= GDK_F1 && keyval <= GDK_F24) {
     635               0 :         return keyval - GDK_F1 + NS_VK_F1;
     636                 :     }
     637                 : 
     638               0 :     return 0;
     639                 : }
     640                 : 
     641                 : /* static */ guint
     642               0 : KeymapWrapper::GuessGDKKeyval(PRUint32 aDOMKeyCode)
     643                 : {
     644                 :     // First, try to handle alphanumeric input, not listed in nsKeycodes:
     645                 :     // most likely, more letters will be getting typed in than things in
     646                 :     // the key list, so we will look through these first.
     647                 : 
     648               0 :     if (aDOMKeyCode >= NS_VK_A && aDOMKeyCode <= NS_VK_Z) {
     649                 :         // gdk and DOM both use the ASCII codes for these keys.
     650               0 :         return aDOMKeyCode;
     651                 :     }
     652                 : 
     653                 :     // numbers
     654               0 :     if (aDOMKeyCode >= NS_VK_0 && aDOMKeyCode <= NS_VK_9) {
     655                 :         // gdk and DOM both use the ASCII codes for these keys.
     656               0 :         return aDOMKeyCode - NS_VK_0 + GDK_0;
     657                 :     }
     658                 : 
     659                 :     // keypad numbers
     660               0 :     if (aDOMKeyCode >= NS_VK_NUMPAD0 && aDOMKeyCode <= NS_VK_NUMPAD9) {
     661               0 :         return aDOMKeyCode - NS_VK_NUMPAD0 + GDK_KP_0;
     662                 :     }
     663                 : 
     664                 :     // misc other things
     665               0 :     for (PRUint32 i = 0; i < ArrayLength(kKeyPairs); ++i) {
     666               0 :         if (kKeyPairs[i].DOMKeyCode == aDOMKeyCode) {
     667               0 :             return kKeyPairs[i].GDKKeyval;
     668                 :         }
     669                 :     }
     670                 : 
     671                 :     // function keys
     672               0 :     if (aDOMKeyCode >= NS_VK_F1 && aDOMKeyCode <= NS_VK_F9) {
     673               0 :         return aDOMKeyCode - NS_VK_F1 + GDK_F1;
     674                 :     }
     675                 : 
     676               0 :     return 0;
     677                 : }
     678                 : 
     679                 : /* static */ void
     680               0 : KeymapWrapper::InitKeyEvent(nsKeyEvent& aKeyEvent,
     681                 :                             GdkEventKey* aGdkKeyEvent)
     682                 : {
     683               0 :     KeymapWrapper* keymapWrapper = GetInstance();
     684                 : 
     685               0 :     aKeyEvent.keyCode = ComputeDOMKeyCode(aGdkKeyEvent);
     686                 : 
     687                 :     // NOTE: The state of given key event indicates adjacent state of
     688                 :     // modifier keys.  E.g., even if the event is Shift key press event,
     689                 :     // the bit for Shift is still false.  By the same token, even if the
     690                 :     // event is Shift key release event, the bit for Shift is still true.
     691                 :     // Unfortunately, gdk_keyboard_get_modifiers() returns current modifier
     692                 :     // state.  It means if there're some pending modifier key press or
     693                 :     // key release events, the result isn't what we want.
     694                 :     // Temporarily, we should compute the state only when the key event
     695                 :     // is GDK_KEY_PRESS.
     696                 :     // XXX If we could know the modifier keys state at the key release event,
     697                 :     //     we should cut out changingMask from modifierState.
     698               0 :     guint modifierState = aGdkKeyEvent->state;
     699               0 :     if (aGdkKeyEvent->is_modifier && aGdkKeyEvent->type == GDK_KEY_PRESS) {
     700                 :         ModifierKey* modifierKey =
     701               0 :             keymapWrapper->GetModifierKey(aGdkKeyEvent->hardware_keycode);
     702               0 :         if (modifierKey) {
     703                 :             // If new modifier key is pressed, add the pressed mod mask.
     704               0 :             modifierState |= modifierKey->mMask;
     705                 :         }
     706                 :     }
     707               0 :     InitInputEvent(aKeyEvent, modifierState);
     708                 : 
     709               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     710                 :         ("KeymapWrapper(%p): InitKeyEvent, modifierState=0x%08X "
     711                 :          "aGdkKeyEvent={ type=%s, keyval=%s(0x%X), state=0x%08X, "
     712                 :          "hardware_keycode=0x%08X, is_modifier=%s } "
     713                 :          "aKeyEvent={ message=%s, isShift=%s, isControl=%s, "
     714                 :          "isAlt=%s, isMeta=%s }",
     715                 :          keymapWrapper, modifierState,
     716                 :          ((aGdkKeyEvent->type == GDK_KEY_PRESS) ?
     717                 :                "GDK_KEY_PRESS" : "GDK_KEY_RELEASE"),
     718                 :          gdk_keyval_name(aGdkKeyEvent->keyval),
     719                 :          aGdkKeyEvent->keyval, aGdkKeyEvent->state,
     720                 :          aGdkKeyEvent->hardware_keycode,
     721                 :          GetBoolName(aGdkKeyEvent->is_modifier),
     722                 :          ((aKeyEvent.message == NS_KEY_DOWN) ? "NS_KEY_DOWN" :
     723                 :                (aKeyEvent.message == NS_KEY_PRESS) ? "NS_KEY_PRESS" :
     724                 :                                                       "NS_KEY_UP"),
     725                 :          GetBoolName(aKeyEvent.isShift), GetBoolName(aKeyEvent.isControl),
     726                 :          GetBoolName(aKeyEvent.isAlt), GetBoolName(aKeyEvent.isMeta)));
     727                 : 
     728               0 :     if (aKeyEvent.message == NS_KEY_PRESS) {
     729               0 :         keymapWrapper->InitKeypressEvent(aKeyEvent, aGdkKeyEvent);
     730                 :     }
     731                 : 
     732                 :     // The transformations above and in gdk for the keyval are not invertible
     733                 :     // so link to the GdkEvent (which will vanish soon after return from the
     734                 :     // event callback) to give plugins access to hardware_keycode and state.
     735                 :     // (An XEvent would be nice but the GdkEvent is good enough.)
     736               0 :     aKeyEvent.pluginEvent = (void *)aGdkKeyEvent;
     737               0 :     aKeyEvent.time = aGdkKeyEvent->time;
     738               0 : }
     739                 : 
     740                 : /* static */ PRUint32
     741               0 : KeymapWrapper::GetCharCodeFor(const GdkEventKey *aGdkKeyEvent)
     742                 : {
     743                 :     // Anything above 0xf000 is considered a non-printable
     744                 :     // Exception: directly encoded UCS characters
     745               0 :     if (aGdkKeyEvent->keyval > 0xf000 &&
     746                 :         (aGdkKeyEvent->keyval & 0xff000000) != 0x01000000) {
     747                 :         // Keypad keys are an exception: they return a value different
     748                 :         // from their non-keypad equivalents, but mozilla doesn't distinguish.
     749               0 :         switch (aGdkKeyEvent->keyval) {
     750               0 :             case GDK_KP_Space:              return ' ';
     751               0 :             case GDK_KP_Equal:              return '=';
     752               0 :             case GDK_KP_Multiply:           return '*';
     753               0 :             case GDK_KP_Add:                return '+';
     754               0 :             case GDK_KP_Separator:          return ',';
     755               0 :             case GDK_KP_Subtract:           return '-';
     756               0 :             case GDK_KP_Decimal:            return '.';
     757               0 :             case GDK_KP_Divide:             return '/';
     758               0 :             case GDK_KP_0:                  return '0';
     759               0 :             case GDK_KP_1:                  return '1';
     760               0 :             case GDK_KP_2:                  return '2';
     761               0 :             case GDK_KP_3:                  return '3';
     762               0 :             case GDK_KP_4:                  return '4';
     763               0 :             case GDK_KP_5:                  return '5';
     764               0 :             case GDK_KP_6:                  return '6';
     765               0 :             case GDK_KP_7:                  return '7';
     766               0 :             case GDK_KP_8:                  return '8';
     767               0 :             case GDK_KP_9:                  return '9';
     768               0 :             default:                        return 0; // non-printables
     769                 :         }
     770                 :     }
     771                 : 
     772                 :     static const long MAX_UNICODE = 0x10FFFF;
     773                 : 
     774                 :     // we're supposedly printable, let's try to convert
     775               0 :     long ucs = keysym2ucs(aGdkKeyEvent->keyval);
     776               0 :     if ((ucs != -1) && (ucs < MAX_UNICODE)) {
     777               0 :          return ucs;
     778                 :     }
     779                 : 
     780                 :     // I guess we couldn't convert
     781               0 :     return 0;
     782                 : }
     783                 : 
     784                 : PRUint32
     785               0 : KeymapWrapper::GetCharCodeFor(const GdkEventKey *aGdkKeyEvent,
     786                 :                               guint aModifierState,
     787                 :                               gint aGroup)
     788                 : {
     789                 :     guint keyval;
     790               0 :     if (!gdk_keymap_translate_keyboard_state(mGdkKeymap,
     791                 :              aGdkKeyEvent->hardware_keycode,
     792                 :              GdkModifierType(aModifierState),
     793               0 :              aGroup, &keyval, NULL, NULL, NULL)) {
     794               0 :         return 0;
     795                 :     }
     796               0 :     GdkEventKey tmpEvent = *aGdkKeyEvent;
     797               0 :     tmpEvent.state = aModifierState;
     798               0 :     tmpEvent.keyval = keyval;
     799               0 :     tmpEvent.group = aGroup;
     800               0 :     return GetCharCodeFor(&tmpEvent);
     801                 : }
     802                 : 
     803                 : 
     804                 : gint
     805               0 : KeymapWrapper::GetKeyLevel(GdkEventKey *aGdkKeyEvent)
     806                 : {
     807                 :     gint level;
     808               0 :     if (!gdk_keymap_translate_keyboard_state(mGdkKeymap,
     809                 :              aGdkKeyEvent->hardware_keycode,
     810                 :              GdkModifierType(aGdkKeyEvent->state),
     811               0 :              aGdkKeyEvent->group, NULL, NULL, &level, NULL)) {
     812               0 :         return -1;
     813                 :     }
     814               0 :     return level;
     815                 : }
     816                 : 
     817                 : /* static */ PRBool
     818               0 : KeymapWrapper::IsBasicLatinLetterOrNumeral(PRUint32 aCharCode)
     819                 : {
     820                 :     return (aCharCode >= 'a' && aCharCode <= 'z') ||
     821                 :            (aCharCode >= 'A' && aCharCode <= 'Z') ||
     822               0 :            (aCharCode >= '0' && aCharCode <= '9');
     823                 : }
     824                 : 
     825                 : void
     826               0 : KeymapWrapper::InitKeypressEvent(nsKeyEvent& aKeyEvent,
     827                 :                                  GdkEventKey* aGdkKeyEvent)
     828                 : {
     829               0 :     NS_ENSURE_TRUE(aKeyEvent.message == NS_KEY_PRESS, );
     830                 : 
     831               0 :     aKeyEvent.charCode = GetCharCodeFor(aGdkKeyEvent);
     832               0 :     if (!aKeyEvent.charCode) {
     833               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     834                 :             ("KeymapWrapper(%p): InitKeypressEvent, "
     835                 :              "keyCode=0x%02X, charCode=0x%08X",
     836                 :              this, aKeyEvent.keyCode, aKeyEvent.charCode));
     837               0 :         return;
     838                 :     }
     839                 : 
     840                 :     // If the event causes inputting a character, keyCode must be zero.
     841               0 :     aKeyEvent.keyCode = 0;
     842                 : 
     843                 :     // If Ctrl or Alt or Meta is pressed, we need to append the key details
     844                 :     // for handling shortcut key.  Otherwise, we have no additional work.
     845               0 :     if (!aKeyEvent.isControl && !aKeyEvent.isAlt && !aKeyEvent.isMeta) {
     846               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     847                 :             ("KeymapWrapper(%p): InitKeypressEvent, "
     848                 :              "keyCode=0x%02X, charCode=0x%08X",
     849                 :              this, aKeyEvent.keyCode, aKeyEvent.charCode));
     850               0 :         return;
     851                 :     }
     852                 : 
     853               0 :     gint level = GetKeyLevel(aGdkKeyEvent);
     854               0 :     if (level != 0 && level != 1) {
     855               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     856                 :             ("KeymapWrapper(%p): InitKeypressEvent, "
     857                 :              "keyCode=0x%02X, charCode=0x%08X, level=%d",
     858                 :              this, aKeyEvent.keyCode, aKeyEvent.charCode, level));
     859               0 :         return;
     860                 :     }
     861                 : 
     862                 :     guint baseState = aGdkKeyEvent->state &
     863               0 :         ~(GetModifierMask(SHIFT) | GetModifierMask(CTRL) |
     864               0 :           GetModifierMask(ALT) | GetModifierMask(META) |
     865               0 :           GetModifierMask(SUPER) | GetModifierMask(HYPER));
     866                 : 
     867                 :     // We shold send both shifted char and unshifted char, all keyboard layout
     868                 :     // users can use all keys.  Don't change event.charCode. On some keyboard
     869                 :     // layouts, Ctrl/Alt/Meta keys are used for inputting some characters.
     870               0 :     nsAlternativeCharCode altCharCodes(0, 0);
     871                 :     // unshifted charcode of current keyboard layout.
     872                 :     altCharCodes.mUnshiftedCharCode =
     873               0 :         GetCharCodeFor(aGdkKeyEvent, baseState, aGdkKeyEvent->group);
     874               0 :     PRBool isLatin = (altCharCodes.mUnshiftedCharCode <= 0xFF);
     875                 :     // shifted charcode of current keyboard layout.
     876                 :     altCharCodes.mShiftedCharCode =
     877                 :         GetCharCodeFor(aGdkKeyEvent,
     878               0 :                        baseState | GetModifierMask(SHIFT),
     879               0 :                        aGdkKeyEvent->group);
     880               0 :     isLatin = isLatin && (altCharCodes.mShiftedCharCode <= 0xFF);
     881               0 :     if (altCharCodes.mUnshiftedCharCode || altCharCodes.mShiftedCharCode) {
     882               0 :         aKeyEvent.alternativeCharCodes.AppendElement(altCharCodes);
     883                 :     }
     884                 : 
     885               0 :     PRBool needLatinKeyCodes = !isLatin;
     886               0 :     if (!needLatinKeyCodes) {
     887                 :         needLatinKeyCodes = 
     888                 :             (IS_ASCII_ALPHABETICAL(altCharCodes.mUnshiftedCharCode) !=
     889               0 :              IS_ASCII_ALPHABETICAL(altCharCodes.mShiftedCharCode));
     890                 :     }
     891                 : 
     892                 :     // If current keyboard layout can input Latin characters, we don't need
     893                 :     // more information.
     894               0 :     if (!needLatinKeyCodes) {
     895               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     896                 :             ("KeymapWrapper(%p): InitKeypressEvent, keyCode=0x%02X, "
     897                 :              "charCode=0x%08X, level=%d, altCharCodes={ "
     898                 :              "mUnshiftedCharCode=0x%08X, mShiftedCharCode=0x%08X }",
     899                 :              this, aKeyEvent.keyCode, aKeyEvent.charCode, level,
     900                 :              altCharCodes.mUnshiftedCharCode, altCharCodes.mShiftedCharCode));
     901               0 :         return;
     902                 :     }
     903                 : 
     904                 :     // Next, find Latin inputtable keyboard layout.
     905                 :     GdkKeymapKey *keys;
     906                 :     gint count;
     907               0 :     gint minGroup = -1;
     908               0 :     if (gdk_keymap_get_entries_for_keyval(mGdkKeymap, GDK_a, &keys, &count)) {
     909                 :         // find the minimum number group for latin inputtable layout
     910               0 :         for (gint i = 0; i < count && minGroup != 0; ++i) {
     911               0 :             if (keys[i].level != 0 && keys[i].level != 1) {
     912               0 :                 continue;
     913                 :             }
     914               0 :             if (minGroup >= 0 && keys[i].group > minGroup) {
     915               0 :                 continue;
     916                 :             }
     917               0 :             minGroup = keys[i].group;
     918                 :         }
     919               0 :         g_free(keys);
     920                 :     }
     921                 : 
     922               0 :     if (minGroup < 0) {
     923               0 :         PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     924                 :             ("KeymapWrapper(%p): InitKeypressEvent, "
     925                 :              "Latin keyboard layout isn't found: "
     926                 :              "keyCode=0x%02X, charCode=0x%08X, level=%d, "
     927                 :              "altCharCodes={ mUnshiftedCharCode=0x%08X, "
     928                 :              "mShiftedCharCode=0x%08X }",
     929                 :              this, aKeyEvent.keyCode, aKeyEvent.charCode, level,
     930                 :              altCharCodes.mUnshiftedCharCode, altCharCodes.mShiftedCharCode));
     931               0 :         return;
     932                 :     }
     933                 : 
     934               0 :     nsAlternativeCharCode altLatinCharCodes(0, 0);
     935                 :     PRUint32 unmodifiedCh =
     936                 :         aKeyEvent.isShift ? altCharCodes.mShiftedCharCode :
     937               0 :                             altCharCodes.mUnshiftedCharCode;
     938                 : 
     939                 :     // unshifted charcode of found keyboard layout.
     940               0 :     PRUint32 ch = GetCharCodeFor(aGdkKeyEvent, baseState, minGroup);
     941                 :     altLatinCharCodes.mUnshiftedCharCode =
     942               0 :         IsBasicLatinLetterOrNumeral(ch) ? ch : 0;
     943                 :     // shifted charcode of found keyboard layout.
     944                 :     ch = GetCharCodeFor(aGdkKeyEvent,
     945               0 :                         baseState | GetModifierMask(SHIFT),
     946               0 :                         minGroup);
     947                 :     altLatinCharCodes.mShiftedCharCode =
     948               0 :         IsBasicLatinLetterOrNumeral(ch) ? ch : 0;
     949               0 :     if (altLatinCharCodes.mUnshiftedCharCode ||
     950                 :         altLatinCharCodes.mShiftedCharCode) {
     951               0 :         aKeyEvent.alternativeCharCodes.AppendElement(altLatinCharCodes);
     952                 :     }
     953                 :     // If the charCode is not Latin, and the level is 0 or 1, we should
     954                 :     // replace the charCode to Latin char if Alt and Meta keys are not
     955                 :     // pressed. (Alt should be sent the localized char for accesskey
     956                 :     // like handling of Web Applications.)
     957                 :     ch = aKeyEvent.isShift ? altLatinCharCodes.mShiftedCharCode :
     958               0 :                              altLatinCharCodes.mUnshiftedCharCode;
     959               0 :     if (ch && !(aKeyEvent.isAlt || aKeyEvent.isMeta) &&
     960                 :         aKeyEvent.charCode == unmodifiedCh) {
     961               0 :         aKeyEvent.charCode = ch;
     962                 :     }
     963                 : 
     964               0 :     PR_LOG(gKeymapWrapperLog, PR_LOG_ALWAYS,
     965                 :         ("KeymapWrapper(%p): InitKeypressEvent, "
     966                 :          "keyCode=0x%02X, charCode=0x%08X, level=%d, minGroup=%d, "
     967                 :          "altCharCodes={ mUnshiftedCharCode=0x%08X, "
     968                 :          "mShiftedCharCode=0x%08X } "
     969                 :          "altLatinCharCodes={ mUnshiftedCharCode=0x%08X, "
     970                 :          "mShiftedCharCode=0x%08X }",
     971                 :          this, aKeyEvent.keyCode, aKeyEvent.charCode, level, minGroup,
     972                 :          altCharCodes.mUnshiftedCharCode, altCharCodes.mShiftedCharCode,
     973                 :          altLatinCharCodes.mUnshiftedCharCode,
     974                 :          altLatinCharCodes.mShiftedCharCode));
     975                 : }
     976                 : 
     977                 : /* static */ bool
     978               0 : KeymapWrapper::IsKeyPressEventNecessary(GdkEventKey* aGdkKeyEvent)
     979                 : {
     980                 :     // If this is a modifier key event, we shouldn't send keypress event.
     981               0 :     switch (ComputeDOMKeyCode(aGdkKeyEvent)) {
     982                 :         case NS_VK_SHIFT:
     983                 :         case NS_VK_CONTROL:
     984                 :         case NS_VK_META:
     985                 :         case NS_VK_ALT:
     986                 :         case NS_VK_CAPS_LOCK:
     987                 :         case NS_VK_NUM_LOCK:
     988                 :         case NS_VK_SCROLL_LOCK:
     989               0 :             return false;
     990                 :         default:
     991               0 :             return true;
     992                 :     }
     993                 : }
     994                 : 
     995                 : } // namespace widget
     996                 : } // namespace mozilla

Generated by: LCOV version 1.7