Back to index

lightning-sunbird  0.9+nobinonly
nsGtkKeyUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 /* ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is mozilla.org code.
00018  *
00019  * The Initial Developer of the Original Code is 
00020  * Christopher Blizzard <blizzard@mozilla.org>.  
00021  * Portions created by the Initial Developer are Copyright (C) 2001 
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include <gdk/gdkkeysyms.h>
00041 #include <gdk/gdkevents.h>
00042 #include <gdk/gdkx.h>
00043 #include "nsGUIEvent.h"
00044 #include "keysym2ucs.h"
00045 
00046 struct nsKeyConverter {
00047     int vkCode; // Platform independent key code
00048     int keysym; // GDK keysym key code
00049 };
00050 
00051 //
00052 // Netscape keycodes are defined in widget/public/nsGUIEvent.h
00053 // GTK keycodes are defined in <gdk/gdkkeysyms.h>
00054 //
00055 struct nsKeyConverter nsKeycodes[] = {
00056     { NS_VK_CANCEL,     GDK_Cancel },
00057     { NS_VK_BACK,       GDK_BackSpace },
00058     { NS_VK_TAB,        GDK_Tab },
00059     { NS_VK_TAB,        GDK_ISO_Left_Tab },
00060     { NS_VK_CLEAR,      GDK_Clear },
00061     { NS_VK_RETURN,     GDK_Return },
00062     { NS_VK_SHIFT,      GDK_Shift_L },
00063     { NS_VK_SHIFT,      GDK_Shift_R },
00064     { NS_VK_CONTROL,    GDK_Control_L },
00065     { NS_VK_CONTROL,    GDK_Control_R },
00066     { NS_VK_ALT,        GDK_Alt_L },
00067     { NS_VK_ALT,        GDK_Alt_R },
00068     { NS_VK_META,       GDK_Meta_L },
00069     { NS_VK_META,       GDK_Meta_R },
00070     { NS_VK_PAUSE,      GDK_Pause },
00071     { NS_VK_CAPS_LOCK,  GDK_Caps_Lock },
00072     { NS_VK_ESCAPE,     GDK_Escape },
00073     { NS_VK_SPACE,      GDK_space },
00074     { NS_VK_PAGE_UP,    GDK_Page_Up },
00075     { NS_VK_PAGE_DOWN,  GDK_Page_Down },
00076     { NS_VK_END,        GDK_End },
00077     { NS_VK_HOME,       GDK_Home },
00078     { NS_VK_LEFT,       GDK_Left },
00079     { NS_VK_UP,         GDK_Up },
00080     { NS_VK_RIGHT,      GDK_Right },
00081     { NS_VK_DOWN,       GDK_Down },
00082     { NS_VK_PRINTSCREEN, GDK_Print },
00083     { NS_VK_INSERT,     GDK_Insert },
00084     { NS_VK_DELETE,     GDK_Delete },
00085 
00086     // keypad keys
00087     { NS_VK_LEFT,       GDK_KP_Left },
00088     { NS_VK_RIGHT,      GDK_KP_Right },
00089     { NS_VK_UP,         GDK_KP_Up },
00090     { NS_VK_DOWN,       GDK_KP_Down },
00091     { NS_VK_PAGE_UP,    GDK_KP_Page_Up },
00092     // Not sure what these are
00093     //{ NS_VK_,       GDK_KP_Prior },
00094     //{ NS_VK_,        GDK_KP_Next },
00095     // GDK_KP_Begin is the 5 on the non-numlock keypad
00096     //{ NS_VK_,        GDK_KP_Begin },
00097     { NS_VK_PAGE_DOWN,  GDK_KP_Page_Down },
00098     { NS_VK_HOME,       GDK_KP_Home },
00099     { NS_VK_END,        GDK_KP_End },
00100     { NS_VK_INSERT,     GDK_KP_Insert },
00101     { NS_VK_DELETE,     GDK_KP_Delete },
00102 
00103     { NS_VK_MULTIPLY,   GDK_KP_Multiply },
00104     { NS_VK_ADD,        GDK_KP_Add },
00105     { NS_VK_SEPARATOR,  GDK_KP_Separator },
00106     { NS_VK_SUBTRACT,   GDK_KP_Subtract },
00107     { NS_VK_DECIMAL,    GDK_KP_Decimal },
00108     { NS_VK_DIVIDE,     GDK_KP_Divide },
00109     { NS_VK_RETURN,     GDK_KP_Enter },
00110     { NS_VK_NUM_LOCK,   GDK_Num_Lock },
00111     { NS_VK_SCROLL_LOCK,GDK_Scroll_Lock },
00112 
00113     { NS_VK_COMMA,      GDK_comma },
00114     { NS_VK_PERIOD,     GDK_period },
00115     { NS_VK_SLASH,      GDK_slash },
00116     { NS_VK_BACK_SLASH, GDK_backslash },
00117     { NS_VK_BACK_QUOTE, GDK_grave },
00118     { NS_VK_OPEN_BRACKET, GDK_bracketleft },
00119     { NS_VK_CLOSE_BRACKET, GDK_bracketright },
00120     { NS_VK_SEMICOLON, GDK_colon },
00121     { NS_VK_QUOTE, GDK_apostrophe },
00122 
00123     // context menu key, keysym 0xff67, typically keycode 117 on 105-key (Microsoft) 
00124     // x86 keyboards, located between right 'Windows' key and right Ctrl key
00125     { NS_VK_CONTEXT_MENU, GDK_Menu },
00126 
00127     // NS doesn't have dash or equals distinct from the numeric keypad ones,
00128     // so we'll use those for now.  See bug 17008:
00129     { NS_VK_SUBTRACT, GDK_minus },
00130     { NS_VK_EQUALS, GDK_equal },
00131 
00132     // Some shifted keys, see bug 15463 as well as 17008.
00133     // These should be subject to different keyboard mappings.
00134     { NS_VK_QUOTE, GDK_quotedbl },
00135     { NS_VK_OPEN_BRACKET, GDK_braceleft },
00136     { NS_VK_CLOSE_BRACKET, GDK_braceright },
00137     { NS_VK_BACK_SLASH, GDK_bar },
00138     { NS_VK_SEMICOLON, GDK_semicolon },
00139     { NS_VK_BACK_QUOTE, GDK_asciitilde },
00140     { NS_VK_COMMA, GDK_less },
00141     { NS_VK_PERIOD, GDK_greater },
00142     { NS_VK_SLASH,      GDK_question },
00143     { NS_VK_1, GDK_exclam },
00144     { NS_VK_2, GDK_at },
00145     { NS_VK_3, GDK_numbersign },
00146     { NS_VK_4, GDK_dollar },
00147     { NS_VK_5, GDK_percent },
00148     { NS_VK_6, GDK_asciicircum },
00149     { NS_VK_7, GDK_ampersand },
00150     { NS_VK_8, GDK_asterisk },
00151     { NS_VK_9, GDK_parenleft },
00152     { NS_VK_0, GDK_parenright },
00153     { NS_VK_SUBTRACT, GDK_underscore },
00154     { NS_VK_EQUALS, GDK_plus }
00155 };
00156 
00157 #define IS_XSUN_XSERVER(dpy) \
00158     (strstr(XServerVendor(dpy), "Sun Microsystems") != NULL)
00159 
00160 // map Sun Keyboard special keysyms on to NS_VK keys
00161 struct nsKeyConverter nsSunKeycodes[] = {
00162     {NS_VK_ESCAPE, GDK_F11 }, //bug 57262, Sun Stop key generates F11 keysym
00163     {NS_VK_F1, GDK_Help }, //Mapping Help key to F1
00164     {NS_VK_F11, 0x1005ff10 }, //Sun F11 key generates SunF36(0x1005ff10) keysym
00165     {NS_VK_F12, 0x1005ff11 }, //Sun F12 key generates SunF37(0x1005ff11) keysym
00166     {NS_VK_PAGE_UP,    GDK_F29 }, //KP_Prior
00167     {NS_VK_PAGE_DOWN,  GDK_F35 }, //KP_Next
00168     {NS_VK_HOME,       GDK_F27 }, //KP_Home
00169     {NS_VK_END,        GDK_F33 }, //KP_End
00170 };
00171 
00172 int
00173 GdkKeyCodeToDOMKeyCode(int aKeysym)
00174 {
00175     int i, length = 0;
00176 
00177     // First, try to handle alphanumeric input, not listed in nsKeycodes:
00178     // most likely, more letters will be getting typed in than things in
00179     // the key list, so we will look through these first.
00180 
00181     // since X has different key symbols for upper and lowercase letters and
00182     // mozilla does not, convert gdk's to mozilla's
00183     if (aKeysym >= GDK_a && aKeysym <= GDK_z)
00184         return aKeysym - GDK_a + NS_VK_A;
00185     if (aKeysym >= GDK_A && aKeysym <= GDK_Z)
00186         return aKeysym - GDK_A + NS_VK_A;
00187 
00188     // numbers
00189     if (aKeysym >= GDK_0 && aKeysym <= GDK_9)
00190         return aKeysym - GDK_0 + NS_VK_0;
00191 
00192     // keypad numbers
00193     if (aKeysym >= GDK_KP_0 && aKeysym <= GDK_KP_9)
00194         return aKeysym - GDK_KP_0 + NS_VK_NUMPAD0;
00195 
00196     // map Sun Keyboard special keysyms
00197     if (IS_XSUN_XSERVER(GDK_DISPLAY())) {
00198         length = sizeof(nsSunKeycodes) / sizeof(struct nsKeyConverter);
00199         for (i = 0; i < length; i++) {
00200             if (nsSunKeycodes[i].keysym == aKeysym)
00201                 return(nsSunKeycodes[i].vkCode);
00202         }
00203     }
00204 
00205     // misc other things
00206     length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);
00207     for (i = 0; i < length; i++) {
00208         if (nsKeycodes[i].keysym == aKeysym)
00209             return(nsKeycodes[i].vkCode);
00210     }
00211 
00212     // function keys
00213     if (aKeysym >= GDK_F1 && aKeysym <= GDK_F24)
00214         return aKeysym - GDK_F1 + NS_VK_F1;
00215 
00216     return((int)0);
00217 }
00218 
00219 int
00220 DOMKeyCodeToGdkKeyCode(PRUint32 aKeysym)
00221 {
00222     int i, length = 0;
00223 
00224     // First, try to handle alphanumeric input, not listed in nsKeycodes:
00225     // most likely, more letters will be getting typed in than things in
00226     // the key list, so we will look through these first.
00227 
00228     if (aKeysym >= NS_VK_A && aKeysym <= NS_VK_Z)
00229       // gdk and DOM both use the ASCII codes for these keys.
00230       return aKeysym;
00231 
00232     // numbers
00233     if (aKeysym >= NS_VK_0 && aKeysym <= NS_VK_9)
00234       // gdk and DOM both use the ASCII codes for these keys.
00235       return aKeysym - GDK_0 + NS_VK_0;
00236 
00237     // keypad numbers
00238     if (aKeysym >= NS_VK_NUMPAD0 && aKeysym <= NS_VK_NUMPAD9)
00239       return aKeysym - NS_VK_NUMPAD0 + GDK_KP_0;
00240 
00241     // misc other things
00242     length = NS_ARRAY_LENGTH(nsKeycodes);
00243     for (i = 0; i < length; ++i) {
00244       if (nsKeycodes[i].vkCode == aKeysym) {
00245         return nsKeycodes[i].keysym;
00246       }
00247     }
00248 
00249     // function keys
00250     if (aKeysym >= NS_VK_F1 && aKeysym <= NS_VK_F9)
00251       return aKeysym - NS_VK_F1 + GDK_F1;
00252 
00253     return 0;
00254 }
00255 
00256 // Convert gdk key event keyvals to char codes if printable, 0 otherwise
00257 PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aEvent)
00258 {
00259     // Anything above 0xf000 is considered a non-printable
00260     // Exception: directly encoded UCS characters
00261     if (aEvent->keyval > 0xf000 && (aEvent->keyval & 0xff000000) != 0x01000000) {
00262 
00263         // Keypad keys are an exception: they return a value different
00264         // from their non-keypad equivalents, but mozilla doesn't distinguish.
00265         switch (aEvent->keyval)
00266             {
00267             case GDK_KP_Space:
00268                 return ' ';
00269             case GDK_KP_Equal:
00270                 return '=';
00271             case GDK_KP_Multiply:
00272                 return '*';
00273             case GDK_KP_Add:
00274                 return '+';
00275             case GDK_KP_Separator:
00276                 return ',';
00277             case GDK_KP_Subtract:
00278                 return '-';
00279             case GDK_KP_Decimal:
00280                 return '.';
00281             case GDK_KP_Divide:
00282                 return '/';
00283             case GDK_KP_0:
00284                 return '0';
00285             case GDK_KP_1:
00286                 return '1';
00287             case GDK_KP_2:
00288                 return '2';
00289             case GDK_KP_3:
00290                 return '3';
00291             case GDK_KP_4:
00292                 return '4';
00293             case GDK_KP_5:
00294                 return '5';
00295             case GDK_KP_6:
00296                 return '6';
00297             case GDK_KP_7:
00298                 return '7';
00299             case GDK_KP_8:
00300                 return '8';
00301             case GDK_KP_9:
00302                 return '9';
00303             }
00304 
00305         // non-printables
00306         return 0;
00307     }
00308 
00309     // we're supposedly printable, let's try to convert
00310     long ucs = keysym2ucs(aEvent->keyval);
00311     if ((ucs != -1) && (ucs < 0x10000))
00312         return ucs;
00313 
00314     // I guess we couldn't convert
00315     return 0;
00316 }